Compare commits

...

18 Commits

Author SHA1 Message Date
Mike Primm 7e850a2668 Add assertPlayerInvisibility() API 2012-02-08 01:05:53 -06:00
Mike Primm 45574b3b9e Add help and security settings for new /dmap commands 2012-02-08 00:15:54 -06:00
Mike Primm 526d5881c7 Merge remote branch 'upstream/master' 2012-02-07 10:22:55 -06:00
Mike Primm 8f9006e594 Retire 'chunkloaded' trigger, add warning for 'playermove' trigger 2012-02-07 10:21:56 -06:00
Mike Primm 87aabf3eca Add 'show-mcr' option to coord control (show region file ID) 2012-02-07 00:48:28 -06:00
Mike Primm 9b31f30f14 Handle cancelled chat events properly 2012-02-06 20:31:41 -06:00
Mike Primm dd0f0c7128 Add plugin_enable and plugin_disable event listener 2012-02-06 11:17:38 -06:00
Mike Primm 86c7dee750 Start worlds.txt edit commands - add /dmap worldlist and /dmap worldset 2012-02-05 15:53:24 -06:00
Mike Primm 3b19d11694 Fix break in 1.1 event processing on /dynmap reload 2012-02-05 12:07:44 -06:00
Mike Primm c7b9bea340 Workaround more Spout custom block flaky crap 2012-02-05 11:45:24 -06:00
Mike Primm 0925212a70 Add log messages for completion of disable - know that we're out of the picture 2012-02-03 23:02:27 -06:00
Mike Primm 84f62ade86 Merge remote-tracking branch 'upstream/master' 2012-02-03 22:38:04 -06:00
Mike Primm d85e810322 Use reflection to improve Spout custom block support - fixes StainedGlass 2012-02-03 22:36:58 -06:00
Mike Primm c6b3569cca Add support for greater-than-128 high worlds 2012-02-01 14:43:33 +08:00
Mike Primm 417b8d6e31 Add support for greater-than-128 high worlds 2012-02-01 00:40:38 -06:00
Mike Primm 9d529de700 Add Kaevator's Superslopes support 2012-01-30 00:52:07 -06:00
Mike Primm 55bc549a6b Add RailCraft block rendering support 2012-01-29 12:35:12 -06:00
Mike Primm 689f1f3105 Back to 0.31 2012-01-27 23:18:10 -06:00
8 changed files with 255 additions and 98 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.dynmap</groupId>
<artifactId>dynmap</artifactId>
<version>0.30.1</version>
<version>0.31</version>
<name>dynmap</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -29,6 +29,9 @@ import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent;
import org.bukkit.event.server.ServerListener;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.ChunkPopulateEvent;
import org.bukkit.event.world.SpawnChangeEvent;
@@ -56,8 +59,9 @@ public class BukkitEventProcessor {
List<Listener> ll = event_handlers.get(t);
ll.clear(); /* Empty list - we use presence of list to remember that we've registered with Bukkit */
}
pm = null;
plugin = null;
if(plugin.getServer().getVersion().contains("(MC: 1.0") == false) {
event_handlers.clear();
}
}
private BlockListener ourBlockEventHandler = new BlockListener() {
@@ -268,6 +272,8 @@ public class BukkitEventProcessor {
@Override
public void onPlayerChat(PlayerChatEvent event) {
if(event.isCancelled())
return;
/* Call listeners */
List<Listener> ll = event_handlers.get(event.getType());
if(ll != null) {
@@ -359,6 +365,29 @@ public class BukkitEventProcessor {
}
};
private ServerListener ourServerEventHandler = new ServerListener() {
@Override
public void onPluginEnable(PluginEnableEvent event) {
/* Call listeners */
List<Listener> ll = event_handlers.get(event.getType());
if(ll != null) {
for(Listener l : ll) {
((ServerListener)l).onPluginEnable(event);
}
}
}
@Override
public void onPluginDisable(PluginDisableEvent event) {
/* Call listeners */
List<Listener> ll = event_handlers.get(event.getType());
if(ll != null) {
for(Listener l : ll) {
((ServerListener)l).onPluginDisable(event);
}
}
}
};
/**
* Register event listener - this will be cleaned up properly on a /dynmap reload, unlike
* registering with Bukkit directly
@@ -404,6 +433,10 @@ public class BukkitEventProcessor {
case ENTITY_EXPLODE:
pm.registerEvent(type, ourEntityEventHandler, Event.Priority.Monitor, plugin);
break;
case PLUGIN_ENABLE:
case PLUGIN_DISABLE:
pm.registerEvent(type, ourServerEventHandler, Event.Priority.Monitor, plugin);
break;
default:
Log.severe("registerEvent() in DynmapPlugin does not handle " + type);
return;
@@ -16,7 +16,7 @@ public class BukkitWorld extends DynmapWorld {
private static BlockLightLevel bll = new BlockLightLevel();
public BukkitWorld(World w) {
super(w.getName());
super(w.getName(), w.getMaxHeight());
world = w;
}
@@ -41,7 +41,6 @@ import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.ChunkPopulateEvent;
import org.bukkit.event.world.SpawnChangeEvent;
import org.bukkit.event.world.WorldListener;
@@ -240,6 +239,14 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public void resetCacheStats() {
sscache.resetStats();
}
@Override
public DynmapWorld getWorldByName(String wname) {
World w = getServer().getWorld(wname); /* FInd world */
if(w != null) {
return new BukkitWorld(w);
}
return null;
}
}
/**
* Player access abstraction class
@@ -400,6 +407,8 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
/* Register our update trigger events */
registerEvents();
Log.info("Enabled");
}
@Override
@@ -413,6 +422,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
sscache.cleanup();
sscache = null;
}
Log.info("Disabled");
}
@Override
@@ -567,7 +577,6 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
private boolean onplayerjoin;
private boolean onplayermove;
private boolean ongeneratechunk;
private boolean onloadchunk;
private boolean onexplosion;
private void registerEvents() {
@@ -797,9 +806,10 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
onplayermove = core.isTrigger("playermove");
bep.registerEvent(Event.Type.PLAYER_JOIN, playerTrigger);
bep.registerEvent(Event.Type.PLAYER_QUIT, playerTrigger);
if(onplayermove)
if(onplayermove) {
bep.registerEvent(Event.Type.PLAYER_MOVE, playerTrigger);
Log.warning("playermove trigger enabled - this trigger can cause excessive tile updating: use with caution");
}
/* Register entity event triggers */
EntityListener entityTrigger = new EntityListener() {
@Override
@@ -836,16 +846,6 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
/* Register world event triggers */
WorldListener worldTrigger = new WorldListener() {
@Override
public void onChunkLoad(ChunkLoadEvent event) {
if(DynmapCore.ignore_chunk_loads)
return;
Chunk c = event.getChunk();
/* Touch extreme corners */
int x = c.getX() << 4;
int z = c.getZ() << 4;
mapManager.touchVolume(event.getWorld().getName(), x, 0, z, x+15, 128, z+16, "chunkload");
}
@Override
public void onChunkPopulate(ChunkPopulateEvent event) {
Chunk c = event.getChunk();
@@ -874,10 +874,6 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
if(ongeneratechunk) {
bep.registerEvent(Event.Type.CHUNK_POPULATED, worldTrigger);
}
onloadchunk = core.isTrigger("chunkloaded");
if(onloadchunk) {
bep.registerEvent(Event.Type.CHUNK_LOAD, worldTrigger);
}
// To link configuration to real loaded worlds.
bep.registerEvent(Event.Type.WORLD_LOAD, worldTrigger);
@@ -892,4 +888,16 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public boolean hasSpout() {
return has_spout;
}
@Override
public void assertPlayerInvisibility(String player, boolean is_invisible,
String plugin_id) {
core.assertPlayerInvisibility(player, is_invisible, plugin_id);
}
@Override
public void assertPlayerInvisibility(Player player, boolean is_invisible,
Plugin plugin) {
core.assertPlayerInvisibility(player.getName(), is_invisible, plugin.getDescription().getName());
}
}
@@ -82,9 +82,11 @@ public class NewMapChunkCache implements MapChunkCache {
private int lastbiome_x = Integer.MIN_VALUE, lastbiome_z = Integer.MIN_VALUE;
private BiomeMap lastbiome;
private int lastcountswamp_x = Integer.MIN_VALUE, lastcountswamp_z = Integer.MIN_VALUE, lastcountswamp;
private final int worldheight;
OurMapIterator(int x0, int y0, int z0) {
initialize(x0, y0, z0);
worldheight = w.getMaxHeight();
}
public final void initialize(int x0, int y0, int z0) {
this.x = x0;
@@ -113,9 +115,6 @@ public class NewMapChunkCache implements MapChunkCache {
blkdata = snap.getBlockData(bx, y, bz);
return blkdata;
}
public final int getHighestBlockYAt() {
return snap.getHighestBlockYAt(bx, bz);
}
public int getBlockSkyLight() {
return snap.getBlockSkyLight(bx, y, bz);
}
@@ -293,7 +292,7 @@ public class NewMapChunkCache implements MapChunkCache {
return snap.getBlockTypeId(bx, y-1, bz);
}
else if(s == BlockStep.Y_PLUS) {
if(y < 127)
if(y < (worldheight-1))
return snap.getBlockTypeId(bx, y+1, bz);
}
else {
@@ -309,6 +308,10 @@ public class NewMapChunkCache implements MapChunkCache {
public BlockStep getLastStep() {
return laststep;
}
@Override
public int getWorldHeight() {
return worldheight;
}
}
private class OurEndMapIterator extends OurMapIterator {
@@ -716,13 +719,6 @@ public class NewMapChunkCache implements MapChunkCache {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return (byte)ss.getBlockData(x & 0xF, y, z & 0xF);
}
/* Get highest block Y
*
*/
public int getHighestBlockYAt(int x, int z) {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return ss.getHighestBlockYAt(x & 0xF, z & 0xF);
}
/* Get sky light level
*/
public int getBlockSkyLight(int x, int y, int z) {
@@ -5,14 +5,20 @@ import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import javax.imageio.ImageIO;
import org.dynmap.Log;
import org.getspout.spoutapi.block.design.BlockDesign;
import org.getspout.spoutapi.block.design.GenericBlockDesign;
import org.getspout.spoutapi.block.design.GenericCuboidBlockDesign;
import org.getspout.spoutapi.block.design.Texture;
import org.getspout.spoutapi.material.CustomBlock;
import org.getspout.spoutapi.material.MaterialData;
@@ -23,9 +29,38 @@ import org.getspout.spoutapi.material.MaterialData;
* directory of downloaded image files (texturepacks/standard/spout/plugin.blockid.png)
*/
public class SpoutPluginBlocks {
private Field textXPosField; /* float[][] textXPos */
private Field textYPosField; /* float[][] textYPos */
private boolean initSpoutAccess() {
boolean success = false;
try {
textXPosField = GenericBlockDesign.class.getDeclaredField("textXPos");
textXPosField.setAccessible(true);
textYPosField = GenericBlockDesign.class.getDeclaredField("textYPos");
textYPosField.setAccessible(true);
success = true;
} catch (NoSuchFieldException nsfx) {
Log.severe("Cannot access needed Spout custom block fields!");
Log.severe(nsfx);
}
return success;
}
private void addDefaultBlock(StringBuilder sb, CustomBlock blk) {
if(blk.isOpaque())
sb.append("block:id=" + blk.getCustomId() + ",data=*,allfaces=1\n");
else
sb.append("block:id=" + blk.getCustomId() + ",allfaces=12049,transparency=TRANSPARENT\n");
}
/* Process spout blocks - return true if something changed */
public boolean processSpoutBlocks(File datadir) {
if(textYPosField == null) {
if(initSpoutAccess() == false)
return false;
}
HashMap<String, String> texturelist = new HashMap<String, String>();
int cnt = 0;
File f = new File(datadir, "texturepacks/standard/spout");
if(f.exists() == false)
@@ -38,68 +73,103 @@ public class SpoutPluginBlocks {
for(CustomBlock b : cb) {
BlockDesign bd = b.getBlockDesign();
String blkid = bd.getTexturePlugin() + "." + b.getName();
File imgfile = new File(f, blkid + ".png");
BufferedImage img = null;
boolean urlloaded = false;
String txname = bd.getTexureURL();
/* If not GenericCubiodBlockDesign, we don't handle it */
if((bd instanceof GenericCuboidBlockDesign) == false) {
Log.info("Block " + blkid + " not suppored - only cubiod blocks");
addDefaultBlock(sb, b);
continue;
}
/* Get texture info */
Texture txt = bd.getTexture();
int w = txt.getWidth();
int h = txt.getHeight();
int sz = txt.getSpriteSize();
GenericCuboidBlockDesign gbd = (GenericCuboidBlockDesign)bd;
int[] txtidx = new int[6];
/* Fetch quad fields - figure out which texture for which side */
try {
URL url = new URL(txname);
img = ImageIO.read(url); /* Load skin for player */
urlloaded = true;
} catch (IOException iox) {
if(txname.startsWith("http") == false) { /* Not URL - try file */
File tf = new File(txname);
if(tf.exists() == false) {
/* Horrible hack - try to find temp file (some SpoutMaterials versions) */
try {
File tmpf = File.createTempFile("dynmap", "test");
tf = new File(tmpf.getParent(), txname);
tmpf.delete();
} catch (IOException iox2) {}
float[][] textXPos = (float[][])textXPosField.get(gbd);
float[][] textYPos = (float[][])textYPosField.get(gbd);
/* Quads on cuboid are bottom, west, south, east, north, top */
for(int i = 0; i < 6; i++) {
float minx = 1.0F;
float miny = 1.0F;
for(int j = 0; j < 4; j++) {
minx = Math.min(minx, textXPos[i][j]);
miny = Math.min(miny, textYPos[i][j]);
}
if(tf.exists()) {
try {
img = ImageIO.read(tf);
urlloaded = true;
} catch (IOException iox3) {
txtidx[i] = (int)((minx * w)/sz) + (w/sz)*(int)((miny * h)/sz);
}
} catch (Exception iax) {
addDefaultBlock(sb, b);
continue;
}
String txname = bd.getTexureURL();
String txtid = texturelist.get(txname); /* Get texture */
if(txtid == null) { /* Not found yet */
File imgfile = new File(f, blkid + ".png");
BufferedImage img = null;
boolean urlloaded = false;
try {
URL url = new URL(txname);
img = ImageIO.read(url); /* Load skin for player */
urlloaded = true;
} catch (IOException iox) {
if(txname.startsWith("http") == false) { /* Not URL - try file */
File tf = new File(txname);
if(tf.exists() == false) {
/* Horrible hack - try to find temp file (some SpoutMaterials versions) */
try {
File tmpf = File.createTempFile("dynmap", "test");
tf = new File(tmpf.getParent(), txname);
tmpf.delete();
} catch (IOException iox2) {}
}
if(tf.exists()) {
try {
img = ImageIO.read(tf);
urlloaded = true;
} catch (IOException iox3) {
}
}
}
if(img == null) {
Log.severe("Error loading texture for custom block '" + blkid + "' (" + b.getCustomId() + ") from " + txname + "(" + iox.getMessage() + ")");
if(imgfile.exists()) {
try {
img = ImageIO.read(imgfile); /* Load existing */
Log.info("Loaded cached texture file for " + blkid);
} catch (IOException iox2) {
Log.severe("Error loading cached texture file for " + blkid + " - " + iox2.getMessage());
}
}
}
}
if(img == null) {
Log.severe("Error loading texture for custom block '" + blkid + "' (" + b.getCustomId() + ") from " + bd.getTexureURL() + "(" + iox.getMessage() + ")");
if(imgfile.exists()) {
try {
img = ImageIO.read(imgfile); /* Load existing */
Log.info("Loaded cached texture file for " + blkid);
} catch (IOException iox2) {
Log.severe("Error loading cached texture file for " + blkid + " - " + iox2.getMessage());
}
if(img != null) {
try {
if(urlloaded)
ImageIO.write(img, "png", imgfile);
} catch (IOException iox) {
Log.severe("Error writing " + blkid + ".png");
} finally {
img.flush();
}
String tfid = "txtid" + texturelist.size();
sb.append("texturefile:id=" + tfid + ",filename=spout/" + blkid + ".png,xcount=" + w/sz + ",ycount=" + h/sz + "\n");
texturelist.put(txname, tfid);
}
}
if(img != null) {
try {
if(urlloaded)
ImageIO.write(img, "png", imgfile);
blks.add(b);
int w = img.getWidth();
int h = img.getHeight();
/* If width >= 6 times height, we're using custom for each side */
sb.append("texturefile:id=" + blkid + ",filename=spout/" + blkid + ".png,xcount=" + w/h + ",ycount=1\n");
if(w >= (6*h)) {
sb.append("block:id=" + b.getCustomId() + ",data=*,bottom=0,north=1,south=2,east=3,west=4,top=5,txtid=" + blkid + "\n");
}
else {
sb.append("block:id=" + b.getCustomId() + ",data=*,allfaces=0,txtid=" + blkid + "\n");
}
cnt++;
} catch (IOException iox) {
Log.severe("Error writing " + blkid + ".png");
} finally {
img.flush();
}
String txfileid = texturelist.get(txname);
if(txfileid != null) {
blks.add(b);
sb.append("block:id=" + b.getCustomId() + ",data=*,bottom=" + txtidx[0] + ",west=" +txtidx[1] + ",south=" + txtidx[2] + ",east=" + txtidx[3] + ",north="+txtidx[4]+",top="+txtidx[5]);
if(b.isOpaque() == false)
sb.append(",transparency=TRANSPARENT");
sb.append(",txtid=" + txfileid + "\n");
cnt++;
}
}
String rslt = sb.toString();
+11 -10
View File
@@ -3,18 +3,13 @@
# All map templates are defined in the templates directory
# The 'classic' FlatMap and KzedMap templates are used, which can be found in normal.txt, nether.txt, and skylands.txt
# To use these, do not set deftemplatesuffix (make sure deftemplatesuffix is commented, below)
#
# To use the HDMap very-low-res map templates as world defaults (normal-vlowres, nether-vlowres and skylands-vlowres), uncomment the following line
# To use the HDMap very-low-res map templates as world defaults (normal-vlowres, nether-vlowres and skylands-vlowres), set value to vlowres
# The definitions of these templates are in normal-vlowres.txt, nether-vlowres.txt, and skylands-vlowres.txt
deftemplatesuffix: vlowres
#
# To use the HDMap low-res map templates as world defaults (normal-lowres, nether-lowres and skylands-lowres), uncomment the following line
# To use the HDMap low-res map templates as world defaults (normal-lowres, nether-lowres and skylands-lowres), set value to lowres
# The definitions of these templates are in normal-lowres.txt, nether-lowres.txt, and skylands-lowres.txt
#deftemplatesuffix: lowres
# To use the HDMap hi-res map templates (these can take a VERY long time for initial fullrender), comment the following line
# To use the HDMap hi-res 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 skylands-hires.txt
#deftemplatesuffix: hires
# Other values will search for templates named normal-<value>, nether-<value>, skylands-<value>
deftemplatesuffix: vlowres
components:
- class: org.dynmap.ClientConfigurationComponent
@@ -131,6 +126,7 @@ components:
type: coord
label: "Location"
hidey: false
show-mcr: false
#- class: org.dynmap.ClientComponent
# type: logo
@@ -226,8 +222,13 @@ compass-mode: newnorth
# Enable NetherOres block rendering support
#netherores-support: true
# Enable RailCraft block rendering support
#railcraft-support: true
# Enable Kaevator's Superslopes block rendering support
#superslopes-support: true
render-triggers:
#- chunkloaded
#- playermove
#- playerjoin
- blockplaced
+49
View File
@@ -73,6 +73,19 @@ commands:
/<command> listareas - list details of all areas
/<command> updatearea <label> <arg>:<value> ... - update attributes of area with given label
/<command> updatearea id:<id> <arg>:<value> ... - update attributes of area with given ID
dmap:
description: List and modify dynmap configuration
usage: |
/<command> worldlist - list all worlds configured (enabled or disabled)
/<command> worldset worldname enabled:<true|false> - enable or disable a world
/<command> worldset worldname center:<x/y/z|here|default> - set map center for given world
/<command> worldset worldname extrazoomout:<N> - set extra zoom out levels for given world
/<command> maplist worldname - list all maps for given world
/<command> mapdelete worldname:mapname - delete given map of given world
/<command> mapadd worldname:mapname attrib:value attrib:value - create map on given world with given attributes
/<command> mapset worldname:mapname attrib:value attrib:value - update given map on given world with given attributes
/<command> worldreset worldname - reset given world to default template for world type
/<command> worldreset worldname templatename - reset given world to given template
permissions:
dynmap.*:
@@ -113,6 +126,15 @@ permissions:
dynmap.marker.updatearea: true
dynmap.marker.listareas: true
dynmap.marker.deletearea: true
dynmap.dmap.worldlist: true
dynmap.dmap.worldset: true
dynmap.dmap.worldreset: true
dynmap.dmap.mapdelete: true
dynmap.dmap.mapset: true
dynmap.dmap.mapadd: true
dynmap.dmap.perspectivelist: true
dynmap.dmap.shaderlist: true
dynmap.dmap.lightinglist: true
dynmap.render:
description: Allows /dynmap render command
default: true
@@ -218,4 +240,31 @@ permissions:
dynmap.marker.deletearea:
description: Allows /dmarker deletearea
default: op
dynmap.dmap.worldlist:
description: Allows /dmap worldlist
default: op
dynmap.dmap.worldset:
description: Allows /dmap worldset
default: op
dynmap.dmap.worldreset:
description: Allows /dmap worldreset
default: op
dynmap.dmap.mapdelete:
description: Allows /dmap mapdelete
default: op
dynmap.dmap.mapset:
description: Allows /dmap mapset
default: op
dynmap.dmap.mapadd:
description: Allows /dmap mapadd
default: op
dynmap.dmap.perspectivelist:
description: Allows /dmap perspectivelist
default: op
dynmap.dmap.shaderlist:
description: Allows /dmap shaderlist
default: op
dynmap.dmap.lightinglist:
description: Allows /dmap lightinglist
default: op