Prevent chunk unload during async relight + delay tasks

This commit is contained in:
Jesse Boyd 2016-06-28 22:09:47 +10:00
parent 478cbbf393
commit a521cb9ac3
4 changed files with 92 additions and 32 deletions

View File

@ -4,19 +4,29 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.example.NMSMappedFaweQueue;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.SetQueue;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedDeque;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkUnloadEvent;
import org.bukkit.plugin.Plugin;
public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMappedFaweQueue<World, CHUNK, CHUNKSECTIONS, SECTION> {
public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMappedFaweQueue<World, CHUNK, CHUNKSECTIONS, SECTION> implements Listener {
public Object adapter;
public Method methodToNative;
@ -25,6 +35,10 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
public BukkitQueue_0(final String world) {
super(world);
setupAdapter(null);
if (!registered) {
registered = true;
Bukkit.getServer().getPluginManager().registerEvents(this, (Plugin) Fawe.imp());
}
}
public void checkVersion(String supported) {
@ -35,34 +49,58 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
}
}
public void setupAdapter(BukkitImplAdapter adapter) {
try {
WorldEditPlugin instance = (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit");
Field fieldAdapter = WorldEditPlugin.class.getDeclaredField("bukkitAdapter");
fieldAdapter.setAccessible(true);
if ((this.adapter = adapter) != null) {
fieldAdapter.set(instance, adapter);
} else {
this.adapter = fieldAdapter.get(instance);
}
for (Method method : this.adapter.getClass().getDeclaredMethods()) {
switch (method.getName()) {
case "toNative":
methodToNative = method;
methodToNative.setAccessible(true);
break;
case "fromNative":
methodFromNative = method;
methodFromNative.setAccessible(true);
break;
private static boolean registered = false;
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public static void onChunkUnload(ChunkUnloadEvent event) {
ConcurrentLinkedDeque<FaweQueue> queues = SetQueue.IMP.activeQueues;
if (queues.isEmpty()) {
return;
}
String world = event.getWorld().getName();
Chunk chunk = event.getChunk();
long pair = MathMan.pairInt(chunk.getX(), chunk.getZ());
for (FaweQueue queue : queues) {
if (queue.getWorldName().equals(world)) {
HashSet<Long> relighting = ((NMSMappedFaweQueue) queue).relighting;
if (!relighting.isEmpty() && relighting.contains(pair)) {
event.setCancelled(true);
return;
}
}
} catch (Throwable e) {
Fawe.debug("====== NO NATIVE WORLDEDIT ADAPTER ======");
Fawe.debug("Try updating WorldEdit: ");
Fawe.debug(" - http://builds.enginehub.org/job/worldedit?branch=master");
Fawe.debug("See also: http://wiki.sk89q.com/wiki/WorldEdit/Bukkit_adapters");
Fawe.debug("=========================================");
}
}
public void setupAdapter(BukkitImplAdapter adapter) {
if (adapter == null) {
try {
WorldEditPlugin instance = (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit");
Field fieldAdapter = WorldEditPlugin.class.getDeclaredField("bukkitAdapter");
fieldAdapter.setAccessible(true);
if ((this.adapter = adapter) != null) {
fieldAdapter.set(instance, adapter);
} else {
this.adapter = fieldAdapter.get(instance);
}
for (Method method : this.adapter.getClass().getDeclaredMethods()) {
switch (method.getName()) {
case "toNative":
methodToNative = method;
methodToNative.setAccessible(true);
break;
case "fromNative":
methodFromNative = method;
methodFromNative.setAccessible(true);
break;
}
}
} catch (Throwable e) {
Fawe.debug("====== NO NATIVE WORLDEDIT ADAPTER ======");
Fawe.debug("Try updating WorldEdit: ");
Fawe.debug(" - http://builds.enginehub.org/job/worldedit?branch=master");
Fawe.debug("See also: http://wiki.sk89q.com/wiki/WorldEdit/Bukkit_adapters");
Fawe.debug("=========================================");
}
}
}

View File

@ -273,7 +273,6 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], DataP
continue;
}
pos.c(X + x, y, Z + z);
if (async && !chunk.isLoaded()) return false;
w.w(pos);
}
continue;
@ -314,7 +313,6 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], DataP
continue;
}
pos.c(X + x, y, Z + z);
if (async && !chunk.isLoaded()) return false;
w.w(pos);
}
}

View File

@ -25,8 +25,8 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
/**
* Map of chunks in the queue
*/
private ConcurrentHashMap<Long, FaweChunk> blocks = new ConcurrentHashMap<>();
private ConcurrentLinkedDeque<FaweChunk> chunks = new ConcurrentLinkedDeque<FaweChunk>() {
public ConcurrentHashMap<Long, FaweChunk> blocks = new ConcurrentHashMap<>();
public ConcurrentLinkedDeque<FaweChunk> chunks = new ConcurrentLinkedDeque<FaweChunk>() {
@Override
public boolean add(FaweChunk o) {
if (getProgressTask() != null) {
@ -35,7 +35,7 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
return super.add(o);
}
};
private ArrayDeque<Runnable> tasks = new ArrayDeque<>();
public ArrayDeque<Runnable> tasks = new ArrayDeque<>();
@Override
public void optimize() {

View File

@ -4,9 +4,12 @@ import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.jnbt.CompoundTag;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@ -16,6 +19,13 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
super(world);
}
public boolean isRelighting(int x, int z) {
long pair = MathMan.pairInt(x, z);
return relighting.contains(pair) || blocks.contains(pair);
}
public final HashSet<Long> relighting = new HashSet<>();
@Override
public void sendChunk(final FaweChunk fc, RelightMode mode) {
if (mode == null) {
@ -25,6 +35,8 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
TaskManager.IMP.taskSyncSoon(new Runnable() {
@Override
public void run() {
final long pair = fc.longHash();
relighting.add(pair);
final boolean result = finalMode == RelightMode.NONE || fixLighting(fc, finalMode);
TaskManager.IMP.taskSyncNow(new Runnable() {
@Override
@ -34,6 +46,10 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
}
CHUNK chunk = (CHUNK) fc.getChunk();
refreshChunk(getWorld(), chunk);
relighting.remove(pair);
if (relighting.isEmpty()) {
runTasks();
}
}
}, false);
}
@ -63,4 +79,12 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
}
return getTileEntity(lastChunk, x, y, z);
}
@Override
public int size() {
if (chunks.size() == 0 && SetQueue.IMP.getStage(this) != SetQueue.QueueStage.INACTIVE && relighting.isEmpty()) {
runTasks();
}
return chunks.size();
}
}