Keep chunks loaded for at least 10s
Optimizations for 1.10
Fix cast for 1.8
Memory/Disk Optimizations for relighting large areas in unloaded chunks
Fix for clipboard entities
This commit is contained in:
Jesse Boyd 2016-08-10 17:18:55 +10:00
parent 1ed87eabbc
commit 5c0ae62b17
7 changed files with 65 additions and 34 deletions

View File

@ -6,6 +6,7 @@ import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.example.NMSMappedFaweQueue;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
@ -16,12 +17,14 @@ import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkUnloadEvent;
import org.bukkit.event.world.WorldInitEvent;
public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMappedFaweQueue<World, CHUNK, CHUNKSECTIONS, SECTION> implements Listener {
@ -80,6 +83,22 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
}
}
public static ConcurrentHashMap<Long, Long> keepLoaded = new ConcurrentHashMap<>();
@EventHandler
public static void onChunkUnload(ChunkUnloadEvent event) {
Chunk chunk = event.getChunk();
long pair = MathMan.pairInt(chunk.getX(), chunk.getZ());
Long lastLoad = keepLoaded.get(pair);
if (lastLoad != null) {
if (System.currentTimeMillis() - lastLoad < 10000) {
event.setCancelled(true);
} else {
keepLoaded.remove(pair);
}
}
}
public World createWorld(final WorldCreator creator) {
World world = TaskManager.IMP.sync(new RunnableVal<World>() {
@Override
@ -154,7 +173,11 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
@Override
public boolean loadChunk(World impWorld, int x, int z, boolean generate) {
return impWorld.loadChunk(x, z, generate);
if (impWorld.loadChunk(x, z, generate)) {
keepLoaded.put(MathMan.pairInt(x, z), System.currentTimeMillis());
return true;
}
return false;
}
private volatile boolean timingsEnabled;

View File

@ -33,7 +33,6 @@ import java.util.Set;
import java.util.UUID;
import net.minecraft.server.v1_10_R1.Block;
import net.minecraft.server.v1_10_R1.BlockPosition;
import net.minecraft.server.v1_10_R1.Blocks;
import net.minecraft.server.v1_10_R1.ChunkSection;
import net.minecraft.server.v1_10_R1.DataBits;
import net.minecraft.server.v1_10_R1.DataPaletteBlock;
@ -64,7 +63,6 @@ import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.WorldCreator;
import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.v1_10_R1.CraftChunk;
import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
import org.bukkit.craftbukkit.v1_10_R1.CraftWorld;
@ -79,6 +77,8 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
private static Field fieldBits;
private static Method getEntitySlices;
public static final IBlockData[] IBD_CACHE = new IBlockData[Character.MAX_VALUE];
public BukkitQueue_1_10(final String world) {
super(world);
checkVersion("v1_10_R1");
@ -95,6 +95,11 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
Fawe.debug("Using adapter: " + adapter);
Fawe.debug("=========================================");
}
for (int i = 0; i < Character.MAX_VALUE; i++) {
try {
IBD_CACHE[i] = Block.getById(i >> 4).fromLegacyData(i & 0xF);
} catch (Throwable ignore) {}
}
} catch (Throwable e) {
throw new RuntimeException(e);
}
@ -658,9 +663,11 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
DataPaletteBlock nibble = section.getBlocks();
int nonEmptyBlockCount = 0;
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
char combinedId = array[FaweCache.CACHE_J[y][x][z]];
short[][] i1 = FaweCache.CACHE_J[y];
for (int x= 0; x < 16; x++) {
short[] i2 = i1[x];
for (int z = 0; z < 16; z++) {
char combinedId = array[i2[z]];
switch (combinedId) {
case 0:
IBlockData existing = nibble.a(x, y, z);
@ -669,11 +676,11 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
}
continue;
case 1:
nibble.setBlock(x, y, z, Blocks.AIR.getBlockData());
nibble.setBlock(x, y, z, air);
continue;
default:
nonEmptyBlockCount++;
nibble.setBlock(x, y, z, Block.getById(combinedId >> 4).fromLegacyData(combinedId & 0xF));
nibble.setBlock(x, y, z, IBD_CACHE[(int) combinedId]);
}
}
}
@ -715,23 +722,6 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
} catch (Throwable e) {
MainUtil.handleError(e);
}
final int[][] biomes = fs.getBiomeArray();
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]);
}
}
}
return true;
}

