Merge branch 'master' of git://github.com/FrozenCow/dynmap

Conflicts:
	colorschemes/ovocean.txt
	src/main/java/org/dynmap/MapManager.java
This commit is contained in:
Jason Booth 2011-03-07 13:39:58 -06:00
commit fe0c6556ed
82 changed files with 1013 additions and 526 deletions

175
colorschemes/ovocean.txt Normal file
View File

@ -0,0 +1,175 @@
Stone
1 119 104 84 255 104 95 80 255 96 87 72 255 77 68 53 255
Grass
2 75 156 43 255 56 117 32 255 35 104 10 255 32 82 0 255
Dirt
3 134 96 67 255 107 76 53 255 67 48 33 255 68 49 33 255
Cobblestone
4 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
Wooden Plank
5 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255
Sappling
6 120 120 120 0 96 96 96 0 60 60 60 0 48 48 48 0
Bedrock
7 84 84 84 255 67 67 67 255 42 42 42 255 33 33 33 255
Water
8 21 88 125 80 7 70 117 80 6 68 115 80 5 53 90 80
Stationary Water
9 21 88 125 80 7 70 117 80 6 68 115 80 5 53 90 80
Lava
10 255 90 0 255 204 72 0 255 127 45 0 255 102 36 0 255
Stationary Lava
11 255 90 0 255 204 72 0 255 127 45 0 255 102 36 0 255
Sand
12 214 182 111 255 203 171 100 255 186 154 83 255 173 141 70 255
Gravel
13 136 126 126 255 108 100 100 255 68 63 63 255 54 50 50 255
Gold Ore
14 143 140 125 255 114 112 100 255 71 70 62 255 57 56 50 255
Iron Ore
15 136 130 127 255 108 104 101 255 68 65 63 255 54 52 50 255
Coal Ore
16 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
Wood
17 102 81 51 255 81 64 40 255 51 40 25 255 40 32 20 255
Leaves
18 23 68 6 100 12 56 0 100 6 52 0 100 0 42 0 100
Sponge
19 193 193 65 255 174 174 47 255 97 97 5 255 76 76 20 255
Glass
20 255 255 255 64 204 204 204 64 127 127 127 64 102 102 102 64
Lapis Lazuli Ore
21 23 68 196 255 18 56 158 255 14 43 122 255 14 43 78 255
Lapis Lazuli Block
22 23 68 196 255 18 56 158 255 14 43 122 255 14 43 78 255
Dispenser
23 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255
Sandstone
24 214 182 111 255 203 171 100 255 186 154 83 255 173 141 70 255
Note Block
25 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
Aqua Green Cloth
26 43 192 117 255 38 168 101 255 34 150 90 255 29 130 78 255
Cyan Cloth
27 43 192 192 255 36 185 185 255 29 130 130 255 22 99 99 255
Blue Cloth
28 0 0 255 255 0 0 204 255 0 0 127 255 0 0 102 255
Purple Cloth
29 101 101 188 255 95 95 175 255 86 86 160 255 78 78 145 255
Indigo Cloth
30 113 41 186 255 99 38 165 255 85 32 142 255 72 27 119 255
Violet Cloth
31 156 65 198 255 132 55 168 255 112 47 142 255 84 35 107 255
Magenta Cloth
32 187 42 187 255 160 36 160 255 135 31 135 255 112 25 112 255
Pink Cloth
33 192 43 117 255 168 38 103 255 142 32 87 255 127 29 78 255
Black Cloth
34 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255
Wool
35 222 222 222 255 177 177 177 255 111 111 111 255 88 88 88 255
Gray Cloth
36 125 125 125 255 114 114 114 255 104 104 104 255 86 86 86 255
Yellow Flower
37 255 255 0 255 204 204 0 255 127 127 0 255 102 102 0 255
Red Rose
38 255 0 0 255 204 0 0 255 127 0 0 255 102 0 0 255
Brown Mushroom
39 204 153 120 32 145 109 85 32 114 86 67 32 73 64 58 32
Red Mushroom
40 255 43 43 32 196 29 38 32 186 105 109 32 124 64 64 32
Gold Block
41 232 245 46 255 185 196 36 255 116 122 23 255 92 98 18 255
Iron Block
42 191 191 191 255 152 152 152 255 95 95 95 255 76 76 76 255
Double Stone Slab
43 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
Stone Slab
44 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
Brick
45 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255
TNT
46 160 83 65 255 128 66 52 255 80 41 32 255 64 33 26 255
Bookshelf
54 125 91 38 192 100 72 30 192 62 45 19 192 50 36 15 192
Moss Stone
48 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
Obsidian
49 26 11 43 255 20 8 34 255 13 5 21 255 10 4 17 255
Torch
50 159 127 80 255 98 88 20 0 245 220 50 255 196 176 40 0
Fire
51 255 170 30 200 204 136 24 200 127 85 15 200 102 68 12 200
Monster Spawner
52 0 150 110 196 0 150 130 196 0 150 110 196 0 150 130 196
Wooden Stair
53 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255
Chest
54 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
Diamond Ore
56 129 140 143 255 103 112 114 255 64 70 71 255 51 56 57 255
Diamond Block
57 45 166 152 255 36 132 121 255 22 83 76 255 18 66 60 255
Workbench
58 114 88 56 255 91 70 44 255 57 44 28 255 45 35 22 255
Crops
59 146 192 0 255 116 153 0 255 73 96 0 255 58 76 0 255
Farmland
60 95 58 30 255 76 46 24 255 47 29 15 255 38 23 12 255
Furnace
61 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255
Burning Furnace
62 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255
Sign Post
63 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
Wooden Door
64 136 109 67 255 108 87 53 255 68 54 33 255 54 43 26 255
Ladder
65 181 140 64 32 144 112 51 32 90 70 32 32 72 56 25 32
Minecart Tracks
66 150 134 102 180 120 107 81 180 75 67 51 180 60 53 40 180
Cobblestone Stairs
67 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
Iron Door
71 191 191 191 255 152 152 152 255 95 95 95 255 76 76 76 255
Redstone Ore
73 131 107 107 255 104 85 85 255 65 53 53 255 52 42 42 255
Glowing Redstone Ore
74 131 107 107 255 104 85 85 255 65 53 53 255 52 42 42 255
Redstone Torch off
75 159 127 80 255 72 56 25 0 181 140 64 255 144 112 51 0
Redstone Torch on
76 159 127 80 255 102 0 0 0 255 0 0 255 204 0 0 0
Snow
78 255 255 255 255 204 204 204 255 127 127 127 255 102 102 102 255
Ice
79 83 113 163 51 66 90 130 51 41 56 81 51 33 45 65 51
Snow Block
80 250 250 250 255 200 200 200 255 125 125 125 255 100 100 100 255
Cactus
81 25 120 25 255 20 96 20 255 12 60 12 255 10 48 10 255
Clay
82 151 157 169 255 120 125 135 255 75 78 84 255 60 62 67 255
Sugar Cane
83 193 234 150 255 154 187 120 255 96 117 75 255 77 93 60 255
Jukebox
84 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
Fence
85 127 98 49 96 95 72 33 96 48 34 9 96 32 21 21 96
Pumpkin
86 255 115 0 200 204 92 0 200 126 57 0 200 102 46 0 200
Netherrack
87 166 89 89 255 141 80 62 255 135 15 15 255 96 6 6 255
Soulsand
88 133 109 94 255 121 97 82 255 90 70 57 255 79 59 46 255
Glowstone
89 249 212 156 255 255 188 94 255 192 143 70 255 122 91 44 255
Portal
90 140 0 196 128 120 0 196 128 140 0 196 128 120 0 196 128
Jack-o-lantern
91 255 115 0 255 204 92 0 255 126 57 0 255 102 46 0 255
Cake Block
92 234 234 234 255 210 210 210 255 203 203 203 255 190 190 190 255

View File

