mirror of https://github.com/webbukkit/dynmap.git
First idea implementation
This commit is contained in:
parent
c8801dbb8c
commit
b0f0a4deb5
|
@ -37,11 +37,13 @@ import net.minecraft.server.v1_16_R2.MinecraftServer;
|
|||
* Helper for isolation of bukkit version specific issues
|
||||
*/
|
||||
public class BukkitVersionHelperSpigot116_2 extends BukkitVersionHelperGeneric {
|
||||
private final boolean unsafeAsync;
|
||||
private Field watercolorfield;
|
||||
|
||||
public BukkitVersionHelperSpigot116_2() {
|
||||
Class biomefog = getNMSClass("net.minecraft.server.BiomeFog");
|
||||
watercolorfield = getPrivateField(biomefog, new String[] { "c" }, int.class);
|
||||
this.unsafeAsync = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,6 +71,12 @@ public class BukkitVersionHelperSpigot116_2 extends BukkitVersionHelperGeneric {
|
|||
}
|
||||
|
||||
private Object[] biomelist;
|
||||
|
||||
@Override
|
||||
public boolean isUnsafeAsync() {
|
||||
return unsafeAsync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of defined biomebase objects
|
||||
*/
|
||||
|
|
|
@ -37,11 +37,13 @@ import net.minecraft.server.v1_16_R2.BlockPosition;
|
|||
* Helper for isolation of bukkit version specific issues
|
||||
*/
|
||||
public class BukkitVersionHelperSpigot116_3 extends BukkitVersionHelperGeneric {
|
||||
private final boolean unsafeAsync;
|
||||
private Field watercolorfield;
|
||||
|
||||
public BukkitVersionHelperSpigot116_3() {
|
||||
Class biomefog = getNMSClass("net.minecraft.server.BiomeFog");
|
||||
watercolorfield = getPrivateField(biomefog, new String[] { "c" }, int.class);
|
||||
this.unsafeAsync = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,6 +71,12 @@ public class BukkitVersionHelperSpigot116_3 extends BukkitVersionHelperGeneric {
|
|||
}
|
||||
|
||||
private Object[] biomelist;
|
||||
|
||||
@Override
|
||||
public boolean isUnsafeAsync() {
|
||||
return unsafeAsync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of defined biomebase objects
|
||||
*/
|
||||
|
|
|
@ -26,11 +26,13 @@ import java.util.List;
|
|||
* Helper for isolation of bukkit version specific issues
|
||||
*/
|
||||
public class BukkitVersionHelperSpigot116_4 extends BukkitVersionHelperGeneric {
|
||||
private final boolean unsafeAsync;
|
||||
private Field watercolorfield;
|
||||
|
||||
public BukkitVersionHelperSpigot116_4() {
|
||||
Class biomefog = getNMSClass("net.minecraft.server.BiomeFog");
|
||||
watercolorfield = getPrivateField(biomefog, new String[] { "c" }, int.class);
|
||||
this.unsafeAsync = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,6 +60,12 @@ public class BukkitVersionHelperSpigot116_4 extends BukkitVersionHelperGeneric {
|
|||
}
|
||||
|
||||
private Object[] biomelist;
|
||||
|
||||
@Override
|
||||
public boolean isUnsafeAsync() {
|
||||
return unsafeAsync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of defined biomebase objects
|
||||
*/
|
||||
|
|
|
@ -36,11 +36,13 @@ import net.minecraft.server.v1_16_R1.BlockPosition;
|
|||
* Helper for isolation of bukkit version specific issues
|
||||
*/
|
||||
public class BukkitVersionHelperSpigot116 extends BukkitVersionHelperGeneric {
|
||||
private final boolean unsafeAsync;
|
||||
private Field watercolorfield;
|
||||
|
||||
public BukkitVersionHelperSpigot116() {
|
||||
Class biomefog = getNMSClass("net.minecraft.server.BiomeFog");
|
||||
watercolorfield = getPrivateField(biomefog, new String[] { "c" }, int.class);
|
||||
this.unsafeAsync = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,6 +61,12 @@ public class BukkitVersionHelperSpigot116 extends BukkitVersionHelperGeneric {
|
|||
}
|
||||
|
||||
private Object[] biomelist;
|
||||
|
||||
@Override
|
||||
public boolean isUnsafeAsync() {
|
||||
return unsafeAsync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of defined biomebase objects
|
||||
*/
|
||||
|
|
|
@ -59,7 +59,15 @@ import java.util.Map;
|
|||
* Helper for isolation of bukkit version specific issues
|
||||
*/
|
||||
public class BukkitVersionHelperSpigot117 extends BukkitVersionHelper {
|
||||
private final boolean unsafeAsync;
|
||||
|
||||
public BukkitVersionHelperSpigot117() {
|
||||
this.unsafeAsync = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnsafeAsync() {
|
||||
return unsafeAsync;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package org.dynmap.bukkit.helper.v118_2;
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.server.level.WorldServer;
|
||||
import net.minecraft.world.level.World;
|
||||
import net.minecraft.world.level.chunk.Chunk;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* The provider used to work with paper libs
|
||||
* Because paper libs need java 17 we can't interact with them directly
|
||||
*/
|
||||
public class AsyncChunkProvider118_2 {
|
||||
private static final Thread ioThread;
|
||||
private static final Method getChunk;
|
||||
private static final Predicate<NBTTagCompound> ifFailed;
|
||||
static {
|
||||
try {
|
||||
Predicate<NBTTagCompound> ifFailed1 = null;
|
||||
Method getChunk1 = null;
|
||||
Thread ioThread1 = null;
|
||||
try {
|
||||
Class<?> threadClass = Class.forName("com.destroystokyo.paper.io.PaperFileIOThread");
|
||||
Class<?>[] classes = threadClass.getClasses();
|
||||
Class<?> holder = Arrays.stream(classes).filter(aClass -> aClass.getSimpleName().equals("Holder")).findAny().orElseThrow(RuntimeException::new);
|
||||
ioThread1 = (Thread) holder.getField("INSTANCE").get(null);
|
||||
getChunk1 = threadClass.getMethod("loadChunkDataAsync", WorldServer.class, int.class, int.class, int.class, Consumer.class, boolean.class, boolean.class, boolean.class);
|
||||
NBTTagCompound failure = (NBTTagCompound) threadClass.getField("FAILURE_VALUE").get(null);
|
||||
ifFailed1 = nbtTagCompound -> nbtTagCompound == failure;
|
||||
} catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException | NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
ifFailed = Objects.requireNonNull(ifFailed1);
|
||||
getChunk = Objects.requireNonNull(getChunk1);
|
||||
ioThread = Objects.requireNonNull(ioThread1);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public NBTTagCompound getChunk(WorldServer world, int x, int y) throws InvocationTargetException, IllegalAccessException, NoSuchFieldException {
|
||||
CompletableFuture<Object> future = new CompletableFuture<>();
|
||||
getChunk.invoke(ioThread,world,x,y,5,(Consumer<Object>) future::complete, false, true, true);
|
||||
Object resultFuture = future.join();
|
||||
if (resultFuture == null) return null;
|
||||
NBTTagCompound result = (NBTTagCompound) resultFuture.getClass().getField("chunkData").get(resultFuture);
|
||||
return ifFailed.test(result) ? null : result;
|
||||
}
|
||||
}
|
|
@ -64,9 +64,22 @@ import java.util.Set;
|
|||
* Helper for isolation of bukkit version specific issues
|
||||
*/
|
||||
public class BukkitVersionHelperSpigot118_2 extends BukkitVersionHelper {
|
||||
private final boolean unsafeAsync;
|
||||
|
||||
public BukkitVersionHelperSpigot118_2() {
|
||||
boolean unsafeAsync1;
|
||||
try {
|
||||
Class.forName("com.destroystokyo.paper.io.PaperFileIOThread");
|
||||
unsafeAsync1 = false;
|
||||
} catch (ClassNotFoundException e) {
|
||||
unsafeAsync1 = true;
|
||||
}
|
||||
this.unsafeAsync = unsafeAsync1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnsafeAsync() {
|
||||
return unsafeAsync;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package org.dynmap.bukkit.helper.v118_2;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
|
||||
import org.dynmap.DynmapChunk;
|
||||
import org.dynmap.bukkit.helper.BukkitVersionHelper;
|
||||
import org.dynmap.bukkit.helper.BukkitWorld;
|
||||
import org.dynmap.common.chunk.GenericChunk;
|
||||
import org.dynmap.common.chunk.GenericChunkCache;
|
||||
|
@ -14,12 +17,15 @@ import net.minecraft.world.level.chunk.storage.ChunkRegionLoader;
|
|||
import net.minecraft.world.level.chunk.Chunk;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread
|
||||
*/
|
||||
public class MapChunkCache118_2 extends GenericMapChunkCache {
|
||||
private final AsyncChunkProvider118_2 provider = BukkitVersionHelper.helper.isUnsafeAsync() ? null : new AsyncChunkProvider118_2();
|
||||
private World w;
|
||||
/**
|
||||
* Construct empty cache
|
||||
|
@ -34,9 +40,13 @@ public class MapChunkCache118_2 extends GenericMapChunkCache {
|
|||
NBTTagCompound nbt = null;
|
||||
GenericChunk gc = null;
|
||||
if (cw.isChunkLoaded(chunk.x, chunk.z)) {
|
||||
Chunk c = cw.getHandle().getChunkIfLoaded(chunk.x, chunk.z);
|
||||
Chunk c = cw.getHandle().getChunkIfLoaded(chunk.x, chunk.z); //already safe async on vanilla
|
||||
if ((c != null) && c.o) { // c.loaded
|
||||
if (provider == null) { //idk why, but paper uses this only sync, so I won't be smarter
|
||||
nbt = ChunkRegionLoader.a(cw.getHandle(), c);
|
||||
} else {
|
||||
nbt = CompletableFuture.supplyAsync(() -> ChunkRegionLoader.a(cw.getHandle(), c), ((CraftServer) Bukkit.getServer()).getServer()).join();
|
||||
}
|
||||
}
|
||||
if (nbt != null) {
|
||||
gc = parseChunkFromNBT(new NBT.NBTCompound(nbt));
|
||||
|
@ -51,8 +61,12 @@ public class MapChunkCache118_2 extends GenericMapChunkCache {
|
|||
ChunkCoordIntPair cc = new ChunkCoordIntPair(chunk.x, chunk.z);
|
||||
GenericChunk gc = null;
|
||||
try {
|
||||
if (provider == null){
|
||||
nbt = cw.getHandle().k().a.f(cc); // playerChunkMap
|
||||
} catch (IOException iox) {
|
||||
} else {
|
||||
nbt = provider.getChunk(cw.getHandle(),chunk.x, chunk.z);
|
||||
}
|
||||
} catch (IOException | InvocationTargetException | IllegalAccessException | NoSuchFieldException ignored) {
|
||||
}
|
||||
if (nbt != null) {
|
||||
gc = parseChunkFromNBT(new NBT.NBTCompound(nbt));
|
||||
|
|
|
@ -65,8 +65,15 @@ import java.util.Set;
|
|||
*/
|
||||
public class BukkitVersionHelperSpigot118 extends BukkitVersionHelper {
|
||||
|
||||
public BukkitVersionHelperSpigot118() {
|
||||
private final boolean unsafeAsync;
|
||||
|
||||
public BukkitVersionHelperSpigot118() {
|
||||
this.unsafeAsync = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnsafeAsync() {
|
||||
return unsafeAsync;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,6 +34,10 @@ public abstract class BukkitVersionHelper {
|
|||
protected BukkitVersionHelper() {
|
||||
|
||||
}
|
||||
/**
|
||||
* Get if it's unsafe to load chunks async
|
||||
*/
|
||||
public abstract boolean isUnsafeAsync();
|
||||
/**
|
||||
* Get list of defined biomebase objects
|
||||
*/
|
||||
|
|
|
@ -54,6 +54,12 @@ public class BukkitVersionHelperCB extends BukkitVersionHelperGeneric {
|
|||
isBadUnload = HDBlockModels.checkVersionRange(mcver, "1.9-");
|
||||
Log.verboseinfo("MCVER=" + mcver + ", isBadUnload=" + isBadUnload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnsafeAsync() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNMSPackage() {
|
||||
Server srv = Bukkit.getServer();
|
||||
|
|
|
@ -33,6 +33,11 @@ public class BukkitVersionHelperGlowstone extends BukkitVersionHelper {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnsafeAsync() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getBiomeBaseList() {
|
||||
return new Object[0];
|
||||
|
|
|
@ -481,6 +481,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
|||
boolean rslt = permissions.hasOfflinePermission(player, perm);
|
||||
return rslt;
|
||||
}
|
||||
private final Object[] lock = {};
|
||||
/**
|
||||
* Render processor helper - used by code running on render threads to request chunk snapshot cache from server/sync thread
|
||||
*/
|
||||
|
@ -514,6 +515,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
|||
final MapChunkCache cc = c;
|
||||
|
||||
while(!cc.isDoneLoading()) {
|
||||
if (BukkitVersionHelper.helper.isUnsafeAsync()) {
|
||||
Future<Boolean> f = core.getServer().callSyncMethod(new Callable<Boolean>() {
|
||||
public Boolean call() throws Exception {
|
||||
boolean exhausted = true;
|
||||
|
@ -552,8 +554,25 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
|||
Log.severe(ix);
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((delay != null) && delay.booleanValue()) {
|
||||
try { Thread.sleep(25); } catch (InterruptedException ix) {}
|
||||
try {
|
||||
Thread.sleep(25);
|
||||
} catch (InterruptedException ix) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
synchronized (lock) {
|
||||
if (prev_tick != cur_tick) {
|
||||
prev_tick = cur_tick;
|
||||
cur_tick_starttime = System.nanoTime();
|
||||
}
|
||||
cc.loadChunks(Integer.MAX_VALUE);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If cancelled due to world unload return nothing */
|
||||
|
|
Loading…
Reference in New Issue