diff --git a/bukkit-helper-114/.gitignore b/bukkit-helper-114/.gitignore new file mode 100644 index 00000000..84c048a7 --- /dev/null +++ b/bukkit-helper-114/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/bukkit-helper-114/build.gradle b/bukkit-helper-114/build.gradle new file mode 100644 index 00000000..2e3993a9 --- /dev/null +++ b/bukkit-helper-114/build.gradle @@ -0,0 +1,10 @@ + +description = 'bukkit-helper-1.14' + +dependencies { + compile project(':bukkit-helper') + compile project(':dynmap-api') + compile project(path: ':DynmapCore', configuration: 'shadow') + compile group: 'org.bukkit', name: 'bukkit', version:'1.14-R0.1-SNAPSHOT' + compile group: 'org.bukkit', name: 'craftbukkit', version:'1.14-R0.1-SNAPSHOT' +} diff --git a/bukkit-helper-114/src/main/java/org/dynmap/bukkit/helper/v114/BukkitVersionHelperSpigot114.java b/bukkit-helper-114/src/main/java/org/dynmap/bukkit/helper/v114/BukkitVersionHelperSpigot114.java new file mode 100644 index 00000000..bbf9b377 --- /dev/null +++ b/bukkit-helper-114/src/main/java/org/dynmap/bukkit/helper/v114/BukkitVersionHelperSpigot114.java @@ -0,0 +1,193 @@ +package org.dynmap.bukkit.helper.v114; + +import java.lang.reflect.Field; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.ChunkSnapshot; +import org.bukkit.Location; +import org.bukkit.Server; +import org.bukkit.World; +import org.bukkit.WorldBorder; +import org.dynmap.DynmapChunk; +import org.dynmap.Log; +import org.dynmap.bukkit.helper.BukkitVersionHelper; +import org.dynmap.bukkit.helper.BukkitVersionHelperCB; +import org.dynmap.bukkit.helper.BukkitWorld; +import org.dynmap.bukkit.helper.v114.MapChunkCache114; +import org.dynmap.hdmap.HDBlockModels; +import org.dynmap.renderer.DynmapBlockState; +import org.dynmap.utils.MapChunkCache; +import org.dynmap.utils.Polygon; +import org.dynmap.common.BiomeMap; + +import net.minecraft.server.v1_14_R1.BiomeBase; +import net.minecraft.server.v1_14_R1.Block; +import net.minecraft.server.v1_14_R1.BlockFluids; +import net.minecraft.server.v1_14_R1.BlockLogAbstract; +import net.minecraft.server.v1_14_R1.IBlockData; +import net.minecraft.server.v1_14_R1.IBlockState; +import net.minecraft.server.v1_14_R1.IRegistry; +import net.minecraft.server.v1_14_R1.Material; + +/** + * Helper for isolation of bukkit version specific issues + */ +public class BukkitVersionHelperSpigot114 extends BukkitVersionHelperCB { + + /** CraftChunkSnapshot */ + protected Class datapalettearray; + private Field blockid_field; + + @Override + protected boolean isBlockIdNeeded() { + return false; + } + + public BukkitVersionHelperSpigot114() { + datapalettearray = getNMSClass("[Lnet.minecraft.server.DataPaletteBlock;"); + blockid_field = getPrivateField(craftchunksnapshot, new String[] { "blockids" }, datapalettearray); + } + + @Override + public Object[] getBlockIDFieldFromSnapshot(ChunkSnapshot css) { + try { + return (Object[]) blockid_field.get(css); + } catch (IllegalArgumentException e) { + } catch (IllegalAccessException e) { + } + return null; + } + @Override + public void unloadChunkNoSave(World w, Chunk c, int cx, int cz) { + w.unloadChunk(cx, cz, false); + } + + private String stripBlockString(String bname) { + int idx = bname.indexOf('{'); + if (idx >= 0) bname = bname.substring(idx+1); + idx = bname.indexOf('}'); + if (idx >= 0) bname = bname.substring(0, idx); + return bname; + } + /** + * Get block short name list + */ + @Override + public String[] getBlockNames() { + int cnt = Block.REGISTRY_ID.a(); + String[] names = new String[cnt]; + for (int i = 0; i < cnt; i++) { + IBlockData bd = Block.getByCombinedId(i); + names[i] = IRegistry.BLOCK.getKey(bd.getBlock()).toString(); + Log.info(i + ": blk=" + names[i] + ", bd=" + bd.toString()); + } + return names; + } + /** Get ID from biomebase */ + @Override + public int getBiomeBaseID(Object bb) { + return IRegistry.BIOME.a((BiomeBase)bb); + } + + public static IdentityHashMap dataToState; + + /** + * Initialize block states (org.dynmap.blockstate.DynmapBlockState) + */ + @Override + public void initializeBlockStates() { + dataToState = new IdentityHashMap(); + HashMap lastBlockState = new HashMap(); + + int cnt = Block.REGISTRY_ID.a(); + // Loop through block data states + for (int i = 0; i < cnt; i++) { + IBlockData bd = Block.getByCombinedId(i); + String bname = IRegistry.BLOCK.getKey(bd.getBlock()).toString(); + DynmapBlockState lastbs = lastBlockState.get(bname); // See if we have seen this one + int idx = 0; + if (lastbs != null) { // Yes + idx = lastbs.getStateCount(); // Get number of states so far, since this is next + } + // Build state name + String sb = ""; + String fname = bd.toString(); + int off1 = fname.indexOf('['); + if (off1 >= 0) { + int off2 = fname.indexOf(']'); + sb = fname.substring(off1+1, off2); + } + Material mat = bd.getMaterial(); + DynmapBlockState bs = new DynmapBlockState(lastbs, idx, bname, sb, mat.toString()); + if ((!bd.p().isEmpty()) && ((bd.getBlock() instanceof BlockFluids) == false)) { // Test if fluid type for block is not empty + bs.setWaterlogged(); + } + if (mat == Material.AIR) { + bs.setAir(); + } + if (mat == Material.LEAVES) { + bs.setLeaves(); + } + if (bd.getBlock() instanceof BlockLogAbstract) { + bs.setLog(); + } + if (mat.isSolid()) { + bs.setSolid(); + } + dataToState.put(bd, bs); + lastBlockState.put(bname, (lastbs == null) ? bs : lastbs); + Log.verboseinfo(i + ": blk=" + bname + ", idx=" + idx + ", state=" + sb + ", waterlogged=" + bs.isWaterlogged()); + } + } + /** + * Create chunk cache for given chunks of given world + * @param dw - world + * @param chunks - chunk list + * @return cache + */ + @Override + public MapChunkCache getChunkCache(BukkitWorld dw, List chunks) { + MapChunkCache114 c = new MapChunkCache114(); + c.setChunks(dw, chunks); + return c; + } + + /** + * Get biome base water multiplier + */ + @Override + public int getBiomeBaseWaterMult(Object bb) { + return ((BiomeBase)bb).n(); + } + + @Override + public Polygon getWorldBorder(World world) { + Polygon p = null; + WorldBorder wb = world.getWorldBorder(); + if (wb != null) { + Location c = wb.getCenter(); + double size = wb.getSize(); + if ((size > 1) && (size < 1E7)) { + size = size / 2; + p = new Polygon(); + p.addVertex(c.getX()-size, c.getZ()-size); + p.addVertex(c.getX()+size, c.getZ()-size); + p.addVertex(c.getX()+size, c.getZ()+size); + p.addVertex(c.getX()-size, c.getZ()+size); + } + } + return p; + } + +} diff --git a/bukkit-helper-114/src/main/java/org/dynmap/bukkit/helper/v114/MapChunkCache114.java b/bukkit-helper-114/src/main/java/org/dynmap/bukkit/helper/v114/MapChunkCache114.java new file mode 100644 index 00000000..927072fa --- /dev/null +++ b/bukkit-helper-114/src/main/java/org/dynmap/bukkit/helper/v114/MapChunkCache114.java @@ -0,0 +1,88 @@ +package org.dynmap.bukkit.helper.v114; + +import org.bukkit.block.Biome; +import org.bukkit.ChunkSnapshot; +import org.bukkit.World; +import org.dynmap.bukkit.helper.AbstractMapChunkCache; +import org.dynmap.bukkit.helper.BukkitVersionHelper; +import org.dynmap.renderer.DynmapBlockState; + +import net.minecraft.server.v1_14_R1.DataPaletteBlock; + +/** + * Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread + */ +public class MapChunkCache114 extends AbstractMapChunkCache { + + public static class WrappedSnapshot implements Snapshot { + private final ChunkSnapshot ss; + private final DataPaletteBlock[] blockids; + private final int sectionmask; + public WrappedSnapshot(ChunkSnapshot ss) { + this.ss = ss; + blockids = (DataPaletteBlock[]) BukkitVersionHelper.helper.getBlockIDFieldFromSnapshot(ss); + int mask = 0; + for (int i = 0; i < blockids.length; i++) { + if (ss.isSectionEmpty(i)) + mask |= (1 << i); + } + sectionmask = mask; + } + @Override + public final DynmapBlockState getBlockType(int x, int y, int z) { + if ((sectionmask & (1 << (y >> 4))) != 0) + return DynmapBlockState.AIR; + return BukkitVersionHelperSpigot114.dataToState.getOrDefault(blockids[y >> 4].a(x & 0xF, y & 0xF, z & 0xF), DynmapBlockState.AIR); + } + @Override + public final int getBlockSkyLight(int x, int y, int z) { + return ss.getBlockSkyLight(x, y, z); + } + @Override + public final int getBlockEmittedLight(int x, int y, int z) { + return ss.getBlockEmittedLight(x, y, z); + } + @Override + public final int getHighestBlockYAt(int x, int z) { + return ss.getHighestBlockYAt(x, z); + } + @Override + public final Biome getBiome(int x, int z) { + return ss.getBiome(x, z); + } + @Override + public final boolean isSectionEmpty(int sy) { + return (sectionmask & (1 << sy)) != 0; + } + @Override + public final Object[] getBiomeBaseFromSnapshot() { + return BukkitVersionHelper.helper.getBiomeBaseFromSnapshot(ss); + } + } + + @Override + public Snapshot wrapChunkSnapshot(ChunkSnapshot css) { + return new WrappedSnapshot(css); + } + @Override + public boolean loadChunkNoGenerate(World w, int x, int z) { + boolean rslt = w.loadChunk(x, z, false); + // Workaround for Spigot 1.13.2 bug - check if generated and do load-with-generate if so to drive migration of old chunks + if (!rslt) { + boolean generated = true; + // Check one in each direction: see if all are generated + for (int xx = x-3; xx <= x+3; xx++) { + for (int zz = z-3; zz <= z+3; zz++) { + if (w.isChunkGenerated(xx, zz) == false) { + generated = false; + break; + } + } + } + if (generated) { + rslt = w.loadChunk(x, z, true); + } + } + return rslt; + } +} diff --git a/settings.gradle b/settings.gradle index ad1b2988..79936c4f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,6 +3,7 @@ include ':spigot' include ':bukkit-helper-113' include ':bukkit-helper-113-1' include ':bukkit-helper-113-2' +include ':bukkit-helper-114' include ':bukkit-helper' include ':dynmap-api' include ':DynmapCore' @@ -18,6 +19,7 @@ project(':spigot').projectDir = "$rootDir/spigot" as File project(':bukkit-helper-113').projectDir = "$rootDir/bukkit-helper-113" as File project(':bukkit-helper-113-1').projectDir = "$rootDir/bukkit-helper-113-1" as File project(':bukkit-helper-113-2').projectDir = "$rootDir/bukkit-helper-113-2" as File +project(':bukkit-helper-114').projectDir = "$rootDir/bukkit-helper-114" as File project(':bukkit-helper').projectDir = "$rootDir/bukkit-helper" as File project(':dynmap-api').projectDir = "$rootDir/dynmap-api" as File project(':DynmapCore').projectDir = "$rootDir/DynmapCore" as File diff --git a/spigot/build.gradle b/spigot/build.gradle index ba60c7b0..f37ac54a 100644 --- a/spigot/build.gradle +++ b/spigot/build.gradle @@ -24,6 +24,9 @@ dependencies { implementation(project(':bukkit-helper-113-2')) { transitive = false } + implementation(project(':bukkit-helper-114')) { + transitive = false + } } processResources { @@ -51,6 +54,7 @@ shadowJar { include(dependency(':bukkit-helper-113')) include(dependency(':bukkit-helper-113-1')) include(dependency(':bukkit-helper-113-2')) + include(dependency(':bukkit-helper-114')) } relocate('org.bstats', 'org.dynmap.bstats') destinationDir = file '../target' diff --git a/spigot/src/main/java/org/dynmap/bukkit/Helper.java b/spigot/src/main/java/org/dynmap/bukkit/Helper.java index bdbb4ef9..033616ff 100644 --- a/spigot/src/main/java/org/dynmap/bukkit/Helper.java +++ b/spigot/src/main/java/org/dynmap/bukkit/Helper.java @@ -8,6 +8,7 @@ import org.dynmap.bukkit.helper.BukkitVersionHelperGlowstone; import org.dynmap.bukkit.helper.v113.BukkitVersionHelperSpigot113; import org.dynmap.bukkit.helper.v113_1.BukkitVersionHelperSpigot113_1; import org.dynmap.bukkit.helper.v113_2.BukkitVersionHelperSpigot113_2; +import org.dynmap.bukkit.helper.v114.BukkitVersionHelperSpigot114; public class Helper { @@ -33,6 +34,9 @@ public class Helper { Log.info("Loading Glowstone support"); BukkitVersionHelper.helper = new BukkitVersionHelperGlowstone(); } + else if (v.contains("(MC: 1.14)")) { + BukkitVersionHelper.helper = new BukkitVersionHelperSpigot114(); + } else if (v.contains("(MC: 1.13.2)")) { BukkitVersionHelper.helper = new BukkitVersionHelperSpigot113_2(); }