diff --git a/bukkit-helper-113-1/.gitignore b/bukkit-helper-113-1/.gitignore new file mode 100644 index 00000000..5d644ec0 --- /dev/null +++ b/bukkit-helper-113-1/.gitignore @@ -0,0 +1,4 @@ +/target/ +/build/ +/bin/ +/.classpath diff --git a/bukkit-helper-113-1/build.gradle b/bukkit-helper-113-1/build.gradle new file mode 100644 index 00000000..b2b5a4a7 --- /dev/null +++ b/bukkit-helper-113-1/build.gradle @@ -0,0 +1,10 @@ + +description = 'bukkit-helper-1.13.1' + +dependencies { + compile project(':bukkit-helper') + compile project(path: ':dynmap-api', configuration: 'shadow') + compile project(path: ':DynmapCore', configuration: 'shadow') + compile group: 'org.bukkit', name: 'bukkit', version:'1.13.1-R0.1-SNAPSHOT' + compile group: 'org.bukkit', name: 'craftbukkit', version:'1.13.1-R0.1-SNAPSHOT' +} diff --git a/bukkit-helper-113-1/src/main/java/org/dynmap/bukkit/helper/v113_1/BukkitVersionHelperSpigot113_1.java b/bukkit-helper-113-1/src/main/java/org/dynmap/bukkit/helper/v113_1/BukkitVersionHelperSpigot113_1.java new file mode 100644 index 00000000..d16cd1aa --- /dev/null +++ b/bukkit-helper-113-1/src/main/java/org/dynmap/bukkit/helper/v113_1/BukkitVersionHelperSpigot113_1.java @@ -0,0 +1,163 @@ +package org.dynmap.bukkit.helper.v113_1; + +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.Server; +import org.bukkit.World; +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.v113_1.MapChunkCache113_1; +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_13_R2.BiomeBase; +import net.minecraft.server.v1_13_R2.Block; +import net.minecraft.server.v1_13_R2.BlockFluids; +import net.minecraft.server.v1_13_R2.BlockLogAbstract; +import net.minecraft.server.v1_13_R2.IBlockData; +import net.minecraft.server.v1_13_R2.IBlockState; +import net.minecraft.server.v1_13_R2.IRegistry; +import net.minecraft.server.v1_13_R2.Material; + +/** + * Helper for isolation of bukkit version specific issues + */ +public class BukkitVersionHelperSpigot113_1 extends BukkitVersionHelperCB { + + /** CraftChunkSnapshot */ + protected Class datapalettearray; + private Field blockid_field; + + public BukkitVersionHelperSpigot113_1() { + 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, 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); + } + DynmapBlockState bs = new DynmapBlockState(lastbs, idx, bname, sb); + if ((!bd.s().e()) && ((bd.getBlock() instanceof BlockFluids) == false)) { // Test if fluid type for block is not empty + bs.setWaterlogged(); + } + if (bd.getMaterial() == Material.AIR) { + bs.setAir(); + } + if (bd.getMaterial() == Material.LEAVES) { + bs.setLeaves(); + } + if (bd.getBlock() instanceof BlockLogAbstract) { + bs.setLog(); + } + 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) { + MapChunkCache113_1 c = new MapChunkCache113_1(); + c.setChunks(dw, chunks); + return c; + } + + /** + * Get biome base water multiplier + */ + @Override + public int getBiomeBaseWaterMult(Object bb) { + return ((BiomeBase)bb).n(); + } + +} diff --git a/bukkit-helper-113-1/src/main/java/org/dynmap/bukkit/helper/v113_1/MapChunkCache113_1.java b/bukkit-helper-113-1/src/main/java/org/dynmap/bukkit/helper/v113_1/MapChunkCache113_1.java new file mode 100644 index 00000000..9332d2fc --- /dev/null +++ b/bukkit-helper-113-1/src/main/java/org/dynmap/bukkit/helper/v113_1/MapChunkCache113_1.java @@ -0,0 +1,66 @@ +package org.dynmap.bukkit.helper.v113_1; + +import org.bukkit.block.Biome; +import org.bukkit.ChunkSnapshot; +import org.dynmap.bukkit.helper.AbstractMapChunkCache; +import org.dynmap.bukkit.helper.BukkitVersionHelper; +import org.dynmap.renderer.DynmapBlockState; + +import net.minecraft.server.v1_13_R2.DataPaletteBlock; + +/** + * Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread + */ +public class MapChunkCache113_1 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 BukkitVersionHelperSpigot113_1.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); + } +} diff --git a/bukkit-helper/src/main/java/org/dynmap/bukkit/helper/BukkitVersionHelperCB.java b/bukkit-helper/src/main/java/org/dynmap/bukkit/helper/BukkitVersionHelperCB.java index cb9a6b94..33d514b5 100644 --- a/bukkit-helper/src/main/java/org/dynmap/bukkit/helper/BukkitVersionHelperCB.java +++ b/bukkit-helper/src/main/java/org/dynmap/bukkit/helper/BukkitVersionHelperCB.java @@ -4,6 +4,7 @@ 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.Map; import java.util.Set; @@ -32,8 +33,10 @@ public class BukkitVersionHelperCB extends BukkitVersionHelperGeneric { private Method worldborderminz; private Method worldbordermaxz; private Method getbiomebyid; + private Method getbiomefunc; private Method getidbybiome; private boolean isBadUnload = false; + protected boolean blockidsneeded = true; public BukkitVersionHelperCB() { @@ -67,9 +70,11 @@ public class BukkitVersionHelperCB extends BukkitVersionHelperGeneric { nmsblock = getNMSClass("net.minecraft.server.Block"); nmsblockarray = getNMSClass("[Lnet.minecraft.server.Block;"); nmsmaterial = getNMSClass("net.minecraft.server.Material"); - blockbyid = getFieldNoFail(nmsblock, new String[] { "byId" }, nmsblockarray); - if (blockbyid == null) { - blockbyidfunc = getMethod(nmsblock, new String[] { "getById", "e" }, new Class[] { int.class }); + if (blockidsneeded) { // Not needed for 1.13+ + blockbyid = getFieldNoFail(nmsblock, new String[] { "byId" }, nmsblockarray); + if (blockbyid == null) { + blockbyidfunc = getMethod(nmsblock, new String[] { "getById", "e" }, new Class[] { int.class }); + } } material = getPrivateField(nmsblock, new String[] { "material" }, nmsmaterial); @@ -78,17 +83,26 @@ public class BukkitVersionHelperCB extends BukkitVersionHelperGeneric { biomebasearray = getNMSClass("[Lnet.minecraft.server.BiomeBase;"); biomebaselist = getPrivateFieldNoFail(biomebase, new String[] { "biomes" }, biomebasearray); if (biomebaselist == null) { - getbiomebyid = getMethod(biomebase, new String[] { "a" }, new Class[] { int.class} ); + getbiomefunc = getMethodNoFail(biomebase, new String[] { "getBiome" }, new Class[] { int.class, biomebase }); + if (getbiomefunc == null) { + getbiomebyid = getMethod(biomebase, new String[] { "a" }, new Class[] { int.class} ); + } } - biomebasetemp = getPrivateFieldNoFail(biomebase, new String[] { "B" }, float.class); - if (biomebasetemp != null) { - biomebasehumi = getPrivateField(biomebase, new String[] { "C" }, float.class); + biomebasetempfunc = getMethodNoFail(biomebase, new String[] { "getTemperature" }, nulltypes); + if (biomebasetempfunc == null) { + biomebasetemp = getPrivateFieldNoFail(biomebase, new String[] { "B" }, float.class); + if (biomebasetemp != null) { + biomebasehumi = getPrivateField(biomebase, new String[] { "C" }, float.class); + } + else { + biomebasetemp = getPrivateField(biomebase, new String[] { "temperature", "F", "C", "aO" }, float.class); + biomebasehumi = getPrivateField(biomebase, new String[] { "humidity", "G", "D", "aP" }, float.class); + } } else { - biomebasetemp = getPrivateField(biomebase, new String[] { "temperature", "F", "C", "aO" }, float.class); - biomebasehumi = getPrivateField(biomebase, new String[] { "humidity", "G", "D", "aP" }, float.class); + biomebasehumifunc = getMethod(biomebase, new String[] { "getHumidity" }, nulltypes); } - biomebaseidstring = getPrivateField(biomebase, new String[] { "y", "af", "ah", "z", "aS" }, String.class); + biomebaseidstring = getPrivateField(biomebase, new String[] { "y", "af", "ah", "z", "aS", "aR" }, String.class); biomebaseid = getFieldNoFail(biomebase, new String[] { "id" }, int.class); if (biomebaseid == null) { getidbybiome = getMethod(biomebase, new String[] { "a" }, new Class[] { biomebase } ); @@ -252,6 +266,7 @@ public class BukkitVersionHelperCB extends BukkitVersionHelperGeneric { public int[] getBlockMaterialMap() { try { int[] map = new int[4096]; + Arrays.fill(map, -1); if (blockbyid != null) { Object[] byid = (Object[])blockbyid.get(nmsblock); ArrayList mats = new ArrayList(); @@ -265,13 +280,10 @@ public class BukkitVersionHelperCB extends BukkitVersionHelperGeneric { mats.add(mat); } } - else { - map[i] = -1; - } } } } - else { + else if (blockbyidfunc != null) { ArrayList mats = new ArrayList(); for (int i = 0; i < map.length; i++) { Object blk = blockbyidfunc.invoke(nmsblock, i); @@ -284,9 +296,6 @@ public class BukkitVersionHelperCB extends BukkitVersionHelperGeneric { mats.add(mat); } } - else { - map[i] = -1; - } } } } @@ -326,12 +335,15 @@ public class BukkitVersionHelperCB extends BukkitVersionHelperGeneric { * Get list of defined biomebase objects */ public Object[] getBiomeBaseList() { - if (getbiomebyid != null) { + if ((getbiomebyid != null) || (getbiomefunc != null)) { if (biomelist == null) { biomelist = new Object[1024]; for (int i = 0; i < 1024; i++) { try { - biomelist[i] = getbiomebyid.invoke(biomebase, i); + if (getbiomefunc != null) + biomelist[i] = getbiomefunc.invoke(biomebase, i, null); + else + biomelist[i] = getbiomebyid.invoke(biomebase, i); } catch (IllegalAccessException x) { } catch (IllegalArgumentException x) { } catch (InvocationTargetException x) { diff --git a/bukkit-helper/src/main/java/org/dynmap/bukkit/helper/BukkitVersionHelperGeneric.java b/bukkit-helper/src/main/java/org/dynmap/bukkit/helper/BukkitVersionHelperGeneric.java index 9ceca8b0..b973db38 100644 --- a/bukkit-helper/src/main/java/org/dynmap/bukkit/helper/BukkitVersionHelperGeneric.java +++ b/bukkit-helper/src/main/java/org/dynmap/bukkit/helper/BukkitVersionHelperGeneric.java @@ -52,6 +52,8 @@ public abstract class BukkitVersionHelperGeneric extends BukkitVersionHelper { protected Field biomebaselist; protected Field biomebasetemp; protected Field biomebasehumi; + protected Method biomebasetempfunc; + protected Method biomebasehumifunc; protected Field biomebaseidstring; protected Field biomebaseid; /** n.m.s.World */ @@ -323,11 +325,21 @@ public abstract class BukkitVersionHelperGeneric extends BukkitVersionHelper { } /** Get temperature from biomebase */ public float getBiomeBaseTemperature(Object bb) { - return (Float) getFieldValue(bb, biomebasetemp, 0.5F); + if (biomebasetempfunc != null) { + return (Float) callMethod(bb, biomebasetempfunc, new Object[0], 0.5f); + } + else { + return (Float) getFieldValue(bb, biomebasetemp, 0.5F); + } } /** Get humidity from biomebase */ public float getBiomeBaseHumidity(Object bb) { - return (Float) getFieldValue(bb, biomebasehumi, 0.5F); + if (biomebasehumifunc != null) { + return (Float) callMethod(bb, biomebasehumifunc, new Object[0], 0.5f); + } + else { + return (Float) getFieldValue(bb, biomebasehumi, 0.5F); + } } /** Get ID string from biomebase */ public String getBiomeBaseIDString(Object bb) { diff --git a/settings.gradle b/settings.gradle index 891d375e..b1e9ff21 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,6 +1,7 @@ rootProject.name = 'dynmap-common' include ':spigot' include ':bukkit-helper-113' +include ':bukkit-helper-113-1' include ':bukkit-helper' include ':dynmap-api' include ':DynmapCore' @@ -13,6 +14,7 @@ include ':forge-1.8.9' 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').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 1ab30409..87efcc9c 100644 --- a/spigot/build.gradle +++ b/spigot/build.gradle @@ -17,6 +17,9 @@ dependencies { implementation(project(':bukkit-helper-113')) { transitive = false } + implementation(project(':bukkit-helper-113-1')) { + transitive = false + } } processResources { @@ -42,6 +45,7 @@ shadowJar { include(dependency(":DynmapCore")) include(dependency(':bukkit-helper')) include(dependency(':bukkit-helper-113')) + include(dependency(':bukkit-helper-113-1')) } 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 558b4005..7cc56a8d 100644 --- a/spigot/src/main/java/org/dynmap/bukkit/Helper.java +++ b/spigot/src/main/java/org/dynmap/bukkit/Helper.java @@ -6,6 +6,7 @@ import org.dynmap.bukkit.helper.BukkitVersionHelper; import org.dynmap.bukkit.helper.BukkitVersionHelperCB; import org.dynmap.bukkit.helper.BukkitVersionHelperGlowstone; import org.dynmap.bukkit.helper.v113.BukkitVersionHelperSpigot113; +import org.dynmap.bukkit.helper.v113_1.BukkitVersionHelperSpigot113_1; public class Helper { @@ -31,6 +32,9 @@ public class Helper { Log.info("Loading Glowstone support"); BukkitVersionHelper.helper = new BukkitVersionHelperGlowstone(); } + else if (v.contains("(MC: 1.13.1)")) { + BukkitVersionHelper.helper = new BukkitVersionHelperSpigot113_1(); + } else if (v.contains("(MC: 1.13)")) { BukkitVersionHelper.helper = new BukkitVersionHelperSpigot113(); }