Start 1.18 Spigot work... need to sort through obfuscation bullshit

This commit is contained in:
Mike Primm 2021-11-23 16:43:55 -06:00
parent 0a54f702c5
commit 50e75e17d2
9 changed files with 998 additions and 3 deletions

View File

@ -9,9 +9,9 @@
* [Where to go for questions and discussions](#where-to-go-for-questions-and-discussions)
* [Where to go to make donations](#where-to-go-to-make-donations)
# How to build
Dynmap 3.x+ uses Gradle for building support for all platforms, with all resulting artifacts produced in the /targets directory. Due to Minecraft 1.17.x+ requirements, the developer's
default JDK must be a JDK 16 (or later) versions - older versions will still be compiled
to run on the default JDK for those platforms (JDK 8), as will all common libraries.
Dynmap 3.x+ uses Gradle for building support for all platforms, with all resulting artifacts produced in the /targets directory. Due to Minecraft 1.18.x+ requirements, the developer's
default JDK must be a JDK 17 (or later) versions - older versions will still be compiled
to run on the default JDK for those platforms (JDK 8, or JDK 16 for 1.17.x, and common libraries are built JDK 8.
To build, run:

1
bukkit-helper-118/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build/

1
bukkit-helper-118/bin/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/main/

View File

@ -0,0 +1,32 @@
plugins {
id "io.papermc.paperweight.userdev" version "1.2.0"
}
description = 'bukkit-helper-1.18'
dependencies {
implementation project(':bukkit-helper')
implementation project(':dynmap-api')
implementation project(path: ':DynmapCore', configuration: 'shadow')
paperDevBundle("1.17.1-R0.1-SNAPSHOT")
}
tasks {
// Run reobfJar on build
build {
dependsOn(reobfJar)
}
compileJava {
options.encoding = Charsets.UTF_8.name()
options.release.set(17)
}
javadoc {
options.encoding = Charsets.UTF_8.name()
}
processResources {
filteringCharset = Charsets.UTF_8.name()
}
}

View File

@ -0,0 +1,429 @@
package org.dynmap.bukkit.helper.v118;
import org.bukkit.*;
import org.bukkit.craftbukkit.v1_18_R1.CraftChunk;
import org.bukkit.craftbukkit.v1_18_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.dynmap.DynmapChunk;
import org.dynmap.Log;
import org.dynmap.bukkit.helper.BukkitMaterial;
import org.dynmap.bukkit.helper.BukkitVersionHelper;
import org.dynmap.bukkit.helper.BukkitWorld;
import org.dynmap.bukkit.helper.BukkitVersionHelperGeneric.TexturesPayload;
import org.dynmap.bukkit.helper.v118.MapChunkCache118;
import org.dynmap.renderer.DynmapBlockState;
import org.dynmap.utils.MapChunkCache;
import org.dynmap.utils.Polygon;
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
import com.google.common.base.Charsets;
import com.google.common.collect.Iterables;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParseException;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import com.mojang.authlib.properties.PropertyMap;
import net.minecraft.core.IdMapper;
import net.minecraft.core.Registry;
import net.minecraft.nbt.ByteArrayTag;
import net.minecraft.nbt.ByteTag;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.DoubleTag;
import net.minecraft.nbt.FloatTag;
import net.minecraft.nbt.IntArrayTag;
import net.minecraft.nbt.IntTag;
import net.minecraft.nbt.LongTag;
import net.minecraft.nbt.ShortTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Helper for isolation of bukkit version specific issues
*/
public class BukkitVersionHelperSpigot118 extends BukkitVersionHelper {
public BukkitVersionHelperSpigot118() {
}
/**
* Get block short name list
*/
@Override
public String[] getBlockNames() {
IdMapper<BlockState> bsids = Block.BLOCK_STATE_REGISTRY;
Block baseb = null;
Iterator<BlockState> iter = bsids.iterator();
ArrayList<String> names = new ArrayList<String>();
while (iter.hasNext()) {
BlockState bs = iter.next();
Block b = bs.getBlock();
// If this is new block vs last, it's the base block state
if (b != baseb) {
baseb = b;
continue;
}
String bn = b.getDescriptionId();
if (bn != null) {
names.add(bn);
}
}
return names.toArray(new String[0]);
}
private static Registry<Biome> reg = null;
private static Registry<Biome> getBiomeReg() {
if (reg == null) {
reg = MinecraftServer.getServer().registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY);
}
return reg;
}
private Object[] biomelist;
/**
* Get list of defined biomebase objects
*/
@Override
public Object[] getBiomeBaseList() {
if (biomelist == null) {
biomelist = new Biome[256];
Iterator<Biome> iter = getBiomeReg().iterator();
while (iter.hasNext()) {
Biome b = iter.next();
int bidx = getBiomeReg().getId(b);
if (bidx >= biomelist.length) {
biomelist = Arrays.copyOf(biomelist, bidx + biomelist.length);
}
biomelist[bidx] = b;
}
}
return biomelist;
}
/** Get ID from biomebase */
@Override
public int getBiomeBaseID(Object bb) {
return getBiomeReg().getId((Biome)bb);
}
public static IdentityHashMap<BlockState, DynmapBlockState> dataToState;
/**
* Initialize block states (org.dynmap.blockstate.DynmapBlockState)
*/
@Override
public void initializeBlockStates() {
dataToState = new IdentityHashMap<BlockState, DynmapBlockState>();
HashMap<String, DynmapBlockState> lastBlockState = new HashMap<String, DynmapBlockState>();
IdMapper<BlockState> bsids = Block.BLOCK_STATE_REGISTRY;
Block baseb = null;
Iterator<BlockState> iter = bsids.iterator();
ArrayList<String> names = new ArrayList<String>();
// Loop through block data states
while (iter.hasNext()) {
BlockState bd = iter.next();
String bname = bd.getBlock().getDescriptionId();
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);
}
net.minecraft.world.level.material.Material mat = bd.getMaterial();
DynmapBlockState bs = new DynmapBlockState(lastbs, idx, bname, sb, mat.toString());
if ((!bd.getFluidState().isEmpty()) && ((bd.getBlock() instanceof LiquidBlock) == false)) { // Test if fluid type for block is not empty
bs.setWaterlogged();
}
if (mat == net.minecraft.world.level.material.Material.AIR) { // AIR
bs.setAir();
}
if (mat == net.minecraft.world.level.material.Material.LEAVES) { // LEAVES
bs.setLeaves();
}
if (mat == net.minecraft.world.level.material.Material.WOOD) { // WOOD
bs.setLog();
}
if (mat.isSolid()) {
bs.setSolid();
}
dataToState.put(bd, bs);
lastBlockState.put(bname, (lastbs == null) ? bs : lastbs);
Log.verboseinfo("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<DynmapChunk> chunks) {
MapChunkCache118 c = new MapChunkCache118();
c.setChunks(dw, chunks);
return c;
}
/**
* Get biome base water multiplier
*/
@Override
public int getBiomeBaseWaterMult(Object bb) {
Biome biome = (Biome) bb;
return biome.getWaterColor(); // waterColor
}
/** Get temperature from biomebase */
@Override
public float getBiomeBaseTemperature(Object bb) {
return ((Biome)bb).getBaseTemperature();
}
/** Get humidity from biomebase */
@Override
public float getBiomeBaseHumidity(Object bb) {
return ((Biome)bb).getDownfall();
}
@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;
}
// Send title/subtitle to user
public void sendTitleText(Player p, String title, String subtitle, int fadeInTicks, int stayTicks, int fadeOutTIcks) {
if (p != null) {
p.sendTitle(title, subtitle, fadeInTicks, stayTicks, fadeOutTIcks);
}
}
/**
* Get material map by block ID
*/
@Override
public BukkitMaterial[] getMaterialList() {
return new BukkitMaterial[4096]; // Not used
}
@Override
public void unloadChunkNoSave(World w, org.bukkit.Chunk c, int cx, int cz) {
Log.severe("unloadChunkNoSave not implemented");
}
private String[] biomenames;
@Override
public String[] getBiomeNames() {
if (biomenames == null) {
biomenames = new String[256];
Iterator<Biome> iter = getBiomeReg().iterator();
while (iter.hasNext()) {
Biome b = iter.next();
int bidx = getBiomeReg().getId(b);
if (bidx >= biomenames.length) {
biomenames = Arrays.copyOf(biomenames, bidx + biomenames.length);
}
biomenames[bidx] = b.toString();
}
}
return biomenames;
}
@Override
public String getStateStringByCombinedId(int blkid, int meta) {
Log.severe("getStateStringByCombinedId not implemented");
return null;
}
@Override
/** Get ID string from biomebase */
public String getBiomeBaseIDString(Object bb) {
String s = ((Biome)bb).toString();
if (s != null) {
String[] ss = s.split("\\.");
return ss[ss.length-1];
}
return null;
}
@Override
public Object getUnloadQueue(World world) {
System.out.println("getUnloadQueue not implemented yet");
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isInUnloadQueue(Object unloadqueue, int x, int z) {
System.out.println("isInUnloadQueue not implemented yet");
// TODO Auto-generated method stub
return false;
}
@Override
public Object[] getBiomeBaseFromSnapshot(ChunkSnapshot css) {
System.out.println("getBiomeBaseFromSnapshot not implemented yet");
// TODO Auto-generated method stub
return new Object[256];
}
@Override
public long getInhabitedTicks(Chunk c) {
return ((CraftChunk)c).getHandle().getInhabitedTime();
}
@Override
public Map<?, ?> getTileEntitiesForChunk(Chunk c) {
return ((CraftChunk)c).getHandle().blockEntities;
}
@Override
public int getTileEntityX(Object te) {
BlockEntity tileent = (BlockEntity) te;
return tileent.getBlockPos().getX();
}
@Override
public int getTileEntityY(Object te) {
BlockEntity tileent = (BlockEntity) te;
return tileent.getBlockPos().getY();
}
@Override
public int getTileEntityZ(Object te) {
BlockEntity tileent = (BlockEntity) te;
return tileent.getBlockPos().getZ();
}
@Override
public Object readTileEntityNBT(Object te) {
BlockEntity tileent = (BlockEntity) te;
CompoundTag nbt = tileent.saveWithId();
return nbt;
}
@Override
public Object getFieldValue(Object nbt, String field) {
CompoundTag rec = (CompoundTag) nbt;
Tag val = rec.get(field);
if(val == null) return null;
if(val instanceof ByteTag) {
return ((ByteTag)val).getAsByte();
}
else if(val instanceof ShortTag) {
return ((ShortTag)val).getAsShort();
}
else if(val instanceof IntTag) {
return ((IntTag)val).getAsInt();
}
else if(val instanceof LongTag) {
return ((LongTag)val).getAsLong();
}
else if(val instanceof FloatTag) {
return ((FloatTag)val).getAsFloat();
}
else if(val instanceof DoubleTag) {
return ((DoubleTag)val).getAsDouble();
}
else if(val instanceof ByteArrayTag) {
return ((ByteArrayTag)val).getAsByteArray();
}
else if(val instanceof StringTag) {
return ((StringTag)val).getAsString();
}
else if(val instanceof IntArrayTag) {
return ((IntArrayTag)val).getAsIntArray();
}
return null;
}
@Override
public Player[] getOnlinePlayers() {
Collection<? extends Player> p = Bukkit.getServer().getOnlinePlayers();
return p.toArray(new Player[0]);
}
@Override
public double getHealth(Player p) {
return p.getHealth();
}
private static final Gson gson = new GsonBuilder().create();
/**
* Get skin URL for player
* @param player
*/
@Override
public String getSkinURL(Player player) {
String url = null;
CraftPlayer cp = (CraftPlayer)player;
GameProfile profile = cp.getProfile();
if (profile != null) {
PropertyMap pm = profile.getProperties();
if (pm != null) {
Collection<Property> txt = pm.get("textures");
Property textureProperty = Iterables.getFirst(pm.get("textures"), null);
if (textureProperty != null) {
String val = textureProperty.getValue();
if (val != null) {
TexturesPayload result = null;
try {
String json = new String(Base64Coder.decode(val), Charsets.UTF_8);
result = gson.fromJson(json, TexturesPayload.class);
} catch (JsonParseException e) {
} catch (IllegalArgumentException x) {
Log.warning("Malformed response from skin URL check: " + val);
}
if ((result != null) && (result.textures != null) && (result.textures.containsKey("SKIN"))) {
url = result.textures.get("SKIN").url;
}
}
}
}
}
return url;
}
// Get minY for world
@Override
public int getWorldMinY(World w) {
CraftWorld cw = (CraftWorld) w;
return cw.getMinHeight();
}
}

View File

@ -0,0 +1,514 @@
package org.dynmap.bukkit.helper.v118;
import org.bukkit.ChunkSnapshot;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.v1_18_R1.CraftWorld;
import org.dynmap.DynmapChunk;
import org.dynmap.DynmapCore;
import org.dynmap.bukkit.helper.AbstractMapChunkCache;
import org.dynmap.bukkit.helper.BukkitVersionHelper;
import org.dynmap.bukkit.helper.SnapshotCache;
import org.dynmap.bukkit.helper.SnapshotCache.SnapshotRec;
import org.dynmap.renderer.DynmapBlockState;
import org.dynmap.utils.DataBitsPacked;
import org.dynmap.utils.DynIntHashMap;
import org.dynmap.utils.VisibilityLimit;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.util.BitStorage;
import net.minecraft.util.SimpleBitStorage;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.storage.ChunkSerializer;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
/**
* Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread
*/
public class MapChunkCache118 extends AbstractMapChunkCache {
public static class NBTSnapshot implements Snapshot {
private static interface Section {
public DynmapBlockState getBlockType(int x, int y, int z);
public int getBlockSkyLight(int x, int y, int z);
public int getBlockEmittedLight(int x, int y, int z);
public boolean isEmpty();
}
private final int x, z;
private final Section[] section;
private final int sectionOffset;
private final int[] hmap; // Height map
private final int[] biome;
private final Object[] biomebase;
private final long captureFulltime;
private final int sectionCnt;
private final long inhabitedTicks;
private static final int BLOCKS_PER_SECTION = 16 * 16 * 16;
private static final int COLUMNS_PER_CHUNK = 16 * 16;
private static final int V1_15_BIOME_PER_CHUNK = 4 * 4 * 64;
private static final byte[] emptyData = new byte[BLOCKS_PER_SECTION / 2];
private static final byte[] fullData = new byte[BLOCKS_PER_SECTION / 2];
static
{
Arrays.fill(fullData, (byte)0xFF);
}
private static byte[] dataCopy(byte[] v) {
if (Arrays.equals(v, emptyData))
return emptyData;
else if (Arrays.equals(v, fullData))
return fullData;
else
return v.clone();
}
private static class EmptySection implements Section {
@Override
public DynmapBlockState getBlockType(int x, int y, int z) {
return DynmapBlockState.AIR;
}
@Override
public int getBlockSkyLight(int x, int y, int z) {
return 15;
}
@Override
public int getBlockEmittedLight(int x, int y, int z) {
return 0;
}
@Override
public boolean isEmpty() {
return true;
}
}
private static final EmptySection empty_section = new EmptySection();
private static class StdSection implements Section {
DynmapBlockState[] states;
byte[] skylight;
byte[] emitlight;
public StdSection() {
states = new DynmapBlockState[BLOCKS_PER_SECTION];
Arrays.fill(states, DynmapBlockState.AIR);
skylight = emptyData;
emitlight = emptyData;
}
@Override
public DynmapBlockState getBlockType(int x, int y, int z) {
return states[((y & 0xF) << 8) | (z << 4) | x];
}
@Override
public int getBlockSkyLight(int x, int y, int z) {
int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1);
return (skylight[off] >> (4 * (x & 1))) & 0xF;
}
@Override
public int getBlockEmittedLight(int x, int y, int z)
{
int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1);
return (emitlight[off] >> (4 * (x & 1))) & 0xF;
}
@Override
public boolean isEmpty() {
return false;
}
}
/**
* Construct empty chunk snapshot
*
* @param x
* @param z
*/
public NBTSnapshot(int worldheight, int x, int z, long captime, long inhabitedTime)
{
this.x = x;
this.z = z;
this.captureFulltime = captime;
this.biome = new int[COLUMNS_PER_CHUNK];
this.biomebase = new Object[COLUMNS_PER_CHUNK];
this.sectionCnt = worldheight / 16;
/* Allocate arrays indexed by section */
this.section = new Section[this.sectionCnt+1];
this.sectionOffset = 0;
/* Fill with empty data */
for (int i = 0; i <= this.sectionCnt; i++) {
this.section[i] = empty_section;
}
/* Create empty height map */
this.hmap = new int[16 * 16];
this.inhabitedTicks = inhabitedTime;
}
public NBTSnapshot(CompoundTag nbt, int worldheight) {
this.x = nbt.getInt("xPos");
this.z = nbt.getInt("zPos");
this.captureFulltime = 0;
this.hmap = nbt.getIntArray("HeightMap");
this.sectionCnt = worldheight / 16;
if (nbt.contains("InhabitedTime")) {
this.inhabitedTicks = nbt.getLong("InhabitedTime");
}
else {
this.inhabitedTicks = 0;
}
/* Allocate arrays indexed by section */
LinkedList<Section> sections = new LinkedList<Section>();
int sectoff = 0; // Default to zero
int sectcnt = 0;
/* Fill with empty data */
for (int i = 0; i <= this.sectionCnt; i++) {
sections.add(empty_section);
sectcnt++;
}
/* Get sections */
ListTag sect = nbt.getList("Sections", 10);
for (int i = 0; i < sect.size(); i++) {
CompoundTag sec = sect.getCompound(i);
int secnum = sec.getByte("Y");
// Beyond end - extend up
while (secnum >= (sectcnt - sectoff)) {
sections.addLast(empty_section); // Pad with empty
sectcnt++;
}
// Negative - see if we need to extend sectionOffset
while ((secnum + sectoff) < 0) {
sections.addFirst(empty_section); // Pad with empty
sectoff++;
sectcnt++;
}
//System.out.println("section(" + secnum + ")=" + sec.asString());
// Create normal section to initialize
StdSection cursect = new StdSection();
sections.set(secnum + sectoff, cursect);
DynmapBlockState[] states = cursect.states;
DynmapBlockState[] palette = null;
// If we've got palette and block states list, process non-empty section
if (sec.contains("Palette", 9) && sec.contains("BlockStates", 12)) {
ListTag plist = sec.getList("Palette", 10);
long[] statelist = sec.getLongArray("BlockStates");
palette = new DynmapBlockState[plist.size()];
for (int pi = 0; pi < plist.size(); pi++) {
CompoundTag tc = plist.getCompound(pi);
String pname = tc.getString("Name");
if (tc.contains("Properties")) {
StringBuilder statestr = new StringBuilder();
CompoundTag prop = tc.getCompound("Properties");
for (String pid : prop.getAllKeys()) {
if (statestr.length() > 0) statestr.append(',');
statestr.append(pid).append('=').append(prop.get(pid).getAsString());
}
palette[pi] = DynmapBlockState.getStateByNameAndState(pname, statestr.toString());
}
if (palette[pi] == null) {
palette[pi] = DynmapBlockState.getBaseStateByName(pname);
}
if (palette[pi] == null) {
palette[pi] = DynmapBlockState.AIR;
}
}
int recsperblock = (4096 + statelist.length - 1) / statelist.length;
int bitsperblock = 64 / recsperblock;
BitStorage db = null;
DataBitsPacked dbp = null;
try {
db = new SimpleBitStorage(bitsperblock, 4096, statelist);
} catch (Exception x) { // Handle legacy encoded
bitsperblock = (statelist.length * 64) / 4096;
dbp = new DataBitsPacked(bitsperblock, 4096, statelist);
}
if (bitsperblock > 8) { // Not palette
for (int j = 0; j < 4096; j++) {
int v = (dbp != null) ? dbp.getAt(j) : db.get(j);
states[j] = DynmapBlockState.getStateByGlobalIndex(v);
}
}
else {
for (int j = 0; j < 4096; j++) {
int v = (dbp != null) ? dbp.getAt(j) : db.get(j);
states[j] = (v < palette.length) ? palette[v] : DynmapBlockState.AIR;
}
}
}
if (sec.contains("BlockLight")) {
cursect.emitlight = dataCopy(sec.getByteArray("BlockLight"));
}
if (sec.contains("SkyLight")) {
cursect.skylight = dataCopy(sec.getByteArray("SkyLight"));
}
}
/* Get biome data */
this.biome = new int[COLUMNS_PER_CHUNK];
this.biomebase = new Object[COLUMNS_PER_CHUNK];
Object[] bbl = BukkitVersionHelper.helper.getBiomeBaseList();
if (nbt.contains("Biomes")) {
int[] bb = nbt.getIntArray("Biomes");
if (bb != null) {
// If v1.15+ format
if (bb.length > COLUMNS_PER_CHUNK) {
// For now, just pad the grid with the first 16
for (int i = 0; i < COLUMNS_PER_CHUNK; i++) {
int off = ((i >> 4) & 0xC) + ((i >> 2) & 0x3);
int bv = bb[off + 64]; // Offset to y=64
if (bv < 0) bv = 0;
this.biome[i] = bv;
this.biomebase[i] = bbl[bv];
}
}
else { // Else, older chunks
for (int i = 0; i < bb.length; i++) {
int bv = bb[i];
if (bv < 0) bv = 0;
this.biome[i] = bv;
this.biomebase[i] = bbl[bv];
}
}
}
}
// Finalize sections array
this.section = sections.toArray(new Section[sections.size()]);
this.sectionOffset = sectoff;
}
public int getX()
{
return x;
}
public int getZ()
{
return z;
}
public DynmapBlockState getBlockType(int x, int y, int z)
{
int idx = (y >> 4) + sectionOffset;
if ((idx < 0) || (idx >= section.length)) return DynmapBlockState.AIR;
return section[idx].getBlockType(x, y, z);
}
public int getBlockSkyLight(int x, int y, int z)
{
int idx = (y >> 4) + sectionOffset;
if ((idx < 0) || (idx >= section.length)) return 15;
return section[idx].getBlockSkyLight(x, y, z);
}
public int getBlockEmittedLight(int x, int y, int z)
{
int idx = (y >> 4) + sectionOffset;
if ((idx < 0) || (idx >= section.length)) return 0;
return section[idx].getBlockEmittedLight(x, y, z);
}
public int getHighestBlockYAt(int x, int z)
{
return hmap[z << 4 | x];
}
public final long getCaptureFullTime()
{
return captureFulltime;
}
public boolean isSectionEmpty(int sy)
{
int idx = sy + sectionOffset;
if ((idx < 0) || (idx >= section.length)) return true;
return section[idx].isEmpty();
}
public long getInhabitedTicks() {
return inhabitedTicks;
}
@Override
public Biome getBiome(int x, int z) {
return AbstractMapChunkCache.getBiomeByID(biome[z << 4 | x]);
}
@Override
public Object[] getBiomeBaseFromSnapshot() {
return this.biomebase;
}
}
private CompoundTag fetchLoadedChunkNBT(World w, int x, int z) {
CraftWorld cw = (CraftWorld) w;
CompoundTag nbt = null;
if (cw.isChunkLoaded(x, z)) {
LevelChunk c = cw.getHandle().getChunk(x, z);
if ((c != null) && c.loaded) { // c.loaded
nbt = ChunkSerializer.write(cw.getHandle(), c);
}
}
if (nbt != null) {
nbt = nbt.getCompound("Level");
if (nbt != null) {
String stat = nbt.getString("Status");
ChunkStatus cs = ChunkStatus.byName(stat);
if ((stat == null) || (!cs.isOrAfter(ChunkStatus.LIGHT))) { // ChunkStatus.LIGHT
nbt = null;
}
}
}
return nbt;
}
private CompoundTag loadChunkNBT(World w, int x, int z) {
CraftWorld cw = (CraftWorld) w;
CompoundTag nbt = null;
ChunkPos cc = new ChunkPos(x, z);
try {
nbt = cw.getHandle().getChunkSource().chunkMap.read(cc); // playerChunkMap
} catch (IOException iox) {
}
if (nbt != null) {
nbt = nbt.getCompound("Level");
if (nbt != null) {
String stat = nbt.getString("Status");
if ((stat == null) || (stat.equals("full") == false)) {
nbt = null;
if ((stat == null) || stat.equals("") && DynmapCore.migrateChunks()) {
LevelChunk c = cw.getHandle().getChunk(x, z);
if (c != null) {
nbt = fetchLoadedChunkNBT(w, x, z);
cw.getHandle().unload(c);
}
}
}
}
}
return nbt;
}
@Override
public Snapshot wrapChunkSnapshot(ChunkSnapshot css) {
// TODO Auto-generated method stub
return null;
}
// Load chunk snapshots
@Override
public int loadChunks(int max_to_load) {
if(dw.isLoaded() == false)
return 0;
int cnt = 0;
if(iterator == null)
iterator = chunks.listIterator();
DynmapCore.setIgnoreChunkLoads(true);
// Load the required chunks.
while((cnt < max_to_load) && iterator.hasNext()) {
long startTime = System.nanoTime();
DynmapChunk chunk = iterator.next();
boolean vis = true;
if(visible_limits != null) {
vis = false;
for(VisibilityLimit limit : visible_limits) {
if (limit.doIntersectChunk(chunk.x, chunk.z)) {
vis = true;
break;
}
}
}
if(vis && (hidden_limits != null)) {
for(VisibilityLimit limit : hidden_limits) {
if (limit.doIntersectChunk(chunk.x, chunk.z)) {
vis = false;
break;
}
}
}
/* Check if cached chunk snapshot found */
Snapshot ss = null;
long inhabited_ticks = 0;
DynIntHashMap tileData = null;
int idx = (chunk.x-x_min) + (chunk.z - z_min)*x_dim;
SnapshotRec ssr = SnapshotCache.sscache.getSnapshot(dw.getName(), chunk.x, chunk.z, blockdata, biome, biomeraw, highesty);
if(ssr != null) {
inhabited_ticks = ssr.inhabitedTicks;
if(!vis) {
if(hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN)
ss = STONE;
else if(hidestyle == HiddenChunkStyle.FILL_OCEAN)
ss = OCEAN;
else
ss = EMPTY;
}
else {
ss = ssr.ss;
}
snaparray[idx] = ss;
snaptile[idx] = ssr.tileData;
inhabitedTicks[idx] = inhabited_ticks;
endChunkLoad(startTime, ChunkStats.CACHED_SNAPSHOT_HIT);
continue;
}
// Fetch NTB for chunk if loaded
CompoundTag nbt = fetchLoadedChunkNBT(w, chunk.x, chunk.z);
boolean did_load = false;
if (nbt == null) {
// Load NTB for chunk, if it exists
nbt = loadChunkNBT(w, chunk.x, chunk.z);
did_load = true;
}
if (nbt != null) {
NBTSnapshot nss = new NBTSnapshot(nbt, w.getMaxHeight());
ss = nss;
inhabited_ticks = nss.getInhabitedTicks();
if(!vis) {
if(hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN)
ss = STONE;
else if(hidestyle == HiddenChunkStyle.FILL_OCEAN)
ss = OCEAN;
else
ss = EMPTY;
}
}
else {
ss = EMPTY;
}
ssr = new SnapshotRec();
ssr.ss = ss;
ssr.inhabitedTicks = inhabited_ticks;
ssr.tileData = tileData;
SnapshotCache.sscache.putSnapshot(dw.getName(), chunk.x, chunk.z, ssr, blockdata, biome, biomeraw, highesty);
snaparray[idx] = ss;
snaptile[idx] = ssr.tileData;
inhabitedTicks[idx] = inhabited_ticks;
if (nbt == null)
endChunkLoad(startTime, ChunkStats.UNGENERATED_CHUNKS);
else if (did_load)
endChunkLoad(startTime, ChunkStats.UNLOADED_CHUNKS);
else
endChunkLoad(startTime, ChunkStats.LOADED_CHUNKS);
cnt++;
}
DynmapCore.setIgnoreChunkLoads(false);
if(iterator.hasNext() == false) { /* If we're done */
isempty = true;
/* Fill missing chunks with empty dummy chunk */
for(int i = 0; i < snaparray.length; i++) {
if(snaparray[i] == null)
snaparray[i] = EMPTY;
else if(snaparray[i] != EMPTY)
isempty = false;
}
}
return cnt;
}
}