@ -3,6 +3,14 @@
# How often a tile gets rendered (in seconds).
renderinterval: 1
render-triggers:
# - playermove
# - playerjoin
- blockplaced
- blockbreak
# - chunkgenerated
# - chunkloaded
# The path where the tile-files are placed.
tilespath: web/tiles
@ -28,21 +36,29 @@ jsonfile-interval: 1
worlds:
- name: world
maps:
- class: org.dynmap.flat.FlatMap
prefix: flat
colorscheme: default
- class: org.dynmap.kzedmap.KzedMap
renderers:
- class: org.dynmap.kzedmap.DefaultTileRenderer
prefix: t
maximumheight: 127
colorscheme: default
- class: org.dynmap.kzedmap.CaveTileRenderer
prefix: ct
maximumheight: 127
- name: nether
maps:
- class: org.dynmap.flat.FlatMap
prefix: flat
colorscheme: default
- class: org.dynmap.kzedmap.KzedMap
renderers:
- class: org.dynmap.kzedmap.DefaultTileRenderer
prefix: nt
maximumheight: 64
colorscheme: default
web:
# Handles the clientside updates differently only enable if using jsonfile
@ -61,15 +77,15 @@ web:
joinmessage: "%playername% joined"
quitmessage: "%playername% quit"
# The clock that is shown alongside the map.
clock: timeofday
#clock: digital
defaultworld: world
worlds:
- title: World
name: world
maps:
- type: FlatMapType
title: Flat
name: flat
prefix: flat
- type: KzedMapType
title: Surface
name: surface
@ -81,19 +97,23 @@ web:
- title: Nether
name: nether
maps:
- type: FlatMapType
title: Flat
name: flat
prefix: flat
- type: KzedMapType
title: Surface
name: nether
prefix: nt
# Example:
#- title: Other World # Under what name the world is displayed.
#- title: Other World # With what name the world is displayed.
# name: world_other # The actual name of the world (equal to your directory-name).
# maps:
# - type: KzedMapType # The type (or perspective) of the map. At the moment, there are no others than KzedMapType.
# title: Surface # The name of the map that will be displayed.
# name: surface # The actual name of the map (should be unique for this world).
# prefix: t # The prefix of the tile-files that are generated.
# icon: block_other.png # Sets the icon of the map. (optional)
# icon: images/block_other.png # Sets a custom icon for the map. (optional)
# - type: KzedMapType
# title: Cave
# name: cave
@ -102,4 +122,3 @@ web:
# Enables debugging.
#debuggers:
# - class: org.dynmap.debug.LogDebugger
# - class: org.dynmap.debug.BukkitPlayerDebugger

View File

@ -1,8 +1,8 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.bukkit</groupId>
<groupId>org.dynmap</groupId>
<artifactId>dynmap</artifactId>
<version>0.0.1-SNAPSHOT</version>
<version>0.13</version>
<name>DynamicMap</name>
<url>http://www.bukkit.org</url>
<build>
@ -20,7 +20,7 @@
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
<descriptor>src/main/assembly/package.xml</descriptor>
</descriptors>
</configuration>
<executions>

View File

@ -1,5 +1,5 @@
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>build</id>
<id>bin</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>tar.bz2</format>
@ -13,13 +13,17 @@
<include>README*</include>
<include>LICENSE*</include>
<include>NOTICE*</include>
<include>LICENSE*</include>
<include>CHANGELOG*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.basedir}/web</directory>
<outputDirectory>/dynmap/web</outputDirectory>
</fileSet>
<fileSet>
<directory>${project.basedir}/colorschemes</directory>
<outputDirectory>/dynmap/colorschemes</outputDirectory>
</fileSet>
<fileSet>
<directory>${project.basedir}</directory>
<outputDirectory>/dynmap/</outputDirectory>

View File

@ -0,0 +1,85 @@
package org.dynmap;
import java.awt.Color;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.dynmap.debug.Debug;
public class ColorScheme {
protected static final Logger log = Logger.getLogger("Minecraft");
private static final HashMap<String, ColorScheme> cache = new HashMap<String, ColorScheme>();
public String name;
public java.util.Map<Integer, Color[]> colors;
public ColorScheme(String name, java.util.Map<Integer, Color[]> colors) {
this.name = name;
this.colors = colors;
}
private static File getColorSchemeDirectory() {
return new File(DynmapPlugin.dataDirectory, "colorschemes");
}
public static ColorScheme getScheme(String name) {
if (name == null)
name = "default";
ColorScheme scheme = cache.get(name);
if (scheme == null) {
scheme = loadScheme(name);
cache.put(name, scheme);
}
return scheme;
}
public static ColorScheme loadScheme(String name) {
File colorSchemeFile = new File(getColorSchemeDirectory(), name + ".txt");
java.util.Map<Integer, Color[]> colors = new HashMap<Integer, Color[]>();
InputStream stream;
try {
Debug.debug("Loading colors from '" + colorSchemeFile + "'...");
stream = new FileInputStream(colorSchemeFile);
Scanner scanner = new Scanner(stream);
int nc = 0;
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.startsWith("#") || line.equals("")) {
continue;
}
String[] split = line.split("\t");
if (split.length < 17) {
continue;
}
Integer id = new Integer(split[0]);
Color[] c = new Color[4];
/* store colors by raycast sequence number */
c[0] = new Color(Integer.parseInt(split[1]), Integer.parseInt(split[2]), Integer.parseInt(split[3]), Integer.parseInt(split[4]));
c[3] = new Color(Integer.parseInt(split[5]), Integer.parseInt(split[6]), Integer.parseInt(split[7]), Integer.parseInt(split[8]));
c[1] = new Color(Integer.parseInt(split[9]), Integer.parseInt(split[10]), Integer.parseInt(split[11]), Integer.parseInt(split[12]));
c[2] = new Color(Integer.parseInt(split[13]), Integer.parseInt(split[14]), Integer.parseInt(split[15]), Integer.parseInt(split[16]));
colors.put(id, c);
nc += 1;
}
scanner.close();
} catch (RuntimeException e) {
log.log(Level.SEVERE, "Could not load colors '" + name + "' ('" + colorSchemeFile + "').", e);
return null;
} catch (FileNotFoundException e) {
log.log(Level.SEVERE, "Could not load colors '" + name + "' ('" + colorSchemeFile + "'): File not found.", e);
}
return new ColorScheme(name, colors);
}
}

View File

@ -1,28 +0,0 @@
package org.dynmap;
import org.bukkit.block.Block;
import org.bukkit.block.BlockDamageLevel;
import org.bukkit.event.block.BlockDamageEvent;
import org.bukkit.event.block.BlockListener;
import org.bukkit.event.block.BlockPlaceEvent;
public class DynmapBlockListener extends BlockListener {
private MapManager mgr;
public DynmapBlockListener(MapManager mgr) {
this.mgr = mgr;
}
@Override
public void onBlockPlace(BlockPlaceEvent event) {
Block blockPlaced = event.getBlockPlaced();
mgr.touch(blockPlaced.getLocation());
}
public void onBlockDamage(BlockDamageEvent event) {
if (event.getDamageLevel() == BlockDamageLevel.BROKEN) {
Block blockBroken = event.getBlock();
mgr.touch(blockBroken.getLocation());
}
}
}

View File

