Merge remote-tracking branch 'origin/v3.0' into fabric

# Conflicts:
#	settings.gradle
This commit is contained in:
Pierre Kisters 2020-08-21 00:33:14 +02:00
commit 86f5179ce1
98 changed files with 6741 additions and 37 deletions

View File

@ -1394,6 +1394,11 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
sender.sendMessage("Error: invalid set - " + setid); sender.sendMessage("Error: invalid set - " + setid);
return true; return true;
} }
// Prevent adding persistent markers to a non-persistent set
if (!set.isMarkerSetPersistent()) {
sender.sendMessage("Error: cannot add to non-persistent marker set - set is likely plugin owned");
return true;
}
MarkerIcon ico = null; MarkerIcon ico = null;
if(iconid == null) { if(iconid == null) {
ico = set.getDefaultMarkerIcon(); ico = set.getDefaultMarkerIcon();
@ -1932,6 +1937,9 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
if (set.getMaxZoom() >= 0) { if (set.getMaxZoom() >= 0) {
msg += ", maxzoom:" + set.getMaxZoom(); msg += ", maxzoom:" + set.getMaxZoom();
} }
if (set.isMarkerSetPersistent()) {
msg += ", persistent=true";
}
sender.sendMessage(msg); sender.sendMessage(msg);
} }
return true; return true;
@ -2193,6 +2201,11 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
sender.sendMessage("Error: invalid set - " + setid); sender.sendMessage("Error: invalid set - " + setid);
return true; return true;
} }
// Prevent adding persistent markers to a non-persistent set
if (!set.isMarkerSetPersistent()) {
sender.sendMessage("Error: cannot add to non-persistent marker set - set is likely plugin owned");
return true;
}
/* Make coord list */ /* Make coord list */
double[] xx = new double[ll.size()]; double[] xx = new double[ll.size()];
double[] zz = new double[ll.size()]; double[] zz = new double[ll.size()];
@ -2395,6 +2408,11 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
sender.sendMessage("Error: invalid set - " + setid); sender.sendMessage("Error: invalid set - " + setid);
return true; return true;
} }
// Prevent adding persistent markers to a non-persistent set
if (!set.isMarkerSetPersistent()) {
sender.sendMessage("Error: cannot add to non-persistent marker set - set is likely plugin owned");
return true;
}
/* Make coord list */ /* Make coord list */
double[] xx = new double[ll.size()]; double[] xx = new double[ll.size()];
double[] yy = new double[ll.size()]; double[] yy = new double[ll.size()];
@ -2611,7 +2629,11 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
sender.sendMessage("Error: invalid set - " + setid); sender.sendMessage("Error: invalid set - " + setid);
return true; return true;
} }
// Prevent adding persistent markers to a non-persistent set
if (!set.isMarkerSetPersistent()) {
sender.sendMessage("Error: cannot add to non-persistent marker set - set is likely plugin owned");
return true;
}
/* Make circle marker */ /* Make circle marker */
CircleMarker m = set.createCircleMarker(id, label, "true".equals(markup), loc.world, loc.x, loc.y, loc.z, 1, 1, true); CircleMarker m = set.createCircleMarker(id, label, "true".equals(markup), loc.world, loc.x, loc.y, loc.z, 1, 1, true);
if(m == null) { if(m == null) {

View File

@ -0,0 +1,53 @@
package org.dynmap.utils;
// Pre 1.16 chunk section data array
public class DataBitsPacked {
private final long[] values;
private final int bitsperrec;
private final long valuemask;
private final int length;
public static int calcLongCount(int i, int j) {
if (j == 0) {
return 0;
} else if (i == 0) {
return j;
} else {
if (i < 0) {
j *= -1;
}
int k = i % j;
return k == 0 ? i : i + j - k;
}
}
public DataBitsPacked(int bitsperrec, int length, long[] values) {
this.length = length;
this.bitsperrec = bitsperrec;
this.values = values;
this.valuemask = (1L << bitsperrec) - 1L;
int properlength = calcLongCount(length * bitsperrec, 64) / 64;
if (values.length != properlength) {
throw new IllegalArgumentException("Invalid length given for storage, got: " + values.length + " but expected: " + properlength);
}
}
public int getAt(int offset) {
int j = offset * this.bitsperrec;
int k = j >> 6;
int l = (offset + 1) * this.bitsperrec - 1 >> 6;
int i1 = j ^ k << 6;
if (k == l) {
return (int) (this.values[k] >>> i1 & this.valuemask);
} else {
int j1 = 64 - i1;
return (int) ((this.values[k] >>> i1 | this.values[l] << j1) & this.valuemask);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -278,12 +278,26 @@ DynMap.prototype = {
worldsadded[wname] = true; worldsadded[wname] = true;
} }
var worldName = wname;
var mapName = mapindex;
if (worldName.endsWith('_nether') || (worldName == 'DIM-1')) {
worldName = 'nether';
mapName = (mapindex == 'nether') ? 'surface' : 'flat';
}
else if (worldName.endsWith('the_end') || (worldName == 'DIM1')) {
worldName = 'the_end';
mapName = (mapindex == 'the_end') ? 'surface' : 'flat';
}
else {
worldName = 'world';
mapName = [ 'surface', 'flat', 'biome', 'cave' ].includes(mapindex) ? mapindex : 'flat';
}
map.element = $('<li/>') map.element = $('<li/>')
.addClass('map item') .addClass('map item')
.append($('<a/>') .append($('<a/>')
.attr({ title: map.options.title, href: '#' }) .attr({ title: map.options.title, href: '#' })
.addClass('maptype') .addClass('maptype')
.css({ backgroundImage: 'url(' + (map.options.icon || ('images/block_' + mapindex + '.png')) + ')' }) .css({ backgroundImage: 'url(' + (map.options.icon || ('images/block_' + worldName + '_' + mapName + '.png')) + ')' })
.text(map.options.title) .text(map.options.title)
) )
.click(function() { .click(function() {

View File

@ -115,9 +115,9 @@ worlds:
# background: "#300806" # background: "#300806"
# mapzoomin: 1 # mapzoomin: 1
# - class: org.dynmap.hdmap.HDMap # - class: org.dynmap.hdmap.HDMap
# name: nether # name: surface
# title: "Surface" # title: "Surface"
# prefix: nt # prefix: surface
# perspective: iso_SE_30_hires # perspective: iso_SE_30_hires
# shader: stdtexture # shader: stdtexture
# lighting: nethershadows # lighting: nethershadows

4
bukkit-helper-116-2/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/target/
/build/
/bin/
/.classpath

View File

@ -0,0 +1,10 @@
description = 'bukkit-helper-1.16'
dependencies {
compile project(':bukkit-helper')
compile project(':dynmap-api')
compile project(path: ':DynmapCore', configuration: 'shadow')
compile group: 'org.spigotmc', name: 'spigot-api', version:'1.16.2-R0.1-SNAPSHOT'
compile group: 'org.spigotmc', name: 'spigot', version:'1.16.2-R0.1-SNAPSHOT'
}

View File

@ -0,0 +1,271 @@
package org.dynmap.bukkit.helper.v116_2;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
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.bukkit.entity.Player;
import org.dynmap.DynmapChunk;
import org.dynmap.Log;
import org.dynmap.bukkit.helper.BukkitMaterial;
import org.dynmap.bukkit.helper.BukkitVersionHelperCB;
import org.dynmap.bukkit.helper.BukkitVersionHelperGeneric;
import org.dynmap.bukkit.helper.BukkitWorld;
import org.dynmap.bukkit.helper.v116_2.MapChunkCache116_2;
import org.dynmap.renderer.DynmapBlockState;
import org.dynmap.utils.MapChunkCache;
import org.dynmap.utils.Polygon;
import net.minecraft.server.v1_16_R2.BiomeBase;
import net.minecraft.server.v1_16_R2.BiomeFog;
import net.minecraft.server.v1_16_R2.Block;
import net.minecraft.server.v1_16_R2.BlockFluids;
import net.minecraft.server.v1_16_R2.BlockRotatable;
import net.minecraft.server.v1_16_R2.IBlockData;
import net.minecraft.server.v1_16_R2.IRegistry;
import net.minecraft.server.v1_16_R2.Material;
import net.minecraft.server.v1_16_R2.MinecraftServer;
/**
* Helper for isolation of bukkit version specific issues
*/
public class BukkitVersionHelperSpigot116_2 extends BukkitVersionHelperGeneric {
private Field watercolorfield;
public BukkitVersionHelperSpigot116_2() {
Class biomefog = getNMSClass("net.minecraft.server.BiomeFog");
watercolorfield = getPrivateField(biomefog, new String[] { "c" }, int.class);
}
/**
* 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;
}
private IRegistry<BiomeBase> reg = null;
private IRegistry<BiomeBase> getBiomeReg() {
if (reg == null) {
reg = MinecraftServer.getServer().aX().b(IRegistry.ay);
}
return reg;
}
private Object[] biomelist;
/**
* Get list of defined biomebase objects
*/
@Override
public Object[] getBiomeBaseList() {
if (biomelist == null) {
biomelist = new Object[1024];
for (int i = 0; i < 1024; i++) {
biomelist[i] = getBiomeReg().fromId(i);
}
}
return biomelist;
}
/** Get ID from biomebase */
@Override
public int getBiomeBaseID(Object bb) {
return getBiomeReg().a((BiomeBase)bb);
}
public static IdentityHashMap<IBlockData, DynmapBlockState> dataToState;
/**
* Initialize block states (org.dynmap.blockstate.DynmapBlockState)
*/
@Override
public void initializeBlockStates() {
dataToState = new IdentityHashMap<IBlockData, DynmapBlockState>();
HashMap<String, DynmapBlockState> lastBlockState = new HashMap<String, DynmapBlockState>();
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.getFluid().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 BlockRotatable) && (bd.getMaterial() == Material.WOOD)) {
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<DynmapChunk> chunks) {
MapChunkCache116_2 c = new MapChunkCache116_2();
c.setChunks(dw, chunks);
return c;
}
/**
* Get biome base water multiplier
*/
@Override
public int getBiomeBaseWaterMult(Object bb) {
try {
return (int) watercolorfield.get(((BiomeBase)bb).l());
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
return 0xFFFFFF;
}
/** Get temperature from biomebase */
@Override
public float getBiomeBaseTemperature(Object bb) {
return ((BiomeBase)bb).k();
}
/** Get humidity from biomebase */
@Override
public float getBiomeBaseHumidity(Object bb) {
return ((BiomeBase)bb).getHumidity();
}
@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
protected void loadNMS() {
// Not needed
}
@Override
protected String getNMSPackage() {
Server srv = Bukkit.getServer();
/* Get getHandle() method */
try {
Method m = srv.getClass().getMethod("getHandle");
Object scm = m.invoke(srv); /* And use it to get SCM (nms object) */
return scm.getClass().getPackage().getName();
} catch (Exception x) {
Log.severe("Error finding net.minecraft.server packages");
return null;
}
}
@Override
public void unloadChunkNoSave(World w, Chunk c, int cx, int cz) {
Log.severe("unloadChunkNoSave not implemented");
}
private String[] biomenames;
@Override
public String[] getBiomeNames() {
if (biomenames == null) {
biomenames = new String[1024];
for (int i = 0; i < 1024; i++) {
BiomeBase bb = getBiomeReg().fromId(i);
if (bb != null) {
biomenames[i] = bb.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 = ((BiomeBase)bb).toString();
if (s != null) {
String[] ss = s.split("\\.");
return ss[ss.length-1];
}
return null;
}
}

View File

@ -0,0 +1,493 @@
package org.dynmap.bukkit.helper.v116_2;
import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.v1_16_R2.CraftWorld;
import java.io.IOException;
import java.util.Arrays;
import org.bukkit.ChunkSnapshot;
import org.bukkit.World;
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.DynIntHashMap;
import org.dynmap.utils.VisibilityLimit;
import net.minecraft.server.v1_16_R2.Chunk;
import net.minecraft.server.v1_16_R2.ChunkCoordIntPair;
import net.minecraft.server.v1_16_R2.ChunkRegionLoader;
import net.minecraft.server.v1_16_R2.ChunkStatus;
import net.minecraft.server.v1_16_R2.DataBits;
import net.minecraft.server.v1_16_R2.DataBitsPacked;
import net.minecraft.server.v1_16_R2.NBTTagCompound;
import net.minecraft.server.v1_16_R2.NBTTagList;
/**
* Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread
*/
public class MapChunkCache116_2 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[] 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];
/* 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(NBTTagCompound 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.hasKey("InhabitedTime")) {
this.inhabitedTicks = nbt.getLong("InhabitedTime");
}
else {
this.inhabitedTicks = 0;
}
/* Allocate arrays indexed by section */
this.section = new Section[this.sectionCnt];
/* Fill with empty data */
for (int i = 0; i < this.sectionCnt; i++) {
this.section[i] = empty_section;
}
/* Get sections */
NBTTagList sect = nbt.getList("Sections", 10);
for (int i = 0; i < sect.size(); i++) {
NBTTagCompound sec = sect.getCompound(i);
int secnum = sec.getByte("Y");
if (secnum >= this.sectionCnt) {
//Log.info("Section " + (int) secnum + " above world height " + worldheight);
continue;
}
if (secnum < 0)
continue;
//System.out.println("section(" + secnum + ")=" + sec.asString());
// Create normal section to initialize
StdSection cursect = new StdSection();
this.section[secnum] = cursect;
DynmapBlockState[] states = cursect.states;
DynmapBlockState[] palette = null;
// If we've got palette and block states list, process non-empty section
if (sec.hasKeyOfType("Palette", 9) && sec.hasKeyOfType("BlockStates", 12)) {
NBTTagList plist = sec.getList("Palette", 10);
long[] statelist = sec.getLongArray("BlockStates");
palette = new DynmapBlockState[plist.size()];
for (int pi = 0; pi < plist.size(); pi++) {
NBTTagCompound tc = plist.getCompound(pi);
String pname = tc.getString("Name");
if (tc.hasKey("Properties")) {
StringBuilder statestr = new StringBuilder();
NBTTagCompound prop = tc.getCompound("Properties");
for (String pid : prop.getKeys()) {
if (statestr.length() > 0) statestr.append(',');
statestr.append(pid).append('=').append(prop.get(pid).asString());
}
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;
DataBits db = null;
DataBitsPacked dbp = null;
try {
db = new DataBits(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 = (db != null) ? db.a(j) : dbp.a(j);
states[j] = DynmapBlockState.getStateByGlobalIndex(v);
}
}
else {
for (int j = 0; j < 4096; j++) {
int v = (db != null) ? db.a(j) : dbp.a(j);
states[j] = (v < palette.length) ? palette[v] : DynmapBlockState.AIR;
}
}
}
if (sec.hasKey("BlockLight")) {
cursect.emitlight = dataCopy(sec.getByteArray("BlockLight"));
}
if (sec.hasKey("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.hasKey("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];
}
}
}
}
}
public int getX()
{
return x;
}
public int getZ()
{
return z;
}
public DynmapBlockState getBlockType(int x, int y, int z)
{
return section[y >> 4].getBlockType(x, y, z);
}
public int getBlockSkyLight(int x, int y, int z)
{
return section[y >> 4].getBlockSkyLight(x, y, z);
}
public int getBlockEmittedLight(int x, int y, int z)
{
return section[y >> 4].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)
{
return section[sy].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 NBTTagCompound fetchLoadedChunkNBT(World w, int x, int z) {
CraftWorld cw = (CraftWorld) w;
NBTTagCompound nbt = null;
if (cw.isChunkLoaded(x, z)) {
Chunk c = cw.getHandle().getChunkAt(x, z);
if ((c != null) && c.loaded) {
nbt = ChunkRegionLoader.saveChunk(cw.getHandle(), c);
}
}
if (nbt != null) {
nbt = nbt.getCompound("Level");
if (nbt != null) {
String stat = nbt.getString("Status");
ChunkStatus cs = ChunkStatus.a(stat);
if ((stat == null) || (!cs.b(ChunkStatus.LIGHT))) {
nbt = null;
}
}
}
return nbt;
}
private NBTTagCompound loadChunkNBT(World w, int x, int z) {
CraftWorld cw = (CraftWorld) w;
NBTTagCompound nbt = null;
ChunkCoordIntPair cc = new ChunkCoordIntPair(x, z);
try {
nbt = cw.getHandle().getChunkProvider().playerChunkMap.read(cc);
} 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()) {
Chunk c = cw.getHandle().getChunkAt(x, z);
if (c != null) {
nbt = fetchLoadedChunkNBT(w, x, z);
cw.getHandle().unloadChunk(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
NBTTagCompound 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

@ -22,7 +22,7 @@ import org.dynmap.bukkit.helper.BukkitMaterial;
import org.dynmap.bukkit.helper.BukkitVersionHelperCB; import org.dynmap.bukkit.helper.BukkitVersionHelperCB;
import org.dynmap.bukkit.helper.BukkitVersionHelperGeneric; import org.dynmap.bukkit.helper.BukkitVersionHelperGeneric;
import org.dynmap.bukkit.helper.BukkitWorld; import org.dynmap.bukkit.helper.BukkitWorld;
import org.dynmap.bukkit.helper.v116.MapChunkCache115; import org.dynmap.bukkit.helper.v116.MapChunkCache116;
import org.dynmap.renderer.DynmapBlockState; import org.dynmap.renderer.DynmapBlockState;
import org.dynmap.utils.MapChunkCache; import org.dynmap.utils.MapChunkCache;
import org.dynmap.utils.Polygon; import org.dynmap.utils.Polygon;
@ -141,7 +141,7 @@ public class BukkitVersionHelperSpigot116 extends BukkitVersionHelperGeneric {
*/ */
@Override @Override
public MapChunkCache getChunkCache(BukkitWorld dw, List<DynmapChunk> chunks) { public MapChunkCache getChunkCache(BukkitWorld dw, List<DynmapChunk> chunks) {
MapChunkCache115 c = new MapChunkCache115(); MapChunkCache116 c = new MapChunkCache116();
c.setChunks(dw, chunks); c.setChunks(dw, chunks);
return c; return c;
} }

View File

@ -32,7 +32,7 @@ import net.minecraft.server.v1_16_R1.NBTTagList;
/** /**
* Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread * Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread
*/ */
public class MapChunkCache115 extends AbstractMapChunkCache { public class MapChunkCache116 extends AbstractMapChunkCache {
public static class NBTSnapshot implements Snapshot { public static class NBTSnapshot implements Snapshot {
private static interface Section { private static interface Section {

View File

@ -136,7 +136,7 @@ public abstract class BukkitVersionHelperGeneric extends BukkitVersionHelper {
ccss_biome = getPrivateFieldNoFail(craftchunksnapshot, new String[] { "biome" }, biomebasearray); ccss_biome = getPrivateFieldNoFail(craftchunksnapshot, new String[] { "biome" }, biomebasearray);
if(ccss_biome == null) { if(ccss_biome == null) {
biomestorage = getNMSClass("net.minecraft.server.BiomeStorage"); biomestorage = getNMSClass("net.minecraft.server.BiomeStorage");
biomestoragebase = getPrivateField(biomestorage, new String[] { "g", "f" }, biomebasearray); biomestoragebase = getPrivateField(biomestorage, new String[] { "h", "g", "f" }, biomebasearray);
ccss_biome = getPrivateField(craftchunksnapshot, new String[] { "biome" }, biomestorage); ccss_biome = getPrivateField(craftchunksnapshot, new String[] { "biome" }, biomestorage);
} }
/* CraftChunk */ /* CraftChunk */

View File

@ -2,6 +2,7 @@ package org.dynmap.forge_1_13_2;
import java.io.File; import java.io.File;
import org.apache.commons.lang3.tuple.Pair;
import org.dynmap.DynmapCommonAPI; import org.dynmap.DynmapCommonAPI;
import org.dynmap.DynmapCommonAPIListener; import org.dynmap.DynmapCommonAPIListener;
import org.dynmap.Log; import org.dynmap.Log;
@ -12,13 +13,16 @@ import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent; import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent; import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent; import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
import net.minecraftforge.fml.event.server.FMLServerStartedEvent; import net.minecraftforge.fml.event.server.FMLServerStartedEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.network.FMLNetworkConstants;
@Mod("dynmap") @Mod("dynmap")
public class DynmapMod public class DynmapMod
@ -66,6 +70,8 @@ public class DynmapMod
MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(this);
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, () -> Pair.of(() -> FMLNetworkConstants.IGNORESERVERONLY, (a, b) -> true));
Log.setLogger(new OurLog()); Log.setLogger(new OurLog());
org.dynmap.modsupport.ModSupportImpl.init(); org.dynmap.modsupport.ModSupportImpl.init();
} }

View File

@ -455,7 +455,7 @@ public class DynmapPlugin
private boolean hasPerm(EntityPlayer psender, String permission) { private boolean hasPerm(EntityPlayer psender, String permission) {
PermissionsHandler ph = PermissionsHandler.getHandler(); PermissionsHandler ph = PermissionsHandler.getHandler();
if((psender != null) && ph.hasPermission(psender.getEntity().getName().getString(), permission)) { if((psender != null) && (ph != null) && ph.hasPermission(psender.getEntity().getName().getString(), permission)) {
return true; return true;
} }
return permissions.has(psender, permission); return permissions.has(psender, permission);
@ -463,7 +463,7 @@ public class DynmapPlugin
private boolean hasPermNode(EntityPlayer psender, String permission) { private boolean hasPermNode(EntityPlayer psender, String permission) {
PermissionsHandler ph = PermissionsHandler.getHandler(); PermissionsHandler ph = PermissionsHandler.getHandler();
if((psender != null) && ph.hasPermissionNode(psender.getEntity().getName().getString(), permission)) { if((psender != null) && (ph != null) && ph.hasPermissionNode(psender.getEntity().getName().getString(), permission)) {
return true; return true;
} }
return permissions.hasPermissionNode(psender, permission); return permissions.hasPermissionNode(psender, permission);
@ -1594,8 +1594,12 @@ public class DynmapPlugin
{ {
dsender = new ForgeCommandSender(sender); dsender = new ForgeCommandSender(sender);
} }
try {
core.processCommand(dsender, cmd, cmd, args); core.processCommand(dsender, cmd, cmd, args);
} catch (Exception x) {
dsender.sendMessage("Command internal error: " + x.getMessage());
Log.severe("Error with command: " + cmd + Arrays.deepToString(args), x);
}
} }
private DynmapLocation toLoc(World worldObj, double x, double y, double z) private DynmapLocation toLoc(World worldObj, double x, double y, double z)

View File

@ -2,6 +2,7 @@ package org.dynmap.forge_1_14_4;
import java.io.File; import java.io.File;
import org.apache.commons.lang3.tuple.Pair;
import org.dynmap.DynmapCommonAPI; import org.dynmap.DynmapCommonAPI;
import org.dynmap.DynmapCommonAPIListener; import org.dynmap.DynmapCommonAPIListener;
import org.dynmap.Log; import org.dynmap.Log;
@ -12,13 +13,16 @@ import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent; import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent; import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent; import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
import net.minecraftforge.fml.event.server.FMLServerStartedEvent; import net.minecraftforge.fml.event.server.FMLServerStartedEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.network.FMLNetworkConstants;
@Mod("dynmap") @Mod("dynmap")
public class DynmapMod public class DynmapMod
@ -66,6 +70,8 @@ public class DynmapMod
MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(this);
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, () -> Pair.of(() -> FMLNetworkConstants.IGNORESERVERONLY, (a, b) -> true));
Log.setLogger(new OurLog()); Log.setLogger(new OurLog());
org.dynmap.modsupport.ModSupportImpl.init(); org.dynmap.modsupport.ModSupportImpl.init();
} }

View File

@ -481,7 +481,7 @@ public class DynmapPlugin
private boolean hasPerm(PlayerEntity psender, String permission) { private boolean hasPerm(PlayerEntity psender, String permission) {
PermissionsHandler ph = PermissionsHandler.getHandler(); PermissionsHandler ph = PermissionsHandler.getHandler();
if((psender != null) && ph.hasPermission(psender.getEntity().getName().getString(), permission)) { if((psender != null) && (ph != null) && ph.hasPermission(psender.getEntity().getName().getString(), permission)) {
return true; return true;
} }
return permissions.has(psender, permission); return permissions.has(psender, permission);
@ -489,7 +489,7 @@ public class DynmapPlugin
private boolean hasPermNode(PlayerEntity psender, String permission) { private boolean hasPermNode(PlayerEntity psender, String permission) {
PermissionsHandler ph = PermissionsHandler.getHandler(); PermissionsHandler ph = PermissionsHandler.getHandler();
if((psender != null) && ph.hasPermissionNode(psender.getEntity().getName().getString(), permission)) { if((psender != null) && (ph != null) && ph.hasPermissionNode(psender.getEntity().getName().getString(), permission)) {
return true; return true;
} }
return permissions.hasPermissionNode(psender, permission); return permissions.hasPermissionNode(psender, permission);
@ -1620,8 +1620,12 @@ public class DynmapPlugin
{ {
dsender = new ForgeCommandSender(sender); dsender = new ForgeCommandSender(sender);
} }
try {
core.processCommand(dsender, cmd, cmd, args); core.processCommand(dsender, cmd, cmd, args);
} catch (Exception x) {
dsender.sendMessage("Command internal error: " + x.getMessage());
Log.severe("Error with command: " + cmd + Arrays.deepToString(args), x);
}
} }
private DynmapLocation toLoc(World worldObj, double x, double y, double z) private DynmapLocation toLoc(World worldObj, double x, double y, double z)

View File

@ -2,23 +2,28 @@ package org.dynmap.forge_1_15_2;
import java.io.File; import java.io.File;
import org.apache.commons.lang3.tuple.Pair;
import org.dynmap.DynmapCommonAPI; import org.dynmap.DynmapCommonAPI;
import org.dynmap.DynmapCommonAPIListener; import org.dynmap.DynmapCommonAPIListener;
import org.dynmap.Log; import org.dynmap.Log;
import org.dynmap.forge_1_15_2.DynmapPlugin.OurLog; import org.dynmap.forge_1_15_2.DynmapPlugin.OurLog;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent; import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent; import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent; import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
import net.minecraftforge.fml.event.server.FMLServerStartedEvent; import net.minecraftforge.fml.event.server.FMLServerStartedEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.network.FMLNetworkConstants;
@Mod("dynmap") @Mod("dynmap")
public class DynmapMod public class DynmapMod
@ -66,6 +71,8 @@ public class DynmapMod
MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(this);
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, () -> Pair.of(() -> FMLNetworkConstants.IGNORESERVERONLY, (a, b) -> true));
Log.setLogger(new OurLog()); Log.setLogger(new OurLog());
org.dynmap.modsupport.ModSupportImpl.init(); org.dynmap.modsupport.ModSupportImpl.init();
} }

View File

@ -482,7 +482,7 @@ public class DynmapPlugin
private boolean hasPerm(PlayerEntity psender, String permission) { private boolean hasPerm(PlayerEntity psender, String permission) {
PermissionsHandler ph = PermissionsHandler.getHandler(); PermissionsHandler ph = PermissionsHandler.getHandler();
if((psender != null) && ph.hasPermission(psender.getEntity().getName().getString(), permission)) { if((psender != null) && (ph != null) && ph.hasPermission(psender.getEntity().getName().getString(), permission)) {
return true; return true;
} }
return permissions.has(psender, permission); return permissions.has(psender, permission);
@ -490,7 +490,7 @@ public class DynmapPlugin
private boolean hasPermNode(PlayerEntity psender, String permission) { private boolean hasPermNode(PlayerEntity psender, String permission) {
PermissionsHandler ph = PermissionsHandler.getHandler(); PermissionsHandler ph = PermissionsHandler.getHandler();
if((psender != null) && ph.hasPermissionNode(psender.getEntity().getName().getString(), permission)) { if((psender != null) && (ph != null) && ph.hasPermissionNode(psender.getEntity().getName().getString(), permission)) {
return true; return true;
} }
return permissions.hasPermissionNode(psender, permission); return permissions.hasPermissionNode(psender, permission);
@ -1620,8 +1620,12 @@ public class DynmapPlugin
{ {
dsender = new ForgeCommandSender(sender); dsender = new ForgeCommandSender(sender);
} }
try {
core.processCommand(dsender, cmd, cmd, args); core.processCommand(dsender, cmd, cmd, args);
} catch (Exception x) {
dsender.sendMessage("Command internal error: " + x.getMessage());
Log.severe("Error with command: " + cmd + Arrays.deepToString(args), x);
}
} }
private DynmapLocation toLoc(World worldObj, double x, double y, double z) private DynmapLocation toLoc(World worldObj, double x, double y, double z)

View File

@ -4,6 +4,7 @@ import java.util.Arrays;
import org.dynmap.Log; import org.dynmap.Log;
import org.dynmap.renderer.DynmapBlockState; import org.dynmap.renderer.DynmapBlockState;
import org.dynmap.utils.DataBitsPacked;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.ListNBT;
@ -178,16 +179,25 @@ public class ChunkSnapshot
palette[pi] = DynmapBlockState.AIR; palette[pi] = DynmapBlockState.AIR;
} }
} }
int bitsperblock = (statelist.length * 64) / 4096; int recsperblock = (4096 + statelist.length - 1) / statelist.length;
BitArray db = new BitArray(bitsperblock, 4096, statelist); int bitsperblock = 64 / recsperblock;
BitArray db = null;
DataBitsPacked dbp = null;
try {
db = new BitArray(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 if (bitsperblock > 8) { // Not palette
for (int j = 0; j < 4096; j++) { for (int j = 0; j < 4096; j++) {
states[j] = DynmapBlockState.getStateByGlobalIndex(db.getAt(j)); int v = (dbp != null) ? dbp.getAt(j) : db.getAt(j);
states[j] = DynmapBlockState.getStateByGlobalIndex(v);
} }
} }
else { else {
for (int j = 0; j < 4096; j++) { for (int j = 0; j < 4096; j++) {
int v = db.getAt(j); int v = (dbp != null) ? dbp.getAt(j) : db.getAt(j);
states[j] = (v < palette.length) ? palette[v] : DynmapBlockState.AIR; states[j] = (v < palette.length) ? palette[v] : DynmapBlockState.AIR;
} }
} }

View File

@ -2,6 +2,7 @@ package org.dynmap.forge_1_16_1;
import java.io.File; import java.io.File;
import org.apache.commons.lang3.tuple.Pair;
import org.dynmap.DynmapCommonAPI; import org.dynmap.DynmapCommonAPI;
import org.dynmap.DynmapCommonAPIListener; import org.dynmap.DynmapCommonAPIListener;
import org.dynmap.Log; import org.dynmap.Log;
@ -12,13 +13,16 @@ import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent; import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent; import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent; import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
import net.minecraftforge.fml.event.server.FMLServerStartedEvent; import net.minecraftforge.fml.event.server.FMLServerStartedEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.network.FMLNetworkConstants;
@Mod("dynmap") @Mod("dynmap")
public class DynmapMod public class DynmapMod
@ -66,6 +70,8 @@ public class DynmapMod
MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(this);
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, () -> Pair.of(() -> FMLNetworkConstants.IGNORESERVERONLY, (a, b) -> true));
Log.setLogger(new OurLog()); Log.setLogger(new OurLog());
org.dynmap.modsupport.ModSupportImpl.init(); org.dynmap.modsupport.ModSupportImpl.init();
} }

View File

@ -479,7 +479,7 @@ public class DynmapPlugin
private boolean hasPerm(PlayerEntity psender, String permission) { private boolean hasPerm(PlayerEntity psender, String permission) {
PermissionsHandler ph = PermissionsHandler.getHandler(); PermissionsHandler ph = PermissionsHandler.getHandler();
if((psender != null) && ph.hasPermission(psender.getEntity().getName().getString(), permission)) { if ((psender != null) && (ph != null) && ph.hasPermission(psender.getEntity().getName().getString(), permission)) {
return true; return true;
} }
return permissions.has(psender, permission); return permissions.has(psender, permission);
@ -487,7 +487,7 @@ public class DynmapPlugin
private boolean hasPermNode(PlayerEntity psender, String permission) { private boolean hasPermNode(PlayerEntity psender, String permission) {
PermissionsHandler ph = PermissionsHandler.getHandler(); PermissionsHandler ph = PermissionsHandler.getHandler();
if((psender != null) && ph.hasPermissionNode(psender.getEntity().getName().getString(), permission)) { if ((psender != null) && (ph != null) && ph.hasPermissionNode(psender.getEntity().getName().getString(), permission)) {
return true; return true;
} }
return permissions.hasPermissionNode(psender, permission); return permissions.hasPermissionNode(psender, permission);
@ -1288,7 +1288,7 @@ public class DynmapPlugin
public void sendMessage(String msg) public void sendMessage(String msg)
{ {
ITextComponent ichatcomponent = new StringTextComponent(msg); ITextComponent ichatcomponent = new StringTextComponent(msg);
server.getPlayerList().func_232641_a_(ichatcomponent, ChatType.CHAT, player.getUniqueID()); player.sendMessage(ichatcomponent, Util.field_240973_b_);
} }
@Override @Override
public boolean isInvisible() { public boolean isInvisible() {
@ -1617,8 +1617,12 @@ public class DynmapPlugin
{ {
dsender = new ForgeCommandSender(sender); dsender = new ForgeCommandSender(sender);
} }
try {
core.processCommand(dsender, cmd, cmd, args); core.processCommand(dsender, cmd, cmd, args);
} catch (Exception x) {
dsender.sendMessage("Command internal error: " + x.getMessage());
Log.severe("Error with command: " + cmd + Arrays.deepToString(args), x);
}
} }
private DynmapLocation toLoc(World worldObj, double x, double y, double z) private DynmapLocation toLoc(World worldObj, double x, double y, double z)

1
forge-1.16.2/.gitignore vendored Normal file
View File

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

View File

@ -0,0 +1,3 @@
public net.minecraft.world.server.ChunkManager field_219251_e # loaded chunk list
public net.minecraft.world.server.ChunkManager field_219252_f # loaded chunk list
public net.minecraft.world.biome.BiomeAmbience field_235206_c_ # waterColor

View File

@ -0,0 +1,25 @@
modLoader="javafml"
loaderVersion="[32,)"
issueTrackerURL="https://github.com/webbukkit/dynmap/issues"
[[mods]]
modId="dynmap"
version="${version}"
displayName="Dynmap"
authors="mikeprimm"
description='''
Dynamic, Google-maps style rendered maps for your Minecraft server
'''
[[dependencies.dynmap]]
modId="forge"
mandatory=true
versionRange="[32,)"
ordering="NONE"
# Side this dependency is applied on - BOTH, CLIENT or SERVER
side="SERVER"
[[dependencies.dynmap]]
modId="minecraft"
mandatory=true
versionRange="[1.16.1]"
ordering="NONE"
side="SERVER"

View File

@ -0,0 +1,457 @@
# All paths in this configuration file are relative to Dynmap's data-folder: minecraft_server/dynmap/
# All map templates are defined in the templates directory
# To use the HDMap very-low-res (2 ppb) map templates as world defaults, set value to vlowres
# The definitions of these templates are in normal-vlowres.txt, nether-vlowres.txt, and the_end-vlowres.txt
# To use the HDMap low-res (4 ppb) map templates as world defaults, set value to lowres
# The definitions of these templates are in normal-lowres.txt, nether-lowres.txt, and the_end-lowres.txt
# To use the HDMap hi-res (16 ppb) map templates (these can take a VERY long time for initial fullrender), set value to hires
# The definitions of these templates are in normal-hires.txt, nether-hires.txt, and the_end-hires.txt
# To use the HDMap low-res (4 ppb) map templates, with support for boosting resolution selectively to hi-res (16 ppb), set value to low_boost_hi
# The definitions of these templates are in normal-low_boost_hi.txt, nether-low_boost_hi.txt, and the_end-low_boost_hi.txt
# To use the HDMap hi-res (16 ppb) map templates, with support for boosting resolution selectively to vhi-res (32 ppb), set value to hi_boost_vhi
# The definitions of these templates are in normal-hi_boost_vhi.txt, nether-hi_boost_vhi.txt, and the_end-hi_boost_vhi.txt
# To use the HDMap hi-res (16 ppb) map templates, with support for boosting resolution selectively to xhi-res (64 ppb), set value to hi_boost_xhi
# The definitions of these templates are in normal-hi_boost_xhi.txt, nether-hi_boost_xhi.txt, and the_end-hi_boost_xhi.txt
deftemplatesuffix: hires
# Map storage scheme: only uncommoent one 'type' value
# filetree: classic and default scheme: tree of files, with all map data under the directory indicated by 'tilespath' setting
# sqlite: single SQLite database file (this can get VERY BIG), located at 'dbfile' setting (default is file dynmap.db in data directory)
# mysql: MySQL database, at hostname:port in database, accessed via userid with password
storage:
# Filetree storage (standard tree of image files for maps)
type: filetree
# SQLite db for map storage (uses dbfile as storage location)
#type: sqlite
#dbfile: dynmap.db
# MySQL DB for map storage (at 'hostname':'port' in database 'database' using user 'userid' password 'password' and table prefix 'prefix'
#type: mysql
#hostname: localhost
#port: 3306
#database: dynmap
#userid: dynmap
#password: dynmap
#prefix: ""
components:
- class: org.dynmap.ClientConfigurationComponent
- class: org.dynmap.InternalClientUpdateComponent
sendhealth: true
sendposition: true
allowwebchat: true
webchat-interval: 5
hidewebchatip: false
trustclientname: false
includehiddenplayers: false
# (optional) if true, color codes in player display names are used
use-name-colors: false
# (optional) if true, player login IDs will be used for web chat when their IPs match
use-player-login-ip: true
# (optional) if use-player-login-ip is true, setting this to true will cause chat messages not matching a known player IP to be ignored
require-player-login-ip: false
# (optional) block player login IDs that are banned from chatting
block-banned-player-chat: true
# Require login for web-to-server chat (requires login-enabled: true)
webchat-requires-login: false
# If set to true, users must have dynmap.webchat permission in order to chat
webchat-permissions: false
# Limit length of single chat messages
chatlengthlimit: 256
# # Optional - make players hidden when they are inside/underground/in shadows (#=light level: 0=full shadow,15=sky)
# hideifshadow: 4
# # Optional - make player hidden when they are under cover (#=sky light level,0=underground,15=open to sky)
# hideifundercover: 14
# # (Optional) if true, players that are crouching/sneaking will be hidden
hideifsneaking: false
# If true, player positions/status is protected (login with ID with dynmap.playermarkers.seeall permission required for info other than self)
protected-player-info: false
# If true, hide players with invisibility potion effects active
hide-if-invisiblity-potion: true
# If true, player names are not shown on map, chat, list
hidenames: false
#- class: org.dynmap.JsonFileClientUpdateComponent
# writeinterval: 1
# sendhealth: true
# sendposition: true
# allowwebchat: true
# webchat-interval: 5
# hidewebchatip: false
# includehiddenplayers: false
# use-name-colors: false
# use-player-login-ip: false
# require-player-login-ip: false
# block-banned-player-chat: true
# hideifshadow: 0
# hideifundercover: 0
# hideifsneaking: false
# # Require login for web-to-server chat (requires login-enabled: true)
# webchat-requires-login: false
# # If set to true, users must have dynmap.webchat permission in order to chat
# webchat-permissions: false
# # Limit length of single chat messages
# chatlengthlimit: 256
# hide-if-invisiblity-potion: true
# hidenames: false
- class: org.dynmap.SimpleWebChatComponent
allowchat: true
# If true, web UI users can supply name for chat using 'playername' URL parameter. 'trustclientname' must also be set true.
allowurlname: false
# Note: this component is needed for the dmarker commands, and for the Marker API to be available to other plugins
- class: org.dynmap.MarkersComponent
type: markers
showlabel: false
enablesigns: false
# Default marker set for sign markers
default-sign-set: markers
# (optional) add spawn point markers to standard marker layer
showspawn: true
spawnicon: world
spawnlabel: "Spawn"
# (optional) layer for showing offline player's positions (for 'maxofflinetime' minutes after logoff)
showofflineplayers: false
offlinelabel: "Offline"
offlineicon: offlineuser
offlinehidebydefault: true
offlineminzoom: 0
maxofflinetime: 30
# (optional) layer for showing player's spawn beds
showspawnbeds: false
spawnbedlabel: "Spawn Beds"
spawnbedicon: bed
spawnbedhidebydefault: true
spawnbedminzoom: 0
spawnbedformat: "%name%'s bed"
# (optional) Show world border (vanilla 1.8+)
showworldborder: true
worldborderlabel: "Border"
- class: org.dynmap.ClientComponent
type: chat
allowurlname: false
- class: org.dynmap.ClientComponent
type: chatballoon
focuschatballoons: false
- class: org.dynmap.ClientComponent
type: chatbox
showplayerfaces: true
messagettl: 5
# Optional: set number of lines in scrollable message history: if set, messagettl is not used to age out messages
#scrollback: 100
# Optional: set maximum number of lines visible for chatbox
#visiblelines: 10
# Optional: send push button
sendbutton: false
- class: org.dynmap.ClientComponent
type: playermarkers
showplayerfaces: true
showplayerhealth: true
# If true, show player body too (only valid if showplayerfaces=true
showplayerbody: false
# Option to make player faces small - don't use with showplayerhealth
smallplayerfaces: false
# Optional - make player faces layer hidden by default
hidebydefault: false
# Optional - ordering priority in layer menu (low goes before high - default is 0)
layerprio: 0
# Optional - label for player marker layer (default is 'Players')
label: "Players"
#- class: org.dynmap.ClientComponent
# type: digitalclock
- class: org.dynmap.ClientComponent
type: link
- class: org.dynmap.ClientComponent
type: timeofdayclock
showdigitalclock: true
#showweather: true
# Mouse pointer world coordinate display
- class: org.dynmap.ClientComponent
type: coord
label: "Location"
hidey: false
show-mcr: false
show-chunk: false
# Note: more than one logo component can be defined
#- class: org.dynmap.ClientComponent
# type: logo
# text: "Dynmap"
# #logourl: "images/block_surface.png"
# linkurl: "http://forums.bukkit.org/threads/dynmap.489/"
# # Valid positions: top-left, top-right, bottom-left, bottom-right
# position: bottom-right
#- class: org.dynmap.ClientComponent
# type: inactive
# timeout: 1800 # in seconds (1800 seconds = 30 minutes)
# redirecturl: inactive.html
# #showmessage: 'You were inactive for too long.'
#- class: org.dynmap.TestComponent
# stuff: "This is some configuration-value"
# Treat hiddenplayers.txt as a whitelist for players to be shown on the map? (Default false)
display-whitelist: false
# How often a tile gets rendered (in seconds).
renderinterval: 1
# How many tiles on update queue before accelerate render interval
renderacceleratethreshold: 60
# How often to render tiles when backlog is above renderacceleratethreshold
renderaccelerateinterval: 0.2
# How many update tiles to work on at once (if not defined, default is 1/2 the number of cores)
tiles-rendered-at-once: 2
# If true, use normal priority threads for rendering (versus low priority) - this can keep rendering
# from starving on busy Windows boxes (Linux JVMs pretty much ignore thread priority), but may result
# in more competition for CPU resources with other processes
usenormalthreadpriority: true
# Save and restore pending tile renders - prevents their loss on server shutdown or /reload
saverestorepending: true
# Save period for pending jobs (in seconds): periodic saving for crash recovery of jobs
save-pending-period: 900
# Zoom-out tile update period - how often to scan for and process tile updates into zoom-out tiles (in seconds)
zoomoutperiod: 30
# Control whether zoom out tiles are validated on startup (can be needed if zoomout processing is interrupted, but can be expensive on large maps)
initial-zoomout-validate: true
# Default delay on processing of updated tiles, in seconds. This can reduce potentially expensive re-rendering
# of frequently updated tiles (such as due to machines, pistons, quarries or other automation). Values can
# also be set on individual worlds and individual maps.
tileupdatedelay: 30
# Tile hashing is used to minimize tile file updates when no changes have occurred - set to false to disable
enabletilehash: true
# Optional - hide ores: render as normal stone (so that they aren't revealed by maps)
#hideores: true
# Optional - enabled BetterGrass style rendering of grass and snow block sides
#better-grass: true
# Optional - enable smooth lighting by default on all maps supporting it (can be set per map as lighting option)
smooth-lighting: true
# Optional - use world provider lighting table (good for custom worlds with custom lighting curves, like nether)
# false=classic Dynmap lighting curve
use-brightness-table: true
# Optional - render specific block names using the textures and models of another block name: can be used to hide/disguise specific
# blocks (e.g. make ores look like stone, hide chests) or to provide simple support for rendering unsupported custom blocks
block-alias:
# "minecraft:quartz_ore": "stone"
# "diamond_ore": "coal_ore"
# Default image format for HDMaps (png, jpg, jpg-q75, jpg-q80, jpg-q85, jpg-q90, jpg-q95, jpg-q100)
# Has no effect on maps with explicit format settings
image-format: jpg-q90
# use-generated-textures: if true, use generated textures (same as client); false is static water/lava textures
# correct-water-lighting: if true, use corrected water lighting (same as client); false is legacy water (darker)
# transparent-leaves: if true, leaves are transparent (lighting-wise): false is needed for some Spout versions that break lighting on leaf blocks
use-generated-textures: true
correct-water-lighting: true
transparent-leaves: true
# ctm-support: if true, Connected Texture Mod (CTM) in texture packs is enabled (default)
ctm-support: true
# custom-colors-support: if true, Custom Colors in texture packs is enabled (default)
custom-colors-support: true
# Control loading of player faces (if set to false, skins are never fetched)
#fetchskins: false
# Control updating of player faces, once loaded (if faces are being managed by other apps or manually)
#refreshskins: false
# Customize URL used for fetching player skins (%player% is macro for name)
skin-url: "http://skins.minecraft.net/MinecraftSkins/%player%.png"
# Control behavior for new (1.0+) compass orientation (sunrise moved 90 degrees: east is now what used to be south)
# default is 'newrose' (preserve pre-1.0 maps, rotate rose)
# 'newnorth' is used to rotate maps and rose (requires fullrender of any HDMap map - same as 'newrose' for FlatMap or KzedMap)
compass-mode: newnorth
# Triggers for automatic updates : blockupdate-with-id is debug for breaking down updates by ID:meta
# To disable, set just 'none' and comment/delete the rest
render-triggers:
- blockupdate
#- blockupdate-with-id
#- lightingupdate
- chunkpopulate
- chunkgenerate
#- none
# Title for the web page - if not specified, defaults to the server's name (unless it is the default of 'Unknown Server')
#webpage-title: "My Awesome Server Map"
# The path where the tile-files are placed.
tilespath: web/tiles
# The path where the web-files are located.
webpath: web
# The path were the /dynmapexp command exports OBJ ZIP files
exportpath: export
# The network-interface the webserver will bind to (0.0.0.0 for all interfaces, 127.0.0.1 for only local access).
# If not set, uses same setting as server in server.properties (or 0.0.0.0 if not specified)
#webserver-bindaddress: 0.0.0.0
# The TCP-port the webserver will listen on.
webserver-port: 8123
# Maximum concurrent session on internal web server - limits resources used in Bukkit server
max-sessions: 30
# Disables Webserver portion of Dynmap (Advanced users only)
disable-webserver: false
# Enable/disable having the web server allow symbolic links (true=compatible with existing code, false=more secure (default))
allow-symlinks: true
# Enable login support
login-enabled: false
# Require login to access website (requires login-enabled: true)
login-required: false
# Period between tile renders for fullrender, in seconds (non-zero to pace fullrenders, lessen CPU load)
timesliceinterval: 0.0
# Maximum chunk loads per server tick (1/20th of a second) - reducing this below 90 will impact render performance, but also will reduce server thread load
maxchunkspertick: 200
# Progress report interval for fullrender/radiusrender, in tiles. Must be 100 or greater
progressloginterval: 100
# Parallel fullrender: if defined, number of concurrent threads used for fullrender or radiusrender
# Note: setting this will result in much more intensive CPU use, some additional memory use. Caution should be used when
# setting this to equal or exceed the number of physical cores on the system.
#parallelrendercnt: 4
# Interval the browser should poll for updates.
updaterate: 2000
# If nonzero, server will pause fullrender/radiusrender processing when 'fullrenderplayerlimit' or more users are logged in
fullrenderplayerlimit: 0
# If nonzero, server will pause update render processing when 'updateplayerlimit' or more users are logged in
updateplayerlimit: 0
# Target limit on server thread use - msec per tick
per-tick-time-limit: 50
# If TPS of server is below this setting, update renders processing is paused
update-min-tps: 18.0
# If TPS of server is below this setting, full/radius renders processing is paused
fullrender-min-tps: 18.0
# If TPS of server is below this setting, zoom out processing is paused
zoomout-min-tps: 18.0
showplayerfacesinmenu: true
# Control whether players that are hidden or not on current map are grayed out (true=yes)
grayplayerswhenhidden: true
# Set sidebaropened: 'true' to pin menu sidebar opened permanently, 'pinned' to default the sidebar to pinned, but allow it to unpin
#sidebaropened: true
# Customized HTTP response headers - add 'id: value' pairs to all HTTP response headers (internal web server only)
#http-response-headers:
# Access-Control-Allow-Origin: "my-domain.com"
# X-Custom-Header-Of-Mine: "MyHeaderValue"
# Trusted proxies for web server - which proxy addresses are trusted to supply valid X-Forwarded-For fields
trusted-proxies:
- "127.0.0.1"
- "0:0:0:0:0:0:0:1"
joinmessage: "%playername% joined"
quitmessage: "%playername% quit"
spammessage: "You may only chat once every %interval% seconds."
# format for messages from web: %playername% substitutes sender ID (typically IP), %message% includes text
webmsgformat: "&color;2[WEB] %playername%: &color;f%message%"
# Control whether layer control is presented on the UI (default is true)
showlayercontrol: true
# Enable checking for banned IPs via banned-ips.txt (internal web server only)
check-banned-ips: true
# Default selection when map page is loaded
defaultzoom: 0
defaultworld: world
defaultmap: flat
# (optional) Zoom level and map to switch to when following a player, if possible
#followzoom: 3
#followmap: surface
# If true, make persistent record of IP addresses used by player logins, to support web IP to player matching
persist-ids-by-ip: true
# If true, map text to cyrillic
cyrillic-support: false
# Messages to customize
msg:
maptypes: "Map Types"
players: "Players"
chatrequireslogin: "Chat Requires Login"
chatnotallowed: "You are not permitted to send chat messages"
hiddennamejoin: "Player joined"
hiddennamequit: "Player quit"
# URL for client configuration (only need to be tailored for proxies or other non-standard configurations)
url:
# configuration URL
#configuration: "up/configuration"
# update URL
#update: "up/world/{world}/{timestamp}"
# sendmessage URL
#sendmessage: "up/sendmessage"
# login URL
#login: "up/login"
# register URL
#register: "up/register"
# tiles base URL
#tiles: "tiles/"
# markers base URL
#markers: "tiles/"
# Snapshot cache size, in chunks
snapshotcachesize: 500
# Snapshot cache uses soft references (true), else weak references (false)
soft-ref-cache: true
# Player enter/exit title messages for map markers
#
# Processing period - how often to check player positions vs markers - default is 1000ms (1 second)
#enterexitperiod: 1000
# Title message fade in time, in ticks (0.05 second intervals) - default is 10 (1/2 second)
#titleFadeIn: 10
# Title message stay time, in ticks (0.05 second intervals) - default is 70 (3.5 seconds)
#titleStay: 70
# Title message fade out time, in ticks (0.05 seocnd intervals) - default is 20 (1 second)
#titleFadeOut: 20
# Enter/exit messages use on screen titles (true - default), if false chat messages are sent instead
#enterexitUseTitle: true
# Set true if new enter messages should supercede pending exit messages (vs being queued in order), default false
#enterReplacesExits: true
# Set to true to enable verbose startup messages - can help with debugging map configuration problems
# Set to false for a much quieter startup log
verbose: false
# Enables debugging.
#debuggers:
# - class: org.dynmap.debug.LogDebugger
# Debug: dump blocks missing render data
dump-missing-blocks: false

View File

@ -0,0 +1,6 @@
{
"pack": {
"description": "Dynmap resources",
"pack_format": 4
}
}

View File

@ -0,0 +1,27 @@
#
# Sample permissions.yml for dynmap - trivial, flat-file based permissions for dynmap features
# To use, copy this file to dynmap/permissions.yml, and edit appropriate. File is YAML format.
#
# All operators have full permissions to all functions.
# All users receive the permissions under the 'defaultuser' section
# Specific users can be given more permissions by defining a section with their name containing their permisssions
# All permissions correspond to those documented here (https://github.com/webbukkit/dynmap/wiki/Permissions), but
# do NOT have the 'dynmap.' prefix when used here (e.g. 'dynmap.fullrender' permission is just 'fullrender' here).
#
defaultuser:
- render
- show.self
- hide.self
- sendtoweb
- stats
- marker.list
- marker.listsets
- marker.icons
- webregister
- webchat
#- marker.sign
#playername1:
# - fullrender
# - cancelrender
# - radiusrender

87
forge-1.16.2/build.gradle Normal file
View File

@ -0,0 +1,87 @@
buildscript {
repositories {
maven { url = 'https://files.minecraftforge.net/maven' }
jcenter()
mavenCentral()
}
dependencies {
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true
}
}
apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'eclipse'
apply plugin: 'com.github.johnrengelman.shadow'
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
ext.buildNumber = System.getenv().BUILD_NUMBER ?: "Dev"
minecraft {
mappings channel: 'snapshot', version: '20200514-1.16'
accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
runs {
server {
workingDirectory project.file('run').canonicalPath
}
}
}
project.archivesBaseName = "${project.archivesBaseName}-forge-1.16.2"
dependencies {
compile project(path: ":DynmapCore", configuration: "shadow")
minecraft 'net.minecraftforge:forge:1.16.2-33.0.5'
}
processResources
{
inputs.property "version", project.version + '-' + project.ext.buildNumber
// replace stuff in mcmod.info, nothing else
from(sourceSets.main.resources.srcDirs) {
include 'META-INF/mods.toml'
// replace version and mcversion
expand(
version: project.version + '-' + project.ext.buildNumber,
mcversion: "1.16.2"
)
}
// copy everything else, thats not the mcmod.info
from(sourceSets.main.resources.srcDirs) {
exclude 'META-INF/mods.toml'
}
}
shadowJar {
dependencies {
include(dependency(':DynmapCore'))
}
archiveName = "Dynmap-${parent.version}-forge-1.16.2.jar"
destinationDir = file '../target'
}
shadowJar.doLast {
task ->
ant.checksum file: task.archivePath
}
afterEvaluate {
reobf {
shadowJar {
mappings = createMcpToSrg.output
}
}
}
task deobfJar(type: Jar) {
from sourceSets.main.output
classifier = 'dev'
}
artifacts {
archives deobfJar
}
build.dependsOn(shadowJar)

View File

@ -0,0 +1,286 @@
package org.dynmap.forge_1_16_2;
import java.util.Arrays;
import org.dynmap.Log;
import org.dynmap.renderer.DynmapBlockState;
import org.dynmap.utils.DataBitsPacked;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.util.BitArray;
/**
* Represents a static, thread-safe snapshot of chunk of blocks
* Purpose is to allow clean, efficient copy of a chunk data to be made, and then handed off for processing in another thread (e.g. map rendering)
*/
public class ChunkSnapshot
{
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[] hmap; // Height map
private final int[] biome;
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 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 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 ChunkSnapshot(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.sectionCnt = worldheight / 16;
/* Allocate arrays indexed by section */
this.section = new Section[this.sectionCnt];
/* 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 ChunkSnapshot(CompoundNBT 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 */
this.section = new Section[this.sectionCnt];
/* Fill with empty data */
for (int i = 0; i < this.sectionCnt; i++) {
this.section[i] = empty_section;
}
/* Get sections */
ListNBT sect = nbt.getList("Sections", 10);
for (int i = 0; i < sect.size(); i++) {
CompoundNBT sec = sect.getCompound(i);
int secnum = sec.getByte("Y");
if (secnum >= this.sectionCnt) {
//Log.info("Section " + (int) secnum + " above world height " + worldheight);
continue;
}
if (secnum < 0)
continue;
//System.out.println("section(" + secnum + ")=" + sec.asString());
// Create normal section to initialize
StdSection cursect = new StdSection();
this.section[secnum] = 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)) {
ListNBT plist = sec.getList("Palette", 10);
long[] statelist = sec.getLongArray("BlockStates");
palette = new DynmapBlockState[plist.size()];
for (int pi = 0; pi < plist.size(); pi++) {
CompoundNBT tc = plist.getCompound(pi);
String pname = tc.getString("Name");
if (tc.contains("Properties")) {
StringBuilder statestr = new StringBuilder();
CompoundNBT prop = tc.getCompound("Properties");
for (String pid : prop.keySet()) {
if (statestr.length() > 0) statestr.append(',');
statestr.append(pid).append('=').append(prop.get(pid).getString());
}
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;
BitArray db = null;
DataBitsPacked dbp = null;
try {
db = new BitArray(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.getAt(j);
states[j] = DynmapBlockState.getStateByGlobalIndex(v);
}
}
else {
for (int j = 0; j < 4096; j++) {
int v = (dbp != null) ? dbp.getAt(j) : db.getAt(j);
states[j] = (v < palette.length) ? palette[v] : DynmapBlockState.AIR;
}
}
}
if (sec.contains("BlockLight")) {
cursect.emitlight = sec.getByteArray("BlockLight");
}
if (sec.contains("SkyLight")) {
cursect.skylight = sec.getByteArray("SkyLight");
}
}
/* Get biome data */
this.biome = new int[COLUMNS_PER_CHUNK];
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;
}
}
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;
}
}
}
}
}
public int getX()
{
return x;
}
public int getZ()
{
return z;
}
public DynmapBlockState getBlockType(int x, int y, int z)
{
return section[y >> 4].getBlockType(x, y, z);
}
public int getBlockSkyLight(int x, int y, int z)
{
return section[y >> 4].getBlockSkyLight(x, y, z);
}
public int getBlockEmittedLight(int x, int y, int z)
{
return section[y >> 4].getBlockEmittedLight(x, y, z);
}
public int getHighestBlockYAt(int x, int z)
{
return hmap[z << 4 | x];
}
public int getBiome(int x, int z)
{
return biome[z << 4 | x];
}
public final long getCaptureFullTime()
{
return captureFulltime;
}
public boolean isSectionEmpty(int sy)
{
return section[sy].isEmpty();
}
public long getInhabitedTicks() {
return inhabitedTicks;
}
}

View File

@ -0,0 +1,6 @@
package org.dynmap.forge_1_16_2;
public class ClientProxy extends Proxy {
public ClientProxy() {
}
}

View File

@ -0,0 +1,133 @@
package org.dynmap.forge_1_16_2;
import java.io.File;
import org.apache.commons.lang3.tuple.Pair;
import org.dynmap.DynmapCommonAPI;
import org.dynmap.DynmapCommonAPIListener;
import org.dynmap.Log;
import org.dynmap.forge_1_16_2.DynmapPlugin.OurLog;
import net.minecraft.server.MinecraftServer;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
import net.minecraftforge.fml.event.server.FMLServerStartedEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.network.FMLNetworkConstants;
@Mod("dynmap")
public class DynmapMod
{
// The instance of your mod that Forge uses.
public static DynmapMod instance;
// Says where the client and server 'proxy' code is loaded.
public static Proxy proxy = DistExecutor.runForDist(() -> ClientProxy::new, () -> Proxy::new);
public static DynmapPlugin plugin;
public static File jarfile;
public static String ver;
public static boolean useforcedchunks;
public class APICallback extends DynmapCommonAPIListener {
@Override
public void apiListenerAdded() {
if(plugin == null) {
plugin = proxy.startServer(server);
}
}
@Override
public void apiEnabled(DynmapCommonAPI api) {
}
}
//TODO
//public class LoadingCallback implements net.minecraftforge.common.ForgeChunkManager.LoadingCallback {
// @Override
// public void ticketsLoaded(List<Ticket> tickets, World world) {
// if(tickets.size() > 0) {
// DynmapPlugin.setBusy(world, tickets.get(0));
// for(int i = 1; i < tickets.size(); i++) {
// ForgeChunkManager.releaseTicket(tickets.get(i));
// }
// }
// }
//}
public DynmapMod() {
instance = this;
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::init);
MinecraftForge.EVENT_BUS.register(this);
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, () -> Pair.of(() -> FMLNetworkConstants.IGNORESERVERONLY, (a, b) -> true));
Log.setLogger(new OurLog());
org.dynmap.modsupport.ModSupportImpl.init();
}
public void setup(final FMLCommonSetupEvent event)
{
//TOOO
jarfile = ModList.get().getModFileById("dynmap").getFile().getFilePath().toFile();
ver = ModList.get().getModContainerById("dynmap").get().getModInfo().getVersion().toString();
//// Load configuration file - use suggested (config/WesterosBlocks.cfg)
//Configuration cfg = new Configuration(event.getSuggestedConfigurationFile());
//try {
// cfg.load();
//
// useforcedchunks = cfg.get("Settings", "UseForcedChunks", true).getBoolean(true);
//}
//finally
//{
// cfg.save();
//}
}
public void init(FMLLoadCompleteEvent event)
{
/* Set up for chunk loading notice from chunk manager */
//TODO
//if(useforcedchunks) {
// ForgeChunkManager.setForcedChunkLoadingCallback(DynmapMod.instance, new LoadingCallback());
//}
//else {
// System.out.println("[Dynmap] World loading using forced chunks is disabled");
//}
}
private MinecraftServer server;
@SubscribeEvent
public void onServerStarting(FMLServerStartingEvent event) {
server = event.getServer();
if(plugin == null)
plugin = proxy.startServer(server);
plugin.onStarting(server.getCommandManager().getDispatcher());
}
@SubscribeEvent
public void onServerStarted(FMLServerStartedEvent event) {
DynmapCommonAPIListener.register(new APICallback());
plugin.serverStarted();
}
@SubscribeEvent
public void serverStopping(FMLServerStoppingEvent event)
{
proxy.stopServer(plugin);
plugin = null;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,234 @@
package org.dynmap.forge_1_16_2;
/**
* Forge specific implementation of DynmapWorld
*/
import java.util.List;
import net.minecraft.util.RegistryKey;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.gen.Heightmap.Type;
import net.minecraft.world.IServerWorld;
import net.minecraft.world.IWorld;
import net.minecraft.world.LightType;
import net.minecraft.world.World;
import net.minecraft.world.border.WorldBorder;
import org.dynmap.DynmapChunk;
import org.dynmap.DynmapLocation;
import org.dynmap.DynmapWorld;
import org.dynmap.utils.MapChunkCache;
import org.dynmap.utils.Polygon;
public class ForgeWorld extends DynmapWorld
{
private IServerWorld world;
private final boolean skylight;
private final boolean isnether;
private final boolean istheend;
private final String env;
private DynmapLocation spawnloc = new DynmapLocation();
private static int maxWorldHeight = 256; // Maximum allows world height
public static int getMaxWorldHeight() {
return maxWorldHeight;
}
public static void setMaxWorldHeight(int h) {
maxWorldHeight = h;
}
public static String getWorldName(IServerWorld w) {
RegistryKey<World> rk = w.getWorld().func_234923_W_();
if (rk == World.field_234918_g_) { // Overworld?
return w.getWorld().getServer().func_240793_aU_().getWorldName();
}
else if (rk == World.field_234920_i_) {
return "DIM1";
}
else if (rk == World.field_234919_h_) {
return "DIM-1";
}
else {
return rk.func_240901_a_().getNamespace() + "_" + rk.func_240901_a_().getPath();
}
}
public ForgeWorld(IServerWorld w)
{
this(getWorldName(w), w.getWorld().getHeight(),
w.getWorld().getSeaLevel(),
w.getWorld().func_234923_W_() == World.field_234920_i_,
w.getWorld().func_234923_W_() == World.field_234919_h_,
w.getWorld().func_234923_W_().func_240901_a_().getPath());
setWorldLoaded(w);
}
public ForgeWorld(String name, int height, int sealevel, boolean nether, boolean the_end, String deftitle)
{
super(name, (height > maxWorldHeight)?maxWorldHeight:height, sealevel);
world = null;
setTitle(deftitle);
isnether = nether;
istheend = the_end;
skylight = !(isnether || istheend);
if (isnether)
{
env = "nether";
}
else if (istheend)
{
env = "the_end";
}
else
{
env = "normal";
}
}
/* Test if world is nether */
@Override
public boolean isNether()
{
return isnether;
}
public boolean isTheEnd()
{
return istheend;
}
/* Get world spawn location */
@Override
public DynmapLocation getSpawnLocation()
{
if(world != null) {
spawnloc.x = world.getWorldInfo().getSpawnX();
spawnloc.y = world.getWorldInfo().getSpawnY();
spawnloc.z = world.getWorldInfo().getSpawnZ();
spawnloc.world = this.getName();
}
return spawnloc;
}
/* Get world time */
@Override
public long getTime()
{
if(world != null)
return world.getWorld().getGameTime();
else
return -1;
}
/* World is storming */
@Override
public boolean hasStorm()
{
if(world != null)
return world.getWorld().isRaining();
else
return false;
}
/* World is thundering */
@Override
public boolean isThundering()
{
if(world != null)
return world.getWorld().isThundering();
else
return false;
}
/* World is loaded */
@Override
public boolean isLoaded()
{
return (world != null);
}
/* Set world to unloaded */
@Override
public void setWorldUnloaded()
{
getSpawnLocation();
world = null;
}
/* Set world to loaded */
public void setWorldLoaded(IServerWorld w) {
world = w;
this.sealevel = w.getSeaLevel(); // Read actual current sealevel from world
// Update lighting table
for (int i = 0; i < 16; i++) {
this.setBrightnessTableEntry(i, w.getWorld().func_230315_m_().func_236021_a_(i));
}
}
/* Get light level of block */
@Override
public int getLightLevel(int x, int y, int z)
{
if(world != null)
return world.getLight(new BlockPos(x, y, z));
else
return -1;
}
/* Get highest Y coord of given location */
@Override
public int getHighestBlockYAt(int x, int z)
{
if(world != null) {
return world.getWorld().getChunk(x >> 4, z >> 4).getHeightmap(Type.MOTION_BLOCKING).getHeight(x & 15, z & 15);
}
else
return -1;
}
/* Test if sky light level is requestable */
@Override
public boolean canGetSkyLightLevel()
{
return skylight;
}
/* Return sky light level */
@Override
public int getSkyLightLevel(int x, int y, int z)
{
if(world != null) {
return world.getLightFor(LightType.SKY, new BlockPos(x, y, z));
}
else
return -1;
}
/**
* Get world environment ID (lower case - normal, the_end, nether)
*/
@Override
public String getEnvironment()
{
return env;
}
/**
* Get map chunk cache for world
*/
@Override
public MapChunkCache getChunkCache(List<DynmapChunk> chunks)
{
if(world != null) {
ForgeMapChunkCache c = new ForgeMapChunkCache();
c.setChunks(this, chunks);
return c;
}
return null;
}
public World getWorld()
{
return world.getWorld();
}
@Override
public Polygon getWorldBorder() {
if (world != null) {
WorldBorder wb = world.getWorldBorder();
if ((wb != null) && (wb.getDiameter() < 5.9E7)) {
Polygon p = new Polygon();
p.addVertex(wb.minX(), wb.minZ());
p.addVertex(wb.minX(), wb.maxZ());
p.addVertex(wb.maxX(), wb.maxZ());
p.addVertex(wb.maxX(), wb.minZ());
return p;
}
}
return null;
}
}

View File

@ -0,0 +1,24 @@
package org.dynmap.forge_1_16_2;
import net.minecraft.server.MinecraftServer;
/**
* Server side proxy - methods for creating and cleaning up plugin
*/
public class Proxy
{
public Proxy()
{
}
public DynmapPlugin startServer(MinecraftServer srv) {
DynmapPlugin plugin = DynmapPlugin.plugin;
if (plugin == null) {
plugin = new DynmapPlugin(srv);
plugin.onEnable();
}
return plugin;
}
public void stopServer(DynmapPlugin plugin) {
plugin.onDisable();
}
}

View File

@ -0,0 +1,191 @@
package org.dynmap.forge_1_16_2;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.ref.SoftReference;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.dynmap.utils.DynIntHashMap;
public class SnapshotCache {
public static class SnapshotRec {
public ChunkSnapshot ss;
public DynIntHashMap tileData;
};
private CacheHashMap snapcache;
private ReferenceQueue<SnapshotRec> refqueue;
private long cache_attempts;
private long cache_success;
private boolean softref;
private static class CacheRec {
Reference<SnapshotRec> ref;
boolean hasbiome;
boolean hasrawbiome;
boolean hasblockdata;
boolean hashighesty;
}
@SuppressWarnings("serial")
public class CacheHashMap extends LinkedHashMap<String, CacheRec> {
private int limit;
private IdentityHashMap<Reference<SnapshotRec>, String> reverselookup;
public CacheHashMap(int lim) {
super(16, (float)0.75, true);
limit = lim;
reverselookup = new IdentityHashMap<Reference<SnapshotRec>, String>();
}
protected boolean removeEldestEntry(Map.Entry<String, CacheRec> last) {
boolean remove = (size() >= limit);
if(remove && (last != null) && (last.getValue() != null)) {
reverselookup.remove(last.getValue().ref);
}
return remove;
}
}
/**
* Create snapshot cache
*/
public SnapshotCache(int max_size, boolean softref) {
snapcache = new CacheHashMap(max_size);
refqueue = new ReferenceQueue<SnapshotRec>();
this.softref = softref;
}
private String getKey(String w, int cx, int cz) {
return w + ":" + cx + ":" + cz;
}
/**
* Invalidate cached snapshot, if in cache
*/
public void invalidateSnapshot(String w, int x, int y, int z) {
String key = getKey(w, x>>4, z>>4);
synchronized(snapcache) {
CacheRec rec = snapcache.remove(key);
if(rec != null) {
snapcache.reverselookup.remove(rec.ref);
rec.ref.clear();
}
}
//processRefQueue();
}
/**
* Invalidate cached snapshot, if in cache
*/
public void invalidateSnapshot(String w, int x0, int y0, int z0, int x1, int y1, int z1) {
for(int xx = (x0>>4); xx <= (x1>>4); xx++) {
for(int zz = (z0>>4); zz <= (z1>>4); zz++) {
String key = getKey(w, xx, zz);
synchronized(snapcache) {
CacheRec rec = snapcache.remove(key);
if(rec != null) {
snapcache.reverselookup.remove(rec.ref);
rec.ref.clear();
}
}
}
}
//processRefQueue();
}
/**
* Look for chunk snapshot in cache
*/
public SnapshotRec getSnapshot(String w, int chunkx, int chunkz,
boolean blockdata, boolean biome, boolean biomeraw, boolean highesty) {
String key = getKey(w, chunkx, chunkz);
processRefQueue();
SnapshotRec ss = null;
CacheRec rec;
synchronized(snapcache) {
rec = snapcache.get(key);
if(rec != null) {
ss = rec.ref.get();
if(ss == null) {
snapcache.reverselookup.remove(rec.ref);
snapcache.remove(key);
}
}
}
if(ss != null) {
if((blockdata && (!rec.hasblockdata)) ||
(biome && (!rec.hasbiome)) ||
(biomeraw && (!rec.hasrawbiome)) ||
(highesty && (!rec.hashighesty))) {
ss = null;
}
}
cache_attempts++;
if(ss != null) cache_success++;
return ss;
}
/**
* Add chunk snapshot to cache
*/
public void putSnapshot(String w, int chunkx, int chunkz, SnapshotRec ss,
boolean blockdata, boolean biome, boolean biomeraw, boolean highesty) {
String key = getKey(w, chunkx, chunkz);
processRefQueue();
CacheRec rec = new CacheRec();
rec.hasblockdata = blockdata;
rec.hasbiome = biome;
rec.hasrawbiome = biomeraw;
rec.hashighesty = highesty;
if (softref)
rec.ref = new SoftReference<SnapshotRec>(ss, refqueue);
else
rec.ref = new WeakReference<SnapshotRec>(ss, refqueue);
synchronized(snapcache) {
CacheRec prevrec = snapcache.put(key, rec);
if(prevrec != null) {
snapcache.reverselookup.remove(prevrec.ref);
}
snapcache.reverselookup.put(rec.ref, key);
}
}
/**
* Process reference queue
*/
private void processRefQueue() {
Reference<? extends SnapshotRec> ref;
while((ref = refqueue.poll()) != null) {
synchronized(snapcache) {
String k = snapcache.reverselookup.remove(ref);
if(k != null) {
snapcache.remove(k);
}
}
}
}
/**
* Get hit rate (percent)
*/
public double getHitRate() {
if(cache_attempts > 0) {
return (100.0*cache_success)/(double)cache_attempts;
}
return 0.0;
}
/**
* Reset cache stats
*/
public void resetStats() {
cache_attempts = cache_success = 0;
}
/**
* Cleanup
*/
public void cleanup() {
if(snapcache != null) {
snapcache.clear();
snapcache.reverselookup.clear();
snapcache.reverselookup = null;
snapcache = null;
}
}
}

View File

@ -0,0 +1,97 @@
package org.dynmap.forge_1_16_2;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import org.dynmap.DynmapCore;
import org.dynmap.Log;
public class VersionCheck {
private static final String VERSION_URL = "http://mikeprimm.com/dynmap/releases.php";
public static void runCheck(final DynmapCore core) {
new Thread(new Runnable() {
public void run() {
doCheck(core);
}
}).start();
}
private static int getReleaseVersion(String s) {
int index = s.lastIndexOf('-');
if(index < 0)
index = s.lastIndexOf('.');
if(index >= 0)
s = s.substring(0, index);
String[] split = s.split("\\.");
int v = 0;
try {
for(int i = 0; (i < split.length) && (i < 3); i++) {
v += Integer.parseInt(split[i]) << (8 * (2 - i));
}
} catch (NumberFormatException nfx) {}
return v;
}
private static int getBuildNumber(String s) {
int index = s.lastIndexOf('-');
if(index < 0)
index = s.lastIndexOf('.');
if(index >= 0)
s = s.substring(index+1);
try {
return Integer.parseInt(s);
} catch (NumberFormatException nfx) {
return 99999999;
}
}
private static void doCheck(DynmapCore core) {
String pluginver = core.getDynmapPluginVersion();
String platform = core.getDynmapPluginPlatform();
String platver = core.getDynmapPluginPlatformVersion();
if((pluginver == null) || (platform == null) || (platver == null))
return;
HttpURLConnection conn = null;
String loc = VERSION_URL;
int cur_ver = getReleaseVersion(pluginver);
int cur_bn = getBuildNumber(pluginver);
try {
while((loc != null) && (!loc.isEmpty())) {
URL url = new URL(loc);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("User-Agent", "Dynmap (" + platform + "/" + platver + "/" + pluginver);
conn.connect();
loc = conn.getHeaderField("Location");
}
BufferedReader rdr = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;
while((line = rdr.readLine()) != null) {
String[] split = line.split(":");
if(split.length < 4) continue;
/* If our platform and version, or wildcard platform version */
if(split[0].equals(platform) && (split[1].equals("*") || split[1].equals(platver))) {
int recommended_ver = getReleaseVersion(split[2]);
int recommended_bn = getBuildNumber(split[2]);
if((recommended_ver > cur_ver) || ((recommended_ver == cur_ver) && (recommended_bn > cur_bn))) { /* Newer recommended build */
Log.info("Version obsolete: new recommended version " + split[2] + " is available.");
}
else if(cur_ver > recommended_ver) { /* Running dev or prerelease? */
int prerel_ver = getReleaseVersion(split[3]);
int prerel_bn = getBuildNumber(split[3]);
if((prerel_ver > cur_ver) || ((prerel_ver == cur_ver) && (prerel_bn > cur_bn))) {
Log.info("Version obsolete: new prerelease version " + split[3] + " is available.");
}
}
}
}
} catch (Exception x) {
Log.info("Error checking for latest version");
} finally {
if(conn != null) {
conn.disconnect();
}
}
}
}

View File

@ -0,0 +1,103 @@
package org.dynmap.forge_1_16_2.permissions;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.minecraft.entity.player.PlayerEntity;
import org.dynmap.ConfigurationNode;
import org.dynmap.Log;
import org.dynmap.forge_1_16_2.DynmapPlugin;
public class FilePermissions implements PermissionProvider {
private HashMap<String, Set<String>> perms;
private Set<String> defperms;
public static FilePermissions create() {
File f = new File("dynmap/permissions.yml");
if(!f.exists())
return null;
ConfigurationNode cfg = new ConfigurationNode(f);
cfg.load();
Log.info("Using permissions.yml for access control");
return new FilePermissions(cfg);
}
private FilePermissions(ConfigurationNode cfg) {
perms = new HashMap<String,Set<String>>();
for(String k : cfg.keySet()) {
List<String> p = cfg.getStrings(k, null);
if(p != null) {
k = k.toLowerCase();
HashSet<String> pset = new HashSet<String>();
for(String perm : p) {
pset.add(perm.toLowerCase());
}
perms.put(k, pset);
if(k.equals("defaultuser")) {
defperms = pset;
}
}
}
}
private boolean hasPerm(String player, String perm) {
Set<String> ps = perms.get(player);
if((ps != null) && (ps.contains(perm))) {
return true;
}
if(defperms.contains(perm)) {
return true;
}
return false;
}
@Override
public Set<String> hasOfflinePermissions(String player, Set<String> perms) {
player = player.toLowerCase();
HashSet<String> rslt = new HashSet<String>();
if(DynmapPlugin.plugin.isOp(player)) {
rslt.addAll(perms);
}
else {
for(String p : perms) {
if(hasPerm(player, p)) {
rslt.add(p);
}
}
}
return rslt;
}
@Override
public boolean hasOfflinePermission(String player, String perm) {
player = player.toLowerCase();
if(DynmapPlugin.plugin.isOp(player)) {
return true;
}
else {
return hasPerm(player, perm);
}
}
@Override
public boolean has(PlayerEntity psender, String permission) {
if(psender != null) {
String n = psender.getName().getString().toLowerCase();
return hasPerm(n, permission);
}
return true;
}
@Override
public boolean hasPermissionNode(PlayerEntity psender, String permission) {
if(psender != null) {
String player = psender.getName().getString().toLowerCase();
return DynmapPlugin.plugin.isOp(player);
}
return false;
}
}

View File

@ -0,0 +1,51 @@
package org.dynmap.forge_1_16_2.permissions;
import java.util.HashSet;
import java.util.Set;
import net.minecraft.entity.player.PlayerEntity;
import org.dynmap.Log;
import org.dynmap.forge_1_16_2.DynmapPlugin;
public class OpPermissions implements PermissionProvider {
public HashSet<String> usrCommands = new HashSet<String>();
public OpPermissions(String[] usrCommands) {
for (String usrCommand : usrCommands) {
this.usrCommands.add(usrCommand);
}
Log.info("Using ops.txt for access control");
}
@Override
public Set<String> hasOfflinePermissions(String player, Set<String> perms) {
HashSet<String> rslt = new HashSet<String>();
if(DynmapPlugin.plugin.isOp(player)) {
rslt.addAll(perms);
}
return rslt;
}
@Override
public boolean hasOfflinePermission(String player, String perm) {
return DynmapPlugin.plugin.isOp(player);
}
@Override
public boolean has(PlayerEntity psender, String permission) {
if(psender != null) {
if(usrCommands.contains(permission)) {
return true;
}
return DynmapPlugin.plugin.isOp(psender.getEntity().getName().getString());
}
return true;
}
@Override
public boolean hasPermissionNode(PlayerEntity psender, String permission) {
if(psender != null) {
return DynmapPlugin.plugin.isOp(psender.getEntity().getName().getString());
}
return true;
}
}

View File

@ -0,0 +1,15 @@
package org.dynmap.forge_1_16_2.permissions;
import java.util.Set;
import net.minecraft.entity.player.PlayerEntity;
public interface PermissionProvider {
boolean has(PlayerEntity sender, String permission);
boolean hasPermissionNode(PlayerEntity sender, String permission);
Set<String> hasOfflinePermissions(String player, Set<String> perms);
boolean hasOfflinePermission(String player, String perm);
}

View File

@ -0,0 +1,3 @@
public net.minecraft.world.server.ChunkManager field_219251_e # loaded chunk list
public net.minecraft.world.server.ChunkManager field_219252_f # loaded chunk list
public net.minecraft.world.biome.BiomeAmbience field_235206_c_ # waterColor

View File

@ -0,0 +1,26 @@
modLoader="javafml"
loaderVersion="[33,)"
issueTrackerURL="https://github.com/webbukkit/dynmap/issues"
license="Apache Public License v2"
[[mods]]
modId="dynmap"
version="${version}"
displayName="Dynmap"
authors="mikeprimm"
description='''
Dynamic, Google-maps style rendered maps for your Minecraft server
'''
[[dependencies.dynmap]]
modId="forge"
mandatory=true
versionRange="[33,)"
ordering="NONE"
# Side this dependency is applied on - BOTH, CLIENT or SERVER
side="SERVER"
[[dependencies.dynmap]]
modId="minecraft"
mandatory=true
versionRange="[1.16.2]"
ordering="NONE"
side="SERVER"

View File

@ -0,0 +1,457 @@
# All paths in this configuration file are relative to Dynmap's data-folder: minecraft_server/dynmap/
# All map templates are defined in the templates directory
# To use the HDMap very-low-res (2 ppb) map templates as world defaults, set value to vlowres
# The definitions of these templates are in normal-vlowres.txt, nether-vlowres.txt, and the_end-vlowres.txt
# To use the HDMap low-res (4 ppb) map templates as world defaults, set value to lowres
# The definitions of these templates are in normal-lowres.txt, nether-lowres.txt, and the_end-lowres.txt
# To use the HDMap hi-res (16 ppb) map templates (these can take a VERY long time for initial fullrender), set value to hires
# The definitions of these templates are in normal-hires.txt, nether-hires.txt, and the_end-hires.txt
# To use the HDMap low-res (4 ppb) map templates, with support for boosting resolution selectively to hi-res (16 ppb), set value to low_boost_hi
# The definitions of these templates are in normal-low_boost_hi.txt, nether-low_boost_hi.txt, and the_end-low_boost_hi.txt
# To use the HDMap hi-res (16 ppb) map templates, with support for boosting resolution selectively to vhi-res (32 ppb), set value to hi_boost_vhi
# The definitions of these templates are in normal-hi_boost_vhi.txt, nether-hi_boost_vhi.txt, and the_end-hi_boost_vhi.txt
# To use the HDMap hi-res (16 ppb) map templates, with support for boosting resolution selectively to xhi-res (64 ppb), set value to hi_boost_xhi
# The definitions of these templates are in normal-hi_boost_xhi.txt, nether-hi_boost_xhi.txt, and the_end-hi_boost_xhi.txt
deftemplatesuffix: hires
# Map storage scheme: only uncommoent one 'type' value
# filetree: classic and default scheme: tree of files, with all map data under the directory indicated by 'tilespath' setting
# sqlite: single SQLite database file (this can get VERY BIG), located at 'dbfile' setting (default is file dynmap.db in data directory)
# mysql: MySQL database, at hostname:port in database, accessed via userid with password
storage:
# Filetree storage (standard tree of image files for maps)
type: filetree
# SQLite db for map storage (uses dbfile as storage location)
#type: sqlite
#dbfile: dynmap.db
# MySQL DB for map storage (at 'hostname':'port' in database 'database' using user 'userid' password 'password' and table prefix 'prefix'
#type: mysql
#hostname: localhost
#port: 3306
#database: dynmap
#userid: dynmap
#password: dynmap
#prefix: ""
components:
- class: org.dynmap.ClientConfigurationComponent
- class: org.dynmap.InternalClientUpdateComponent
sendhealth: true
sendposition: true
allowwebchat: true
webchat-interval: 5
hidewebchatip: false
trustclientname: false
includehiddenplayers: false
# (optional) if true, color codes in player display names are used
use-name-colors: false
# (optional) if true, player login IDs will be used for web chat when their IPs match
use-player-login-ip: true
# (optional) if use-player-login-ip is true, setting this to true will cause chat messages not matching a known player IP to be ignored
require-player-login-ip: false
# (optional) block player login IDs that are banned from chatting
block-banned-player-chat: true
# Require login for web-to-server chat (requires login-enabled: true)
webchat-requires-login: false
# If set to true, users must have dynmap.webchat permission in order to chat
webchat-permissions: false
# Limit length of single chat messages
chatlengthlimit: 256
# # Optional - make players hidden when they are inside/underground/in shadows (#=light level: 0=full shadow,15=sky)
# hideifshadow: 4
# # Optional - make player hidden when they are under cover (#=sky light level,0=underground,15=open to sky)
# hideifundercover: 14
# # (Optional) if true, players that are crouching/sneaking will be hidden
hideifsneaking: false
# If true, player positions/status is protected (login with ID with dynmap.playermarkers.seeall permission required for info other than self)
protected-player-info: false
# If true, hide players with invisibility potion effects active
hide-if-invisiblity-potion: true
# If true, player names are not shown on map, chat, list
hidenames: false
#- class: org.dynmap.JsonFileClientUpdateComponent
# writeinterval: 1
# sendhealth: true
# sendposition: true
# allowwebchat: true
# webchat-interval: 5
# hidewebchatip: false
# includehiddenplayers: false
# use-name-colors: false
# use-player-login-ip: false
# require-player-login-ip: false
# block-banned-player-chat: true
# hideifshadow: 0
# hideifundercover: 0
# hideifsneaking: false
# # Require login for web-to-server chat (requires login-enabled: true)
# webchat-requires-login: false
# # If set to true, users must have dynmap.webchat permission in order to chat
# webchat-permissions: false
# # Limit length of single chat messages
# chatlengthlimit: 256
# hide-if-invisiblity-potion: true
# hidenames: false
- class: org.dynmap.SimpleWebChatComponent
allowchat: true
# If true, web UI users can supply name for chat using 'playername' URL parameter. 'trustclientname' must also be set true.
allowurlname: false
# Note: this component is needed for the dmarker commands, and for the Marker API to be available to other plugins
- class: org.dynmap.MarkersComponent
type: markers
showlabel: false
enablesigns: false
# Default marker set for sign markers
default-sign-set: markers
# (optional) add spawn point markers to standard marker layer
showspawn: true
spawnicon: world
spawnlabel: "Spawn"
# (optional) layer for showing offline player's positions (for 'maxofflinetime' minutes after logoff)
showofflineplayers: false
offlinelabel: "Offline"
offlineicon: offlineuser
offlinehidebydefault: true
offlineminzoom: 0
maxofflinetime: 30
# (optional) layer for showing player's spawn beds
showspawnbeds: false
spawnbedlabel: "Spawn Beds"
spawnbedicon: bed
spawnbedhidebydefault: true
spawnbedminzoom: 0
spawnbedformat: "%name%'s bed"
# (optional) Show world border (vanilla 1.8+)
showworldborder: true
worldborderlabel: "Border"
- class: org.dynmap.ClientComponent
type: chat
allowurlname: false
- class: org.dynmap.ClientComponent
type: chatballoon
focuschatballoons: false
- class: org.dynmap.ClientComponent
type: chatbox
showplayerfaces: true
messagettl: 5
# Optional: set number of lines in scrollable message history: if set, messagettl is not used to age out messages
#scrollback: 100
# Optional: set maximum number of lines visible for chatbox
#visiblelines: 10
# Optional: send push button
sendbutton: false
- class: org.dynmap.ClientComponent
type: playermarkers
showplayerfaces: true
showplayerhealth: true
# If true, show player body too (only valid if showplayerfaces=true
showplayerbody: false
# Option to make player faces small - don't use with showplayerhealth
smallplayerfaces: false
# Optional - make player faces layer hidden by default
hidebydefault: false
# Optional - ordering priority in layer menu (low goes before high - default is 0)
layerprio: 0
# Optional - label for player marker layer (default is 'Players')
label: "Players"
#- class: org.dynmap.ClientComponent
# type: digitalclock
- class: org.dynmap.ClientComponent
type: link
- class: org.dynmap.ClientComponent
type: timeofdayclock
showdigitalclock: true
#showweather: true
# Mouse pointer world coordinate display
- class: org.dynmap.ClientComponent
type: coord
label: "Location"
hidey: false
show-mcr: false
show-chunk: false
# Note: more than one logo component can be defined
#- class: org.dynmap.ClientComponent
# type: logo
# text: "Dynmap"
# #logourl: "images/block_surface.png"
# linkurl: "http://forums.bukkit.org/threads/dynmap.489/"
# # Valid positions: top-left, top-right, bottom-left, bottom-right
# position: bottom-right
#- class: org.dynmap.ClientComponent
# type: inactive
# timeout: 1800 # in seconds (1800 seconds = 30 minutes)
# redirecturl: inactive.html
# #showmessage: 'You were inactive for too long.'
#- class: org.dynmap.TestComponent
# stuff: "This is some configuration-value"
# Treat hiddenplayers.txt as a whitelist for players to be shown on the map? (Default false)
display-whitelist: false
# How often a tile gets rendered (in seconds).
renderinterval: 1
# How many tiles on update queue before accelerate render interval
renderacceleratethreshold: 60
# How often to render tiles when backlog is above renderacceleratethreshold
renderaccelerateinterval: 0.2
# How many update tiles to work on at once (if not defined, default is 1/2 the number of cores)
tiles-rendered-at-once: 2
# If true, use normal priority threads for rendering (versus low priority) - this can keep rendering
# from starving on busy Windows boxes (Linux JVMs pretty much ignore thread priority), but may result
# in more competition for CPU resources with other processes
usenormalthreadpriority: true
# Save and restore pending tile renders - prevents their loss on server shutdown or /reload
saverestorepending: true
# Save period for pending jobs (in seconds): periodic saving for crash recovery of jobs
save-pending-period: 900
# Zoom-out tile update period - how often to scan for and process tile updates into zoom-out tiles (in seconds)
zoomoutperiod: 30
# Control whether zoom out tiles are validated on startup (can be needed if zoomout processing is interrupted, but can be expensive on large maps)
initial-zoomout-validate: true
# Default delay on processing of updated tiles, in seconds. This can reduce potentially expensive re-rendering
# of frequently updated tiles (such as due to machines, pistons, quarries or other automation). Values can
# also be set on individual worlds and individual maps.
tileupdatedelay: 30
# Tile hashing is used to minimize tile file updates when no changes have occurred - set to false to disable
enabletilehash: true
# Optional - hide ores: render as normal stone (so that they aren't revealed by maps)
#hideores: true
# Optional - enabled BetterGrass style rendering of grass and snow block sides
#better-grass: true
# Optional - enable smooth lighting by default on all maps supporting it (can be set per map as lighting option)
smooth-lighting: true
# Optional - use world provider lighting table (good for custom worlds with custom lighting curves, like nether)
# false=classic Dynmap lighting curve
use-brightness-table: true
# Optional - render specific block names using the textures and models of another block name: can be used to hide/disguise specific
# blocks (e.g. make ores look like stone, hide chests) or to provide simple support for rendering unsupported custom blocks
block-alias:
# "minecraft:quartz_ore": "stone"
# "diamond_ore": "coal_ore"
# Default image format for HDMaps (png, jpg, jpg-q75, jpg-q80, jpg-q85, jpg-q90, jpg-q95, jpg-q100)
# Has no effect on maps with explicit format settings
image-format: jpg-q90
# use-generated-textures: if true, use generated textures (same as client); false is static water/lava textures
# correct-water-lighting: if true, use corrected water lighting (same as client); false is legacy water (darker)
# transparent-leaves: if true, leaves are transparent (lighting-wise): false is needed for some Spout versions that break lighting on leaf blocks
use-generated-textures: true
correct-water-lighting: true
transparent-leaves: true
# ctm-support: if true, Connected Texture Mod (CTM) in texture packs is enabled (default)
ctm-support: true
# custom-colors-support: if true, Custom Colors in texture packs is enabled (default)
custom-colors-support: true
# Control loading of player faces (if set to false, skins are never fetched)
#fetchskins: false
# Control updating of player faces, once loaded (if faces are being managed by other apps or manually)
#refreshskins: false
# Customize URL used for fetching player skins (%player% is macro for name)
skin-url: "http://skins.minecraft.net/MinecraftSkins/%player%.png"
# Control behavior for new (1.0+) compass orientation (sunrise moved 90 degrees: east is now what used to be south)
# default is 'newrose' (preserve pre-1.0 maps, rotate rose)
# 'newnorth' is used to rotate maps and rose (requires fullrender of any HDMap map - same as 'newrose' for FlatMap or KzedMap)
compass-mode: newnorth
# Triggers for automatic updates : blockupdate-with-id is debug for breaking down updates by ID:meta
# To disable, set just 'none' and comment/delete the rest
render-triggers:
- blockupdate
#- blockupdate-with-id
#- lightingupdate
- chunkpopulate
- chunkgenerate
#- none
# Title for the web page - if not specified, defaults to the server's name (unless it is the default of 'Unknown Server')
#webpage-title: "My Awesome Server Map"
# The path where the tile-files are placed.
tilespath: web/tiles
# The path where the web-files are located.
webpath: web
# The path were the /dynmapexp command exports OBJ ZIP files
exportpath: export
# The network-interface the webserver will bind to (0.0.0.0 for all interfaces, 127.0.0.1 for only local access).
# If not set, uses same setting as server in server.properties (or 0.0.0.0 if not specified)
#webserver-bindaddress: 0.0.0.0
# The TCP-port the webserver will listen on.
webserver-port: 8123
# Maximum concurrent session on internal web server - limits resources used in Bukkit server
max-sessions: 30
# Disables Webserver portion of Dynmap (Advanced users only)
disable-webserver: false
# Enable/disable having the web server allow symbolic links (true=compatible with existing code, false=more secure (default))
allow-symlinks: true
# Enable login support
login-enabled: false
# Require login to access website (requires login-enabled: true)
login-required: false
# Period between tile renders for fullrender, in seconds (non-zero to pace fullrenders, lessen CPU load)
timesliceinterval: 0.0
# Maximum chunk loads per server tick (1/20th of a second) - reducing this below 90 will impact render performance, but also will reduce server thread load
maxchunkspertick: 200
# Progress report interval for fullrender/radiusrender, in tiles. Must be 100 or greater
progressloginterval: 100
# Parallel fullrender: if defined, number of concurrent threads used for fullrender or radiusrender
# Note: setting this will result in much more intensive CPU use, some additional memory use. Caution should be used when
# setting this to equal or exceed the number of physical cores on the system.
#parallelrendercnt: 4
# Interval the browser should poll for updates.
updaterate: 2000
# If nonzero, server will pause fullrender/radiusrender processing when 'fullrenderplayerlimit' or more users are logged in
fullrenderplayerlimit: 0
# If nonzero, server will pause update render processing when 'updateplayerlimit' or more users are logged in
updateplayerlimit: 0
# Target limit on server thread use - msec per tick
per-tick-time-limit: 50
# If TPS of server is below this setting, update renders processing is paused
update-min-tps: 18.0
# If TPS of server is below this setting, full/radius renders processing is paused
fullrender-min-tps: 18.0
# If TPS of server is below this setting, zoom out processing is paused
zoomout-min-tps: 18.0
showplayerfacesinmenu: true
# Control whether players that are hidden or not on current map are grayed out (true=yes)
grayplayerswhenhidden: true
# Set sidebaropened: 'true' to pin menu sidebar opened permanently, 'pinned' to default the sidebar to pinned, but allow it to unpin
#sidebaropened: true
# Customized HTTP response headers - add 'id: value' pairs to all HTTP response headers (internal web server only)
#http-response-headers:
# Access-Control-Allow-Origin: "my-domain.com"
# X-Custom-Header-Of-Mine: "MyHeaderValue"
# Trusted proxies for web server - which proxy addresses are trusted to supply valid X-Forwarded-For fields
trusted-proxies:
- "127.0.0.1"
- "0:0:0:0:0:0:0:1"
joinmessage: "%playername% joined"
quitmessage: "%playername% quit"
spammessage: "You may only chat once every %interval% seconds."
# format for messages from web: %playername% substitutes sender ID (typically IP), %message% includes text
webmsgformat: "&color;2[WEB] %playername%: &color;f%message%"
# Control whether layer control is presented on the UI (default is true)
showlayercontrol: true
# Enable checking for banned IPs via banned-ips.txt (internal web server only)
check-banned-ips: true
# Default selection when map page is loaded
defaultzoom: 0
defaultworld: world
defaultmap: flat
# (optional) Zoom level and map to switch to when following a player, if possible
#followzoom: 3
#followmap: surface
# If true, make persistent record of IP addresses used by player logins, to support web IP to player matching
persist-ids-by-ip: true
# If true, map text to cyrillic
cyrillic-support: false
# Messages to customize
msg:
maptypes: "Map Types"
players: "Players"
chatrequireslogin: "Chat Requires Login"
chatnotallowed: "You are not permitted to send chat messages"
hiddennamejoin: "Player joined"
hiddennamequit: "Player quit"
# URL for client configuration (only need to be tailored for proxies or other non-standard configurations)
url:
# configuration URL
#configuration: "up/configuration"
# update URL
#update: "up/world/{world}/{timestamp}"
# sendmessage URL
#sendmessage: "up/sendmessage"
# login URL
#login: "up/login"
# register URL
#register: "up/register"
# tiles base URL
#tiles: "tiles/"
# markers base URL
#markers: "tiles/"
# Snapshot cache size, in chunks
snapshotcachesize: 500
# Snapshot cache uses soft references (true), else weak references (false)
soft-ref-cache: true
# Player enter/exit title messages for map markers
#
# Processing period - how often to check player positions vs markers - default is 1000ms (1 second)
#enterexitperiod: 1000
# Title message fade in time, in ticks (0.05 second intervals) - default is 10 (1/2 second)
#titleFadeIn: 10
# Title message stay time, in ticks (0.05 second intervals) - default is 70 (3.5 seconds)
#titleStay: 70
# Title message fade out time, in ticks (0.05 seocnd intervals) - default is 20 (1 second)
#titleFadeOut: 20
# Enter/exit messages use on screen titles (true - default), if false chat messages are sent instead
#enterexitUseTitle: true
# Set true if new enter messages should supercede pending exit messages (vs being queued in order), default false
#enterReplacesExits: true
# Set to true to enable verbose startup messages - can help with debugging map configuration problems
# Set to false for a much quieter startup log
verbose: false
# Enables debugging.
#debuggers:
# - class: org.dynmap.debug.LogDebugger
# Debug: dump blocks missing render data
dump-missing-blocks: false

View File

@ -0,0 +1,6 @@
{
"pack": {
"description": "Dynmap resources",
"pack_format": 6
}
}

View File

@ -0,0 +1,27 @@
#
# Sample permissions.yml for dynmap - trivial, flat-file based permissions for dynmap features
# To use, copy this file to dynmap/permissions.yml, and edit appropriate. File is YAML format.
#
# All operators have full permissions to all functions.
# All users receive the permissions under the 'defaultuser' section
# Specific users can be given more permissions by defining a section with their name containing their permisssions
# All permissions correspond to those documented here (https://github.com/webbukkit/dynmap/wiki/Permissions), but
# do NOT have the 'dynmap.' prefix when used here (e.g. 'dynmap.fullrender' permission is just 'fullrender' here).
#
defaultuser:
- render
- show.self
- hide.self
- sendtoweb
- stats
- marker.list
- marker.listsets
- marker.icons
- webregister
- webchat
#- marker.sign
#playername1:
# - fullrender
# - cancelrender
# - radiusrender

View File

@ -4,12 +4,14 @@ include ':bukkit-helper-113-2'
include ':bukkit-helper-114-1' include ':bukkit-helper-114-1'
include ':bukkit-helper-115' include ':bukkit-helper-115'
include ':bukkit-helper-116' include ':bukkit-helper-116'
include ':bukkit-helper-116-2'
include ':bukkit-helper' include ':bukkit-helper'
include ':dynmap-api' include ':dynmap-api'
include ':DynmapCore' include ':DynmapCore'
include ':DynmapCoreAPI' include ':DynmapCoreAPI'
include ':fabric-1.16.1'
include ':fabric-1.16.2' include ':fabric-1.16.2'
include ':fabric-1.16.1'
include ':forge-1.16.2'
include ':forge-1.16.1' include ':forge-1.16.1'
include ':forge-1.15.2' include ':forge-1.15.2'
include ':forge-1.14.4' include ':forge-1.14.4'
@ -22,12 +24,14 @@ project(':bukkit-helper-113-2').projectDir = "$rootDir/bukkit-helper-113-2" as F
project(':bukkit-helper-114-1').projectDir = "$rootDir/bukkit-helper-114-1" as File project(':bukkit-helper-114-1').projectDir = "$rootDir/bukkit-helper-114-1" as File
project(':bukkit-helper-115').projectDir = "$rootDir/bukkit-helper-115" as File project(':bukkit-helper-115').projectDir = "$rootDir/bukkit-helper-115" as File
project(':bukkit-helper-116').projectDir = "$rootDir/bukkit-helper-116" as File project(':bukkit-helper-116').projectDir = "$rootDir/bukkit-helper-116" as File
project(':bukkit-helper-116-2').projectDir = "$rootDir/bukkit-helper-116-2" as File
project(':bukkit-helper').projectDir = "$rootDir/bukkit-helper" as File project(':bukkit-helper').projectDir = "$rootDir/bukkit-helper" as File
project(':dynmap-api').projectDir = "$rootDir/dynmap-api" as File project(':dynmap-api').projectDir = "$rootDir/dynmap-api" as File
project(':DynmapCore').projectDir = "$rootDir/DynmapCore" as File project(':DynmapCore').projectDir = "$rootDir/DynmapCore" as File
project(':DynmapCoreAPI').projectDir = "$rootDir/DynmapCoreAPI" as File project(':DynmapCoreAPI').projectDir = "$rootDir/DynmapCoreAPI" as File
project(':fabric-1.16.1').projectDir = "$rootDir/fabric-1.16.1" as File
project(':fabric-1.16.2').projectDir = "$rootDir/fabric-1.16.2" as File project(':fabric-1.16.2').projectDir = "$rootDir/fabric-1.16.2" as File
project(':fabric-1.16.1').projectDir = "$rootDir/fabric-1.16.1" as File
project(':forge-1.16.2').projectDir = "$rootDir/forge-1.16.2" as File
project(':forge-1.16.1').projectDir = "$rootDir/forge-1.16.1" as File project(':forge-1.16.1').projectDir = "$rootDir/forge-1.16.1" as File
project(':forge-1.15.2').projectDir = "$rootDir/forge-1.15.2" as File project(':forge-1.15.2').projectDir = "$rootDir/forge-1.15.2" as File
project(':forge-1.14.4').projectDir = "$rootDir/forge-1.14.4" as File project(':forge-1.14.4').projectDir = "$rootDir/forge-1.14.4" as File

View File

@ -39,6 +39,9 @@ dependencies {
implementation(project(':bukkit-helper-116')) { implementation(project(':bukkit-helper-116')) {
transitive = false transitive = false
} }
implementation(project(':bukkit-helper-116-2')) {
transitive = false
}
} }
processResources { processResources {
@ -67,6 +70,7 @@ shadowJar {
include(dependency(':bukkit-helper-114-1')) include(dependency(':bukkit-helper-114-1'))
include(dependency(':bukkit-helper-115')) include(dependency(':bukkit-helper-115'))
include(dependency(':bukkit-helper-116')) include(dependency(':bukkit-helper-116'))
include(dependency(':bukkit-helper-116-2'))
} }
relocate('org.bstats', 'org.dynmap.bstats') relocate('org.bstats', 'org.dynmap.bstats')
destinationDir = file '../target' destinationDir = file '../target'

View File

@ -779,7 +779,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
BiomeMap.loadWellKnownByVersion(mcver); BiomeMap.loadWellKnownByVersion(mcver);
/* Find array of biomes in biomebase */ /* Find array of biomes in biomebase */
Object[] biomelist = helper.getBiomeBaseList(); Object[] biomelist = helper.getBiomeBaseList();
Log.verboseinfo("biomelist length = " + biomelist.length); //Log.info("biomelist length = " + biomelist.length);
/* Loop through list, skipping well known biomes */ /* Loop through list, skipping well known biomes */
for(int i = 0; i < biomelist.length; i++) { for(int i = 0; i < biomelist.length; i++) {
Object bb = biomelist[i]; Object bb = biomelist[i];
@ -787,7 +787,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
float tmp = helper.getBiomeBaseTemperature(bb); float tmp = helper.getBiomeBaseTemperature(bb);
float hum = helper.getBiomeBaseHumidity(bb); float hum = helper.getBiomeBaseHumidity(bb);
int watermult = helper.getBiomeBaseWaterMult(bb); int watermult = helper.getBiomeBaseWaterMult(bb);
Log.verboseinfo("biome[" + i + "]: hum=" + hum + ", tmp=" + tmp + ", mult=" + Integer.toHexString(watermult)); //Log.info("biome[" + i + "]: hum=" + hum + ", tmp=" + tmp + ", mult=" + Integer.toHexString(watermult));
BiomeMap bmap = BiomeMap.byBiomeID(i); BiomeMap bmap = BiomeMap.byBiomeID(i);
if (bmap.isDefault()) { if (bmap.isDefault()) {
@ -796,7 +796,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
id = "BIOME_" + i; id = "BIOME_" + i;
} }
bmap = new BiomeMap(i, id, tmp, hum); bmap = new BiomeMap(i, id, tmp, hum);
Log.verboseinfo("Add custom biome [" + bmap.toString() + "] (" + i + ")"); //Log.info("Add custom biome [" + bmap.toString() + "] (" + i + ")");
cnt++; cnt++;
} }
else { else {
@ -805,7 +805,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
} }
if (watermult != -1) { if (watermult != -1) {
bmap.setWaterColorMultiplier(watermult); bmap.setWaterColorMultiplier(watermult);
Log.verboseinfo("Set watercolormult for " + bmap.toString() + " (" + i + ") to " + Integer.toHexString(watermult)); //Log.info("Set watercolormult for " + bmap.toString() + " (" + i + ") to " + Integer.toHexString(watermult));
} }
} }
} }

View File

@ -9,6 +9,7 @@ import org.dynmap.bukkit.helper.v113_2.BukkitVersionHelperSpigot113_2;
import org.dynmap.bukkit.helper.v114_1.BukkitVersionHelperSpigot114_1; import org.dynmap.bukkit.helper.v114_1.BukkitVersionHelperSpigot114_1;
import org.dynmap.bukkit.helper.v115.BukkitVersionHelperSpigot115; import org.dynmap.bukkit.helper.v115.BukkitVersionHelperSpigot115;
import org.dynmap.bukkit.helper.v116.BukkitVersionHelperSpigot116; import org.dynmap.bukkit.helper.v116.BukkitVersionHelperSpigot116;
import org.dynmap.bukkit.helper.v116_2.BukkitVersionHelperSpigot116_2;
public class Helper { public class Helper {
@ -34,9 +35,12 @@ public class Helper {
Log.info("Loading Glowstone support"); Log.info("Loading Glowstone support");
BukkitVersionHelper.helper = new BukkitVersionHelperGlowstone(); BukkitVersionHelper.helper = new BukkitVersionHelperGlowstone();
} }
else if (v.contains("(MC: 1.16)") || v.contains("(MC: 1.16.")) { else if (v.contains("(MC: 1.16)") || v.contains("(MC: 1.16.1")) {
BukkitVersionHelper.helper = new BukkitVersionHelperSpigot116(); BukkitVersionHelper.helper = new BukkitVersionHelperSpigot116();
} }
else if (v.contains("(MC: 1.16.")) {
BukkitVersionHelper.helper = new BukkitVersionHelperSpigot116_2();
}
else if (v.contains("(MC: 1.15)") || v.contains("(MC: 1.15.")) { else if (v.contains("(MC: 1.15)") || v.contains("(MC: 1.15.")) {
BukkitVersionHelper.helper = new BukkitVersionHelperSpigot115(); BukkitVersionHelper.helper = new BukkitVersionHelperSpigot115();
} }

View File

@ -49,7 +49,7 @@ public class VaultPermissions implements PermissionProvider, Listener {
@EventHandler @EventHandler
public void onServiceRegister(ServiceRegisterEvent event) { public void onServiceRegister(ServiceRegisterEvent event) {
if (event.getProvider().getService().equals(Permission.class)) { if (event.getProvider().getService().equals(Permission.class)) {
RegisteredServiceProvider<Permission> newProvider = (RegisteredServiceProvider<Permission>) event.getProvider().getProvider(); RegisteredServiceProvider<Permission> newProvider = (RegisteredServiceProvider<Permission>) event.getProvider();
if (newProvider != this.permissionProvider && newProvider.getPriority().compareTo(this.permissionProvider.getPriority()) >= 0) { if (newProvider != this.permissionProvider && newProvider.getPriority().compareTo(this.permissionProvider.getPriority()) >= 0) {
this.permissionProvider = newProvider; this.permissionProvider = newProvider;
Log.info("Using Vault provider " + this.permissionProvider.getProvider().getName() + " for access control"); Log.info("Using Vault provider " + this.permissionProvider.getProvider().getName() + " for access control");