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
|
* - The `/wea` command will give/remove the required bypass permission
|
||||||
*/
|
*/
|
||||||
if (Fawe.<FaweBukkit> imp().getVault() == null || Fawe.<FaweBukkit> imp().getVault().permission == null) {
|
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) {
|
} else if (flag) {
|
||||||
if (!Fawe.<FaweBukkit> imp().getVault().permission.playerAdd(this.parent, perm)) {
|
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 {
|
} else {
|
||||||
if (!Fawe.<FaweBukkit> imp().getVault().permission.playerRemove(this.parent, perm)) {
|
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.TownyFeature;
|
||||||
import com.boydti.fawe.bukkit.regions.Worldguard;
|
import com.boydti.fawe.bukkit.regions.Worldguard;
|
||||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_All;
|
import com.boydti.fawe.bukkit.v0.BukkitQueue_All;
|
||||||
import com.boydti.fawe.bukkit.v1_8.BukkitEditSessionWrapper_1_8;
|
import com.boydti.fawe.bukkit.v0.ChunkListener;
|
||||||
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.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.object.EditSessionWrapper;
|
import com.boydti.fawe.object.EditSessionWrapper;
|
||||||
import com.boydti.fawe.object.FaweCommand;
|
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.PlayerChangedWorldEvent;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
import org.bukkit.plugin.Plugin;
|
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 VaultUtil vault;
|
||||||
private WorldEditPlugin worldedit;
|
private WorldEditPlugin worldedit;
|
||||||
|
|
||||||
@ -61,10 +58,10 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
|||||||
return this.worldedit;
|
return this.worldedit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public FaweBukkit(BukkitMain plugin) {
|
||||||
public void onEnable() {
|
this.plugin = plugin;
|
||||||
try {
|
try {
|
||||||
Bukkit.getPluginManager().registerEvents(this, this);
|
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||||
Fawe.set(this);
|
Fawe.set(this);
|
||||||
if (Bukkit.getVersion().contains("git-Spigot") && FaweAPI.checkVersion(this.getVersion(), 1, 7, 10)) {
|
if (Bukkit.getVersion().contains("git-Spigot") && FaweAPI.checkVersion(this.getVersion(), 1, 7, 10)) {
|
||||||
debug("====== USE PAPER SPIGOT ======");
|
debug("====== USE PAPER SPIGOT ======");
|
||||||
@ -76,23 +73,29 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
|||||||
|
|
||||||
} catch (final Throwable e) {
|
} catch (final Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
this.getServer().shutdown();
|
Bukkit.getServer().shutdown();
|
||||||
}
|
}
|
||||||
|
TaskManager.IMP.task(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
new ChunkListener();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void debug(final String s) {
|
public void debug(final String s) {
|
||||||
this.getLogger().info(ChatColor.translateAlternateColorCodes('&', s));
|
Bukkit.getLogger().info(ChatColor.translateAlternateColorCodes('&', s));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getDirectory() {
|
public File getDirectory() {
|
||||||
return this.getDataFolder();
|
return plugin.getDataFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setupCommand(final String label, final FaweCommand cmd) {
|
public void setupCommand(final String label, final FaweCommand cmd) {
|
||||||
this.getCommand(label).setExecutor(new BukkitCommand(cmd));
|
plugin.getCommand(label).setExecutor(new BukkitCommand(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -115,7 +118,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startMetrics() {
|
public void startMetrics() {
|
||||||
Metrics metrics = new Metrics(this);
|
Metrics metrics = new Metrics(plugin);
|
||||||
metrics.start();
|
metrics.start();
|
||||||
debug("&6Metrics enabled.");
|
debug("&6Metrics enabled.");
|
||||||
}
|
}
|
||||||
@ -131,7 +134,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setupWEListener() {
|
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
|
@Override
|
||||||
public TaskManager getTaskManager() {
|
public TaskManager getTaskManager() {
|
||||||
return new BukkitTaskMan(this);
|
return new BukkitTaskMan(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int[] version;
|
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>
|
* - 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
|
@Override
|
||||||
public FaweQueue getNewQueue(String world) {
|
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||||
try {
|
try {
|
||||||
Field fieldDirtyCount = ReflectionUtils.getRefClass("{nms}.PlayerChunk").getField("dirtyCount").getRealField();
|
Field fieldDirtyCount = ReflectionUtils.getRefClass("{nms}.PlayerChunk").getField("dirtyCount").getRealField();
|
||||||
fieldDirtyCount.setAccessible(true);
|
fieldDirtyCount.setAccessible(true);
|
||||||
@ -200,19 +203,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
|||||||
}
|
}
|
||||||
} catch (Throwable ignore) {}
|
} catch (Throwable ignore) {}
|
||||||
try {
|
try {
|
||||||
if (FaweAPI.checkVersion(this.getVersion(), 1, 9, 0)) {
|
return plugin.getQueue(world);
|
||||||
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);
|
|
||||||
} catch (Throwable ignore) {}
|
} catch (Throwable ignore) {}
|
||||||
if (hasNMS) {
|
if (hasNMS) {
|
||||||
debug("====== NO NMS BLOCK PLACER FOUND ======");
|
debug("====== NO NMS BLOCK PLACER FOUND ======");
|
||||||
@ -226,6 +217,10 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
|||||||
return new BukkitQueue_All(world);
|
return new BukkitQueue_All(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BukkitMain getPlugin() {
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getWorldName(World world) {
|
public String getWorldName(World world) {
|
||||||
return world.getName();
|
return world.getName();
|
||||||
@ -236,7 +231,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public EditSessionWrapper getEditSessionWrapper(final EditSession session) {
|
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 57:
|
||||||
case 58:
|
case 58:
|
||||||
case 60:
|
case 60:
|
||||||
case 61:
|
|
||||||
case 62:
|
|
||||||
case 7:
|
case 7:
|
||||||
case 8:
|
case 8:
|
||||||
case 9:
|
case 9:
|
@ -1,14 +1,9 @@
|
|||||||
package com.boydti.fawe.bukkit.v0;
|
package com.boydti.fawe.bukkit.v0;
|
||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
|
||||||
import com.boydti.fawe.FaweCache;
|
import com.boydti.fawe.FaweCache;
|
||||||
import com.boydti.fawe.bukkit.v1_8.BukkitChunk_1_8;
|
import com.boydti.fawe.example.CharFaweChunk;
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
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.LocalWorld;
|
||||||
import com.sk89q.worldedit.Vector2D;
|
import com.sk89q.worldedit.Vector2D;
|
||||||
import com.sk89q.worldedit.bukkit.BukkitUtil;
|
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.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.Block;
|
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);
|
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());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
private boolean physicsFreeze = false;
|
public World getWorld(String world) {
|
||||||
|
return Bukkit.getWorld(world);
|
||||||
@EventHandler
|
|
||||||
public void onPhysics(BlockPhysicsEvent event) {
|
|
||||||
if (physicsFreeze) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@Override
|
||||||
public void onItemSpawn(ItemSpawnEvent event) {
|
public boolean isChunkLoaded(World world, int x, int z) {
|
||||||
if (physicsFreeze) {
|
return world.isChunkLoaded(x, z);
|
||||||
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;
|
private volatile boolean timingsEnabled;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startSet(boolean parallel) {
|
public void startSet(boolean parallel) {
|
||||||
|
ChunkListener.physicsFreeze = true;
|
||||||
if (parallel) {
|
if (parallel) {
|
||||||
try {
|
try {
|
||||||
Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled");
|
Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled");
|
||||||
@ -80,6 +76,7 @@ public class BukkitQueue_All extends BukkitQueue_0 {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void endSet(boolean parallel) {
|
public void endSet(boolean parallel) {
|
||||||
|
ChunkListener.physicsFreeze = false;
|
||||||
if (parallel) {
|
if (parallel) {
|
||||||
try {Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled");fieldEnabled.setAccessible(true);fieldEnabled.set(null, timingsEnabled);
|
try {Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled");fieldEnabled.setAccessible(true);fieldEnabled.set(null, timingsEnabled);
|
||||||
} catch (Throwable ignore) {ignore.printStackTrace();}
|
} catch (Throwable ignore) {ignore.printStackTrace();}
|
||||||
@ -88,15 +85,9 @@ public class BukkitQueue_All extends BukkitQueue_0 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<FaweChunk<Chunk>> sendChunk(Collection<FaweChunk<Chunk>> fcs) {
|
public boolean setComponents(FaweChunk fc) {
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setComponents(FaweChunk<Chunk> fc) {
|
|
||||||
try {
|
try {
|
||||||
startSet();
|
final CharFaweChunk<Chunk> fs = ((CharFaweChunk<Chunk>) fc);
|
||||||
final BukkitChunk_1_8 fs = ((BukkitChunk_1_8) fc);
|
|
||||||
final Chunk chunk = fs.getChunk();
|
final Chunk chunk = fs.getChunk();
|
||||||
chunk.load(true);
|
chunk.load(true);
|
||||||
final World world = chunk.getWorld();
|
final World world = chunk.getWorld();
|
||||||
@ -191,115 +182,20 @@ public class BukkitQueue_All extends BukkitQueue_0 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
endSet();
|
|
||||||
return true;
|
return true;
|
||||||
} catch (final Throwable e) {
|
} catch (final Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
endSet();
|
|
||||||
return false;
|
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
|
@Override
|
||||||
public FaweChunk<Chunk> getChunk(int x, int z) {
|
public FaweChunk getChunk(final int x, final int z) {
|
||||||
return new BukkitChunk_1_8(this, x, z);
|
return new CharFaweChunk<Chunk>(this, x, z) {
|
||||||
}
|
@Override
|
||||||
|
public Chunk getNewChunk() {
|
||||||
@Override
|
return getWorld().getChunkAt(x, z);
|
||||||
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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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.Fawe;
|
||||||
import com.boydti.fawe.FaweCache;
|
import com.boydti.fawe.FaweCache;
|
||||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_All;
|
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||||
import com.boydti.fawe.bukkit.v1_8.BukkitChunk_1_8;
|
import com.boydti.fawe.example.CharFaweChunk;
|
||||||
import com.boydti.fawe.config.Settings;
|
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
import com.boydti.fawe.object.IntegerPair;
|
import com.boydti.fawe.object.IntegerPair;
|
||||||
import com.boydti.fawe.object.PseudoRandom;
|
import com.boydti.fawe.object.PseudoRandom;
|
||||||
import com.boydti.fawe.util.MemUtil;
|
import com.boydti.fawe.util.MemUtil;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
|
||||||
import com.sk89q.worldedit.LocalSession;
|
import com.sk89q.worldedit.LocalSession;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -24,6 +21,7 @@ import java.util.Map;
|
|||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import net.minecraft.server.v1_9_R1.Block;
|
import net.minecraft.server.v1_9_R1.Block;
|
||||||
import net.minecraft.server.v1_9_R1.BlockPosition;
|
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.ChunkSection;
|
||||||
import net.minecraft.server.v1_9_R1.DataBits;
|
import net.minecraft.server.v1_9_R1.DataBits;
|
||||||
import net.minecraft.server.v1_9_R1.DataPalette;
|
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.BlockPopulator;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
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);
|
super(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getCachedChunk(int cx, int cz) {
|
@Override
|
||||||
CraftChunk chunk = (CraftChunk) bukkitWorld.getChunkAt(cx, cz);
|
public ChunkSection[] getCachedChunk(World world, int cx, int cz) {
|
||||||
|
CraftChunk chunk = (CraftChunk) world.getChunkAt(cx, cz);
|
||||||
return chunk.getHandle().getSections();
|
return chunk.getHandle().getSections();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getCachedSection(Object chunk, int cy) {
|
@Override
|
||||||
ChunkSection[] chunkSections = (ChunkSection[]) chunk;
|
public DataPaletteBlock getCachedSection(ChunkSection[] chunkSections, int cy) {
|
||||||
ChunkSection nibble = chunkSections[cy];
|
ChunkSection nibble = chunkSections[cy];
|
||||||
return nibble != null ? nibble.getBlocks() : null;
|
return nibble != null ? nibble.getBlocks() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCombinedId4Data(Object section, int x, int y, int z) {
|
@Override
|
||||||
DataPaletteBlock lastSection = (DataPaletteBlock) section;
|
public int getCombinedId4Data(DataPaletteBlock lastSection, int x, int y, int z) {
|
||||||
IBlockData ibd = lastSection.a(x & 15, y & 15, z & 15);
|
IBlockData ibd = lastSection.a(x & 15, y & 15, z & 15);
|
||||||
Block block = ibd.getBlock();
|
Block block = ibd.getBlock();
|
||||||
int id = Block.getId(block);
|
int id = Block.getId(block);
|
||||||
@ -73,37 +72,15 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<FaweChunk<Chunk>> sendChunk(final Collection<FaweChunk<Chunk>> fcs) {
|
public void refreshChunk(World world, Chunk fc) {
|
||||||
for (final FaweChunk<Chunk> fc : fcs) {
|
world.refreshChunk(fc.getX(), fc.getZ());
|
||||||
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
|
@Override
|
||||||
public boolean fixLighting(final FaweChunk<?> pc, final boolean fixAll) {
|
public boolean fixLighting(final FaweChunk pc, final boolean fixAll) {
|
||||||
try {
|
try {
|
||||||
final BukkitChunk_1_8 bc = (BukkitChunk_1_8) pc;
|
final CharFaweChunk bc = (CharFaweChunk) pc;
|
||||||
final Chunk chunk = bc.getChunk();
|
final Chunk chunk = (Chunk) bc.getChunk();
|
||||||
if (!chunk.isLoaded()) {
|
if (!chunk.isLoaded()) {
|
||||||
if (Fawe.get().getMainThread() != Thread.currentThread()) {
|
if (Fawe.get().getMainThread() != Thread.currentThread()) {
|
||||||
return false;
|
return false;
|
||||||
@ -232,10 +209,16 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
|
|||||||
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
|
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
|
@Override
|
||||||
public boolean setComponents(final FaweChunk<Chunk> pc) {
|
public boolean setComponents(final FaweChunk pc) {
|
||||||
final BukkitChunk_1_8 fs = (BukkitChunk_1_8) pc;
|
final BukkitChunk_1_9 fs = (BukkitChunk_1_9) pc;
|
||||||
final Chunk chunk = pc.getChunk();
|
final Chunk chunk = (Chunk) fs.getChunk();
|
||||||
final World world = chunk.getWorld();
|
final World world = chunk.getWorld();
|
||||||
chunk.load(true);
|
chunk.load(true);
|
||||||
try {
|
try {
|
||||||
@ -286,10 +269,10 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
|
|||||||
entities[i].clear();
|
entities[i].clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Efficiently merge sections
|
// Efficiently merge sections
|
||||||
for (int j = 0; j < sections.length; j++) {
|
for (int j = 0; j < sections.length; j++) {
|
||||||
if (fs.getCount(j) == 0) {
|
int count = fs.getCount(j);
|
||||||
|
if (count == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final char[] array = fs.getIdArray(j);
|
final char[] array = fs.getIdArray(j);
|
||||||
@ -298,7 +281,23 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
|
|||||||
}
|
}
|
||||||
ChunkSection section = sections[j];
|
ChunkSection section = sections[j];
|
||||||
if (section == null) {
|
if (section == null) {
|
||||||
sections[j] = new ChunkSection(j << 4, flag, array);
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
DataPaletteBlock nibble = section.getBlocks();
|
DataPaletteBlock nibble = section.getBlocks();
|
||||||
@ -309,95 +308,25 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
|
|||||||
Field fieldPalette = nibble.getClass().getDeclaredField("c");
|
Field fieldPalette = nibble.getClass().getDeclaredField("c");
|
||||||
fieldPalette.setAccessible(true);
|
fieldPalette.setAccessible(true);
|
||||||
DataPalette palette = (DataPalette) fieldPalette.get(nibble);
|
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 nonEmptyBlockCount = 0;
|
||||||
int lastId = -1;
|
for (int y = 0; y < 16; y++) {
|
||||||
int lastBit = -1;
|
for (int z = 0; z < 16; z++) {
|
||||||
for (int k = 0; k < array.length; k++) {
|
for (int x = 0; x < 16; x++) {
|
||||||
final char combined = array[k];
|
char combinedId = array[FaweCache.CACHE_J[y][x][z]];
|
||||||
switch (combined) {
|
switch (combinedId) {
|
||||||
case 0:
|
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;
|
continue;
|
||||||
}
|
case 1:
|
||||||
Block block = ibd.getBlock();
|
// TODO check existing
|
||||||
int id = Block.getId(block);
|
nibble.setBlock(x, y, z, Blocks.AIR.getBlockData());
|
||||||
if (FaweCache.hasData(id)) {
|
continue;
|
||||||
lastId = (id << 4) + block.toLegacyData(ibd);
|
default:
|
||||||
} else {
|
nonEmptyBlockCount++;
|
||||||
lastId = id << 4;
|
nibble.setBlock(x, y, z, Block.getById(combinedId >> 4).fromLegacyData(combinedId & 0xF));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (lastId != 0) {
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fill) {
|
|
||||||
fs.setCount(j, Short.MAX_VALUE);
|
|
||||||
}
|
|
||||||
setCount(0, nonEmptyBlockCount, section);
|
setCount(0, nonEmptyBlockCount, section);
|
||||||
}
|
}
|
||||||
// Clear
|
// Clear
|
||||||
@ -534,11 +463,6 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
|
|||||||
players = null;
|
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) {
|
public boolean unloadChunk(final String world, final Chunk chunk) {
|
||||||
net.minecraft.server.v1_9_R1.Chunk c = ((CraftChunk) chunk).getHandle();
|
net.minecraft.server.v1_9_R1.Chunk c = ((CraftChunk) chunk).getHandle();
|
||||||
c.mustSave = false;
|
c.mustSave = false;
|
||||||
@ -674,4 +598,9 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
|
|||||||
}
|
}
|
||||||
return null;
|
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
|
* @return
|
||||||
*/
|
*/
|
||||||
public FaweQueue createQueue(String worldName, boolean autoqueue) {
|
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) {
|
public static World getWorld(String worldName) {
|
||||||
@ -295,7 +295,7 @@ public class FaweAPI {
|
|||||||
* @param fixAll
|
* @param fixAll
|
||||||
*/
|
*/
|
||||||
public static void fixLighting(String world, int x, int z, final boolean 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);
|
queue.fixLighting(queue.getChunk(x, z), fixAll);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,7 +305,7 @@ public class FaweAPI {
|
|||||||
* @param fixAll
|
* @param fixAll
|
||||||
*/
|
*/
|
||||||
public static void fixLighting(final Chunk chunk, final boolean 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);
|
queue.fixLighting(queue.getChunk(chunk.getX(), chunk.getZ()), fixAll);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,7 +388,7 @@ public class FaweAPI {
|
|||||||
tagMap = null;
|
tagMap = null;
|
||||||
tag = 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++) {
|
for (int y = 0; y < height; y++) {
|
||||||
final int yy = y_offset + y;
|
final int yy = y_offset + y;
|
||||||
|
@ -5,7 +5,13 @@ import com.sk89q.worldedit.CuboidClipboard;
|
|||||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||||
|
|
||||||
public class FaweCache {
|
public class FaweCache {
|
||||||
|
/**
|
||||||
|
* y | x | z
|
||||||
|
*/
|
||||||
public final static short[][][] CACHE_I = new short[256][16][16];
|
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 short[][][] CACHE_J = new short[256][16][16];
|
||||||
|
|
||||||
public final static byte[][] CACHE_X = new byte[16][4096];
|
public final static byte[][] CACHE_X = new byte[16][4096];
|
||||||
@ -105,13 +111,10 @@ public class FaweCache {
|
|||||||
case 49:
|
case 49:
|
||||||
case 51:
|
case 51:
|
||||||
case 52:
|
case 52:
|
||||||
case 54:
|
|
||||||
case 56:
|
case 56:
|
||||||
case 57:
|
case 57:
|
||||||
case 58:
|
case 58:
|
||||||
case 60:
|
case 60:
|
||||||
case 61:
|
|
||||||
case 62:
|
|
||||||
case 7:
|
case 7:
|
||||||
case 8:
|
case 8:
|
||||||
case 9:
|
case 9:
|
||||||
|
@ -29,7 +29,7 @@ public interface IFawe {
|
|||||||
|
|
||||||
public int[] getVersion();
|
public int[] getVersion();
|
||||||
|
|
||||||
public FaweQueue getNewQueue(String world);
|
public FaweQueue getNewQueue(String world, boolean fast);
|
||||||
|
|
||||||
public String getWorldName(World world);
|
public String getWorldName(World world);
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ public class Settings {
|
|||||||
public static boolean ENABLE_HARD_LIMIT = true;
|
public static boolean ENABLE_HARD_LIMIT = true;
|
||||||
public static boolean STORE_HISTORY_ON_DISK = false;
|
public static boolean STORE_HISTORY_ON_DISK = false;
|
||||||
public static boolean STORE_CLIPBOARD_ON_DISK = false;
|
public static boolean STORE_CLIPBOARD_ON_DISK = false;
|
||||||
|
|
||||||
public static int DELETE_HISTORY_AFTER_DAYS = 7;
|
public static int DELETE_HISTORY_AFTER_DAYS = 7;
|
||||||
public static int DELETE_CLIPBOARD_AFTER_DAYS = 1;
|
public static int DELETE_CLIPBOARD_AFTER_DAYS = 1;
|
||||||
public static int COMPRESSION_LEVEL = 0;
|
public static int COMPRESSION_LEVEL = 0;
|
||||||
@ -39,6 +38,8 @@ public class Settings {
|
|||||||
public static int UNSAFE_PARALLEL_THREADS = 1;
|
public static int UNSAFE_PARALLEL_THREADS = 1;
|
||||||
public static boolean FIX_ALL_LIGHTING = true;
|
public static boolean FIX_ALL_LIGHTING = true;
|
||||||
public static boolean ASYNC_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;
|
public static HashMap<String, FaweLimit> limits;
|
||||||
|
|
||||||
@ -103,6 +104,9 @@ public class Settings {
|
|||||||
options.put("extent.debug", EXTENT_DEBUG);
|
options.put("extent.debug", EXTENT_DEBUG);
|
||||||
options.put("metrics", METRICS);
|
options.put("metrics", METRICS);
|
||||||
|
|
||||||
|
options.put("tick-limiter.physics", PHYSICS_PER_TICK);
|
||||||
|
options.put("tick-limiter.items", ITEMS_PER_TICK);
|
||||||
|
|
||||||
// Default limit
|
// Default limit
|
||||||
FaweLimit defaultLimit = new FaweLimit();
|
FaweLimit defaultLimit = new FaweLimit();
|
||||||
if (!config.contains("limits.default")) {
|
if (!config.contains("limits.default")) {
|
||||||
@ -141,6 +145,9 @@ public class Settings {
|
|||||||
EXTENT_DEBUG = config.getBoolean("extent.debug");
|
EXTENT_DEBUG = config.getBoolean("extent.debug");
|
||||||
STORE_CLIPBOARD_ON_DISK = config.getBoolean("clipboard.use-disk");
|
STORE_CLIPBOARD_ON_DISK = config.getBoolean("clipboard.use-disk");
|
||||||
DELETE_CLIPBOARD_AFTER_DAYS = config.getInt("clipboard.delete-after-days");
|
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")) {
|
if (STORE_HISTORY_ON_DISK = config.getBoolean("history.use-disk")) {
|
||||||
LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE;
|
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.FaweCache;
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
@ -6,24 +6,25 @@ import com.boydti.fawe.util.FaweQueue;
|
|||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||||
import java.util.Arrays;
|
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;
|
public T chunk;
|
||||||
private short[] air;
|
|
||||||
private short[] relight;
|
|
||||||
private int[][] biomes;
|
|
||||||
|
|
||||||
public Chunk chunk;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
* 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);
|
super(parent, x, z);
|
||||||
this.ids = new char[16][];
|
this.ids = new char[16][];
|
||||||
this.count = new short[16];
|
this.count = new short[16];
|
||||||
@ -32,13 +33,15 @@ public class BukkitChunk_1_8 extends FaweChunk<Chunk> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Chunk getChunk() {
|
public T getChunk() {
|
||||||
if (this.chunk == null) {
|
if (this.chunk == null) {
|
||||||
this.chunk = Bukkit.getWorld(getParent().world).getChunkAt(getX(), getZ());
|
this.chunk = getNewChunk();
|
||||||
}
|
}
|
||||||
return this.chunk;
|
return this.chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract T getNewChunk();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLoc(final FaweQueue parent, int x, int z) {
|
public void setLoc(final FaweQueue parent, int x, int z) {
|
||||||
super.setLoc(parent, x, z);
|
super.setLoc(parent, x, z);
|
||||||
@ -199,15 +202,17 @@ public class BukkitChunk_1_8 extends FaweChunk<Chunk> {
|
|||||||
case 130:
|
case 130:
|
||||||
case 76:
|
case 76:
|
||||||
case 62:
|
case 62:
|
||||||
|
case 50:
|
||||||
this.relight[i]++;
|
this.relight[i]++;
|
||||||
case 54:
|
case 54:
|
||||||
case 146:
|
case 146:
|
||||||
case 61:
|
case 61:
|
||||||
case 65:
|
case 65:
|
||||||
case 68:
|
case 68:
|
||||||
if (data < 2) {
|
// if (data < 2) {
|
||||||
data = 2;
|
// data = 2;
|
||||||
}
|
// }
|
||||||
|
|
||||||
default:
|
default:
|
||||||
vs[j] = (char) ((id << 4) + data);
|
vs[j] = (char) ((id << 4) + data);
|
||||||
return;
|
return;
|
||||||
@ -227,8 +232,8 @@ public class BukkitChunk_1_8 extends FaweChunk<Chunk> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FaweChunk<Chunk> copy(boolean shallow) {
|
public CharFaweChunk<T> copy(boolean shallow) {
|
||||||
BukkitChunk_1_8 copy = new BukkitChunk_1_8(getParent(), getX(), getZ());
|
CharFaweChunk<T> copy = (CharFaweChunk<T>) getParent().getChunk(getX(), getZ());
|
||||||
if (shallow) {
|
if (shallow) {
|
||||||
copy.ids = ids;
|
copy.ids = ids;
|
||||||
copy.air = air;
|
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.FaweCache;
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
@ -6,24 +6,26 @@ import com.boydti.fawe.util.FaweQueue;
|
|||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||||
import java.util.Arrays;
|
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 int[][] ids;
|
||||||
|
|
||||||
private short[] count;
|
private short[] count;
|
||||||
private short[] air;
|
private short[] air;
|
||||||
private short[] relight;
|
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.
|
* 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);
|
super(parent, x, z);
|
||||||
this.ids = new int[16][];
|
this.ids = new int[16][];
|
||||||
this.count = new short[16];
|
this.count = new short[16];
|
||||||
@ -32,13 +34,15 @@ public class BukkitChunk_1_9 extends FaweChunk<Chunk> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Chunk getChunk() {
|
public T getChunk() {
|
||||||
if (this.chunk == null) {
|
if (this.chunk == null) {
|
||||||
this.chunk = Bukkit.getWorld(getParent().world).getChunkAt(getX(), getZ());
|
this.chunk = getNewChunk();
|
||||||
}
|
}
|
||||||
return this.chunk;
|
return this.chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract T getNewChunk();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLoc(final FaweQueue parent, int x, int z) {
|
public void setLoc(final FaweQueue parent, int x, int z) {
|
||||||
super.setLoc(parent, x, z);
|
super.setLoc(parent, x, z);
|
||||||
@ -197,6 +201,7 @@ public class BukkitChunk_1_9 extends FaweChunk<Chunk> {
|
|||||||
vs[j] = (id);
|
vs[j] = (id);
|
||||||
return;
|
return;
|
||||||
case 130:
|
case 130:
|
||||||
|
case 50:
|
||||||
case 76:
|
case 76:
|
||||||
case 62:
|
case 62:
|
||||||
this.relight[i]++;
|
this.relight[i]++;
|
||||||
@ -205,9 +210,9 @@ public class BukkitChunk_1_9 extends FaweChunk<Chunk> {
|
|||||||
case 61:
|
case 61:
|
||||||
case 65:
|
case 65:
|
||||||
case 68:
|
case 68:
|
||||||
if (data < 2) {
|
// if (data < 2) {
|
||||||
data = 2;
|
// data = 2;
|
||||||
}
|
// }
|
||||||
default:
|
default:
|
||||||
vs[j] = id + (data << 12);
|
vs[j] = id + (data << 12);
|
||||||
return;
|
return;
|
||||||
@ -227,8 +232,8 @@ public class BukkitChunk_1_9 extends FaweChunk<Chunk> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FaweChunk<Chunk> copy(boolean shallow) {
|
public IntFaweChunk<T> copy(boolean shallow) {
|
||||||
BukkitChunk_1_9 copy = new BukkitChunk_1_9(getParent(), getX(), getZ());
|
IntFaweChunk<T> copy = (IntFaweChunk<T>) getParent().getChunk(getX(), getZ());
|
||||||
if (shallow) {
|
if (shallow) {
|
||||||
copy.ids = ids;
|
copy.ids = ids;
|
||||||
copy.air = air;
|
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.boydti.fawe.util.FaweQueue;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||||
import com.sk89q.worldedit.blocks.BlockType;
|
import com.sk89q.worldedit.blocks.BlockType;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
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) {
|
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) {
|
for (int y = maxY; y >= minY; --y) {
|
||||||
final Vector pt = new Vector(x, y, z);
|
BaseBlock block = session.getLazyBlock(x, y, z);
|
||||||
final int id = this.session.getBlockType(pt);
|
final int id = block.getId();
|
||||||
final int data = this.session.getBlockData(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)) {
|
if (naturalOnly ? BlockType.isNaturalTerrainBlock(id, data) : !BlockType.canPassThrough(id, data)) {
|
||||||
return y;
|
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 abstract void setBiome(final int x, final int z, final BaseBiome biome);
|
||||||
|
|
||||||
|
public void optimize() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object obj) {
|
public boolean equals(final Object obj) {
|
||||||
if ((obj == null) || obj.hashCode() != hashCode() || !(obj instanceof FaweChunk)) {
|
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);
|
DiskStorageHistory set = new DiskStorageHistory(world, uuid, index);
|
||||||
EditSession edit = set.toEditSession(getPlayer());
|
EditSession edit = set.toEditSession(getPlayer());
|
||||||
if (world.equals(getWorld())) {
|
if (world.equals(getWorld())) {
|
||||||
session.remember(edit, 0);
|
session.remember(edit, false);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -184,7 +184,7 @@ public abstract class FawePlayer<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the player's limit
|
* Get the player's limit
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public FaweLimit getLimit() {
|
public FaweLimit getLimit() {
|
||||||
|
@ -26,6 +26,11 @@ public abstract class FaweClipboard {
|
|||||||
|
|
||||||
public void setOrigin(Vector offset) {} // Do nothing
|
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);
|
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
|
// x,z,y+15>>4 | y&15
|
||||||
private final byte[][] ids;
|
private final byte[][] ids;
|
||||||
|
private final byte[] heights;
|
||||||
private byte[][] datas;
|
private byte[][] datas;
|
||||||
private final HashMap<IntegerTrio, CompoundTag> nbtMap;
|
private final HashMap<IntegerTrio, CompoundTag> nbtMap;
|
||||||
private final HashSet<ClipboardEntity> entities;
|
private final HashSet<ClipboardEntity> entities;
|
||||||
@ -33,6 +34,10 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
|
|||||||
this.height = height;
|
this.height = height;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
this.area = width * 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)][];
|
ids = new byte[width * length * ((height + 15) >> 4)][];
|
||||||
nbtMap = new HashMap<>();
|
nbtMap = new HashMap<>();
|
||||||
entities = new HashSet<>();
|
entities = new HashSet<>();
|
||||||
@ -186,7 +191,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
|
|||||||
int y2 = y & 0xF;
|
int y2 = y & 0xF;
|
||||||
byte[] idArray = ids[i];
|
byte[] idArray = ids[i];
|
||||||
if (idArray == null) {
|
if (idArray == null) {
|
||||||
idArray = new byte[16];
|
idArray = new byte[heights[ylast >> 4]];
|
||||||
ids[i] = idArray;
|
ids[i] = idArray;
|
||||||
}
|
}
|
||||||
idArray[y2] = (byte) id;
|
idArray[y2] = (byte) id;
|
||||||
@ -200,7 +205,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
|
|||||||
}
|
}
|
||||||
byte[] dataArray = datas[i];
|
byte[] dataArray = datas[i];
|
||||||
if (dataArray == null) {
|
if (dataArray == null) {
|
||||||
dataArray = datas[i] = new byte[16];
|
dataArray = datas[i] = new byte[heights[ylast >> 4]];
|
||||||
}
|
}
|
||||||
dataArray[y2] = (byte) data;
|
dataArray[y2] = (byte) data;
|
||||||
}
|
}
|
||||||
@ -275,7 +280,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
|
|||||||
int y2 = y & 0xF;
|
int y2 = y & 0xF;
|
||||||
byte[] idArray = ids[i];
|
byte[] idArray = ids[i];
|
||||||
if (idArray == null) {
|
if (idArray == null) {
|
||||||
idArray = new byte[16];
|
idArray = new byte[heights[ylast >> 4]];
|
||||||
ids[i] = idArray;
|
ids[i] = idArray;
|
||||||
}
|
}
|
||||||
idArray[y2] = (byte) id;
|
idArray[y2] = (byte) id;
|
||||||
@ -286,7 +291,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
|
|||||||
int y2 = y & 0xF;
|
int y2 = y & 0xF;
|
||||||
byte[] idArray = ids[i];
|
byte[] idArray = ids[i];
|
||||||
if (idArray == null) {
|
if (idArray == null) {
|
||||||
idArray = new byte[16];
|
idArray = new byte[heights[ylast >> 4]];
|
||||||
ids[i] = idArray;
|
ids[i] = idArray;
|
||||||
}
|
}
|
||||||
idArray[y2] = (byte) id;
|
idArray[y2] = (byte) id;
|
||||||
@ -299,7 +304,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
|
|||||||
}
|
}
|
||||||
byte[] dataArray = datas[i];
|
byte[] dataArray = datas[i];
|
||||||
if (dataArray == null) {
|
if (dataArray == null) {
|
||||||
dataArray = datas[i] = new byte[16];
|
dataArray = datas[i] = new byte[heights[ylast >> 4]];
|
||||||
}
|
}
|
||||||
dataArray[y2] = (byte) data;
|
dataArray[y2] = (byte) data;
|
||||||
return true;
|
return true;
|
||||||
|
@ -29,12 +29,14 @@ public class FastWorldEditExtent extends FaweExtent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Entity createEntity(final Location location, final BaseEntity entity) {
|
public Entity createEntity(final Location location, final BaseEntity entity) {
|
||||||
TaskManager.IMP.task(new Runnable() {
|
if (entity != null) {
|
||||||
@Override
|
TaskManager.IMP.task(new Runnable() {
|
||||||
public void run() {
|
@Override
|
||||||
FastWorldEditExtent.super.createEntity(location, entity);
|
public void run() {
|
||||||
}
|
FastWorldEditExtent.super.createEntity(location, entity);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ public class ProcessedWEExtent extends FaweExtent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Entity createEntity(final Location location, final BaseEntity entity) {
|
public Entity createEntity(final Location location, final BaseEntity entity) {
|
||||||
if (limit.MAX_ENTITIES-- < 0) {
|
if (limit.MAX_ENTITIES-- < 0 || entity == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (WEManager.IMP.maskContains(this.mask, location.getBlockX(), location.getBlockZ())) {
|
if (WEManager.IMP.maskContains(this.mask, location.getBlockX(), location.getBlockZ())) {
|
||||||
@ -227,13 +227,10 @@ public class ProcessedWEExtent extends FaweExtent {
|
|||||||
case 49:
|
case 49:
|
||||||
case 51:
|
case 51:
|
||||||
case 52:
|
case 52:
|
||||||
case 54:
|
|
||||||
case 56:
|
case 56:
|
||||||
case 57:
|
case 57:
|
||||||
case 58:
|
case 58:
|
||||||
case 60:
|
case 60:
|
||||||
case 61:
|
|
||||||
case 62:
|
|
||||||
case 7:
|
case 7:
|
||||||
case 8:
|
case 8:
|
||||||
case 9:
|
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);
|
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 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);
|
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) {
|
public void enqueue(FaweQueue queue) {
|
||||||
inactiveQueues.remove(queue);
|
inactiveQueues.remove(queue);
|
||||||
if (queue.size() > 0 && !activeQueues.contains(queue)) {
|
if (queue.size() > 0 && !activeQueues.contains(queue)) {
|
||||||
|
queue.optimize();
|
||||||
activeQueues.add(queue);
|
activeQueues.add(queue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,8 +133,8 @@ public class SetQueue {
|
|||||||
return new ArrayList<>(inactiveQueues);
|
return new ArrayList<>(inactiveQueues);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FaweQueue getNewQueue(String world, boolean autoqueue) {
|
public FaweQueue getNewQueue(String world, boolean fast, boolean autoqueue) {
|
||||||
FaweQueue queue = Fawe.imp().getNewQueue(world);
|
FaweQueue queue = Fawe.imp().getNewQueue(world, fast);
|
||||||
if (autoqueue) {
|
if (autoqueue) {
|
||||||
inactiveQueues.add(queue);
|
inactiveQueues.add(queue);
|
||||||
}
|
}
|
||||||
@ -155,18 +156,15 @@ public class SetQueue {
|
|||||||
if (Settings.QUEUE_MAX_WAIT >= 0) {
|
if (Settings.QUEUE_MAX_WAIT >= 0) {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
if (lastSuccess != 0) {
|
if (lastSuccess != 0) {
|
||||||
long diff = now - lastSuccess;
|
for (FaweQueue queue : tmp) {
|
||||||
if (diff > Settings.QUEUE_MAX_WAIT) {
|
if (queue != null && queue.size() > 0 && now - queue.modified > Settings.QUEUE_MAX_WAIT) {
|
||||||
for (FaweQueue queue : tmp) {
|
queue.modified = now;
|
||||||
if (queue != null && queue.size() > 0) {
|
return queue;
|
||||||
queue.modified = now;
|
} else if (now - queue.modified > Settings.QUEUE_DISCARD_AFTER) {
|
||||||
return queue;
|
inactiveQueues.remove(queue);
|
||||||
} else if (now - queue.modified > Settings.QUEUE_DISCARD_AFTER) {
|
|
||||||
inactiveQueues.remove(queue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Settings.QUEUE_SIZE != -1) {
|
if (Settings.QUEUE_SIZE != -1) {
|
||||||
|
@ -39,12 +39,12 @@ public abstract class TaskManager {
|
|||||||
public abstract void task(final Runnable r);
|
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()
|
* - If it's already the main thread, it will jst call run()
|
||||||
* @param r
|
* @param r
|
||||||
* @param async
|
* @param async
|
||||||
*/
|
*/
|
||||||
public void task(final Runnable r, boolean async) {
|
public void taskNow(final Runnable r, boolean async) {
|
||||||
if (async) {
|
if (async) {
|
||||||
async(r);
|
async(r);
|
||||||
} else {
|
} 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) {
|
if (async) {
|
||||||
async(r);
|
async(r);
|
||||||
} else if (r != null && Thread.currentThread() == Fawe.get().getMainThread()){
|
} 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
|
* 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.Fawe;
|
||||||
import com.boydti.fawe.object.RunnableVal;
|
import com.boydti.fawe.object.RunnableVal;
|
||||||
|
import com.boydti.fawe.util.SetQueue;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
import com.boydti.fawe.util.TaskManager;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.EditSessionFactory;
|
import com.sk89q.worldedit.EditSessionFactory;
|
||||||
@ -170,7 +171,7 @@ public class PlayerWrapper implements Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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();
|
EditSessionFactory factory = WorldEdit.getInstance().getEditSessionFactory();
|
||||||
EditSession edit = factory.getEditSession(parent.getWorld(), -1, null, this);
|
EditSession edit = factory.getEditSession(parent.getWorld(), -1, null, this);
|
||||||
try {
|
try {
|
||||||
@ -182,7 +183,12 @@ public class PlayerWrapper implements Player {
|
|||||||
} catch (MaxChangedBlocksException e) {
|
} catch (MaxChangedBlocksException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
setPosition(new Vector(x + 0.5, y, z + 0.5));
|
SetQueue.IMP.addTask(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
setPosition(new Vector(x + 0.5, y, z + 0.5));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -234,8 +234,6 @@ public class EditSession implements Extent {
|
|||||||
this.wrapper = Fawe.imp().getEditSessionWrapper(this);
|
this.wrapper = Fawe.imp().getEditSessionWrapper(this);
|
||||||
return;
|
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)
|
// Set the world of the event to the actual world (workaround for CoreProtect)
|
||||||
try {
|
try {
|
||||||
Class<? extends EditSessionEvent> eventClass = event.getClass();
|
Class<? extends EditSessionEvent> eventClass = event.getClass();
|
||||||
@ -262,6 +260,8 @@ public class EditSession implements Extent {
|
|||||||
this.bypassHistory = extent;
|
this.bypassHistory = extent;
|
||||||
this.bypassNone = extent;
|
this.bypassNone = extent;
|
||||||
this.changeSet = new NullChangeSet();
|
this.changeSet = new NullChangeSet();
|
||||||
|
this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true, true);
|
||||||
|
queue.addEditSession(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.changeSet = Settings.STORE_HISTORY_ON_DISK ? new DiskStorageHistory(world, actor.getUniqueId()) : new MemoryOptimizedHistory(actor);
|
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();
|
final LocalSession session = fp.getSession();
|
||||||
this.fastmode = session.hasFastMode();
|
this.fastmode = session.hasFastMode();
|
||||||
if (fp.hasWorldEditBypass()) {
|
if (fp.hasWorldEditBypass()) {
|
||||||
|
this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true, true);
|
||||||
|
queue.addEditSession(this);
|
||||||
// Bypass skips processing and area restrictions
|
// Bypass skips processing and area restrictions
|
||||||
extent = (this.faweExtent = new FastWorldEditExtent(world, queue));
|
extent = (this.faweExtent = new FastWorldEditExtent(world, queue));
|
||||||
if (this.hasFastMode()) {
|
if (this.hasFastMode()) {
|
||||||
@ -283,6 +285,8 @@ public class EditSession implements Extent {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), false, true);
|
||||||
|
queue.addEditSession(this);
|
||||||
this.limit = fp.getLimit();
|
this.limit = fp.getLimit();
|
||||||
final HashSet<RegionWrapper> mask = WEManager.IMP.getMask(fp);
|
final HashSet<RegionWrapper> mask = WEManager.IMP.getMask(fp);
|
||||||
if (mask.size() == 0) {
|
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 {
|
public int fixLiquid(final Vector origin, final double radius, final int moving, final int stationary) throws MaxChangedBlocksException {
|
||||||
checkNotNull(origin);
|
checkNotNull(origin);
|
||||||
checkArgument(radius >= 0, "radius >= 0 required");
|
checkArgument(radius >= 0, "radius >= 0 required");
|
||||||
|
|
||||||
// Our origins can only be liquids
|
// 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
|
// 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
|
// 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(
|
MaskIntersection mask = new MaskIntersection(
|
||||||
null, origin, new Vector(radius, radius, radius))), blockMask);
|
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)));
|
BlockReplace replace = new BlockReplace(this, new BlockPattern(new BaseBlock(stationary)));
|
||||||
final NonRisingVisitor visitor = new NonRisingVisitor(mask, replace);
|
NonRisingVisitor visitor = new NonRisingVisitor(mask, replace);
|
||||||
|
|
||||||
// Around the origin in a 3x3 block
|
// 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)) {
|
if (liquidMask.test(position)) {
|
||||||
visitor.visit(position);
|
visitor.visit(position);
|
||||||
}
|
}
|
||||||
@ -1559,7 +1573,7 @@ public class EditSession implements Extent {
|
|||||||
EditSession.this.flushQueue();
|
EditSession.this.flushQueue();
|
||||||
}
|
}
|
||||||
}, true);
|
}, 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.World;
|
||||||
import com.sk89q.worldedit.world.snapshot.Snapshot;
|
import com.sk89q.worldedit.world.snapshot.Snapshot;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
@ -76,7 +78,7 @@ public class LocalSession {
|
|||||||
// Session related
|
// Session related
|
||||||
private transient RegionSelector selector = new CuboidRegionSelector();
|
private transient RegionSelector selector = new CuboidRegionSelector();
|
||||||
private transient boolean placeAtPos1 = false;
|
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 int historyPointer = 0;
|
||||||
private transient ClipboardHolder clipboard;
|
private transient ClipboardHolder clipboard;
|
||||||
private transient boolean toolControl = true;
|
private transient boolean toolControl = true;
|
||||||
@ -194,10 +196,10 @@ public class LocalSession {
|
|||||||
* @param editSession the edit session
|
* @param editSession the edit session
|
||||||
*/
|
*/
|
||||||
public void remember(EditSession editSession) {
|
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
|
// Enqueue it
|
||||||
if (editSession.getQueue() != null) {
|
if (editSession.getQueue() != null) {
|
||||||
FaweQueue queue = editSession.getQueue();
|
FaweQueue queue = editSession.getQueue();
|
||||||
@ -217,7 +219,11 @@ public class LocalSession {
|
|||||||
if (set instanceof FaweChangeSet) {
|
if (set instanceof FaweChangeSet) {
|
||||||
((FaweChangeSet) set).flush();
|
((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) {
|
while (history.size() > MAX_HISTORY_SIZE) {
|
||||||
history.remove(0);
|
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.Direction;
|
||||||
import com.sk89q.worldedit.internal.annotation.Selection;
|
import com.sk89q.worldedit.internal.annotation.Selection;
|
||||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
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.Region;
|
||||||
import com.sk89q.worldedit.regions.RegionSelector;
|
import com.sk89q.worldedit.regions.RegionSelector;
|
||||||
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
|
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
|
||||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
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.binding.Switch;
|
||||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -97,17 +96,18 @@ public class ClipboardCommands {
|
|||||||
@Selection final Region region, @Switch('e') boolean copyEntities,
|
@Selection final Region region, @Switch('e') boolean copyEntities,
|
||||||
@Switch('m') Mask mask) throws WorldEditException {
|
@Switch('m') Mask mask) throws WorldEditException {
|
||||||
|
|
||||||
Vector origin = region.getMinimumPoint();
|
final Vector origin = region.getMinimumPoint();
|
||||||
final int mx = origin.getBlockX();
|
final int mx = origin.getBlockX();
|
||||||
final int my = origin.getBlockY();
|
final int my = origin.getBlockY();
|
||||||
final int mz = origin.getBlockZ();
|
final int mz = origin.getBlockZ();
|
||||||
LazyClipboard lazyClipboard = new LazyClipboard() {
|
LazyClipboard lazyClipboard = new LazyClipboard() {
|
||||||
@Override
|
@Override
|
||||||
public BaseBlock getBlock(int x, int y, int z) {
|
public BaseBlock getBlock(int x, int y, int z) {
|
||||||
int xx = mx + x;
|
return editSession.getLazyBlock(mx + x, my + y, mz + z);
|
||||||
int yy = my + y;
|
}
|
||||||
int zz = mz + z;
|
|
||||||
return editSession.getLazyBlock(xx, yy, zz);
|
public BaseBlock getBlockAbs(int x, int y, int z) {
|
||||||
|
return editSession.getLazyBlock(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -120,10 +120,13 @@ public class ClipboardCommands {
|
|||||||
Iterator<BlockVector> iter = region.iterator();
|
Iterator<BlockVector> iter = region.iterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
BlockVector pos = iter.next();
|
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) {
|
if (!air && block == EditSession.nullBlock) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
pos.x -= mx;
|
||||||
|
pos.y -= my;
|
||||||
|
pos.z -= mz;
|
||||||
task.run(pos, block);
|
task.run(pos, block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -269,29 +272,24 @@ public class ClipboardCommands {
|
|||||||
ClipboardHolder holder = session.getClipboard();
|
ClipboardHolder holder = session.getClipboard();
|
||||||
Clipboard clipboard = holder.getClipboard();
|
Clipboard clipboard = holder.getClipboard();
|
||||||
Region region = clipboard.getRegion().clone();
|
Region region = clipboard.getRegion().clone();
|
||||||
Vector origin = clipboard.getOrigin();
|
|
||||||
final Transform transform = holder.getTransform();
|
|
||||||
// Optimize for CuboidRegion
|
final Vector bot = clipboard.getMinimumPoint();
|
||||||
if (region instanceof CuboidRegion) {
|
final Vector origin = clipboard.getOrigin();
|
||||||
CuboidRegion cuboid = (CuboidRegion) region;
|
final Vector to = atOrigin ? origin : session.getPlacementPosition(player);
|
||||||
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();
|
|
||||||
// Optimize for BlockArrayClipboard
|
// Optimize for BlockArrayClipboard
|
||||||
if (clipboard instanceof 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;
|
BlockArrayClipboard bac = (BlockArrayClipboard) clipboard;
|
||||||
bac.IMP.forEach(new RunnableVal2<Vector, BaseBlock>() {
|
bac.IMP.forEach(new RunnableVal2<Vector, BaseBlock>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(Vector pos, BaseBlock block) {
|
public void run(Vector pos, BaseBlock block) {
|
||||||
pos.x += tx;
|
pos.x += relx;
|
||||||
pos.y += ty;
|
pos.y += rely;
|
||||||
pos.z += tz;
|
pos.z += relz;
|
||||||
try {
|
try {
|
||||||
editSession.setBlock(pos, block);
|
editSession.setBlock(pos, block);
|
||||||
} catch (MaxChangedBlocksException e) {
|
} catch (MaxChangedBlocksException e) {
|
||||||
@ -300,7 +298,10 @@ public class ClipboardCommands {
|
|||||||
}
|
}
|
||||||
}, !ignoreAirBlocks);
|
}, !ignoreAirBlocks);
|
||||||
} else {
|
} 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();
|
Iterator<BlockVector> iter = region.iterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
BlockVector loc = iter.next();
|
BlockVector loc = iter.next();
|
||||||
@ -308,15 +309,21 @@ public class ClipboardCommands {
|
|||||||
if (block == EditSession.nullBlock && ignoreAirBlocks) {
|
if (block == EditSession.nullBlock && ignoreAirBlocks) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
loc.x += tx;
|
loc.x += relx;
|
||||||
loc.y += ty;
|
loc.y += rely;
|
||||||
loc.z += tz;
|
loc.z += relz;
|
||||||
editSession.setBlock(transform.apply(loc), block);
|
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
|
// entities
|
||||||
for (Entity entity : clipboard.getEntities()) {
|
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) {
|
if (selectPasted) {
|
||||||
Vector max = to.add(region.getMaximumPoint().subtract(region.getMinimumPoint()));
|
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 byte data = (byte) block.getData();
|
||||||
final FaweChunk<?> fc = queue.getChunk(0, 0);
|
final FaweChunk<?> fc = queue.getChunk(0, 0);
|
||||||
fc.fillCuboid(0, 15, minY, maxY, 0, 15, id, data);
|
fc.fillCuboid(0, 15, minY, maxY, 0, 15, id, data);
|
||||||
|
fc.optimize();
|
||||||
|
|
||||||
int bcx = (current.minX) >> 4;
|
int bcx = (current.minX) >> 4;
|
||||||
int bcz = (current.minZ) >> 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
|
* @throws MaxChangedBlocksException thrown when too many blocks have been changed
|
||||||
*/
|
*/
|
||||||
public static void completeLegacy(Operation operation) throws MaxChangedBlocksException {
|
public static void completeLegacy(Operation operation) throws MaxChangedBlocksException {
|
||||||
try {
|
completeBlindly(operation);
|
||||||
while (true) {
|
|
||||||
operation = operation.resume(context);
|
|
||||||
}
|
|
||||||
} catch (final WorldEditException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (NullPointerException ignore) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -113,7 +113,7 @@ public class FaweForge implements IFawe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FaweQueue getNewQueue(String world) {
|
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||||
return new ForgeQueue_All(world);
|
return new ForgeQueue_All(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,15 +197,16 @@ public class ForgeChunk_All extends FaweChunk<Chunk> {
|
|||||||
case 130:
|
case 130:
|
||||||
case 76:
|
case 76:
|
||||||
case 62:
|
case 62:
|
||||||
|
case 50:
|
||||||
this.relight[i]++;
|
this.relight[i]++;
|
||||||
case 54:
|
case 54:
|
||||||
case 146:
|
case 146:
|
||||||
case 61:
|
case 61:
|
||||||
case 65:
|
case 65:
|
||||||
case 68:
|
case 68:
|
||||||
if (data < 2) {
|
// if (data < 2) {
|
||||||
data = 2;
|
// data = 2;
|
||||||
}
|
// }
|
||||||
default:
|
default:
|
||||||
vs[j] = (byte) id;
|
vs[j] = (byte) id;
|
||||||
NibbleArray dataArray = datas[i];
|
NibbleArray dataArray = datas[i];
|
||||||
|
@ -2,24 +2,18 @@ package com.boydti.fawe.forge.v0;
|
|||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.FaweCache;
|
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.forge.ForgePlayer;
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
import com.boydti.fawe.object.IntegerPair;
|
import com.boydti.fawe.object.IntegerPair;
|
||||||
import com.boydti.fawe.object.PseudoRandom;
|
import com.boydti.fawe.object.PseudoRandom;
|
||||||
import com.boydti.fawe.object.RunnableVal;
|
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.lang.reflect.Field;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.LinkedBlockingDeque;
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
import net.minecraft.network.NetHandlerPlayServer;
|
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.chunk.storage.ExtendedBlockStorage;
|
||||||
import net.minecraft.world.gen.ChunkProviderServer;
|
import net.minecraft.world.gen.ChunkProviderServer;
|
||||||
|
|
||||||
public class ForgeQueue_All extends FaweQueue {
|
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, ExtendedBlockStorage> {
|
||||||
|
|
||||||
private World forgeWorld;
|
|
||||||
|
|
||||||
private ConcurrentHashMap<Long, FaweChunk<Chunk>> blocks = new ConcurrentHashMap<>();
|
|
||||||
private LinkedBlockingDeque<FaweChunk<Chunk>> chunks = new LinkedBlockingDeque<>();
|
|
||||||
|
|
||||||
public ForgeQueue_All(final String world) {
|
public ForgeQueue_All(final String world) {
|
||||||
super(world);
|
super(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isChunkLoaded(int x, int z) {
|
public boolean loadChunk(World world, int x, int z, boolean generate) {
|
||||||
return getWorld().getChunkProvider().chunkExists(x, z);
|
return getCachedChunk(world, x, z) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public World getWorld() {
|
@Override
|
||||||
if (forgeWorld != null) {
|
public Chunk getCachedChunk(World world, int cx, int cz) {
|
||||||
return forgeWorld;
|
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;
|
WorldServer[] worlds = MinecraftServer.getServer().worldServers;
|
||||||
for (WorldServer ws : worlds) {
|
for (WorldServer ws : worlds) {
|
||||||
if (ws.provider.getDimensionName().equals(world)) {
|
if (ws.provider.getDimensionName().equals(world)) {
|
||||||
return forgeWorld = ws;
|
return ws;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean regenerateChunk(int x, int z) {
|
public boolean regenerateChunk(World world, int x, int z) {
|
||||||
try {
|
try {
|
||||||
IChunkProvider provider = getWorld().getChunkProvider();
|
IChunkProvider provider = world.getChunkProvider();
|
||||||
if (!(provider instanceof ChunkProviderServer)) {
|
if (!(provider instanceof ChunkProviderServer)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -88,7 +98,7 @@ public class ForgeQueue_All extends FaweQueue {
|
|||||||
u = ChunkProviderServer.class.getDeclaredField("chunksToUnload");
|
u = ChunkProviderServer.class.getDeclaredField("chunksToUnload");
|
||||||
}
|
}
|
||||||
u.setAccessible(true);
|
u.setAccessible(true);
|
||||||
Set<?> unloadQueue = (Set<?>) u.get(chunkServer);
|
Set unloadQueue = (Set) u.get(chunkServer);
|
||||||
Field m;
|
Field m;
|
||||||
try {
|
try {
|
||||||
m = ChunkProviderServer.class.getDeclaredField("field_73244_f"); // loadedChunkHashMap
|
m = ChunkProviderServer.class.getDeclaredField("field_73244_f"); // loadedChunkHashMap
|
||||||
@ -104,7 +114,7 @@ public class ForgeQueue_All extends FaweQueue {
|
|||||||
lc = ChunkProviderServer.class.getDeclaredField("loadedChunks");
|
lc = ChunkProviderServer.class.getDeclaredField("loadedChunks");
|
||||||
}
|
}
|
||||||
lc.setAccessible(true);
|
lc.setAccessible(true);
|
||||||
@SuppressWarnings("unchecked") List<Chunk> loaded = (List<Chunk>) lc.get(chunkServer);
|
@SuppressWarnings("unchecked") List loaded = (List) lc.get(chunkServer);
|
||||||
Field p;
|
Field p;
|
||||||
try {
|
try {
|
||||||
p = ChunkProviderServer.class.getDeclaredField("field_73246_d"); // currentChunkProvider
|
p = ChunkProviderServer.class.getDeclaredField("field_73246_d"); // currentChunkProvider
|
||||||
@ -134,30 +144,6 @@ public class ForgeQueue_All extends FaweQueue {
|
|||||||
return true;
|
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>() {
|
private final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(IntegerPair loc) {
|
public void run(IntegerPair loc) {
|
||||||
@ -170,215 +156,39 @@ public class ForgeQueue_All extends FaweQueue {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
|
public void refreshChunk(World world, Chunk chunk) {
|
||||||
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) {
|
if (!chunk.isChunkLoaded) {
|
||||||
chunk.onChunkLoad();
|
return;
|
||||||
}
|
}
|
||||||
// Set blocks / entities / biome
|
ChunkCoordIntPair pos = chunk.getChunkCoordIntPair();
|
||||||
if (!this.setComponents(fc)) {
|
int cx = pos.chunkXPos;
|
||||||
return false;
|
int cz = pos.chunkZPos;
|
||||||
}
|
for (FawePlayer fp : Fawe.get().getCachedPlayers()) {
|
||||||
fc.executeTasks();
|
ForgePlayer forgePlayer = (ForgePlayer) fp;
|
||||||
return true;
|
EntityPlayerMP player = forgePlayer.parent;
|
||||||
}
|
if (!player.worldObj.equals(world)) {
|
||||||
|
continue;
|
||||||
@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();
|
|
||||||
if (!chunk.isChunkLoaded) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
World world = chunk.worldObj;
|
|
||||||
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;
|
|
||||||
ChunkCoordinates loc = player.getPlayerCoordinates();
|
|
||||||
int px = loc.posX >> 4;
|
|
||||||
int pz = loc.posZ >> 4;
|
|
||||||
int dx = Math.abs(cx - (loc.posX >> 4));
|
|
||||||
int dz = Math.abs(cz - (loc.posZ >> 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);
|
int view = MinecraftServer.getServer().getConfigurationManager().getViewDistance();
|
||||||
|
EntityPlayerMP nmsPlayer = (EntityPlayerMP) player;
|
||||||
|
ChunkCoordinates loc = player.getPlayerCoordinates();
|
||||||
|
int px = loc.posX >> 4;
|
||||||
|
int pz = loc.posZ >> 4;
|
||||||
|
int dx = Math.abs(cx - (loc.posX >> 4));
|
||||||
|
int dz = Math.abs(cz - (loc.posZ >> 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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean setComponents(FaweChunk<Chunk> fc) {
|
public boolean setComponents(FaweChunk fc) {
|
||||||
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
||||||
Chunk forgeChunk = fc.getChunk();
|
Chunk forgeChunk = fs.getChunk();
|
||||||
net.minecraft.world.World nmsWorld = forgeChunk.worldObj;
|
net.minecraft.world.World nmsWorld = forgeChunk.worldObj;
|
||||||
try {
|
try {
|
||||||
boolean flag = !nmsWorld.provider.hasNoSky;
|
boolean flag = !nmsWorld.provider.hasNoSky;
|
||||||
@ -485,12 +295,12 @@ public class ForgeQueue_All extends FaweQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FaweChunk<Chunk> getChunk(int x, int z) {
|
public FaweChunk getChunk(int x, int z) {
|
||||||
return new ForgeChunk_All(this, x, z);
|
return new ForgeChunk_All(this, x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean fixLighting(FaweChunk<?> chunk, boolean fixAll) {
|
public boolean fixLighting(FaweChunk chunk, boolean fixAll) {
|
||||||
try {
|
try {
|
||||||
ForgeChunk_All fc = (ForgeChunk_All) chunk;
|
ForgeChunk_All fc = (ForgeChunk_All) chunk;
|
||||||
Chunk forgeChunk = fc.getChunk();
|
Chunk forgeChunk = fc.getChunk();
|
||||||
|
@ -114,7 +114,7 @@ public class FaweForge implements IFawe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FaweQueue getNewQueue(String world) {
|
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||||
return new ForgeQueue_All(world);
|
return new ForgeQueue_All(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,256 +1,25 @@
|
|||||||
package com.boydti.fawe.forge.v0;
|
package com.boydti.fawe.forge.v0;
|
||||||
|
|
||||||
import com.boydti.fawe.FaweCache;
|
import com.boydti.fawe.example.CharFaweChunk;
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
|
||||||
import com.boydti.fawe.util.FaweQueue;
|
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.World;
|
||||||
import net.minecraft.world.chunk.Chunk;
|
import net.minecraft.world.chunk.Chunk;
|
||||||
|
|
||||||
public class ForgeChunk_All extends FaweChunk<Chunk> {
|
public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
||||||
|
/**
|
||||||
public char[][] ids;
|
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
||||||
public short[] count;
|
*
|
||||||
public short[] air;
|
* @param parent
|
||||||
public short[] relight;
|
* @param x
|
||||||
public byte[][] biomes;
|
* @param z
|
||||||
public Chunk chunk;
|
*/
|
||||||
|
|
||||||
public ForgeChunk_All(FaweQueue parent, int x, int z) {
|
public ForgeChunk_All(FaweQueue parent, int x, int z) {
|
||||||
super(parent, x, 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 = ((ForgeQueue_All) getParent()).getWorld();
|
|
||||||
this.chunk = world.getChunkProvider().provideChunk(getX(), getZ());
|
|
||||||
}
|
|
||||||
return this.chunk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLoc(final FaweQueue parent, int x, int z) {
|
public Chunk getNewChunk() {
|
||||||
super.setLoc(parent, x, z);
|
World world = ((ForgeQueue_All) getParent()).getWorld();
|
||||||
this.chunk = null;
|
return world.getChunkProvider().provideChunk(getX(), getZ());
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,23 +2,15 @@ package com.boydti.fawe.forge.v0;
|
|||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.FaweCache;
|
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.forge.ForgePlayer;
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
import com.boydti.fawe.object.IntegerPair;
|
|
||||||
import com.boydti.fawe.object.PseudoRandom;
|
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.lang.reflect.Field;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.LinkedBlockingDeque;
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
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.chunk.storage.ExtendedBlockStorage;
|
||||||
import net.minecraft.world.gen.ChunkProviderServer;
|
import net.minecraft.world.gen.ChunkProviderServer;
|
||||||
|
|
||||||
public class ForgeQueue_All extends FaweQueue {
|
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, char[]> {
|
||||||
|
|
||||||
private World forgeWorld;
|
|
||||||
|
|
||||||
private ConcurrentHashMap<Long, FaweChunk<Chunk>> blocks = new ConcurrentHashMap<>();
|
|
||||||
private LinkedBlockingDeque<FaweChunk<Chunk>> chunks = new LinkedBlockingDeque<>();
|
|
||||||
|
|
||||||
public ForgeQueue_All(final String world) {
|
public ForgeQueue_All(final String world) {
|
||||||
super(world);
|
super(world);
|
||||||
@ -52,22 +39,19 @@ public class ForgeQueue_All extends FaweQueue {
|
|||||||
return getWorld().getChunkProvider().chunkExists(x, z);
|
return getWorld().getChunkProvider().chunkExists(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public World getWorld() {
|
public World getWorld(String world) {
|
||||||
if (forgeWorld != null) {
|
|
||||||
return forgeWorld;
|
|
||||||
}
|
|
||||||
WorldServer[] worlds = MinecraftServer.getServer().worldServers;
|
WorldServer[] worlds = MinecraftServer.getServer().worldServers;
|
||||||
for (WorldServer ws : worlds) {
|
for (WorldServer ws : worlds) {
|
||||||
if (ws.provider.getDimensionName().equals(world)) {
|
if (ws.provider.getDimensionName().equals(world)) {
|
||||||
return forgeWorld = ws;
|
return ws;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean regenerateChunk(int x, int z) {
|
public boolean regenerateChunk(World world, int x, int z) {
|
||||||
IChunkProvider provider = getWorld().getChunkProvider();
|
IChunkProvider provider = world.getChunkProvider();
|
||||||
if (!(provider instanceof ChunkProviderServer)) {
|
if (!(provider instanceof ChunkProviderServer)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -100,240 +84,33 @@ public class ForgeQueue_All extends FaweQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTask(int x, int z, Runnable runnable) {
|
public boolean loadChunk(World world, int x, int z, boolean generate) {
|
||||||
long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL;
|
return getCachedChunk(world, x, z) != null;
|
||||||
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;
|
@Override
|
||||||
private int lcz = Integer.MIN_VALUE;
|
public Chunk getCachedChunk(World world, int x, int z) {
|
||||||
private int lcy = Integer.MIN_VALUE;
|
Chunk chunk = world.getChunkProvider().provideChunk(x, z);
|
||||||
private net.minecraft.world.chunk.Chunk lc;
|
if (chunk != null && !chunk.isLoaded()) {
|
||||||
private char[] ls;
|
chunk.onChunkLoad();
|
||||||
|
|
||||||
private final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
|
|
||||||
@Override
|
|
||||||
public void run(IntegerPair loc) {
|
|
||||||
getWorld().getChunkProvider().provideChunk(loc.x, loc.z);
|
|
||||||
}
|
}
|
||||||
};
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
|
public int getCombinedId4Data(char[] ls, int x, int y, int z) {
|
||||||
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(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();
|
|
||||||
}
|
|
||||||
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();
|
|
||||||
return ls[FaweCache.CACHE_J[y][x & 15][z & 15]];
|
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
|
@Override
|
||||||
public boolean setBlock(int x, int y, int z, short id, byte data) {
|
public boolean isChunkLoaded(World world, int x, int z) {
|
||||||
if ((y > 255) || (y < 0)) {
|
return world.getChunkProvider().chunkExists(x, z);
|
||||||
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
|
@Override
|
||||||
public boolean setBiome(int x, int z, BaseBiome biome) {
|
public boolean setComponents(FaweChunk fc) {
|
||||||
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) {
|
|
||||||
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
||||||
Chunk forgeChunk = fc.getChunk();
|
Chunk forgeChunk = fs.getChunk();
|
||||||
net.minecraft.world.World nmsWorld = forgeChunk.getWorld();
|
net.minecraft.world.World nmsWorld = forgeChunk.getWorld();
|
||||||
try {
|
try {
|
||||||
boolean flag = !nmsWorld.provider.getHasNoSky();
|
boolean flag = !nmsWorld.provider.getHasNoSky();
|
||||||
@ -407,19 +184,19 @@ public class ForgeQueue_All extends FaweQueue {
|
|||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
byte[][] biomes = fs.biomes;
|
int[][] biomes = fs.biomes;
|
||||||
if (biomes != null) {
|
if (biomes != null) {
|
||||||
for (int x = 0; x < 16; x++) {
|
for (int x = 0; x < 16; x++) {
|
||||||
byte[] array = biomes[x];
|
int[] array = biomes[x];
|
||||||
if (array == null) {
|
if (array == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (int z = 0; z < 16; z++) {
|
for (int z = 0; z < 16; z++) {
|
||||||
byte biome = array[z];
|
int biome = array[z];
|
||||||
if (biome == 0) {
|
if (biome == 0) {
|
||||||
continue;
|
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;
|
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
|
@Override
|
||||||
public FaweChunk<Chunk> getChunk(int x, int z) {
|
public FaweChunk<Chunk> getChunk(int x, int z) {
|
||||||
return new ForgeChunk_All(this, x, z);
|
return new ForgeChunk_All(this, x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean fixLighting(FaweChunk<?> chunk, boolean fixAll) {
|
public boolean fixLighting(FaweChunk chunk, boolean fixAll) {
|
||||||
try {
|
try {
|
||||||
ForgeChunk_All fc = (ForgeChunk_All) chunk;
|
ForgeChunk_All fc = (ForgeChunk_All) chunk;
|
||||||
Chunk forgeChunk = fc.getChunk();
|
Chunk forgeChunk = fc.getChunk();
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
rootProject.name = 'FastAsyncWorldEdit'
|
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.Fawe;
|
||||||
import com.boydti.fawe.IFawe;
|
import com.boydti.fawe.IFawe;
|
||||||
import com.boydti.fawe.config.BBC;
|
|
||||||
import com.boydti.fawe.SpongeCommand;
|
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.EditSessionWrapper;
|
||||||
import com.boydti.fawe.object.FaweCommand;
|
import com.boydti.fawe.object.FaweCommand;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
import com.boydti.fawe.regions.FaweMaskManager;
|
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.FaweQueue;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
import com.boydti.fawe.util.TaskManager;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
@ -112,8 +113,15 @@ public class FaweSponge implements IFawe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FaweQueue getNewQueue(String world) {
|
public FaweQueue getNewQueue(String world, boolean fast) {
|
||||||
return new SpongeQueue_1_8(world);
|
if (fast) {
|
||||||
|
try {
|
||||||
|
return new SpongeQueue_1_8(world);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new SpongeQueue_ALL(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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.Fawe;
|
||||||
import com.boydti.fawe.FaweCache;
|
import com.boydti.fawe.FaweCache;
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||||
import com.boydti.fawe.sponge.SpongeUtil;
|
|
||||||
import com.boydti.fawe.v0.SpongeQueue_0;
|
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.IntegerPair;
|
|
||||||
import com.boydti.fawe.object.PseudoRandom;
|
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.lang.reflect.Field;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
@ -38,150 +29,114 @@ import org.spongepowered.api.world.Chunk;
|
|||||||
import org.spongepowered.api.world.Location;
|
import org.spongepowered.api.world.Location;
|
||||||
import org.spongepowered.api.world.World;
|
import org.spongepowered.api.world.World;
|
||||||
|
|
||||||
public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.world.chunk.Chunk, ExtendedBlockStorage[], char[]> {
|
||||||
|
|
||||||
public World spongeWorld;
|
|
||||||
|
|
||||||
public SpongeQueue_1_8(String world) {
|
public SpongeQueue_1_8(String world) {
|
||||||
super(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
|
@Override
|
||||||
public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
|
public void refreshChunk(World world, net.minecraft.world.chunk.Chunk chunk) {
|
||||||
if (y < 0 || y > 255) {
|
if (!chunk.isLoaded()) {
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
int cx = x >> 4;
|
int cx = chunk.xPosition;
|
||||||
int cz = z >> 4;
|
int cz = chunk.zPosition;
|
||||||
int cy = y >> 4;
|
for (Player player : Sponge.getServer().getOnlinePlayers()) {
|
||||||
if (cx != lcx || cz != lcz) {
|
if (!player.getWorld().equals(world)) {
|
||||||
if (spongeWorld == null) {
|
continue;
|
||||||
spongeWorld = Sponge.getServer().getWorld(world).get();
|
|
||||||
}
|
}
|
||||||
lcx = cx;
|
int view = player.getViewDistance();
|
||||||
lcz = cz;
|
EntityPlayerMP nmsPlayer = (EntityPlayerMP) player;
|
||||||
Chunk chunk = spongeWorld.getChunk(cx, 0, cz).orElse(null);
|
Location<World> loc = player.getLocation();
|
||||||
if (chunk == null || !chunk.isLoaded()) {
|
int px = loc.getBlockX() >> 4;
|
||||||
boolean sync = Thread.currentThread() == Fawe.get().getMainThread();
|
int pz = loc.getBlockZ() >> 4;
|
||||||
if (sync) {
|
int dx = Math.abs(cx - (loc.getBlockX() >> 4));
|
||||||
chunk = spongeWorld.loadChunk(cx, 0, cz, true).orElse(null);
|
int dz = Math.abs(cz - (loc.getBlockZ() >> 4));
|
||||||
} else if (Settings.CHUNK_WAIT > 0) {
|
if ((dx > view) || (dz > view)) {
|
||||||
loadChunk.value = new IntegerPair(cx, cz);
|
continue;
|
||||||
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;
|
NetHandlerPlayServer con = nmsPlayer.playerNetServerHandler;
|
||||||
} else if (cy == lcy) {
|
net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) chunk;
|
||||||
return ls != null ? ls[FaweCache.CACHE_J[y][x & 15][z & 15]] : 0;
|
con.sendPacket(new S21PacketChunkData(nmsChunk, false, 65535));
|
||||||
|
// Try sending true, 0 first
|
||||||
|
// Try bulk chunk packet
|
||||||
}
|
}
|
||||||
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
|
@Override
|
||||||
public Collection<FaweChunk<Chunk>> sendChunk(Collection<FaweChunk<Chunk>> fcs) {
|
public char[] getCachedSection(ExtendedBlockStorage[] chunk, int cy) {
|
||||||
if (fcs.isEmpty()) {
|
ExtendedBlockStorage value = chunk[cy];
|
||||||
return fcs;
|
return value == null ? null : value.getData();
|
||||||
}
|
|
||||||
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();
|
|
||||||
if (!chunk.isLoaded()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
World world = chunk.getWorld();
|
|
||||||
Vector3i pos = chunk.getBlockMin();
|
|
||||||
int cx = pos.getX() >> 4;
|
|
||||||
int cz = pos.getZ() >> 4;
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 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
|
@Override
|
||||||
public boolean setComponents(FaweChunk<Chunk> fc) {
|
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;
|
SpongeChunk_1_8 fs = (SpongeChunk_1_8) fc;
|
||||||
Chunk spongeChunk = fc.getChunk();
|
net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk();
|
||||||
net.minecraft.world.World nmsWorld = (net.minecraft.world.World) spongeChunk.getWorld();
|
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
|
||||||
try {
|
try {
|
||||||
boolean flag = !nmsWorld.provider.getHasNoSky();
|
boolean flag = !nmsWorld.provider.getHasNoSky();
|
||||||
// Sections
|
// Sections
|
||||||
net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) spongeChunk;
|
|
||||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||||
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
|
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
|
||||||
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||||
// Trim tiles
|
// Trim tiles
|
||||||
Set<Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
|
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
|
||||||
Iterator<Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
|
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
Entry<BlockPos, TileEntity> tile = iterator.next();
|
Map.Entry<BlockPos, TileEntity> tile = iterator.next();
|
||||||
BlockPos pos = tile.getKey();
|
BlockPos pos = tile.getKey();
|
||||||
int lx = pos.getX() & 15;
|
int lx = pos.getX() & 15;
|
||||||
int ly = pos.getY();
|
int ly = pos.getY();
|
||||||
@ -204,7 +159,8 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
|||||||
}
|
}
|
||||||
// Efficiently merge sections
|
// Efficiently merge sections
|
||||||
for (int j = 0; j < sections.length; j++) {
|
for (int j = 0; j < sections.length; j++) {
|
||||||
if (fs.getCount(j) == 0) {
|
int count = fs.getCount(j);
|
||||||
|
if (count == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
char[] newArray = fs.getIdArray(j);
|
char[] newArray = fs.getIdArray(j);
|
||||||
@ -212,14 +168,20 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ExtendedBlockStorage section = sections[j];
|
ExtendedBlockStorage section = sections[j];
|
||||||
if ((section == null) || (fs.getCount(j) >= 4096)) {
|
|
||||||
|
if ((section == null)) {
|
||||||
section = new ExtendedBlockStorage(j << 4, flag);
|
section = new ExtendedBlockStorage(j << 4, flag);
|
||||||
section.setData(newArray);
|
section.setData(newArray);
|
||||||
sections[j] = section;
|
sections[j] = section;
|
||||||
continue;
|
continue;
|
||||||
|
} else if (count >= 4096){
|
||||||
|
section.setData(newArray);
|
||||||
|
setCount(0, count - fs.getAir(j), section);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
char[] currentArray = section.getData();
|
char[] currentArray = section.getData();
|
||||||
boolean fill = true;
|
boolean fill = true;
|
||||||
|
int solid = 0;
|
||||||
for (int k = 0; k < newArray.length; k++) {
|
for (int k = 0; k < newArray.length; k++) {
|
||||||
char n = newArray[k];
|
char n = newArray[k];
|
||||||
switch (n) {
|
switch (n) {
|
||||||
@ -228,18 +190,22 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
|||||||
continue;
|
continue;
|
||||||
case 1:
|
case 1:
|
||||||
fill = false;
|
fill = false;
|
||||||
|
if (currentArray[k] > 1) {
|
||||||
|
solid++;
|
||||||
|
}
|
||||||
currentArray[k] = 0;
|
currentArray[k] = 0;
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
|
solid++;
|
||||||
currentArray[k] = n;
|
currentArray[k] = n;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setCount(0, solid, section);
|
||||||
if (fill) {
|
if (fill) {
|
||||||
fs.setCount(j, Short.MAX_VALUE);
|
fs.setCount(j, Short.MAX_VALUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// // Clear
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -255,7 +221,7 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
|||||||
if (biome == 0) {
|
if (biome == 0) {
|
||||||
continue;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException {
|
||||||
* This should be overridden by any specialized queues.
|
Class<? extends ExtendedBlockStorage> clazz = section.getClass();
|
||||||
* @param x
|
Field fieldTickingBlockCount = clazz.getDeclaredField("field_76683_c");
|
||||||
* @param z
|
Field fieldNonEmptyBlockCount = clazz.getDeclaredField("field_76682_b");
|
||||||
*/
|
fieldTickingBlockCount.setAccessible(true);
|
||||||
@Override
|
fieldNonEmptyBlockCount.setAccessible(true);
|
||||||
public SpongeChunk_1_8 getChunk(int x, int z) {
|
fieldTickingBlockCount.set(section, tickingBlockCount);
|
||||||
return new SpongeChunk_1_8(this, x, z);
|
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 {
|
try {
|
||||||
SpongeChunk_1_8 bc = (SpongeChunk_1_8) pc;
|
SpongeChunk_1_8 bc = (SpongeChunk_1_8) fc;
|
||||||
Chunk spongeChunk = bc.getChunk();
|
net.minecraft.world.chunk.Chunk nmsChunk = bc.getChunk();
|
||||||
net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) spongeChunk;
|
if (!nmsChunk.isLoaded()) {
|
||||||
if (!spongeChunk.isLoaded()) {
|
if (!((Chunk) nmsChunk).loadChunk(false)) {
|
||||||
if (!spongeChunk.loadChunk(false)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -291,8 +262,8 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
|||||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||||
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
|
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
|
||||||
|
|
||||||
int X = pc.getX() << 4;
|
int X = bc.getX() << 4;
|
||||||
int Z = pc.getZ() << 4;
|
int Z = bc.getZ() << 4;
|
||||||
|
|
||||||
|
|
||||||
for (int j = 0; j < sections.length; j++) {
|
for (int j = 0; j < sections.length; j++) {
|
||||||
@ -355,50 +326,6 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
|||||||
return false;
|
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) {
|
public boolean isSurrounded(ExtendedBlockStorage[] sections, int x, int y, int z) {
|
||||||
return isSolid(getId(sections, x, y + 1, z))
|
return isSolid(getId(sections, x, y + 1, z))
|
||||||
&& isSolid(getId(sections, x + 1, 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];
|
int j = FaweCache.CACHE_J[y][x][z];
|
||||||
return array[j] >> 4;
|
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