@ -1,40 +1,50 @@
package org.dynmap;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.Timer;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.BlockDamageLevel;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.Event.Priority;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockDamageEvent;
import org.bukkit.event.block.BlockListener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.WorldEvent;
import org.bukkit.event.world.WorldListener;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.config.Configuration;
import org.dynmap.Event.Listener;
import org.dynmap.debug.Debug;
import org.dynmap.debug.Debugger;
import org.dynmap.web.HttpServer;
import org.dynmap.web.Json;
import org.dynmap.web.handlers.ClientConfigurationHandler;
import org.dynmap.web.handlers.ClientUpdateHandler;
import org.dynmap.web.handlers.FilesystemHandler;
import org.dynmap.web.handlers.SendMessageHandler;
import org.dynmap.web.handlers.SendMessageHandler.Message;
import org.dynmap.web.Json;
public class DynmapPlugin extends JavaPlugin {
@ -44,9 +54,11 @@ public class DynmapPlugin extends JavaPlugin {
public MapManager mapManager = null;
public PlayerList playerList;
public Configuration configuration;
public HashSet<String> enabledTriggers = new HashSet<String>();
public Timer timer;
public static File dataDirectory;
public static File tilesDirectory;
public World getWorld() {
@ -62,13 +74,17 @@ public class DynmapPlugin extends JavaPlugin {
}
public void onEnable() {
dataDirectory = this.getDataFolder();
configuration = new Configuration(new File(this.getDataFolder(), "configuration.txt"));
configuration.load();
loadDebuggers();
tilesDirectory = getFile(configuration.getString("tilespath", "web/tiles"));
tilesDirectory.mkdirs();
if (!tilesDirectory.isDirectory() && !tilesDirectory.mkdirs()) {
log.warning("Could not create directory for tiles ('" + tilesDirectory + "').");
}
playerList = new PlayerList(getServer(), getFile("hiddenplayers.txt"));
playerList.load();
@ -76,7 +92,9 @@ public class DynmapPlugin extends JavaPlugin {
mapManager = new MapManager(this, configuration);
mapManager.startRendering();
if (!configuration.getBoolean("disable-webserver", false)) {
loadWebserver();
}
if (configuration.getBoolean("jsonfile", false)) {
jsonConfig();
@ -85,6 +103,11 @@ public class DynmapPlugin extends JavaPlugin {
timer.scheduleAtFixedRate(new JsonTimerTask(this, configuration), jsonInterval, jsonInterval);
}
enabledTriggers.clear();
for (Object trigger : configuration.getList("render-triggers")) {
enabledTriggers.add((String) trigger);
}
registerEvents();
}
@ -141,25 +164,81 @@ public class DynmapPlugin extends JavaPlugin {
Debug.clearDebuggers();
}
public void registerEvents() {
BlockListener blockListener = new DynmapBlockListener(mapManager);
getServer().getPluginManager().registerEvent(Event.Type.BLOCK_PLACED, blockListener, Priority.Monitor, this);
getServer().getPluginManager().registerEvent(Event.Type.BLOCK_DAMAGED, blockListener, Priority.Monitor, this);
public boolean isTrigger(String s) {
return enabledTriggers.contains(s);
}
public void registerEvents() {
final PluginManager pm = getServer().getPluginManager();
final MapManager mm = mapManager;
// To trigger rendering.
{
BlockListener renderTrigger = new BlockListener() {
@Override
public void onBlockPlace(BlockPlaceEvent event) {
mm.touch(event.getBlockPlaced().getLocation());
}
@Override
public void onBlockBreak(BlockBreakEvent event) {
mm.touch(event.getBlock().getLocation());
}
};
if (isTrigger("blockplaced")) pm.registerEvent(Event.Type.BLOCK_PLACED, renderTrigger, Priority.Monitor, this);
if (isTrigger("blockbreak")) pm.registerEvent(Event.Type.BLOCK_BREAK, renderTrigger, Priority.Monitor, this);
}
{
PlayerListener renderTrigger = new PlayerListener() {
@Override
public void onPlayerJoin(PlayerEvent event) {
mm.touch(event.getPlayer().getLocation());
}
@Override
public void onPlayerMove(PlayerMoveEvent event) {
mm.touch(event.getPlayer().getLocation());
}
};
if (isTrigger("playerjoin")) pm.registerEvent(Event.Type.PLAYER_JOIN, renderTrigger, Priority.Monitor, this);
if (isTrigger("playermove")) pm.registerEvent(Event.Type.PLAYER_MOVE, renderTrigger, Priority.Monitor, this);
}
{
WorldListener renderTrigger = new WorldListener() {
@Override
public void onChunkLoaded(ChunkLoadEvent event) {
int x = event.getChunk().getX() * 16 + 8;
int z = event.getChunk().getZ() * 16 + 8;
mm.touch(new Location(event.getWorld(), x, 127, z));
}
/*@Override
public void onChunkGenerated(ChunkLoadEvent event) {
int x = event.getChunk().getX() * 16 + 8;
int z = event.getChunk().getZ() * 16 + 8;
mm.touch(new Location(event.getWorld(), x, 127, z));
}*/
};
if (isTrigger("chunkloaded")) pm.registerEvent(Event.Type.CHUNK_LOADED, renderTrigger, Priority.Monitor, this);
//if (isTrigger("chunkgenerated")) pm.registerEvent(Event.Type.CHUNK_GENERATED, renderTrigger, Priority.Monitor, this);
}
// To link configuration to real loaded worlds.
WorldListener worldListener = new WorldListener() {
@Override
public void onWorldLoaded(WorldEvent event) {
mapManager.activateWorld(event.getWorld());
mm.activateWorld(event.getWorld());
}
};
getServer().getPluginManager().registerEvent(Event.Type.WORLD_LOADED, worldListener, Priority.Monitor, this);
pm.registerEvent(Event.Type.WORLD_LOADED, worldListener, Priority.Monitor, this);
// To handle webchat.
PlayerListener playerListener = new DynmapPlayerListener(this);
//getServer().getPluginManager().registerEvent(Event.Type.PLAYER_COMMAND, playerListener, Priority.Normal, this);
getServer().getPluginManager().registerEvent(Event.Type.PLAYER_CHAT, playerListener, Priority.Normal, this);
getServer().getPluginManager().registerEvent(Event.Type.PLAYER_LOGIN, playerListener, Priority.Normal, this);
getServer().getPluginManager().registerEvent(Event.Type.PLAYER_JOIN, playerListener, Priority.Normal, this);
getServer().getPluginManager().registerEvent(Event.Type.PLAYER_QUIT, playerListener, Priority.Normal, this);
pm.registerEvent(Event.Type.PLAYER_CHAT, playerListener, Priority.Monitor, this);
pm.registerEvent(Event.Type.PLAYER_LOGIN, playerListener, Priority.Monitor, this);
pm.registerEvent(Event.Type.PLAYER_JOIN, playerListener, Priority.Monitor, this);
pm.registerEvent(Event.Type.PLAYER_QUIT, playerListener, Priority.Monitor, this);
}
private static File combinePaths(File parent, String path) {
@ -269,9 +348,9 @@ public class DynmapPlugin extends JavaPlugin {
fos.write(Json.stringifyJson(clientConfig).getBytes());
fos.close();
} catch (FileNotFoundException ex) {
System.out.println("FileNotFoundException : " + ex);
log.log(Level.SEVERE, "Exception while writing JSON-configuration-file.", ex);
} catch (IOException ioe) {
System.out.println("IOException : " + ioe);
log.log(Level.SEVERE, "Exception while writing JSON-configuration-file.", ioe);
}
}
}

View File

@ -5,6 +5,8 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.Location;
import org.bukkit.Server;
@ -14,6 +16,8 @@ import org.bukkit.util.config.Configuration;
import org.dynmap.web.Json;
class JsonTimerTask extends TimerTask {
protected static final Logger log = Logger.getLogger("Minecraft");
private final DynmapPlugin plugin;
private Server server;
private MapManager mapManager;
@ -57,9 +61,9 @@ class JsonTimerTask extends TimerTask {
fos.write(Json.stringifyJson(update).getBytes());
fos.close();
} catch (FileNotFoundException ex) {
System.out.println("FileNotFoundException : " + ex);
log.log(Level.SEVERE, "Exception while writing JSON-file.", ex);
} catch (IOException ioe) {
System.out.println("IOException : " + ioe);
log.log(Level.SEVERE, "Exception while writing JSON-file.", ioe);
}
}
}

View File

@ -107,7 +107,6 @@ public class MapManager {
}
}
found.remove(tile);
System.gc();
}
// Unload remaining chunks to clean-up.
@ -202,7 +201,9 @@ public class MapManager {
worldTileDirectory = new File(DynmapPlugin.tilesDirectory, tile.getWorld().getName());
worldTileDirectories.put(world, worldTileDirectory);
}
worldTileDirectory.mkdirs();
if (!worldTileDirectory.isDirectory() && !worldTileDirectory.mkdirs()) {
log.warning("Could not create directory for tiles ('" + worldTileDirectory + "').");
}
return new File(worldTileDirectory, tile.getFilename());
}

View File

@ -25,4 +25,13 @@ public abstract class MapTile {
public int hashCode() {
return getFilename().hashCode() ^ getWorld().hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof MapTile) {
MapTile t = (MapTile)obj;
return getFilename().equals(t.getFilename()) && getWorld().equals(t.getWorld());
}
return super.equals(obj);
}
}

View File