View File

@ -579,12 +579,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
@Override
public FaweChunk getFaweChunk(int x, int z) {
return new CharFaweChunk<Chunk>(this, x, z) {
@Override
public Chunk getNewChunk() {
return BukkitQueue18R3.this.getWorld().getChunkAt(getX(), getZ());
}
};
return new BukkitChunk_1_8(this, x, z);
}
@Override

View File

@ -8,6 +8,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class NMSRelighter {
@ -15,6 +16,8 @@ public class NMSRelighter {
private final HashMap<Long, RelightSkyEntry> skyToRelight;
private final HashMap<Long, RelightBlockEntry> blocksToRelight;
private static final int DISPATCH_SIZE = 64;
public NMSRelighter(NMSMappedFaweQueue queue) {
this.queue = queue;
skyToRelight = new HashMap<>();
@ -127,7 +130,22 @@ public class NMSRelighter {
// Order chunks
ArrayList<RelightSkyEntry> chunksList = new ArrayList<>(skyToRelight.values());
Collections.sort(chunksList);
RelightSkyEntry[] chunks = chunksList.toArray(new RelightSkyEntry[chunksList.size()]);
int size = chunksList.size();
if (size > DISPATCH_SIZE) {
int amount = (size + 1) / DISPATCH_SIZE;
for (int i = 0; i <= amount; i++) {
int start = i * DISPATCH_SIZE;
int end = Math.min(size, start + DISPATCH_SIZE);
List<RelightSkyEntry> sub = chunksList.subList(start, end);
fixSkyLighting(sub);
}
} else {
fixSkyLighting(chunksList);
}
}
private void fixSkyLighting(List<RelightSkyEntry> sorted) {
RelightSkyEntry[] chunks = sorted.toArray(new RelightSkyEntry[sorted.size()]);
byte[] cacheX = FaweCache.CACHE_X[0];
byte[] cacheZ = FaweCache.CACHE_Z[0];
for (int y = 255; y > 0; y--) {

View File

@ -83,7 +83,7 @@ public class SchematicStreamer extends NBTStreamer {
ListTag positionTag = compound.getListTag("Pos");
ListTag directionTag = compound.getListTag("Rotation");
BaseEntity state = new BaseEntity(id, compound);
fc.createEntity(null, positionTag.asDouble(0), positionTag.asDouble(1), positionTag.asDouble(2), (float) directionTag.asDouble(0), (float) directionTag.asDouble(1), state);
fc.createEntity(clipboard, positionTag.asDouble(0), positionTag.asDouble(1), positionTag.asDouble(2), (float) directionTag.asDouble(0), (float) directionTag.asDouble(1), state);
}
});
}

View File

@ -57,6 +57,7 @@ public abstract class FaweClipboard {
public ClipboardEntity(Extent world, double x, double y, double z, float yaw, float pitch, BaseEntity entity) {
checkNotNull(entity);
checkNotNull(world);
this.world = world;
this.x = x;
this.y = y;

View File

@ -159,7 +159,11 @@ public class MainUtil {
}
int highAmount = amount > 3 ? 1 : 0;
for (int i = 0; i < highAmount; i++) {
os = new LZ4OutputStream(os, buffer, factory.highCompressor());
if (amount == 9) {
os = new LZ4OutputStream(os, buffer, factory.highCompressor(17));
} else {
os = new LZ4OutputStream(os, buffer, factory.highCompressor());
}
}
return new FaweOutputStream(os);
}