mirror of
https://github.com/webbukkit/dynmap.git
synced 2025-01-12 19:00:44 +01:00
Merge remote-tracking branch 'upstream/master'
Conflicts: src/main/java/org/dynmap/flat/FlatMap.java
This commit is contained in:
commit
69b562a5bf
@ -75,7 +75,7 @@ worlds:
|
||||
renderers:
|
||||
- class: org.dynmap.kzedmap.DefaultTileRenderer
|
||||
prefix: nt
|
||||
maximumheight: 64
|
||||
maximumheight: 127
|
||||
colorscheme: default
|
||||
|
||||
web:
|
||||
@ -88,6 +88,12 @@ web:
|
||||
allowchat: true
|
||||
allowwebchat: true
|
||||
webchat-interval: 5
|
||||
# Set to true to enable HeroChat support
|
||||
enableherochat: false
|
||||
# Control which HeroChat channel messages from web are directed to
|
||||
herochatwebchannel: Global
|
||||
# Control which channels are monitored and reported to the web
|
||||
herochatchannels: [ Global ]
|
||||
|
||||
showplayerfacesinmenu: true
|
||||
|
||||
|
46
src/main/java/org/dynmap/Color.java
Normal file
46
src/main/java/org/dynmap/Color.java
Normal file
@ -0,0 +1,46 @@
|
||||
package org.dynmap;
|
||||
|
||||
/**
|
||||
* Simple replacement for java.awt.Color for dynmap - it's not an invariant, so we don't make millions
|
||||
* of them during rendering
|
||||
*/
|
||||
public class Color {
|
||||
/* RGBA value */
|
||||
private int val;
|
||||
|
||||
public static final int TRANSPARENT = 0;
|
||||
|
||||
public Color(int red, int green, int blue, int alpha) {
|
||||
setRGBA(red, green, blue, alpha);
|
||||
}
|
||||
public Color(int red, int green, int blue) {
|
||||
setRGBA(red, green, blue, 0xFF);
|
||||
}
|
||||
public Color() {
|
||||
setTransparent();
|
||||
}
|
||||
public final int getRed() {
|
||||
return (val >> 24) & 0xFF;
|
||||
}
|
||||
public final int getGreen() {
|
||||
return (val >> 16) & 0xFF;
|
||||
}
|
||||
public final int getBlue() {
|
||||
return (val >> 8) & 0xFF;
|
||||
}
|
||||
public final int getAlpha() {
|
||||
return (val & 0xFF);
|
||||
}
|
||||
public final boolean isTransparent() {
|
||||
return (val == TRANSPARENT);
|
||||
}
|
||||
public final void setTransparent() {
|
||||
val = TRANSPARENT;
|
||||
}
|
||||
public final void setColor(Color c) {
|
||||
val = c.val;
|
||||
}
|
||||
public final void setRGBA(int red, int green, int blue, int alpha) {
|
||||
val = ((red & 0xFF) << 24) | ((green & 0xFF) << 16) | ((blue & 0xFF) << 8) | (alpha & 0xFF);
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.awt.Color;
|
||||
import org.dynmap.Color;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
|
@ -58,6 +58,7 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
public Configuration configuration;
|
||||
public HashSet<String> enabledTriggers = new HashSet<String>();
|
||||
public PermissionProvider permissions;
|
||||
public HeroChatHandler hchand;
|
||||
|
||||
public Timer timer;
|
||||
|
||||
@ -106,12 +107,18 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
timer.scheduleAtFixedRate(new JsonTimerTask(this, configuration), jsonInterval, jsonInterval);
|
||||
}
|
||||
|
||||
hchand = new HeroChatHandler(configuration, this, getServer());
|
||||
|
||||
enabledTriggers.clear();
|
||||
for (Object trigger : configuration.getList("render-triggers")) {
|
||||
enabledTriggers.add((String) trigger);
|
||||
}
|
||||
|
||||
registerEvents();
|
||||
|
||||
/* Print version info */
|
||||
PluginDescriptionFile pdfFile = this.getDescription();
|
||||
log.info("[dynmap] version " + pdfFile.getVersion() + " is enabled" );
|
||||
}
|
||||
|
||||
public void loadWebserver() {
|
||||
@ -154,9 +161,7 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
} catch (IOException e) {
|
||||
log.severe("Failed to start WebServer on " + bindAddress + ":" + port + "!");
|
||||
}
|
||||
/* Print version info */
|
||||
PluginDescriptionFile pdfFile = this.getDescription();
|
||||
log.info("[dynmap] version " + pdfFile.getVersion() + " is enabled" );
|
||||
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
@ -402,6 +407,8 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
public void webChat(String name, String message) {
|
||||
mapManager.pushUpdate(new Client.ChatMessage("web", name, message));
|
||||
log.info("[WEB]" + name + ": " + message);
|
||||
getServer().broadcastMessage("[WEB]" + name + ": " + message);
|
||||
/* Let HeroChat take a look - only broadcast to players if it doesn't handle it */
|
||||
if(hchand.sendWebMessageToHeroChat(name, message) == false)
|
||||
getServer().broadcastMessage("[WEB]" + name + ": " + message);
|
||||
}
|
||||
}
|
||||
|
282
src/main/java/org/dynmap/HeroChatHandler.java
Normal file
282
src/main/java/org/dynmap/HeroChatHandler.java
Normal file
@ -0,0 +1,282 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.event.CustomEventListener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.util.config.Configuration;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.server.PluginEnableEvent;
|
||||
import org.bukkit.event.server.ServerListener;
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class HeroChatHandler {
|
||||
protected static final Logger log = Logger.getLogger("Minecraft");
|
||||
|
||||
private static final String DEF_CHANNEL = "Global";
|
||||
private static final List<String> DEF_CHANNELS = Collections
|
||||
.singletonList(DEF_CHANNEL);
|
||||
|
||||
private List<String> hcchannels;
|
||||
private String hcwebinputchannel;
|
||||
private HeroChatChannel hcwebinputchan;
|
||||
private DynmapPlugin plugin;
|
||||
|
||||
private class OurPluginListener extends ServerListener {
|
||||
@Override
|
||||
public void onPluginEnable(PluginEnableEvent event) {
|
||||
Plugin plugin = event.getPlugin();
|
||||
String name = plugin.getDescription().getName();
|
||||
|
||||
if (name.equals("HeroChat")) {
|
||||
activateHeroChat(plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reflection-based access wrapper for ChannelChatEvent from HeroChat */
|
||||
private static class HeroChatChannelChatEvent {
|
||||
private static Class channelchatevent;
|
||||
private static Method getsource;
|
||||
private static Method getmessage;
|
||||
private static boolean isgood = false;
|
||||
private Event evt;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static boolean initialize() {
|
||||
try {
|
||||
channelchatevent = Class
|
||||
.forName("com.herocraftonline.dthielke.herochat.event.ChannelChatEvent");
|
||||
getsource = channelchatevent.getMethod("getSource", new Class[0]);
|
||||
getmessage = channelchatevent.getMethod("getMessage", new Class[0]);
|
||||
isgood = true;
|
||||
} catch (ClassNotFoundException cnfx) {
|
||||
} catch (NoSuchMethodException nsmx) {
|
||||
}
|
||||
return isgood;
|
||||
}
|
||||
|
||||
public HeroChatChannelChatEvent(Event evt) {
|
||||
this.evt = evt;
|
||||
}
|
||||
|
||||
public static boolean isInstance(Event evt) {
|
||||
return channelchatevent.isInstance(evt);
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
try {
|
||||
return (String) getsource.invoke(evt);
|
||||
} catch (Exception x) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
try {
|
||||
return (String) getmessage.invoke(evt);
|
||||
} catch (Exception x) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reflection-based access wrapper for ChannelEvent from HeroChat */
|
||||
private static class HeroChatChannelEvent {
|
||||
private static Class channelevent;
|
||||
private static Method getchannel;
|
||||
private static Method iscancelled;
|
||||
private static boolean isgood = false;
|
||||
private Event evt;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static boolean initialize() {
|
||||
try {
|
||||
channelevent = Class
|
||||
.forName("com.herocraftonline.dthielke.herochat.event.ChannelEvent");
|
||||
getchannel = channelevent.getMethod("getChannel", new Class[0]);
|
||||
iscancelled = channelevent.getMethod("isCancelled", new Class[0]);
|
||||
isgood = true;
|
||||
} catch (ClassNotFoundException cnfx) {
|
||||
} catch (NoSuchMethodException nsmx) {
|
||||
}
|
||||
return isgood;
|
||||
}
|
||||
|
||||
public HeroChatChannelEvent(Event evt) {
|
||||
this.evt = evt;
|
||||
}
|
||||
|
||||
public static boolean isInstance(Event evt) {
|
||||
return channelevent.isInstance(evt);
|
||||
}
|
||||
|
||||
public HeroChatChannel getChannel() {
|
||||
try {
|
||||
Object o;
|
||||
o = getchannel.invoke(evt);
|
||||
if (o != null) {
|
||||
return new HeroChatChannel(o);
|
||||
}
|
||||
} catch (Exception x) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
try {
|
||||
return (Boolean) iscancelled.invoke(evt);
|
||||
} catch (Exception x) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reflection-based access wrapper for Channel from HeroChat */
|
||||
private static class HeroChatChannel {
|
||||
private static Class channel;
|
||||
private static Method getname;
|
||||
private static Method getnick;
|
||||
private static Method sendmessage;
|
||||
private static boolean isgood = false;
|
||||
private Object chan;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static boolean initialize() {
|
||||
try {
|
||||
channel = Class
|
||||
.forName("com.herocraftonline.dthielke.herochat.channels.Channel");
|
||||
getname = channel.getMethod("getName");
|
||||
getnick = channel.getMethod("getNick", new Class[0]);
|
||||
sendmessage = channel.getMethod("sendMessage", new Class[] {
|
||||
String.class, String.class, String.class, boolean.class } );
|
||||
isgood = true;
|
||||
} catch (ClassNotFoundException cnfx) {
|
||||
} catch (NoSuchMethodException nsmx) {
|
||||
System.out.println(nsmx);
|
||||
}
|
||||
return isgood;
|
||||
}
|
||||
|
||||
public HeroChatChannel(Object chan) {
|
||||
this.chan = chan;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
try {
|
||||
return (String) getname.invoke(chan);
|
||||
} catch (Exception x) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getNick() {
|
||||
try {
|
||||
return (String) getnick.invoke(chan);
|
||||
} catch (Exception x) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessage(String source, String msg, String format, boolean sentByPlayer) {
|
||||
try {
|
||||
sendmessage.invoke(chan, source, msg, format, sentByPlayer);
|
||||
} catch (Exception x) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class OurEventListener extends CustomEventListener {
|
||||
/**
|
||||
* Handle custom events
|
||||
*/
|
||||
@Override
|
||||
public void onCustomEvent(Event event) {
|
||||
if (HeroChatChannelEvent.isInstance(event)) {
|
||||
HeroChatChannelEvent ce = new HeroChatChannelEvent(event);
|
||||
/* Snoop for our web channel - we'll need it, and we'll see it before it matters,
|
||||
* since anyone that joins the channel will give us an event (and reflection on
|
||||
* the plugin class to get the manager didn't work, due to a dependency on the IRC
|
||||
* plugin that may not be present....)
|
||||
*/
|
||||
HeroChatChannel c = ce.getChannel();
|
||||
/* If channel name or nickname matches out web channel, remember it */
|
||||
if((c != null) && (hcwebinputchannel != null) &&
|
||||
((c.getName().equals(hcwebinputchannel)) ||
|
||||
c.getNick().equals(hcwebinputchannel))) {
|
||||
hcwebinputchan = c;
|
||||
}
|
||||
if (ce.isCancelled())
|
||||
return;
|
||||
if (HeroChatChannelChatEvent.isInstance(event)) {
|
||||
HeroChatChannelChatEvent cce = new HeroChatChannelChatEvent(
|
||||
event);
|
||||
/* Match on name or nickname of channel */
|
||||
if (hcchannels.contains(c.getName()) ||
|
||||
hcchannels.contains(c.getNick())) {
|
||||
plugin.mapManager.pushUpdate(new Client.ChatMessage(
|
||||
"player", "[" + c.getNick() + "] "
|
||||
+ cce.getSource(), cce.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HeroChatHandler(Configuration cfg, DynmapPlugin plugin, Server server) {
|
||||
/* If we're enabling hero chat support */
|
||||
if (cfg.getNode("web").getBoolean("enableherochat", false)) {
|
||||
log.info("[dynmap] HeroChat support configured");
|
||||
this.plugin = plugin;
|
||||
/* Now, get the monitored channel list */
|
||||
hcchannels = cfg.getNode("web").getStringList("herochatchannels",
|
||||
DEF_CHANNELS);
|
||||
/* And get channel to send web messages */
|
||||
hcwebinputchannel = cfg.getNode("web").getString(
|
||||
"herochatwebchannel", DEF_CHANNEL);
|
||||
/* Set up to hear when HeroChat is enabled */
|
||||
server.getPluginManager().registerEvent(Event.Type.PLUGIN_ENABLE,
|
||||
new OurPluginListener(), Event.Priority.Normal, plugin);
|
||||
}
|
||||
}
|
||||
|
||||
private void activateHeroChat(Plugin herochat) {
|
||||
if (HeroChatChannelChatEvent.initialize() == false) {
|
||||
log.severe("[dynmap] Cannot load HeroChat chat event class!");
|
||||
return;
|
||||
}
|
||||
if (HeroChatChannel.initialize() == false) {
|
||||
log.severe("[dynmap] Cannot load HeroChat channel class!");
|
||||
return;
|
||||
}
|
||||
if (HeroChatChannelEvent.initialize() == false) {
|
||||
log.severe("[dynmap] Cannot load HeroChat channel event class!");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Register event handler */
|
||||
plugin.getServer().getPluginManager().registerEvent(Event.Type.CUSTOM_EVENT,
|
||||
new OurEventListener(), Event.Priority.Monitor, plugin);
|
||||
log.info("[dynmap] HeroChat integration active");
|
||||
}
|
||||
/**
|
||||
* Send message from web to appropriate HeroChat channel
|
||||
* @param sender - sender ID
|
||||
* @param message - message
|
||||
* @return true if herochat is handling this, false if not
|
||||
*/
|
||||
public boolean sendWebMessageToHeroChat(String sender, String message) {
|
||||
if(hcwebinputchannel != null) { /* Are we handling them? */
|
||||
if(hcwebinputchan != null) { /* Have we seen it yet? Maybe no if nobody has logged on or
|
||||
* joined it, but then who would see it anyway?
|
||||
*/
|
||||
hcwebinputchan.sendMessage(sender, message, "{default}", false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -11,10 +11,11 @@ public class UpdateQueue {
|
||||
|
||||
private static final int maxUpdateAge = 120000;
|
||||
|
||||
public synchronized void pushUpdate(Object obj) {
|
||||
long now = System.currentTimeMillis();
|
||||
long deadline = now - maxUpdateAge;
|
||||
public void pushUpdate(Object obj) {
|
||||
synchronized (lock) {
|
||||
/* Do inside lock - prevent delay between time and actual work */
|
||||
long now = System.currentTimeMillis();
|
||||
long deadline = now - maxUpdateAge;
|
||||
ListIterator<Update> i = updateQueue.listIterator(0);
|
||||
while (i.hasNext()) {
|
||||
Update u = i.next();
|
||||
@ -27,11 +28,11 @@ public class UpdateQueue {
|
||||
|
||||
private ArrayList<Object> tmpupdates = new ArrayList<Object>();
|
||||
|
||||
public synchronized Object[] getUpdatedObjects(long since) {
|
||||
long now = System.currentTimeMillis();
|
||||
long deadline = now - maxUpdateAge;
|
||||
public Object[] getUpdatedObjects(long since) {
|
||||
Object[] updates;
|
||||
synchronized (lock) {
|
||||
long now = System.currentTimeMillis();
|
||||
long deadline = now - maxUpdateAge;
|
||||
tmpupdates.clear();
|
||||
Iterator<Update> it = updateQueue.descendingIterator();
|
||||
while (it.hasNext()) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
package org.dynmap.flat;
|
||||
|
||||
import java.awt.Color;
|
||||
import org.dynmap.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.io.File;
|
||||
@ -11,6 +11,7 @@ import javax.imageio.ImageIO;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.dynmap.Client;
|
||||
import org.dynmap.ColorScheme;
|
||||
import org.dynmap.DynmapChunk;
|
||||
@ -22,10 +23,17 @@ import org.dynmap.debug.Debug;
|
||||
public class FlatMap extends MapType {
|
||||
private String prefix;
|
||||
private ColorScheme colorScheme;
|
||||
|
||||
private int maximumHeight = 127;
|
||||
|
||||
public FlatMap(Map<String, Object> configuration) {
|
||||
prefix = (String) configuration.get("prefix");
|
||||
colorScheme = ColorScheme.getScheme((String) configuration.get("colorscheme"));
|
||||
Object o = configuration.get("maximumheight");
|
||||
if (o != null) {
|
||||
maximumHeight = Integer.parseInt(String.valueOf(o));
|
||||
if (maximumHeight > 127)
|
||||
maximumHeight = 127;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -68,6 +76,7 @@ public class FlatMap extends MapType {
|
||||
public boolean render(MapTile tile, File outputFile) {
|
||||
FlatMapTile t = (FlatMapTile) tile;
|
||||
World w = t.getWorld();
|
||||
boolean isnether = (w.getEnvironment() == Environment.NETHER) && (maximumHeight == 127);
|
||||
|
||||
boolean rendered = false;
|
||||
BufferedImage im = new BufferedImage(t.size, t.size, BufferedImage.TYPE_INT_RGB);
|
||||
@ -79,17 +88,40 @@ public class FlatMap extends MapType {
|
||||
for (int y = 0; y < t.size; y++) {
|
||||
int mx = x + t.x * t.size;
|
||||
int mz = y + t.y * t.size;
|
||||
int my = w.getHighestBlockYAt(mx, mz) - 1;
|
||||
int blockType = w.getBlockTypeIdAt(mx, my, mz);
|
||||
byte data = 0;
|
||||
if(colorScheme.datacolors[blockType] != null) { /* If data colored */
|
||||
data = w.getBlockAt(mx, my, mz).getData();
|
||||
int my;
|
||||
int blockType;
|
||||
if(isnether) {
|
||||
/* Scan until we hit air */
|
||||
my = 127;
|
||||
while((blockType = w.getBlockTypeIdAt(mx, my, mz)) != 0) {
|
||||
my--;
|
||||
if(my < 0) { /* Solid - use top */
|
||||
my = 127;
|
||||
blockType = w.getBlockTypeIdAt(mx, my, mz);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(blockType == 0) { /* Hit air - now find non-air */
|
||||
while((blockType = w.getBlockTypeIdAt(mx, my, mz)) == 0) {
|
||||
my--;
|
||||
if(my < 0) {
|
||||
my = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
my = w.getHighestBlockYAt(mx, mz) - 1;
|
||||
if(my > maximumHeight) my = maximumHeight;
|
||||
blockType = w.getBlockTypeIdAt(mx, my, mz);
|
||||
}
|
||||
byte data = 0;
|
||||
Color[] colors = colorScheme.colors[blockType];
|
||||
if(colorScheme.datacolors[blockType] != null) {
|
||||
data = w.getBlockAt(mx, my, mz).getData();
|
||||
colors = colorScheme.datacolors[blockType][data];
|
||||
}
|
||||
Color[] colors;
|
||||
if(data != 0)
|
||||
colors = colorScheme.datacolors[blockType][data];
|
||||
else
|
||||
colors = colorScheme.colors[blockType];
|
||||
if (colors == null)
|
||||
continue;
|
||||
Color c = colors[0];
|
||||
@ -103,7 +135,7 @@ public class FlatMap extends MapType {
|
||||
|
||||
// Defines the 'step' in coloring.
|
||||
float step = 10 / 128.0f;
|
||||
|
||||
|
||||
// The step applied to height.
|
||||
float scale = ((int)(height/step))*step;
|
||||
|
||||
@ -135,19 +167,19 @@ public class FlatMap extends MapType {
|
||||
final MapTile mtile = tile;
|
||||
final BufferedImage img = im;
|
||||
MapManager.mapman.enqueueImageWrite(new Runnable() {
|
||||
public void run() {
|
||||
Debug.debug("saving image " + fname.getPath());
|
||||
try {
|
||||
ImageIO.write(img, "png", fname);
|
||||
} catch (IOException e) {
|
||||
Debug.error("Failed to save image: " + fname.getPath(), e);
|
||||
} catch (java.lang.NullPointerException e) {
|
||||
Debug.error("Failed to save image (NullPointerException): " + fname.getPath(), e);
|
||||
}
|
||||
img.flush();
|
||||
MapManager.mapman.pushUpdate(mtile.getWorld(),
|
||||
new Client.Tile(mtile.getFilename()));
|
||||
}
|
||||
public void run() {
|
||||
Debug.debug("saving image " + fname.getPath());
|
||||
try {
|
||||
ImageIO.write(img, "png", fname);
|
||||
} catch (IOException e) {
|
||||
Debug.error("Failed to save image: " + fname.getPath(), e);
|
||||
} catch (java.lang.NullPointerException e) {
|
||||
Debug.error("Failed to save image (NullPointerException): " + fname.getPath(), e);
|
||||
}
|
||||
img.flush();
|
||||
MapManager.mapman.pushUpdate(mtile.getWorld(),
|
||||
new Client.Tile(mtile.getFilename()));
|
||||
}
|
||||
});
|
||||
|
||||
return rendered;
|
||||
|
@ -1,6 +1,6 @@
|
||||
package org.dynmap.kzedmap;
|
||||
|
||||
import java.awt.Color;
|
||||
import org.dynmap.Color;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.World;
|
||||
@ -12,14 +12,20 @@ public class CaveTileRenderer extends DefaultTileRenderer {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Color scan(World world, int x, int y, int z, int seq) {
|
||||
protected void scan(World world, int x, int y, int z, int seq, boolean isnether, final Color result) {
|
||||
boolean air = true;
|
||||
|
||||
result.setTransparent();
|
||||
for (;;) {
|
||||
if (y < 0)
|
||||
return translucent;
|
||||
return;
|
||||
|
||||
int id = world.getBlockTypeIdAt(x, y, z);
|
||||
if(isnether) { /* Make ceiling into air in nether */
|
||||
if(id != 0)
|
||||
id = 0;
|
||||
else
|
||||
isnether = false;
|
||||
}
|
||||
|
||||
switch (seq) {
|
||||
case 0:
|
||||
@ -87,7 +93,8 @@ public class CaveTileRenderer extends DefaultTileRenderer {
|
||||
cg = cg * mult / 256;
|
||||
cb = cb * mult / 256;
|
||||
|
||||
return new Color(cr, cg, cb);
|
||||
result.setRGBA(cr, cg, cb, 255);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package org.dynmap.kzedmap;
|
||||
|
||||
import java.awt.Color;
|
||||
import org.dynmap.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
@ -12,7 +12,9 @@ import java.util.Map;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.dynmap.Client;
|
||||
import org.dynmap.ColorScheme;
|
||||
import org.dynmap.MapManager;
|
||||
@ -28,25 +30,6 @@ public class DefaultTileRenderer implements MapTileRenderer {
|
||||
protected HashSet<Integer> highlightBlocks = new HashSet<Integer>();
|
||||
protected Color highlightColor = new Color(255, 0, 0);
|
||||
|
||||
private static final Color[] woolshades = {
|
||||
Color.WHITE,
|
||||
Color.ORANGE,
|
||||
Color.MAGENTA,
|
||||
new Color(51,204,255),
|
||||
Color.YELLOW,
|
||||
new Color(102,255,102),
|
||||
Color.PINK,
|
||||
Color.GRAY,
|
||||
Color.LIGHT_GRAY,
|
||||
Color.CYAN,
|
||||
new Color(255,0,255),
|
||||
Color.BLUE,
|
||||
new Color(102,51,51),
|
||||
Color.GREEN,
|
||||
Color.RED,
|
||||
Color.BLACK
|
||||
};
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
@ -65,6 +48,7 @@ public class DefaultTileRenderer implements MapTileRenderer {
|
||||
|
||||
public boolean render(KzedMapTile tile, File outputFile) {
|
||||
World world = tile.getWorld();
|
||||
boolean isnether = (world.getEnvironment() == Environment.NETHER);
|
||||
BufferedImage im = new BufferedImage(KzedMap.tileWidth, KzedMap.tileHeight, BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
WritableRaster r = im.getRaster();
|
||||
@ -74,28 +58,36 @@ public class DefaultTileRenderer implements MapTileRenderer {
|
||||
int iy = maximumHeight;
|
||||
int iz = KzedMap.anchorz + tile.px / 2 - tile.py / 2 + ((127-maximumHeight)/2);
|
||||
|
||||
/* Don't mess with existing height-clipped renders */
|
||||
if(maximumHeight < 127)
|
||||
isnether = false;
|
||||
|
||||
int jx, jz;
|
||||
|
||||
|
||||
int x, y;
|
||||
|
||||
Color c1 = new Color();
|
||||
Color c2 = new Color();
|
||||
int[] rgb = new int[3];
|
||||
/* draw the map */
|
||||
for (y = 0; y < KzedMap.tileHeight;) {
|
||||
jx = ix;
|
||||
jz = iz;
|
||||
|
||||
for (x = KzedMap.tileWidth - 1; x >= 0; x -= 2) {
|
||||
Color c1 = scan(world, jx, iy, jz, 0);
|
||||
Color c2 = scan(world, jx, iy, jz, 2);
|
||||
isempty = isempty && c1 == translucent && c2 == translucent;
|
||||
r.setPixel(x, y, new int[] {
|
||||
c1.getRed(),
|
||||
c1.getGreen(),
|
||||
c1.getBlue() });
|
||||
r.setPixel(x - 1, y, new int[] {
|
||||
c2.getRed(),
|
||||
c2.getGreen(),
|
||||
c2.getBlue() });
|
||||
|
||||
scan(world, jx, iy, jz, 0, isnether, c1);
|
||||
scan(world, jx, iy, jz, 2, isnether, c2);
|
||||
if(c1.isTransparent() == false) {
|
||||
rgb[0] = c1.getRed(); rgb[1] = c1.getGreen(); rgb[2] = c1.getBlue();
|
||||
r.setPixel(x, y, rgb);
|
||||
isempty = false;
|
||||
}
|
||||
if(c2.isTransparent() == false) {
|
||||
rgb[0] = c2.getRed(); rgb[1] = c2.getGreen(); rgb[2] = c2.getBlue();
|
||||
r.setPixel(x - 1, y, rgb);
|
||||
isempty = false;
|
||||
}
|
||||
|
||||
jx++;
|
||||
jz++;
|
||||
|
||||
@ -107,19 +99,21 @@ public class DefaultTileRenderer implements MapTileRenderer {
|
||||
jz = iz - 1;
|
||||
|
||||
for (x = KzedMap.tileWidth - 1; x >= 0; x -= 2) {
|
||||
Color c1 = scan(world, jx, iy, jz, 2);
|
||||
scan(world, jx, iy, jz, 2, isnether, c1);
|
||||
jx++;
|
||||
jz++;
|
||||
Color c2 = scan(world, jx, iy, jz, 0);
|
||||
isempty = isempty && c1 == translucent && c2 == translucent;
|
||||
r.setPixel(x, y, new int[] {
|
||||
c1.getRed(),
|
||||
c1.getGreen(),
|
||||
c1.getBlue() });
|
||||
r.setPixel(x - 1, y, new int[] {
|
||||
c2.getRed(),
|
||||
c2.getGreen(),
|
||||
c2.getBlue() });
|
||||
scan(world, jx, iy, jz, 0, isnether, c2);
|
||||
if(c1.isTransparent() == false) {
|
||||
rgb[0] = c1.getRed(); rgb[1] = c1.getGreen(); rgb[2] = c1.getBlue();
|
||||
r.setPixel(x, y, rgb);
|
||||
isempty = false;
|
||||
}
|
||||
if(c2.isTransparent() == false) {
|
||||
rgb[0] = c2.getRed(); rgb[1] = c2.getGreen(); rgb[2] = c2.getBlue();
|
||||
|
||||
r.setPixel(x - 1, y, rgb);
|
||||
isempty = false;
|
||||
}
|
||||
}
|
||||
|
||||
y++;
|
||||
@ -132,100 +126,112 @@ public class DefaultTileRenderer implements MapTileRenderer {
|
||||
final File fname = outputFile;
|
||||
final KzedMapTile mtile = tile;
|
||||
final BufferedImage img = im;
|
||||
final KzedZoomedMapTile zmtile = new KzedZoomedMapTile(mtile.getWorld(),
|
||||
(KzedMap) mtile.getMap(), mtile);
|
||||
final File zoomFile = MapManager.mapman.getTileFile(zmtile);
|
||||
|
||||
MapManager.mapman.enqueueImageWrite(new Runnable() {
|
||||
public void run() {
|
||||
doFileWrites(fname, mtile, img, zmtile, zoomFile);
|
||||
}
|
||||
final KzedZoomedMapTile zmtile = new KzedZoomedMapTile(mtile.getWorld(),
|
||||
(KzedMap) mtile.getMap(), mtile);
|
||||
final File zoomFile = MapManager.mapman.getTileFile(zmtile);
|
||||
|
||||
MapManager.mapman.enqueueImageWrite(new Runnable() {
|
||||
public void run() {
|
||||
doFileWrites(fname, mtile, img, zmtile, zoomFile);
|
||||
}
|
||||
});
|
||||
|
||||
return !isempty;
|
||||
}
|
||||
|
||||
private void doFileWrites(final File fname, final KzedMapTile mtile,
|
||||
final BufferedImage img, final KzedZoomedMapTile zmtile, final File zoomFile) {
|
||||
Debug.debug("saving image " + fname.getPath());
|
||||
try {
|
||||
ImageIO.write(img, "png", fname);
|
||||
} catch (IOException e) {
|
||||
Debug.error("Failed to save image: " + fname.getPath(), e);
|
||||
} catch (java.lang.NullPointerException e) {
|
||||
Debug.error("Failed to save image (NullPointerException): " + fname.getPath(), e);
|
||||
}
|
||||
mtile.file = fname;
|
||||
// Since we've already got the new tile, and we're on an async thread, just
|
||||
// make the zoomed tile here
|
||||
int px = mtile.px;
|
||||
int py = mtile.py;
|
||||
int zpx = zmtile.getTileX();
|
||||
int zpy = zmtile.getTileY();
|
||||
final BufferedImage img, final KzedZoomedMapTile zmtile, final File zoomFile) {
|
||||
Debug.debug("saving image " + fname.getPath());
|
||||
try {
|
||||
ImageIO.write(img, "png", fname);
|
||||
} catch (IOException e) {
|
||||
Debug.error("Failed to save image: " + fname.getPath(), e);
|
||||
} catch (java.lang.NullPointerException e) {
|
||||
Debug.error("Failed to save image (NullPointerException): " + fname.getPath(), e);
|
||||
}
|
||||
mtile.file = fname;
|
||||
// Since we've already got the new tile, and we're on an async thread, just
|
||||
// make the zoomed tile here
|
||||
int px = mtile.px;
|
||||
int py = mtile.py;
|
||||
int zpx = zmtile.getTileX();
|
||||
int zpy = zmtile.getTileY();
|
||||
|
||||
/* scaled size */
|
||||
int scw = KzedMap.tileWidth / 2;
|
||||
int sch = KzedMap.tileHeight / 2;
|
||||
/* scaled size */
|
||||
int scw = KzedMap.tileWidth / 2;
|
||||
int sch = KzedMap.tileHeight / 2;
|
||||
|
||||
/* origin in zoomed-out tile */
|
||||
int ox = 0;
|
||||
int oy = 0;
|
||||
/* origin in zoomed-out tile */
|
||||
int ox = 0;
|
||||
int oy = 0;
|
||||
|
||||
if (zpx != px)
|
||||
ox = scw;
|
||||
if (zpy != py)
|
||||
oy = sch;
|
||||
if (zpx != px)
|
||||
ox = scw;
|
||||
if (zpy != py)
|
||||
oy = sch;
|
||||
|
||||
BufferedImage zIm = null;
|
||||
try {
|
||||
zIm = ImageIO.read(zoomFile);
|
||||
} catch (IOException e) {
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
}
|
||||
BufferedImage zIm = null;
|
||||
try {
|
||||
zIm = ImageIO.read(zoomFile);
|
||||
} catch (IOException e) {
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
}
|
||||
|
||||
if (zIm == null) {
|
||||
/* create new one */
|
||||
zIm = new BufferedImage(KzedMap.tileWidth, KzedMap.tileHeight, BufferedImage.TYPE_INT_RGB);
|
||||
Debug.debug("New zoom-out tile created " + zmtile.getFilename());
|
||||
} else {
|
||||
Debug.debug("Loaded zoom-out tile from " + zmtile.getFilename());
|
||||
}
|
||||
|
||||
/* blit scaled rendered tile onto zoom-out tile */
|
||||
Graphics2D g2 = zIm.createGraphics();
|
||||
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||
g2.drawImage(img, ox, oy, scw, sch, null);
|
||||
if (zIm == null) {
|
||||
/* create new one */
|
||||
zIm = new BufferedImage(KzedMap.tileWidth, KzedMap.tileHeight, BufferedImage.TYPE_INT_RGB);
|
||||
Debug.debug("New zoom-out tile created " + zmtile.getFilename());
|
||||
} else {
|
||||
Debug.debug("Loaded zoom-out tile from " + zmtile.getFilename());
|
||||
}
|
||||
|
||||
/* blit scaled rendered tile onto zoom-out tile */
|
||||
Graphics2D g2 = zIm.createGraphics();
|
||||
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||
g2.drawImage(img, ox, oy, scw, sch, null);
|
||||
|
||||
img.flush();
|
||||
img.flush();
|
||||
|
||||
/* save zoom-out tile */
|
||||
|
||||
try {
|
||||
ImageIO.write(zIm, "png", zoomFile);
|
||||
Debug.debug("Saved zoom-out tile at " + zoomFile.getName());
|
||||
} catch (IOException e) {
|
||||
Debug.error("Failed to save zoom-out tile: " + zoomFile.getName(), e);
|
||||
} catch (java.lang.NullPointerException e) {
|
||||
Debug.error("Failed to save zoom-out tile (NullPointerException): " + zoomFile.getName(), e);
|
||||
}
|
||||
zIm.flush();
|
||||
/* Push updates for both files.*/
|
||||
MapManager.mapman.pushUpdate(mtile.getWorld(),
|
||||
new Client.Tile(mtile.getFilename()));
|
||||
MapManager.mapman.pushUpdate(zmtile.getWorld(),
|
||||
new Client.Tile(zmtile.getFilename()));
|
||||
/* save zoom-out tile */
|
||||
|
||||
try {
|
||||
ImageIO.write(zIm, "png", zoomFile);
|
||||
Debug.debug("Saved zoom-out tile at " + zoomFile.getName());
|
||||
} catch (IOException e) {
|
||||
Debug.error("Failed to save zoom-out tile: " + zoomFile.getName(), e);
|
||||
} catch (java.lang.NullPointerException e) {
|
||||
Debug.error("Failed to save zoom-out tile (NullPointerException): " + zoomFile.getName(), e);
|
||||
}
|
||||
zIm.flush();
|
||||
/* Push updates for both files.*/
|
||||
MapManager.mapman.pushUpdate(mtile.getWorld(),
|
||||
new Client.Tile(mtile.getFilename()));
|
||||
MapManager.mapman.pushUpdate(zmtile.getWorld(),
|
||||
new Client.Tile(zmtile.getFilename()));
|
||||
}
|
||||
|
||||
|
||||
protected Color scan(World world, int x, int y, int z, int seq) {
|
||||
protected void scan(World world, int x, int y, int z, int seq, boolean isnether, final Color result) {
|
||||
result.setTransparent();
|
||||
for (;;) {
|
||||
if (y < 0)
|
||||
return translucent;
|
||||
|
||||
if (y < 0) {
|
||||
return;
|
||||
}
|
||||
int id = world.getBlockTypeIdAt(x, y, z);
|
||||
byte data = 0;
|
||||
if(colorScheme.datacolors[id] != null) { /* If data colored */
|
||||
data = world.getBlockAt(x, y, z).getData();
|
||||
if(isnether) { /* Make bedrock ceiling into air in nether */
|
||||
if(id != 0) {
|
||||
/* Remember first color we see, in case we wind up solid */
|
||||
if(result.isTransparent())
|
||||
if(colorScheme.colors[id] != null)
|
||||
result.setColor(colorScheme.colors[id][seq]);
|
||||
id = 0;
|
||||
}
|
||||
else
|
||||
isnether = false;
|
||||
}
|
||||
if(colorScheme.datacolors[id] != null) { /* If data colored */
|
||||
data = world.getBlockAt(x, y, z).getData();
|
||||
}
|
||||
switch (seq) {
|
||||
case 0:
|
||||
@ -246,24 +252,26 @@ public class DefaultTileRenderer implements MapTileRenderer {
|
||||
|
||||
if (id != 0) {
|
||||
if (highlightBlocks.contains(id)) {
|
||||
return highlightColor;
|
||||
result.setColor(highlightColor);
|
||||
return;
|
||||
}
|
||||
Color[] colors;
|
||||
if(data != 0)
|
||||
colors = colorScheme.datacolors[id][data];
|
||||
colors = colorScheme.datacolors[id][data];
|
||||
else
|
||||
colors = colorScheme.colors[id];
|
||||
colors = colorScheme.colors[id];
|
||||
if (colors != null) {
|
||||
Color c = colors[seq];
|
||||
if (c.getAlpha() > 0) {
|
||||
/* we found something that isn't transparent! */
|
||||
if (c.getAlpha() == 255) {
|
||||
/* it's opaque - the ray ends here */
|
||||
return c;
|
||||
result.setColor(c);
|
||||
return;
|
||||
}
|
||||
|
||||
/* this block is transparent, so recurse */
|
||||
Color bg = scan(world, x, y, z, seq);
|
||||
scan(world, x, y, z, seq, isnether, result);
|
||||
|
||||
int cr = c.getRed();
|
||||
int cg = c.getGreen();
|
||||
@ -273,8 +281,8 @@ public class DefaultTileRenderer implements MapTileRenderer {
|
||||
cg *= ca;
|
||||
cb *= ca;
|
||||
int na = 255 - ca;
|
||||
|
||||
return new Color((bg.getRed() * na + cr) >> 8, (bg.getGreen() * na + cg) >> 8, (bg.getBlue() * na + cb) >> 8);
|
||||
result.setRGBA((result.getRed() * na + cr) >> 8, (result.getGreen() * na + cg) >> 8, (result.getBlue() * na + cb) >> 8, 255);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package org.dynmap.kzedmap;
|
||||
|
||||
import java.awt.Color;
|
||||
import org.dynmap.Color;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -21,19 +21,30 @@ public class HighlightTileRenderer extends DefaultTileRenderer {
|
||||
highlightBlocks.add((Integer)highlightObj);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Color scan(World world, int x, int y, int z, int seq) {
|
||||
Color result = translucent;
|
||||
protected void scan(World world, int x, int y, int z, int seq, boolean isnether, final Color result) {
|
||||
result.setTransparent();
|
||||
for (;;) {
|
||||
if (y < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
int id = world.getBlockTypeIdAt(x, y, z);
|
||||
if(isnether) { /* Make bedrock ceiling into air in nether */
|
||||
if(id != 0) {
|
||||
/* Remember first color we see, in case we wind up solid */
|
||||
if(result.isTransparent())
|
||||
if(colorScheme.colors[id] != null)
|
||||
result.setColor(colorScheme.colors[id][seq]);
|
||||
id = 0;
|
||||
}
|
||||
else
|
||||
isnether = false;
|
||||
}
|
||||
byte data = 0;
|
||||
if(colorScheme.datacolors[id] != null) { /* If data colored */
|
||||
data = world.getBlockAt(x, y, z).getData();
|
||||
if(colorScheme.datacolors[id] != null) { /* If data colored */
|
||||
data = world.getBlockAt(x, y, z).getData();
|
||||
}
|
||||
|
||||
switch (seq) {
|
||||
@ -56,14 +67,15 @@ public class HighlightTileRenderer extends DefaultTileRenderer {
|
||||
if (id != 0) {
|
||||
Color[] colors;
|
||||
if(data != 0)
|
||||
colors = colorScheme.datacolors[id][data];
|
||||
colors = colorScheme.datacolors[id][data];
|
||||
else
|
||||
colors = colorScheme.colors[id];
|
||||
colors = colorScheme.colors[id];
|
||||
if (colors != null) {
|
||||
Color c = colors[seq];
|
||||
|
||||
if (highlightBlocks.contains(id)) {
|
||||
return c;
|
||||
result.setColor(c);
|
||||
return;
|
||||
}
|
||||
|
||||
if (c.getAlpha() > 0) {
|
||||
@ -76,26 +88,22 @@ public class HighlightTileRenderer extends DefaultTileRenderer {
|
||||
|
||||
// No need to blend if result is opaque.
|
||||
if (result.getAlpha() < 255) {
|
||||
Color bg = c;
|
||||
c = result;
|
||||
|
||||
int cr = c.getRed();
|
||||
int cg = c.getGreen();
|
||||
int cb = c.getBlue();
|
||||
int ca = c.getAlpha();
|
||||
int cr = result.getRed();
|
||||
int cg = result.getGreen();
|
||||
int cb = result.getBlue();
|
||||
int ca = result.getAlpha();
|
||||
cr *= ca;
|
||||
cg *= ca;
|
||||
cb *= ca;
|
||||
int na = 255 - ca;
|
||||
|
||||
result = new Color((bg.getRed() * na + cr) >> 8, (bg.getGreen() * na + cg) >> 8, (bg.getBlue() * na + cb) >> 8,
|
||||
Math.min(255, bg.getAlpha()+c.getAlpha()) // Not really correct, but gets the job done without recursion while still looking ok.
|
||||
result.setRGBA((c.getRed() * na + cr) >> 8, (c.getGreen() * na + cg) >> 8, (c.getBlue() * na + cb) >> 8,
|
||||
Math.min(255, c.getAlpha()+ca) // Not really correct, but gets the job done without recursion while still looking ok.
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -138,6 +138,26 @@ public class KzedMap extends MapType {
|
||||
onTileInvalidated.trigger(tile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if point x,z is inside rectangle with corner at r0x,r0z and with
|
||||
* size vectors s1x,s1z and s2x,s2z
|
||||
*
|
||||
*/
|
||||
private boolean testPointInRectangle(int x, int z, int r0x, int r0z, int s1x, int s1z,
|
||||
int s2x, int s2z) {
|
||||
int xr = x - r0x;
|
||||
int zr = z - r0z; /* Get position relative to rectangle corner */
|
||||
int dots1 = xr*s1x + zr*s1z;
|
||||
int dots2 = xr*s2x + zr*s2z;
|
||||
/* If dot product of relative point and each side is between zero and dot product
|
||||
* of each side and itself, we're inside
|
||||
*/
|
||||
if((dots1 >= 0) && (dots1 <= (s1x*s1x+s1z*s1z)) &&
|
||||
(dots2 >= 0) && (dots2 <= (s2x*s2x+s2z*s2z))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public DynmapChunk[] getRequiredChunks(MapTile tile) {
|
||||
if (tile instanceof KzedMapTile) {
|
||||
@ -155,13 +175,43 @@ public class KzedMap extends MapType {
|
||||
|
||||
int x, z;
|
||||
|
||||
/* Actual pattern of chunks needed is create by the slanted
|
||||
* square prism corresponding to the render path of the tile.
|
||||
* Top of prism (corresponding to y=127) is diamond shape from
|
||||
* ix, iz to ix+64,iz+64 to ix+128,iz to ix+64,iz-64
|
||||
* Bottom is same shape, offset by -64 on x, +64 on z (net
|
||||
* render path to y=0), correspond to ix-64, iz+64 to
|
||||
* ix,iz+128 to ix+64,iz+64 to ix,iz. Projection of
|
||||
* the prism on to the x,z plane (which is all that matters for
|
||||
* chunks) yields a diagonal rectangular area from ix-64(x1),iz+64
|
||||
* to ix,iz+128(z2) to ix+128(x2),iz to ix+64,iz-64(z1).
|
||||
* Chunks outside this are not needed - we scan a simple rectangle
|
||||
* (chunk grid aligned) and skip adding the ones that are outside.
|
||||
* This results in 42% less chunks being loaded.
|
||||
*/
|
||||
ArrayList<DynmapChunk> chunks = new ArrayList<DynmapChunk>();
|
||||
|
||||
for (x = x1; x < x2; x += 16) {
|
||||
for (z = z1; z < z2; z += 16) {
|
||||
/* If any of the chunk corners are inside the rectangle, we need it */
|
||||
if((!testPointInRectangle(x, z, x1, iz + KzedMap.tileWidth/2,
|
||||
KzedMap.tileWidth/2, KzedMap.tileHeight/2,
|
||||
KzedMap.tileWidth, -KzedMap.tileHeight)) &&
|
||||
(!testPointInRectangle(x+15, z, x1, iz + KzedMap.tileWidth/2,
|
||||
KzedMap.tileWidth/2, KzedMap.tileHeight/2,
|
||||
KzedMap.tileWidth, -KzedMap.tileHeight)) &&
|
||||
(!testPointInRectangle(x+15, z+15, x1, iz + KzedMap.tileWidth/2,
|
||||
KzedMap.tileWidth/2, KzedMap.tileHeight/2,
|
||||
KzedMap.tileWidth, -KzedMap.tileHeight)) &&
|
||||
(!testPointInRectangle(x, z+15, x1, iz + KzedMap.tileWidth/2,
|
||||
KzedMap.tileWidth/2, KzedMap.tileHeight/2,
|
||||
KzedMap.tileWidth, -KzedMap.tileHeight)))
|
||||
continue;
|
||||
DynmapChunk chunk = new DynmapChunk(x / 16, z / 16);
|
||||
chunks.add(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
DynmapChunk[] result = new DynmapChunk[chunks.size()];
|
||||
chunks.toArray(result);
|
||||
return result;
|
||||
|
@ -1,18 +1,8 @@
|
||||
package org.dynmap.kzedmap;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.dynmap.Client;
|
||||
import org.dynmap.MapManager;
|
||||
import org.dynmap.debug.Debug;
|
||||
|
||||
public class ZoomedTileRenderer {
|
||||
public ZoomedTileRenderer(Map<String, Object> configuration) {
|
||||
}
|
||||
|
@ -386,7 +386,7 @@ DynMap.prototype = {
|
||||
|
||||
swtch(update.type, {
|
||||
tile: function() {
|
||||
me.onTileUpdated(update.name);
|
||||
me.onTileUpdated(update.name,update.timestamp);
|
||||
},
|
||||
playerjoin: function() {
|
||||
$(me).trigger('playerjoin', [ update.playerName ]);
|
||||
@ -436,12 +436,12 @@ DynMap.prototype = {
|
||||
unregisterTile: function(mapType, tileName) {
|
||||
delete this.registeredTiles[tileName];
|
||||
},
|
||||
onTileUpdated: function(tileName) {
|
||||
onTileUpdated: function(tileName,timestamp) {
|
||||
var me = this;
|
||||
var tile = this.registeredTiles[tileName];
|
||||
|
||||
if (tile) {
|
||||
tile.lastseen = this.lasttimestamp;
|
||||
tile.lastseen = timestamp;
|
||||
tile.mapType.onTileUpdated(tile.tileElement, tileName);
|
||||
}
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user