@ -58,7 +58,7 @@ public class UpdateQueue {
return updates;
}
public class Update {
public static class Update {
public long time;
public Object obj;

View File

@ -1,90 +0,0 @@
package org.dynmap.debug;
import java.util.HashSet;
import java.util.Map;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.Event.Priority;
import org.bukkit.event.player.PlayerChatEvent;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.plugin.java.JavaPlugin;
public class BukkitPlayerDebugger implements Debugger {
private JavaPlugin plugin;
private HashSet<Player> debugees = new HashSet<Player>();
private String debugCommand;
private String undebugCommand;
private String prepend;
public BukkitPlayerDebugger(JavaPlugin plugin, Map<String, Object> configuration) {
this.plugin = plugin;
String name = "dynmap";
debugCommand = "/debug_" + name;
undebugCommand = "/undebug_" + name;
prepend = name + ": ";
}
public synchronized void enable() {
plugin.getServer().getPluginManager().registerEvent(Event.Type.PLAYER_COMMAND, new CommandListener(), Priority.Normal, plugin);
plugin.getServer().getPluginManager().registerEvent(Event.Type.PLAYER_QUIT, new CommandListener(), Priority.Normal, plugin);
}
public synchronized void disable() {
clearDebugees();
}
public synchronized void addDebugee(Player p) {
debugees.add(p);
}
public synchronized void removeDebugee(Player p) {
debugees.remove(p);
}
public synchronized void clearDebugees() {
debugees.clear();
}
public synchronized void sendToDebuggees(String message) {
for (Player p : debugees) {
p.sendMessage(prepend + message);
}
}
public synchronized void debug(String message) {
sendToDebuggees(message);
}
public synchronized void error(String message) {
sendToDebuggees(prepend + ChatColor.RED + message);
}
public synchronized void error(String message, Throwable thrown) {
sendToDebuggees(prepend + ChatColor.RED + message);
sendToDebuggees(thrown.toString());
}
protected class CommandListener extends PlayerListener {
@Override
public void onPlayerCommand(PlayerChatEvent event) {
String[] split = event.getMessage().split(" ");
Player player = event.getPlayer();
if (split[0].equalsIgnoreCase(debugCommand)) {
addDebugee(player);
event.setCancelled(true);
} else if (split[0].equalsIgnoreCase(undebugCommand)) {
removeDebugee(player);
event.setCancelled(true);
}
}
@Override
public void onPlayerQuit(PlayerEvent event) {
removeDebugee(event.getPlayer());
}
}
}

View File

@ -0,0 +1,123 @@
package org.dynmap.flat;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import javax.imageio.ImageIO;
import org.bukkit.Location;
import org.bukkit.World;
import org.dynmap.ColorScheme;
import org.dynmap.DynmapChunk;
import org.dynmap.MapTile;
import org.dynmap.MapType;
import org.dynmap.debug.Debug;
public class FlatMap extends MapType {
private String prefix;
private ColorScheme colorScheme;
public FlatMap(Map<String, Object> configuration) {
prefix = (String)configuration.get("prefix");
colorScheme = ColorScheme.getScheme((String)configuration.get("colorscheme"));
}
@Override
public MapTile[] getTiles(Location l) {
return new MapTile[] { new FlatMapTile(l.getWorld(), this, (int) Math.floor(l.getBlockX() / 128.0), (int) Math.floor(l.getBlockZ() / 128.0), 128) };
}
@Override
public MapTile[] getAdjecentTiles(MapTile tile) {
FlatMapTile t = (FlatMapTile) tile;
World w = t.getWorld();
int x = t.x;
int y = t.y;
int s = t.size;
return new MapTile[] {
new FlatMapTile(w, this, x, y - 1, s),
new FlatMapTile(w, this, x + 1, y, s),
new FlatMapTile(w, this, x, y + 1, s),
new FlatMapTile(w, this, x - 1, y, s) };
}
@Override
public DynmapChunk[] getRequiredChunks(MapTile tile) {
FlatMapTile t = (FlatMapTile) tile;
int chunksPerTile = t.size / 16;
int sx = t.x * chunksPerTile;
int sz = t.y * chunksPerTile;
DynmapChunk[] result = new DynmapChunk[chunksPerTile * chunksPerTile];
int index = 0;
for (int x = 0; x < chunksPerTile; x++)
for (int z = 0; z < chunksPerTile; z++) {
result[index] = new DynmapChunk(sx + x, sz + z);
index++;
}
return result;
}
@Override
public boolean render(MapTile tile, File outputFile) {
FlatMapTile t = (FlatMapTile) tile;
World w = t.getWorld();
boolean rendered = false;
BufferedImage im = new BufferedImage(t.size, t.size, BufferedImage.TYPE_INT_RGB);
WritableRaster r = im.getRaster();
for (int x = 0; x < t.size; x++)
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);
Color[] colors = colorScheme.colors.get(blockType);
if (colors == null)
continue;
Color c = colors[0];
if (c == null)
continue;
r.setPixel(x, y, new int[] {
c.getRed(),
c.getGreen(),
c.getBlue() });
rendered = true;
}
try {
ImageIO.write(im, "png", outputFile);
} catch (IOException e) {
Debug.error("Failed to save image: " + outputFile.getPath(), e);
} catch (java.lang.NullPointerException e) {
Debug.error("Failed to save image (NullPointerException): " + outputFile.getPath(), e);
}
im.flush();
return rendered;
}
public static class FlatMapTile extends MapTile {
FlatMap map;
public int x;
public int y;
public int size;
public FlatMapTile(World world, FlatMap map, int x, int y, int size) {
super(world, map);
this.map = map;
this.x = x;
this.y = y;
this.size = size;
}
@Override
public String getFilename() {
return map.prefix + "_" + size + "_" + x + "_" + y + ".png";
}
}
}

View File