View File

@ -1,4 +1,12 @@
pluginManagement {
repositories {
gradlePluginPortal()
maven { url "https://papermc.io/repo/repository/maven-public/" }
}
}
rootProject.name = 'dynmap-common'
include ':spigot'
include ':bukkit-helper-113-2'
include ':bukkit-helper-114-1'
@ -8,6 +16,7 @@ include ':bukkit-helper-116-2'
include ':bukkit-helper-116-3'
include ':bukkit-helper-116-4'
include ':bukkit-helper-117'
//NOTYET include ':bukkit-helper-118'
include ':bukkit-helper'
include ':dynmap-api'
include ':DynmapCore'
@ -31,6 +40,7 @@ project(':bukkit-helper-116-2').projectDir = "$rootDir/bukkit-helper-116-2" as F
project(':bukkit-helper-116-3').projectDir = "$rootDir/bukkit-helper-116-3" as File
project(':bukkit-helper-116-4').projectDir = "$rootDir/bukkit-helper-116-4" as File
project(':bukkit-helper-117').projectDir = "$rootDir/bukkit-helper-117" as File
//NOTYET project(':bukkit-helper-118').projectDir = "$rootDir/bukkit-helper-118" 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

View File

@ -50,6 +50,9 @@ dependencies {
implementation(project(':bukkit-helper-117')) {
transitive = false
}
//NOTYET implementation(project(':bukkit-helper-118')) {
//NOTYET transitive = false
//NOTYET }
}
processResources {
@ -81,6 +84,7 @@ shadowJar {
include(dependency(':bukkit-helper-116-3'))
include(dependency(':bukkit-helper-116-4'))
include(dependency(':bukkit-helper-117'))
//NOTYET include(dependency(':bukkit-helper-118'))
}
relocate('org.bstats', 'org.dynmap.bstats')
destinationDir = file '../target'

View File

@ -13,6 +13,7 @@ import org.dynmap.bukkit.helper.v116_2.BukkitVersionHelperSpigot116_2;
import org.dynmap.bukkit.helper.v116_3.BukkitVersionHelperSpigot116_3;
import org.dynmap.bukkit.helper.v116_4.BukkitVersionHelperSpigot116_4;
import org.dynmap.bukkit.helper.v117.BukkitVersionHelperSpigot117;
//NOTYET import org.dynmap.bukkit.helper.v118.BukkitVersionHelperSpigot118;
public class Helper {
@ -38,6 +39,9 @@ public class Helper {
Log.info("Loading Glowstone support");
BukkitVersionHelper.helper = new BukkitVersionHelperGlowstone();
}
//NOTYET else if (v.contains("(MC: 1.18")) {
//NOTYET BukkitVersionHelper.helper = new BukkitVersionHelperSpigot118();
//NOTYET }
else if (v.contains("(MC: 1.17")) {
BukkitVersionHelper.helper = new BukkitVersionHelperSpigot117();
}