@ -10,12 +10,14 @@ import java.util.Map;
import javax.imageio.ImageIO;
import org.bukkit.World;
import org.dynmap.ColorScheme;
import org.dynmap.debug.Debug;
public class DefaultTileRenderer implements MapTileRenderer {
protected static Color translucent = new Color(0, 0, 0, 0);
private String name;
protected int maximumHeight = 127;
private ColorScheme colorScheme;
@Override
public String getName() {
@ -30,6 +32,7 @@ public class DefaultTileRenderer implements MapTileRenderer {
if (maximumHeight > 127)
maximumHeight = 127;
}
colorScheme = ColorScheme.getScheme((String)configuration.get("colorscheme"));
}
public boolean render(KzedMapTile tile, File outputFile) {
@ -39,9 +42,9 @@ public class DefaultTileRenderer implements MapTileRenderer {
WritableRaster r = im.getRaster();
boolean isempty = true;
int ix = KzedMap.anchorx + tile.px / 2 + tile.py / 2;
int ix = KzedMap.anchorx + tile.px / 2 + tile.py / 2 - ((127-maximumHeight)/2);
int iy = maximumHeight;
int iz = KzedMap.anchorz + tile.px / 2 - tile.py / 2;
int iz = KzedMap.anchorz + tile.px / 2 - tile.py / 2 + ((127-maximumHeight)/2);
int jx, jz;
@ -132,7 +135,7 @@ public class DefaultTileRenderer implements MapTileRenderer {
seq = (seq + 1) & 3;
if (id != 0) {
Color[] colors = KzedMap.colors.get(id);
Color[] colors = colorScheme.colors.get(id);
if (colors != null) {
Color c = colors[seq];
if (c.getAlpha() > 0) {

View File

@ -1,15 +1,10 @@
package org.dynmap.kzedmap;
import java.awt.Color;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.logging.Logger;
import org.bukkit.Location;
@ -38,15 +33,10 @@ public class KzedMap extends MapType {
public static final int anchory = 127;
public static final int anchorz = 0;
public static java.util.Map<Integer, Color[]> colors;
MapTileRenderer[] renderers;
ZoomedTileRenderer zoomrenderer;
public KzedMap(Map<String, Object> configuration) {
if (colors == null) {
colors = loadColorSet("colors.txt");
}
renderers = loadRenderers(configuration);
zoomrenderer = new ZoomedTileRenderer(configuration);
}
@ -223,54 +213,4 @@ public class KzedMap extends MapType {
else
return y - (y % zTileHeight);
}
public java.util.Map<Integer, Color[]> loadColorSet(String colorsetpath) {
java.util.Map<Integer, Color[]> colors = new HashMap<Integer, Color[]>();
InputStream stream;
try {
/* load colorset */
File cfile = new File(colorsetpath);
if (cfile.isFile()) {
Debug.debug("Loading colors from '" + colorsetpath + "'...");
stream = new FileInputStream(cfile);
} else {
Debug.debug("Loading colors from jar...");
stream = KzedMap.class.getResourceAsStream("/colors.txt");
}
Scanner scanner = new Scanner(stream);
int nc = 0;
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.startsWith("#") || line.equals("")) {
continue;
}
String[] split = line.split("\t");
if (split.length < 17) {
continue;
}
Integer id = new Integer(split[0]);
Color[] c = new Color[4];
/* store colors by raycast sequence number */
c[0] = new Color(Integer.parseInt(split[1]), Integer.parseInt(split[2]), Integer.parseInt(split[3]), Integer.parseInt(split[4]));
c[3] = new Color(Integer.parseInt(split[5]), Integer.parseInt(split[6]), Integer.parseInt(split[7]), Integer.parseInt(split[8]));
c[1] = new Color(Integer.parseInt(split[9]), Integer.parseInt(split[10]), Integer.parseInt(split[11]), Integer.parseInt(split[12]));
c[2] = new Color(Integer.parseInt(split[13]), Integer.parseInt(split[14]), Integer.parseInt(split[15]), Integer.parseInt(split[16]));
colors.put(id, c);
nc += 1;
}
scanner.close();
} catch (Exception e) {
Debug.error("Could not load colors", e);
return null;
}
return colors;
}
}

View File

@ -1,20 +0,0 @@
package org.dynmap.web;
import java.io.IOException;
public class HttpErrorHandler {
public static void handle(HttpResponse response, int statusCode, String statusMessage) throws IOException {
response.statusCode = statusCode;
response.statusMessage = statusMessage;
response.fields.put("Content-Length", "0");
response.getBody();
}
public static void handleNotFound(HttpResponse response) throws IOException {
handle(response, 404, "Not found");
}
public static void handleMethodNotAllowed(HttpResponse response) throws IOException {
handle(response, 405, "Method not allowed");
}
}

View File

@ -1,6 +1,52 @@
package org.dynmap.web;
public class HttpField {
public static final String contentLength = "Content-Length";
public static final String contentType = "Content-Type";
// Reference: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
public static final String Accept = "Accept";
public static final String AcceptCharset = "Accept-Charset";
public static final String AcceptEncoding = "Accept-Encoding";
public static final String AcceptLanguage = "Accept-Language";
public static final String AcceptRanges = "Accept-Ranges";
public static final String Age = "Age";
public static final String Allow = "Allow";
public static final String Authorization = "Authorization";
public static final String CacheControl = "Cache-Control";
public static final String Connection = "Connection";
public static final String ContentEncoding = "Content-Encoding";
public static final String ContentLanguage = "Content-Language";
public static final String ContentLength = "Content-Length";
public static final String ContentLocation = "Content-Location";
public static final String ContentRange = "Content-Range";
public static final String ContentType = "Content-Type";
public static final String Date = "Date";
public static final String ETag = "ETag";
public static final String Expect = "Expect";
public static final String Expires = "Expires";
public static final String From = "From";
public static final String Host = "Host";
public static final String IfMatch = "If-Match";
public static final String IfModifiedSince = "If-Modified-Since";
public static final String IfNoneMatch = "If-None-Match";
public static final String IfRange = "If-Range";
public static final String IfUnmodifiedSince = "If-Unmodified-Since";
public static final String LastModified = "Last-Modified";
public static final String Location = "Location";
public static final String MaxForwards = "Max-Forwards";
public static final String Pragma = "Pragma";
public static final String ProxyAuthenticate = "Proxy-Authenticate";
public static final String ProxyAuthorization = "Proxy-Authorization";
public static final String Range = "Range";
public static final String Referer = "Referer";
public static final String RetryAfter = "Retry-After";
public static final String Server = "Server";
public static final String TE = "TE";
public static final String Trailer = "Trailer";
public static final String TransferEncoding = "Transfer-Encoding";
public static final String Upgrade = "Upgrade";
public static final String UserAgent = "User-Agent";
public static final String Vary = "Vary";
public static final String Via = "Via";
public static final String Warning = "Warning";
public static final String WwwAuthenticate = "WWW-Authenticate";
}

View File

@ -1,6 +1,6 @@
package org.dynmap.web;
public class HttpMethods {
public final class HttpMethod {
public static final String Get = "GET";
public static final String Post = "POST";
public static final String Put = "PUT";

View File

@ -8,8 +8,7 @@ import java.util.Map;
public class HttpResponse {
private HttpServerConnection connection;
public String version = "1.1";
public int statusCode = 200;
public String statusMessage = "OK";
public HttpStatus status = null;
public Map<String, String> fields = new HashMap<String, String>();
private OutputStream body;

View File

@ -95,9 +95,9 @@ public class HttpServerConnection extends Thread {
out.append("HTTP/");
out.append(response.version);
out.append(" ");
out.append(String.valueOf(response.statusCode));
out.append(String.valueOf(response.status.getCode()));
out.append(" ");
out.append(response.statusMessage);
out.append(response.status.getText());
out.append("\r\n");
for (Entry<String, String> field : response.fields.entrySet()) {
out.append(field.getKey());
@ -115,6 +115,8 @@ public class HttpServerConnection extends Thread {
public void run() {
try {
if (socket == null)
return;
socket.setSoTimeout(5000);
InputStream in = socket.getInputStream();
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream(), 40960);
@ -131,7 +133,7 @@ public class HttpServerConnection extends Thread {
long bound = -1;
BoundInputStream boundBody = null;
{
String contentLengthStr = request.fields.get(HttpField.contentLength);
String contentLengthStr = request.fields.get(HttpField.ContentLength);
if (contentLengthStr != null) {
try {
bound = Long.parseLong(contentLengthStr);
@ -178,8 +180,10 @@ public class HttpServerConnection extends Thread {
return;
}
if (bound > 0) {
boundBody.skip(bound);
if (bound > 0 && boundBody.skip(bound) < bound) {
Debug.debug("Incoming stream was only read partially by handler '" + handler + "'.");
//socket.close();
//return;
}
String connection = response.fields.get("Connection");

View File

@ -0,0 +1,61 @@
package org.dynmap.web;
public final class HttpStatus {
private int code;
private String text;
public int getCode() {
return code;
}
public String getText() {
return text;
}
public HttpStatus(int code, String text) {
this.code = code;
this.text = text;
}
// Reference: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
public static final HttpStatus Continue = new HttpStatus(100, "Continue");
public static final HttpStatus SwitchingProtocols = new HttpStatus(101, "Switching Protocols");
public static final HttpStatus OK = new HttpStatus(200, "OK");
public static final HttpStatus Created = new HttpStatus(201, "Created");
public static final HttpStatus Accepted = new HttpStatus(202, "Accepted");
public static final HttpStatus NonAuthoritativeInformation = new HttpStatus(203, "Non-Authoritative Information");
public static final HttpStatus NoContent = new HttpStatus(204, "No Content");
public static final HttpStatus ResetContent = new HttpStatus(205, "Reset Content");
public static final HttpStatus PartialContent = new HttpStatus(206, "Partial Content");
public static final HttpStatus MultipleChoices = new HttpStatus(300, "Multiple Choices");
public static final HttpStatus MovedPermanently = new HttpStatus(301, "Moved Permanently");
public static final HttpStatus Found = new HttpStatus(302, "Found");
public static final HttpStatus SeeOther = new HttpStatus(303, "See Other");
public static final HttpStatus NotModified = new HttpStatus(304, "Not Modified");
public static final HttpStatus UseProxy = new HttpStatus(305, "Use Proxy");
public static final HttpStatus TemporaryRedirect = new HttpStatus(307, "Temporary Redirect");
public static final HttpStatus BadRequest = new HttpStatus(400, "Bad Request");
public static final HttpStatus Unauthorized = new HttpStatus(401, "Unauthorized");
public static final HttpStatus PaymentRequired = new HttpStatus(402, "Payment Required");
public static final HttpStatus Forbidden = new HttpStatus(403, "Forbidden");
public static final HttpStatus NotFound = new HttpStatus(404, "Not Found");
public static final HttpStatus MethodNotAllowed = new HttpStatus(405, "Method Not Allowed");
public static final HttpStatus NotAcceptable = new HttpStatus(406, "Not Acceptable");
public static final HttpStatus ProxyAuthenticationRequired = new HttpStatus(407, "Proxy Authentication Required");
public static final HttpStatus RequestTimeout = new HttpStatus(408, "Request Timeout");
public static final HttpStatus Conflict = new HttpStatus(409, "Conflict");
public static final HttpStatus Gone = new HttpStatus(410, "Gone");
public static final HttpStatus LengthRequired = new HttpStatus(411, "Length Required");
public static final HttpStatus PreconditionFailed = new HttpStatus(412, "Precondition Failed");
public static final HttpStatus RequestEntityTooLarge = new HttpStatus(413, "Request Entity Too Large");
public static final HttpStatus RequestURITooLong = new HttpStatus(414, "Request-URI Too Long");
public static final HttpStatus UnsupportedMediaType = new HttpStatus(415, "Unsupported Media Type");
public static final HttpStatus RequestedRangeNotSatisfiable = new HttpStatus(416, "Requested Range Not Satisfiable");
public static final HttpStatus ExpectationFailed = new HttpStatus(417, "Expectation Failed");
public static final HttpStatus InternalServerError = new HttpStatus(500, "Internal Server Error");
public static final HttpStatus NotImplemented = new HttpStatus(501, "Not Implemented");
public static final HttpStatus BadGateway = new HttpStatus(502, "Bad Gateway");
public static final HttpStatus ServiceUnavailable = new HttpStatus(503, "Service Unavailable");
public static final HttpStatus GatewayTimeout = new HttpStatus(504, "Gateway Timeout");
public static final HttpStatus HttpVersionNotSupported = new HttpStatus(505, "HTTP Version Not Supported");
}

View File

@ -3,61 +3,62 @@ package org.dynmap.web;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.KeyStore.Entry;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class Json {
public static String stringifyJson(Object o) {
StringBuilder sb = new StringBuilder();
appendJson(o, sb);
return sb.toString();
}
public static void appendJson(Object o, StringBuilder s) {
if (o == null) {
return "null";
s.append("null");
} else if (o instanceof Boolean) {
return ((Boolean) o) ? "true" : "false";
s.append(((Boolean) o) ? "true" : "false");
} else if (o instanceof String) {
return "\"" + ((String)o).replace("\"", "\\\"") + "\"";
s.append("\"" + ((String)o).replace("\"", "\\\"") + "\"");
} else if (o instanceof Integer || o instanceof Long || o instanceof Float || o instanceof Double) {
return o.toString();
s.append(o.toString());
} else if (o instanceof LinkedHashMap<?, ?>) {
LinkedHashMap<?, ?> m = (LinkedHashMap<?, ?>) o;
StringBuilder sb = new StringBuilder();
sb.append("{");
s.append("{");
boolean first = true;
for (Object key : m.keySet()) {
for (Map.Entry<?, ?> entry : m.entrySet()) {
if (first)
first = false;
else
sb.append(",");
s.append(",");
sb.append(stringifyJson(key));
sb.append(": ");
sb.append(stringifyJson(m.get(key)));
appendJson(entry.getKey(), s);
s.append(": ");
appendJson(entry.getValue(), s);
}
sb.append("}");
return sb.toString();
s.append("}");
} else if (o instanceof List<?>) {
List<?> l = (List<?>) o;
StringBuilder sb = new StringBuilder();
sb.append("[");
s.append("[");
int count = 0;
for (int i = 0; i < l.size(); i++) {
if (count++ > 0) sb.append(",");
sb.append(stringifyJson(l.get(i)));
if (count++ > 0) s.append(",");
appendJson(l.get(i), s);
}
sb.append("]");
return sb.toString();
s.append("]");
} else if (o.getClass().isArray()) {
int length = Array.getLength(o);
StringBuilder sb = new StringBuilder();
sb.append("[");
s.append("[");
int count = 0;
for (int i = 0; i < length; i++) {
if (count++ > 0) sb.append(",");
sb.append(stringifyJson(Array.get(o, i)));
if (count++ > 0) s.append(",");
appendJson(Array.get(o, i), s);
}
sb.append("]");
return sb.toString();
s.append("]");
} else if (o instanceof Object) /* TODO: Always true, maybe interface? */ {
StringBuilder sb = new StringBuilder();
sb.append("{");
s.append("{");
boolean first = true;
Class<?> c = o.getClass();
@ -77,15 +78,14 @@ public class Json {
if (first)
first = false;
else
sb.append(",");
sb.append(stringifyJson(fieldName));
sb.append(": ");
sb.append(stringifyJson(fieldValue));
s.append(",");
appendJson(fieldName, s);
s.append(": ");
appendJson(fieldValue, s);
}
sb.append("}");
return sb.toString();
s.append("}");
} else {
return "undefined";
s.append("undefined");
}
}
}

View File

@ -7,27 +7,33 @@ import java.util.Map;
import org.dynmap.web.HttpHandler;
import org.dynmap.web.HttpRequest;
import org.dynmap.web.HttpResponse;
import org.dynmap.web.HttpStatus;
import org.dynmap.web.Json;
public class ClientConfigurationHandler implements HttpHandler {
private Map<?, ?> configuration;
private byte[] cachedConfiguration = null;
public ClientConfigurationHandler(Map<?, ?> configuration) {
this.configuration = configuration;
}
@Override
public void handle(String path, HttpRequest request, HttpResponse response) throws Exception {
if (cachedConfiguration == null) {
String s = Json.stringifyJson(configuration);
byte[] bytes = s.getBytes();
cachedConfiguration = s.getBytes();
}
String dateStr = new Date().toString();
response.fields.put("Date", dateStr);
response.fields.put("Content-Type", "text/plain");
response.fields.put("Expires", "Thu, 01 Dec 1994 16:00:00 GMT");
response.fields.put("Last-modified", dateStr);
response.fields.put("Content-Length", Integer.toString(bytes.length));
response.fields.put("Content-Length", Integer.toString(cachedConfiguration.length));
response.status = HttpStatus.OK;
BufferedOutputStream out = new BufferedOutputStream(response.getBody());
out.write(s.getBytes());
out.write(cachedConfiguration);
out.flush();
}
}

View File

@ -12,9 +12,11 @@ import org.bukkit.entity.Player;
import org.dynmap.Client;
import org.dynmap.MapManager;
import org.dynmap.PlayerList;
import org.dynmap.web.HttpField;
import org.dynmap.web.HttpHandler;
import org.dynmap.web.HttpRequest;
import org.dynmap.web.HttpResponse;
import org.dynmap.web.HttpStatus;
import org.dynmap.web.Json;
public class ClientUpdateHandler implements HttpHandler {
@ -28,21 +30,26 @@ public class ClientUpdateHandler implements HttpHandler {
this.server = server;
}
Pattern updatePathPattern = Pattern.compile("world/([a-zA-Z0-9_]+)/([0-9]*)");
Pattern updatePathPattern = Pattern.compile("world/([a-zA-Z0-9_\\-\\.]+)/([0-9]*)");
private static final HttpStatus WorldNotFound = new HttpStatus(HttpStatus.NotFound.getCode(), "World Not Found");
@Override
public void handle(String path, HttpRequest request, HttpResponse response) throws Exception {
Matcher match = updatePathPattern.matcher(path);
if (!match.matches())
if (!match.matches()) {
response.status = HttpStatus.Forbidden;
return;
}
String worldName = match.group(1);
String timeKey = match.group(2);
World world = server.getWorld(worldName);
if (world == null)
if (world == null) {
response.status = WorldNotFound;
return;
}
long current = System.currentTimeMillis();
long since = 0;
@ -73,11 +80,13 @@ public class ClientUpdateHandler implements HttpHandler {
byte[] bytes = Json.stringifyJson(update).getBytes();
String dateStr = new Date().toString();
response.fields.put("Date", dateStr);
response.fields.put("Content-Type", "text/plain");
response.fields.put("Expires", "Thu, 01 Dec 1994 16:00:00 GMT");
response.fields.put("Last-modified", dateStr);
response.fields.put("Content-Length", Integer.toString(bytes.length));
response.fields.put(HttpField.Date, dateStr);
response.fields.put(HttpField.ContentType, "text/plain");
response.fields.put(HttpField.Expires, "Thu, 01 Dec 1994 16:00:00 GMT");
response.fields.put(HttpField.LastModified, dateStr);
response.fields.put(HttpField.ContentLength, Integer.toString(bytes.length));
response.status = HttpStatus.OK;
BufferedOutputStream out = new BufferedOutputStream(response.getBody());
out.write(bytes);
out.flush();

View File

@ -7,9 +7,11 @@ import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.dynmap.web.HttpField;
import org.dynmap.web.HttpHandler;
import org.dynmap.web.HttpRequest;
import org.dynmap.web.HttpResponse;
import org.dynmap.web.HttpStatus;
public abstract class FileHandler implements HttpHandler {
protected static final Logger log = Logger.getLogger("Minecraft");
@ -64,17 +66,15 @@ public abstract class FileHandler implements HttpHandler {
path = formatPath(path);
fileInput = getFileInput(path, request, response);
if (fileInput == null) {
response.statusCode = 404;
response.statusMessage = "Not found";
response.fields.put("Content-Length", "0");
response.getBody();
response.status = HttpStatus.NotFound;
return;
}
String extension = getExtension(path);
String mimeType = getMimeTypeFromExtension(extension);
response.fields.put("Content-Type", mimeType);
response.fields.put(HttpField.ContentType, mimeType);
response.status = HttpStatus.OK;
OutputStream out = response.getBody();
try {
int readBytes;

View File

@ -5,6 +5,7 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import org.dynmap.web.HttpField;
import org.dynmap.web.HttpRequest;
import org.dynmap.web.HttpResponse;
@ -26,7 +27,7 @@ public class FilesystemHandler extends FileHandler {
} catch (FileNotFoundException e) {
return null;
}
response.fields.put("Content-Length", Long.toString(file.length()));
response.fields.put(HttpField.ContentLength, Long.toString(file.length()));
return result;
}
return null;

View File

@ -4,12 +4,12 @@ import java.io.InputStreamReader;
import java.util.logging.Logger;
import org.dynmap.Event;
import org.dynmap.web.HttpErrorHandler;
import org.dynmap.web.HttpField;
import org.dynmap.web.HttpHandler;
import org.dynmap.web.HttpMethods;
import org.dynmap.web.HttpMethod;
import org.dynmap.web.HttpRequest;
import org.dynmap.web.HttpResponse;
import org.dynmap.web.HttpStatus;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
@ -20,8 +20,9 @@ public class SendMessageHandler implements HttpHandler {
public Event<Message> onMessageReceived = new Event<SendMessageHandler.Message>();
@Override
public void handle(String path, HttpRequest request, HttpResponse response) throws Exception {
if (!request.method.equals(HttpMethods.Post)) {
HttpErrorHandler.handleMethodNotAllowed(response);
if (!request.method.equals(HttpMethod.Post)) {
response.status = HttpStatus.MethodNotAllowed;
response.fields.put(HttpField.Accept, HttpMethod.Post);
return;
}
@ -34,10 +35,11 @@ public class SendMessageHandler implements HttpHandler {
onMessageReceived.trigger(message);
response.fields.put(HttpField.contentLength, "0");
response.fields.put(HttpField.ContentLength, "0");
response.status = HttpStatus.OK;
response.getBody();
}
public class Message {
public static class Message {
public String name;
public String message;
}

View File

@ -1,6 +1,6 @@
name: dynmap
main: org.dynmap.DynmapPlugin
version: 0.1
version: 0.13
commands:
dynmap:
description: Controls Dynmap.

View File

@ -29,7 +29,7 @@
color: white;
border: 0px;
background: rgba(0, 0, 0, 0.6);
background: url(chat_cursor.png) rgba(0,0,0,0.6); background-repeat: no-repeat; background-position:left;
background: url(images/chat_cursor.png) rgba(0,0,0,0.6); background-repeat: no-repeat; background-position:left;
outline: none;
}
.messagelist {

View File

@ -182,8 +182,8 @@ body {
text-align: center;
background: url(sidebar_hint.png) rgb(0,0,0);
background: url(sidebar_hint.png) rgba(0,0,0,0.6);
background: url(images/sidebar_hint.png) rgb(0,0,0);
background: url(images/sidebar_hint.png) rgba(0,0,0,0.6);
background-repeat: no-repeat;
background-position:center;
@ -223,19 +223,19 @@ body {
width: 16px;
height: 16px;
background-image: url(window_close.png);
background-image: url(images/window_close.png);
}
.dynmap .sidebar .panel > .pin:hover {
background-image: url(window_pinned_hover.png);
background-image: url(images/window_pinned_hover.png);
}
.dynmap .sidebar.pinned .panel > .pin:hover {
background-image: url(window_close_hover.png);
background-image: url(images/window_close_hover.png);
}
.dynmap .sidebar.pinned .panel > .pin {
background-image: url(window_pinned.png);
background-image: url(images/window_pinned.png);
}
@ -260,12 +260,12 @@ body {
}
.clock.night {
/* background-image: url(clock_night.png); */
/* background-image: url(images/clock_night.png); */
color: #dff;
}
.clock.day {
/* background-image: url(clock_day.png); */
/* background-image: url(images/clock_day.png); */
color: #fd3;
}
@ -299,11 +299,11 @@ body {
}
.timeofday.sun {
background-image: url(sun.png);
background-image: url(images/sun.png);
}
.timeofday.moon {
background-image: url(moon.png);
background-image: url(images/moon.png);
}
/*******************
@ -418,11 +418,11 @@ body {
}
.dynmap .playerlist .player:hover .playericon {
background: url(player_follow_off.png) no-repeat;
background: url(images/player_follow_off.png) no-repeat;
}
.dynmap .playerlist .player.following .playericon {
background: url(player_follow_on.gif) no-repeat;
background: url(images/player_follow_on.gif) no-repeat;
}
.dynmap .playerlist .player.following .playericon > *,
@ -465,7 +465,7 @@ body {
width: 83px;
background-repeat: no-repeat;
background-image: url(compass.png);
background-image: url(images/compass.png);
}
/*******************
@ -499,7 +499,7 @@ body {
border: 0px;
background: rgba(0, 0, 0, 0.6);
background: url(chat_cursor.png) rgba(0,0,0,0.6);
background: url(images/chat_cursor.png) rgba(0,0,0,0.6);
background-repeat: no-repeat;
background-position: 1px center;

43
web/flatmap.js Normal file
View File

@ -0,0 +1,43 @@
function FlatProjection() {}
FlatProjection.prototype = {
fromLatLngToPoint: function(latLng) {
return new google.maps.Point(latLng.lat()*128.0, latLng.lng()*128.0);
},
fromPointToLatLng: function(point) {
return new google.maps.LatLng(point.x/128.0, point.y/128.0);
},
fromWorldToLatLng: function(x, y, z) {
return new google.maps.LatLng(x / 128.0, z / 128.0);
}
};
function FlatMapType(configuration) {
$.extend(this, configuration); }
FlatMapType.prototype = $.extend(new DynMapType(), {
constructor: FlatMapType,
projection: new FlatProjection(),
tileSize: new google.maps.Size(128.0, 128.0),
minZoom: 0,
maxZoom: 0,
prefix: null,
getTile: function(coord, zoom, doc) {
var tileName;
var tile = $('<img/>')
.attr('src', this.dynmap.getTileUrl(tileName = this.prefix + '_128_' + coord.x + '_' + coord.y + '.png'))
.error(function() { tile.hide(); })
.bind('load', function() { tile.show(); })
.css({
width: '128px',
height: '128px',
borderStyle: 'none'
})
.hide();
this.dynmap.registerTile(this, tileName, tile);
//this.dynmap.unregisterTile(this, tileName);
return tile.get(0);
},
updateTileSize: function(zoom) {
}
});
maptypes.FlatMapType = function(configuration) { return new FlatMapType(configuration); };

View File

Before

Width:  |  Height:  |  Size: 339 B

After

Width:  |  Height:  |  Size: 339 B

View File

Before

Width:  |  Height:  |  Size: 340 B

After

Width:  |  Height:  |  Size: 340 B

View File

Before

Width:  |  Height:  |  Size: 330 B

After

Width:  |  Height:  |  Size: 330 B

View File

Before

Width:  |  Height:  |  Size: 342 B

After

Width:  |  Height:  |  Size: 342 B

View File

Before

Width:  |  Height:  |  Size: 829 B

After

Width:  |  Height:  |  Size: 829 B

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 868 B

After

Width:  |  Height:  |  Size: 868 B

View File

Before

Width:  |  Height:  |  Size: 395 B

After

Width:  |  Height:  |  Size: 395 B

View File

Before

Width:  |  Height:  |  Size: 261 B

After

Width:  |  Height:  |  Size: 261 B

View File

Before

Width:  |  Height:  |  Size: 357 B

After

Width:  |  Height:  |  Size: 357 B

View File

Before

Width:  |  Height:  |  Size: 360 B

After

Width:  |  Height:  |  Size: 360 B

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 802 B

After

Width:  |  Height:  |  Size: 802 B

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 377 B

After

Width:  |  Height:  |  Size: 377 B

View File

Before

Width:  |  Height:  |  Size: 376 B

After

Width:  |  Height:  |  Size: 376 B

View File

Before

Width:  |  Height:  |  Size: 428 B

After

Width:  |  Height:  |  Size: 428 B

View File

Before

Width:  |  Height:  |  Size: 351 B

After

Width:  |  Height:  |  Size: 351 B

View File

Before

Width:  |  Height:  |  Size: 360 B

After

Width:  |  Height:  |  Size: 360 B

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 328 B

After

Width:  |  Height:  |  Size: 328 B

View File

Before

Width:  |  Height:  |  Size: 404 B

After

Width:  |  Height:  |  Size: 404 B

View File

Before

Width:  |  Height:  |  Size: 459 B

After

Width:  |  Height:  |  Size: 459 B

View File

Before

Width:  |  Height:  |  Size: 361 B

After

Width:  |  Height:  |  Size: 361 B

View File

Before

Width:  |  Height:  |  Size: 332 B

After

Width:  |  Height:  |  Size: 332 B

View File

Before

Width:  |  Height:  |  Size: 355 B

After

Width:  |  Height:  |  Size: 355 B

View File

Before

Width:  |  Height:  |  Size: 454 B

After

Width:  |  Height:  |  Size: 454 B

View File

Before

Width:  |  Height:  |  Size: 368 B

After

Width:  |  Height:  |  Size: 368 B

View File

Before

Width:  |  Height:  |  Size: 271 B

After

Width:  |  Height:  |  Size: 271 B

View File

Before

Width:  |  Height:  |  Size: 681 B

After

Width:  |  Height:  |  Size: 681 B

View File

Before

Width:  |  Height:  |  Size: 407 B

After

Width:  |  Height:  |  Size: 407 B

View File

Before

Width:  |  Height:  |  Size: 431 B

After

Width:  |  Height:  |  Size: 431 B

View File

Before

Width:  |  Height:  |  Size: 431 B

After

Width:  |  Height:  |  Size: 431 B

View File

Before

Width:  |  Height:  |  Size: 435 B

After

Width:  |  Height:  |  Size: 435 B

View File

Before

Width:  |  Height:  |  Size: 943 B

After

Width:  |  Height:  |  Size: 943 B

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 374 B

After

Width:  |  Height:  |  Size: 374 B

View File

Before

Width:  |  Height:  |  Size: 355 B

After

Width:  |  Height:  |  Size: 355 B

View File

Before

Width:  |  Height:  |  Size: 326 B

After

Width:  |  Height:  |  Size: 326 B

View File

Before

Width:  |  Height:  |  Size: 299 B

After

Width:  |  Height:  |  Size: 299 B

View File

Before

Width:  |  Height:  |  Size: 290 B

After

Width:  |  Height:  |  Size: 290 B

View File

Before

Width:  |  Height:  |  Size: 326 B

After

Width:  |  Height:  |  Size: 326 B

View File

Before

Width:  |  Height:  |  Size: 366 B

After

Width:  |  Height:  |  Size: 366 B

View File

Before

Width:  |  Height:  |  Size: 336 B

After

Width:  |  Height:  |  Size: 336 B

View File

@ -8,7 +8,7 @@
<meta name="keywords" content="minecraft, map, dynamic" />
<meta name="description" content="Minecraft Dynamic Map" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<link rel="icon" href="dynmap.ico" type="image/ico" />
<link rel="icon" href="images/dynmap.ico" type="image/ico" />
<link rel="stylesheet" type="text/css" href="dynmap_style.css" media="screen" />
<!-- <link rel="stylesheet" type="text/css" href="override.css" media="screen" /> -->
@ -20,6 +20,7 @@
<script type="text/javascript" src="minecraft.js"></script>
<script type="text/javascript" src="map.js"></script>
<script type="text/javascript" src="kzedmaps.js"></script>
<script type="text/javascript" src="flatmap.js"></script>
<script type="text/javascript" src="clock.timeofday.js"></script>
<script type="text/javascript" src="clock.digital.js"></script>
<script type="text/javascript" src="chat.js"></script>

View File

@ -39,14 +39,12 @@ KzedMapType.prototype = $.extend(new DynMapType(), {
var tileSize = 128;
var tileName;
var imgSize;
var offset = {x: 0, y: 0};
var debugred;
var debugblue;
if (zoom == 0) {
// Most zoomed out tiles.
tileSize = 128;
imgSize = tileSize;
tileName = 'z' + this.prefix + '_' + (-coord.x * tileSize*2) + '_' + (coord.y * tileSize*2) + '.png';
@ -54,14 +52,8 @@ KzedMapType.prototype = $.extend(new DynMapType(), {
// Other zoom levels.
tileSize = 128;
// Helper functions.
/*var floor = Math.floor;
var div = function(x,y){return floor(x/y);}
var mod = function(x,y){return ((x%y)+y)%y;};*/
imgSize = Math.pow(2, 6+zoom);
var mapcoord = {x: coord.x*tileSize, y: coord.y*tileSize};
tileName = this.prefix + '_' + (-mapcoord.x) + '_' + mapcoord.y + '.png';
tileName = this.prefix + '_' + (-coord.x*tileSize) + '_' + (coord.y*tileSize) + '.png';
}
var img;
var tile = $('<div/>')
@ -87,9 +79,7 @@ KzedMapType.prototype = $.extend(new DynMapType(), {
.css({
width: imgSize + 'px',
height: imgSize + 'px',
borderStyle: 'none',
/*marginLeft: offset.x + 'px',
marginTop: offset.y + 'px'*/
borderStyle: 'none'
})
.hide()
.appendTo(tile);

View File

@ -44,6 +44,8 @@ function DynMap(options) {
$.getJSON(me.options.updateUrl + 'configuration', function(configuration) {
me.configure(configuration);
me.initialize();
}, function(status, statusMessage) {
alert('Could not retrieve configuration: ' + statusMessage);
});
}
DynMap.prototype = {
@ -156,7 +158,7 @@ DynMap.prototype = {
.append($('<a/>')
.attr({ title: map.title, href: '#' })
.addClass('maptype')
.css({ backgroundImage: 'url(' + (map.icon || 'block_' + map.name + '.png') + ')' })
.css({ backgroundImage: 'url(' + (map.icon || 'images/block_' + map.name + '.png') + ')' })
.text(map.title)
)
.click(function() {
@ -208,7 +210,7 @@ DynMap.prototype = {
value: ''
})
.keydown(function(event) {
if (event.keyCode === '13') {
if (event.keyCode == '13') {
event.preventDefault();
sendChat(chatinput.val());
chatinput.val('');
@ -232,6 +234,7 @@ DynMap.prototype = {
var alertbox = me.alertbox = $('<div/>')
.addClass('alertbox')
.hide()
.appendTo(container);
me.selectMap(me.defaultworld.defaultmap);
@ -333,9 +336,9 @@ DynMap.prototype = {
//divs.filter(function(i){return parseInt(divs[i].attr('rel')) > timestamp+me.options.messagettl;}).remove();
});
setTimeout(function() { me.update(); }, me.options.updaterate);
}, function(request, statusText, ex) {
}, function(status, statusText, request) {
me.alertbox
.text('Could not update map')
.text('Could not update map: ' + (statusText || 'Could not connect to server'))
.show();
setTimeout(function() { me.update(); }, me.options.updaterate);
}
@ -488,7 +491,7 @@ DynMap.prototype = {
.addClass('Marker')
.addClass('playerMarker')
.append(playerImage = $('<img/>')
.attr({ src: 'player.png' }))
.attr({ src: 'images/player.png' }))
.append($('<span/>')
.addClass('playerName')
.text(player.name));
@ -509,7 +512,7 @@ DynMap.prototype = {
.addClass('player')
.append(playerIconContainer = $('<span/>')
.addClass('playerIcon')
.append($('<img/>').attr({ src: 'player_face.png' }))
.append($('<img/>').attr({ src: 'images/player_face.png' }))
.attr({ title: 'Follow ' + player.name })
.click(function() {
var follow = player !== me.followingPlayer;
@ -523,7 +526,10 @@ DynMap.prototype = {
})
.text(player.name)
)
.click(function(e) { me.panTo(player.location); })
.click(function(e) {
me.followPlayer(null);
me.panTo(player.location);
})
.appendTo(me.playerlist);
if (me.options.showplayerfacesinmenu) {
getMinecraftHead(player.name, 16, function(head) {

View File

@ -34,7 +34,7 @@ function createMinecraftHead(player,completed,failed) {
skinImage.src = 'http://www.minecraft.net/img/char.png';
}
};
skinImage.src = 'http://www.minecraft.net/skin/' + player + '.png';
skinImage.src = 'http://s3.amazonaws.com/MinecraftSkins/' + player + '.png';
}
function resizeImage(img,size) {

View File

@ -1,17 +1,19 @@
/*******************
* This is the over-ride CSS file.
*
* if you know any CSS you can easily add any custom rules to change how
* Dynmap looks for your particular install.
* if you know any CSS you can easily add custom rules to change how DynMap
* looks and behaves under your DynMap installation.
*
* Simply uncomment the override.css in the index.html and rename this file
* to override.css to use these custom rules.
* 1. Uncomment the override.css in the index.html.
* 2. Rename this file or create a new override.css.
* 3. Add your own rules (or steal these) to personalize how DynMap looks.
*
* By adding these rules here you can easily save your changes between updates.
* By adding your own rules here, you can then save your changes
* between DynMap updates and they won't get over-written.
*/
/* IE : Use the alternate compass image */
/* Use the alternate compass image */
.compass {
top: 20px;
@ -20,5 +22,18 @@
height: 50px;
width: 50px;
background-image: url(compass_alt.png);
background-image: url(images/compass_alt.png);
}
/* These next two keep the DynMap sidebar open... */
.dynmap .sidebar {
margin-right: 0px;
}
/* ...and hide the hitbar along with the sidebar controls */
.dynmap .sidebar .hitbar,
.dynmap .sidebar .panel > .pin {
display: none;
}