Compare commits

...

93 Commits

Author SHA1 Message Date
Mike Primm 4152337568 Set to 0.19.2 for bug-fix release for 1.7 items 2011-07-03 18:03:04 -05:00
Mike Primm c393eec159 Workaround for CB 953 furnace freakout (fixed in CB955) 2011-07-03 12:03:06 -05:00
Mike Primm e724a7bccb Fix premature timeouts on tile read waits, causing missed tile loads 2011-07-03 11:30:48 -05:00
Mike Primm 97ff6a2c2d Add sticky piston block, too 2011-07-03 11:28:09 -05:00
Mike Primm 33206e089f Add piston and piston-head block color definitions 2011-06-30 15:29:47 -05:00
FrozenCow cb4f6aaf82 Changed version to 0.20. 2011-06-30 12:38:02 +02:00
mikeprimm c978d87fef Merge pull request #254 from mikeprimm/master
Set head branch back to 0.19.1 - need bug fix build
2011-06-29 19:11:58 -07:00
Mike Primm 1c32aebff9 Set to 0.19.1 - need bug fix release 2011-06-29 21:10:43 -05:00
Mike Primm 00a660d019 Don't throw exception on bogus absolute path (http://xxx//blah) 2011-06-30 03:19:04 +08:00
Mike Primm 1102c08b3e Don't throw exception on bogus absolute path (http://xxx//blah) 2011-06-29 14:16:12 -05:00
mikeprimm 3875486fbf Merge pull request #253 from mikeprimm/master
Add better URI path normalization, option to allow symlinks in web path
2011-06-29 11:44:58 -07:00
Mike Primm e6a8e54172 Add better URI path normalization, option to allow symlinks in web
path
2011-06-29 13:40:02 -05:00
mikeprimm e0f9a2f1e2 Merge pull request #251 from mikeprimm/master
Add some cleanup to help avoid exceptions on /reload and shutdown/disable
2011-06-28 23:38:04 -07:00
Mike Primm e2b55c3b54 Add some cleanup to help avoid exceptions on /reload and shutdown/disable 2011-06-29 01:37:09 -05:00
mikeprimm be983825ab Merge pull request #250 from mikeprimm/master
Fix WorldGuard regions code to handle polygon regions (WG5)
2011-06-28 22:45:15 -07:00
Mike Primm faceab68f1 Fix WorldGuard regions support to include WG5 polygon support 2011-06-29 00:43:39 -05:00
mikeprimm aa796deeff Merge pull request #249 from mikeprimm/master
Tighten up logic for assuring unlock of locked files during exceptions, fix version number display
2011-06-28 20:39:00 -07:00
Mike Primm 2863dd0acc Put timeout on read lock used by web server - make sure it can't be indefinite 2011-06-28 22:33:11 -05:00
Mike Primm 48fea32500 Tighten up lock release logic on I/O and other exceptions
Make version in plugin.yml string so that 0.20 isn't 0.2
2011-06-28 22:13:42 -05:00
mikeprimm b4b11329c2 Merge pull request #248 from mikeprimm/master
Fix 'visibleregions' option on JSON implementation of WorldGuard regions
2011-06-28 09:07:28 -07:00
Mike Primm f118ada39e Fix 'visibleregions' option on JSON (gotta kill those parallel code
paths at some point....)
2011-06-28 11:00:05 -05:00
mikeprimm 1a23f24b81 Merge pull request #247 from mikeprimm/master
Fix break in processing center: coordinates due to mistake in url-parameter code
2011-06-27 18:49:40 -07:00
Mike Primm edf898ae1a Fix "center" processing - broke it with URL args change :< 2011-06-27 20:38:26 -05:00
FrozenCow bf29c09522 Changed version to 0.20. 2011-06-27 21:44:12 +02:00
Jason Booth d3b621f90b Fix Security Exploit 2011-06-27 21:27:23 +02:00
FrozenCow 47620fe79e Revert "Disallow .. in file path. Also logging, imports"
This reverts commit 1bc275ea46.
2011-06-27 21:26:52 +02:00
zeeZ 1bc275ea46 Disallow .. in file path. Also logging, imports 2011-06-27 22:48:39 +08:00
mikeprimm d4f0161e14 Merge pull request #245 from mikeprimm/master
Add icon for Biome maps, and color mapping for SKY biome
2011-06-26 22:08:35 -07:00
Mike Primm d59c8f1506 Add SKY biome mappings 2011-06-27 00:07:00 -05:00
Mike Primm 752a076236 Add default icon for Biome maps 2011-06-26 22:36:17 -05:00
mikeprimm 8089e75ab2 Merge pull request #244 from mikeprimm/master
Add support for URL-based parameter overrides for selecting world, map, zoom, and center coordinates
2011-06-26 20:12:49 -07:00
Mike Primm 3720c2adf7 Add support for URL-based parameter to override initial world, map, zoom, and center coordinate settings 2011-06-26 22:05:43 -05:00
mikeprimm dbbff3d04f Merge pull request #243 from mikeprimm/master
Add verbose: false option to make dynmap much less chatty during startup
2011-06-26 12:33:55 -07:00
Mike Primm b937c4bf38 Add option to have Dynmap STFU during start (verbose: false)
Add softdep, authors, stats commands to plugin.yml
2011-06-26 14:31:40 -05:00
mikeprimm 54f5de4c2c Merge pull request #241 from mikeprimm/master
Change autogenerate-to-visbilitylimits to have 3 options: none, map-only, permanent
2011-06-25 14:07:57 -07:00
Mike Primm 39281188bc Change autogenerate-to-visibilitylimits to have options for map-only (temporary generated chunks) versus permanent (world growing)
Fix exception catching code in thread pool
2011-06-25 16:01:06 -05:00
mikeprimm 4678c53a48 Merge pull request #240 from mikeprimm/master
Add option to use visibilitylimits to define area to automatically prime chunk generation
2011-06-24 23:23:06 -07:00
Mike Primm 6dac7f0689 Add autogenerate-to-visibilitylimits option to allow automatic priming/generating of chunks within defined visibility area
Avoid rendering tiles with nothing but empty chunks
Limit size of hash-file cache, and move hash files to world-specific tile directories
2011-06-25 01:13:40 -05:00
mikeprimm 3310e07c9b Merge pull request #239 from mikeprimm/master
Add support for 'chunkgenerated' render trigger, now that CB has functional chunk generate events
2011-06-24 17:14:16 -07:00
Mike Primm 3674ba3786 Add support for now-functional chunk generate detection
(chunkgenerated render trigger)
2011-06-24 19:10:10 -05:00
mikeprimm f81dc8cdac Merge pull request #238 from mikeprimm/master
Fix bigworld+iso-maps+zoom-out issue with directory name logic inconsistency
2011-06-24 12:20:23 -07:00
Mike Primm f3ac3d9be4 Another bigworld+isomaps+zoom-out fix - directory name inconsistency 2011-06-24 14:18:21 -05:00
mikeprimm fcb865ea28 Merge pull request #237 from mikeprimm/master
Fix occasional broken zoom-out tiles due to hash code calculation error
2011-06-24 10:06:27 -07:00
Mike Primm 5bb3249dfe Fix hash code problem with zoomed-out tiles - caused incomplete
updates
2011-06-24 11:44:21 -05:00
mikeprimm eb12834ee3 Merge pull request #236 from mikeprimm/master
Add invalidate events to zoom out processing - avoids problems with linux file time resolution
2011-06-24 06:32:20 -07:00
Mike Primm 214fec208d Add queued update triggers for zoom-out updates - deals with file time
resolution issues on Linux (1 second is too long to be reliable)
2011-06-24 08:25:26 -05:00
mikeprimm ec948f980e Merge pull request #235 from mikeprimm/master
Add file hashing to reduce zoom-out tile recalc, fix bigworld support
2011-06-24 00:50:05 -07:00
Mike Primm d63db655d8 More tuning on zoom-out, fix zoomout on bigworld on iso-maps 2011-06-24 02:46:16 -05:00
mikeprimm 2ab7339381 Merge pull request #234 from mikeprimm/master
Per request, add 'trustclientname' option to sendMessage on InternalClientUpdaeComponent
2011-06-23 14:40:26 -07:00
Mike Primm c2ee0ebd42 Add requestion option to trust client-provided name in sendMessage for
internal web server
2011-06-23 16:35:17 -05:00
mikeprimm 654769af1e Merge pull request #233 from mikeprimm/master
Fix reported trap in Armor calculation when player has incomplete set of armor
2011-06-23 06:13:32 -07:00
Mike Primm 244419d686 Fix reported traps in Armor calculation when armor is incomplete - not
sure how this didn't happen more - possibly bukkit behavior change?
2011-06-23 08:08:33 -05:00
mikeprimm 6d6a5f4db0 Merge pull request #232 from mikeprimm/master
Add support for configurable extra zoom out levels on each world - generates more tiers of zoomed images
2011-06-22 23:10:35 -07:00
Mike Primm f722c6fdc8 Finish zoom out on normal and 'bigworld' mode, fix marker coordinates 2011-06-23 00:53:56 -05:00
Mike Primm 9db23444db Fix problem with coordinate offsets due to negative coordinate walk on
kzedmaps
2011-06-22 17:24:12 -05:00
Mike Primm 8e102446fe First pass UI support for extra zoom out levels 2011-06-22 16:43:41 -05:00
Mike Primm e7e4406e77 Finish rest of zoom out core logic - still need to finish web UI 2011-06-22 13:56:21 -05:00
Mike Primm bec1108fa1 Settable zoom out code - incomplete prototype 2011-06-22 08:27:21 -05:00
mikeprimm 42f4d4e4a6 Merge pull request #230 from mikeprimm/master
Add support for optional 'visibleregions' list attribute for regions component, to limit visible region population
2011-06-20 16:50:48 -07:00
Mike Primm a7c6a20dcc Add support for visibleregions list for regions component - limit
which regions are shown
2011-06-20 18:48:23 -05:00
mikeprimm 90bff11417 Merge pull request #229 from mikeprimm/master
Fix reading of webpath by regions component - load from top-level setting, instead of component local config
2011-06-20 15:36:18 -07:00
Mike Primm 2c3e8fbdc0 Fix reading of 'webpath' by Regions component - was reading its own
config instead of top-level one
2011-06-20 17:33:01 -05:00
mikeprimm 690be9d80a Merge pull request #228 from mikeprimm/master
Add delay-retry on image file writes, to recover from locked file exceptions from external web servers
2011-06-20 15:01:08 -07:00
Mike Primm e584e3202b Add delay-retry loop for handling temporarily locked image file writes 2011-06-20 16:58:07 -05:00
mikeprimm 427249b5a9 Merge pull request #226 from mikeprimm/master
Add support for biome-data-based shading on surface map renderer
2011-06-20 14:11:42 -07:00
Mike Primm 6efbf3a3df Update biomecolored to support biome-type-based,
biome-temperature-based and biome-rainfail-based shading
2011-06-20 16:00:28 -05:00
Mike Primm edf7d4f5c8 Add biome-based coloring option for surface map 2011-06-20 00:09:22 -05:00
mikeprimm 287d3cbe63 Merge pull request #225 from mikeprimm/master
Add support for throttling chunk load rate, splitting tile loads across multiple server ticks if needed
2011-06-18 17:50:26 -07:00
Mike Primm 2bc9b410a6 Add support for throttling chunk load rate, spreading over ticks 2011-06-18 19:43:47 -05:00
mikeprimm 6ecb271576 Merge pull request #224 from mikeprimm/master
Alter 'textured' setting on flat map to have 'none'/'smooth'/'dither' choices
2011-06-18 14:11:00 -07:00
Mike Primm 8b35f4d3b7 Alter 'textured' setting for flat map to have none/smooth/dither opts 2011-06-18 16:05:47 -05:00
mikeprimm 4a9eb76944 Merge pull request #220 from mikeprimm/master
Add 'textured' option to Flat render - when set, causes color dither to match surface map (looks more consistent)
2011-06-16 22:14:43 -07:00
Mike Primm e18ab1a880 Add 'textured' option for Flat - matches color scheme tone better 2011-06-17 00:08:13 -05:00
mikeprimm fa34aafabe Merge pull request #219 from mikeprimm/master
Support defining visibility limits on each world, and selectiong methods for how to present hidden areas
2011-06-16 21:45:22 -07:00
Mike Primm ffc08173b4 Add support for limiting visible areas on each world, selective fill
of hidden areas (air, stone, ocean)
2011-06-16 23:37:28 -05:00
mikeprimm 4fdcc0bf92 Merge pull request #218 from mikeprimm/master
Report output from fullrender to command sender, not log
2011-06-16 00:01:10 -07:00
Mike Primm 81dbb8483f Merge remote branch 'upstream/master' 2011-06-16 01:58:38 -05:00
Mike Primm fa33977469 Log fullrender messages to commandsender, versus just log 2011-06-16 01:58:12 -05:00
mikeprimm 5bd7c64c97 Merge pull request #217 from mikeprimm/master
MAKE IE SUCK LESS!
2011-06-15 11:50:07 -07:00
mikeprimm 095f7b5338 Make IE happy (or, at least, suck much less) by providing a valid background color! 2011-06-15 11:45:59 -07:00
mikeprimm 0b735eba40 Merge pull request #216 from mikeprimm/master
Support new Bukkit ChunkSnapshot API, maintain legacy chunksnapshot support
2011-06-14 23:42:57 -07:00
Mike Primm 0b7bd72231 Merge remote branch 'upstream/master' 2011-06-15 01:40:42 -05:00
Mike Primm b1d1075dfe Add support for ChunkSnapshot API (CB860), maintain legacy support too 2011-06-15 01:27:59 -05:00
mikeprimm 8b730dc543 Merge pull request #215 from mikeprimm/master
Prevent chat balloons being shown when speaking player is not on currently shown world
2011-06-14 15:59:15 -07:00
Mike Primm dc74901638 Clean up linefeed changes... 2011-06-14 17:57:51 -05:00
mikeprimm 5115c587ff Merge pull request #214 from mikeprimm/master
Add support for new render triggers - snowform, blockburn, leavesdecay
2011-06-13 21:22:42 -07:00
Mike Primm 9286cfff66 Add blockburn, snowform, leavesdecay render events 2011-06-13 23:19:02 -05:00
mikeprimm 2c66044550 Merge pull request #213 from mikeprimm/master
Clean up random compile warnings
2011-06-13 20:08:20 -07:00
Mike Primm 2f22560f3d Clean up warnings 2011-06-13 22:05:14 -05:00
mikeprimm 1eb9789780 Merge pull request #212 from mikeprimm/master
Add support for alternate tile directory structure, to better support huge worlds
2011-06-13 19:50:53 -07:00
Mike Primm 0cf7b4be9b Add alternate directory structure to better support huge worlds 2011-06-13 21:43:02 -05:00
FrozenCow b19d8f8745 Fixed urls for php and aspx proxies. 2011-06-13 23:37:35 +02:00
FrozenCow 864d815bc4 Changed version to 0.19. 2011-06-13 21:12:35 +02:00
57 changed files with 3071 additions and 720 deletions
+40
View File
@@ -54,12 +54,18 @@ Powered Rail
27 150 134 102 180 120 107 81 180 75 67 51 180 60 53 40 180
Detector Rail
28 150 134 102 180 120 107 81 180 75 67 51 180 60 53 40 180
Sticky Piston
29 157 128 79 255 96 96 96 255 78 64 39 255 48 48 48 255
Cobweb
30 138 145 145 255 110 115 115 255 69 72 72 255 55 57 57 255
Tall Grass
31 97 156 53 255 73 120 38 255 38 68 16 255 26 50 9 255
Dead Shrubs
32 75 44 24 255 60 35 19 255 37 22 12 255 30 18 10 255
Piston
33 157 128 79 255 96 96 96 255 78 64 39 255 48 48 48 255
Piston Head
34 157 128 79 255 96 96 96 255 78 64 39 255 48 48 48 255
Wool
35 222 222 222 255 177 177 177 255 111 111 111 255 88 88 88 255
35:0 222 222 222 255 177 177 177 255 111 111 111 255 88 88 88 255
@@ -227,3 +233,37 @@ Locked Chest
95 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
Trap Door
96 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
Biome Rainforest - Dark Green
[RAINFOREST] 49 67 21 255 39 53 17 255 24 34 10 255 19 27 8 255
Biome Swampland - Brown
[SWAMPLAND] 75 44 24 255 60 35 19 255 37 22 12 255 30 18 10 255
Biome Seasonal Forest - Light Green
[SEASONAL_FOREST] 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
Biome Forest - Light Gray
[FOREST] 138 145 145 255 110 115 115 255 69 72 72 255 55 57 57 255
Biome Savanna - Dark Gray
[SAVANNA] 58 58 58 255 47 47 47 255 29 29 29 255 23 23 23 255
Biome Shrubland - Yellow
[SHRUBLAND] 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
Biome Taiga - Cyan
[TAIGA] 34 102 131 255 27 81 104 255 17 51 65 255 13 40 52 255
Biome Desert - Orange
[DESERT] 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
Biome Plains - Magenta
[PLAINS] 166 66 175 255 133 53 140 255 83 33 87 255 66 26 69 255
Biome Ice Desert - Dark Blue
[ICE_DESERT] 26 33 103 255 20 26 80 255 13 17 50 255 9 14 40 255
Biome Tundra - White
[TUNDRA] 222 222 222 255 177 177 177 255 111 111 111 255 88 88 88 255
Biome Hell - Pink
[HELL] 190 115 135 255 151 92 108 255 95 57 67 255 75 46 53 255
Biome Sky - Blue
[SKY] 34 44 134 255 27 35 107 255 17 22 67 255 13 18 53 255
[RAINFALL-0.0] 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
[RAINFALL-1.0] 38 92 255 255 30 73 204 255 19 46 127 255 15 36 102 255
[TEMPERATURE-0.0] 38 92 255 255 30 73 204 255 19 46 127 255 15 36 102 255
[TEMPERATURE-0.5] 91 121 185 255 73 96 147 255 46 61 92 255 36 48 73 255
[TEMPERATURE-0.8] 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
[TEMPERATURE-0.9] 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
[TEMPERATURE-0.95] 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
[TEMPERATURE-1.0] 143 39 36 255 114 31 28 255 71 20 18 255 57 16 14 255
+40
View File
@@ -54,12 +54,18 @@ Powered Rail
27 150 134 102 180 120 107 81 180 75 67 51 180 60 53 40 180
Detector Rail
28 150 134 102 180 120 107 81 180 75 67 51 180 60 53 40 180
Sticky Piston
29 157 128 79 255 96 96 96 255 78 64 39 255 48 48 48 255
Cobweb
30 138 145 145 255 110 115 115 255 69 72 72 255 55 57 57 255
Tall Grass
31 97 156 53 255 73 120 38 255 38 68 16 255 26 50 9 255
Dead Shrubs
32 75 44 24 255 60 35 19 255 37 22 12 255 30 18 10 255
Piston
33 157 128 79 255 96 96 96 255 78 64 39 255 48 48 48 255
Piston Head
34 157 128 79 255 96 96 96 255 78 64 39 255 48 48 48 255
Wool
35 247 255 239 255 244 251 236 255 204 210 197 255 244 251 236 255
35:0 247 255 239 255 244 251 236 255 204 210 197 255 244 251 236 255
@@ -227,3 +233,37 @@ Locked Chest
95 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
Trap Door
96 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
Biome Rainforest - Dark Green
[RAINFOREST] 49 67 21 255 39 53 17 255 24 34 10 255 19 27 8 255
Biome Swampland - Brown
[SWAMPLAND] 75 44 24 255 60 35 19 255 37 22 12 255 30 18 10 255
Biome Seasonal Forest - Light Green
[SEASONAL_FOREST] 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
Biome Forest - Light Gray
[FOREST] 138 145 145 255 110 115 115 255 69 72 72 255 55 57 57 255
Biome Savanna - Dark Gray
[SAVANNA] 58 58 58 255 47 47 47 255 29 29 29 255 23 23 23 255
Biome Shrubland - Yellow
[SHRUBLAND] 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
Biome Taiga - Cyan
[TAIGA] 34 102 131 255 27 81 104 255 17 51 65 255 13 40 52 255
Biome Desert - Orange
[DESERT] 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
Biome Plains - Magenta
[PLAINS] 166 66 175 255 133 53 140 255 83 33 87 255 66 26 69 255
Biome Ice Desert - Dark Blue
[ICE_DESERT] 26 33 103 255 20 26 80 255 13 17 50 255 9 14 40 255
Biome Tundra - White
[TUNDRA] 222 222 222 255 177 177 177 255 111 111 111 255 88 88 88 255
Biome Hell - Pink
[HELL] 190 115 135 255 151 92 108 255 95 57 67 255 75 46 53 255
Biome Sky - Blue
[SKY] 34 44 134 255 27 35 107 255 17 22 67 255 13 18 53 255
[RAINFALL-0.0] 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
[RAINFALL-1.0] 38 92 255 255 30 73 204 255 19 46 127 255 15 36 102 255
[TEMPERATURE-0.0] 38 92 255 255 30 73 204 255 19 46 127 255 15 36 102 255
[TEMPERATURE-0.5] 91 121 185 255 73 96 147 255 46 61 92 255 36 48 73 255
[TEMPERATURE-0.8] 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
[TEMPERATURE-0.9] 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
[TEMPERATURE-0.95] 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
[TEMPERATURE-1.0] 143 39 36 255 114 31 28 255 71 20 18 255 57 16 14 255
+40 -1
View File
@@ -54,12 +54,18 @@ Powered Rail
27 150 134 102 180 120 107 81 180 75 67 51 180 60 53 40 180
Detector Rail
28 150 134 102 180 120 107 81 180 75 67 51 180 60 53 40 180
Sticky Piston
29 157 128 79 255 125 122 116 255 78 64 39 255 88 85 81 255
Cobweb
30 138 145 145 255 110 115 115 255 69 72 72 255 55 57 57 255
Tall Grass
31 111 185 79 255 86 158 53 255 65 131 40 255 57 105 21 255
Dead Shrubs
32 75 44 24 255 60 35 19 255 37 22 12 255 30 18 10 255
Piston
33 157 128 79 255 125 122 116 255 78 64 39 255 88 85 81 255
Piston Head
34 157 128 79 255 125 122 116 255 78 64 39 255 88 85 81 255
Wool
35 222 222 222 255 177 177 177 255 111 111 111 255 88 88 88 255
35:0 222 222 222 255 177 177 177 255 111 111 111 255 88 88 88 255
@@ -227,4 +233,37 @@ Locked Chest
95 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
Trap Door
96 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
Biome Rainforest - Dark Green
[RAINFOREST] 49 67 21 255 39 53 17 255 24 34 10 255 19 27 8 255
Biome Swampland - Brown
[SWAMPLAND] 75 44 24 255 60 35 19 255 37 22 12 255 30 18 10 255
Biome Seasonal Forest - Light Green
[SEASONAL_FOREST] 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
Biome Forest - Light Gray
[FOREST] 138 145 145 255 110 115 115 255 69 72 72 255 55 57 57 255
Biome Savanna - Dark Gray
[SAVANNA] 58 58 58 255 47 47 47 255 29 29 29 255 23 23 23 255
Biome Shrubland - Yellow
[SHRUBLAND] 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
Biome Taiga - Cyan
[TAIGA] 34 102 131 255 27 81 104 255 17 51 65 255 13 40 52 255
Biome Desert - Orange
[DESERT] 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
Biome Plains - Magenta
[PLAINS] 166 66 175 255 133 53 140 255 83 33 87 255 66 26 69 255
Biome Ice Desert - Dark Blue
[ICE_DESERT] 26 33 103 255 20 26 80 255 13 17 50 255 9 14 40 255
Biome Tundra - White
[TUNDRA] 222 222 222 255 177 177 177 255 111 111 111 255 88 88 88 255
Biome Hell - Pink
[HELL] 190 115 135 255 151 92 108 255 95 57 67 255 75 46 53 255
Biome Sky - Blue
[SKY] 34 44 134 255 27 35 107 255 17 22 67 255 13 18 53 255
[RAINFALL-0.0] 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
[RAINFALL-1.0] 38 92 255 255 30 73 204 255 19 46 127 255 15 36 102 255
[TEMPERATURE-0.0] 38 92 255 255 30 73 204 255 19 46 127 255 15 36 102 255
[TEMPERATURE-0.5] 91 121 185 255 73 96 147 255 46 61 92 255 36 48 73 255
[TEMPERATURE-0.8] 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
[TEMPERATURE-0.9] 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
[TEMPERATURE-0.95] 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
[TEMPERATURE-1.0] 143 39 36 255 114 31 28 255 71 20 18 255 57 16 14 255
+38 -1
View File
@@ -25,9 +25,12 @@
26 200 20 20 255 160 16 16 255 100 10 10 255 80 8 8 255
27 150 134 102 180 120 107 81 180 75 67 51 180 60 53 40 180
28 150 134 102 180 120 107 81 180 75 67 51 180 60 53 40 180
29 109 80 60 255 111 108 98 255 76 56 41 255 111 108 98 255
30 138 145 145 255 110 115 115 255 69 72 72 255 55 57 57 255
31 97 156 53 255 73 120 38 255 38 68 16 255 26 50 9 255
32 75 44 24 255 60 35 19 255 37 22 12 255 30 18 10 255
33 109 80 60 255 111 108 98 255 76 56 41 255 111 108 98 255
34 109 80 60 255 111 108 98 255 76 56 41 255 111 108 98 255
35 247 255 239 255 244 251 236 255 204 210 197 255 244 251 236 255
35:0 247 255 239 255 244 251 236 255 204 210 197 255 244 251 236 255
35:1 227 128 52 255 224 126 51 255 187 105 42 255 224 126 51 255
@@ -112,4 +115,38 @@
93 159 127 80 255 72 56 25 0 181 140 64 255 144 112 51 0
94 159 127 80 255 102 0 0 0 255 0 0 255 204 0 0 0
95 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
96 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
96 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
Biome Rainforest - Dark Green
[RAINFOREST] 49 67 21 255 39 53 17 255 24 34 10 255 19 27 8 255
Biome Swampland - Brown
[SWAMPLAND] 75 44 24 255 60 35 19 255 37 22 12 255 30 18 10 255
Biome Seasonal Forest - Light Green
[SEASONAL_FOREST] 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
Biome Forest - Light Gray
[FOREST] 138 145 145 255 110 115 115 255 69 72 72 255 55 57 57 255
Biome Savanna - Dark Gray
[SAVANNA] 58 58 58 255 47 47 47 255 29 29 29 255 23 23 23 255
Biome Shrubland - Yellow
[SHRUBLAND] 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
Biome Taiga - Cyan
[TAIGA] 34 102 131 255 27 81 104 255 17 51 65 255 13 40 52 255
Biome Desert - Orange
[DESERT] 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
Biome Plains - Magenta
[PLAINS] 166 66 175 255 133 53 140 255 83 33 87 255 66 26 69 255
Biome Ice Desert - Dark Blue
[ICE_DESERT] 26 33 103 255 20 26 80 255 13 17 50 255 9 14 40 255
Biome Tundra - White
[TUNDRA] 222 222 222 255 177 177 177 255 111 111 111 255 88 88 88 255
Biome Hell - Pink
[HELL] 190 115 135 255 151 92 108 255 95 57 67 255 75 46 53 255
Biome Sky - Blue
[SKY] 34 44 134 255 27 35 107 255 17 22 67 255 13 18 53 255
[RAINFALL-0.0] 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
[RAINFALL-1.0] 38 92 255 255 30 73 204 255 19 46 127 255 15 36 102 255
[TEMPERATURE-0.0] 38 92 255 255 30 73 204 255 19 46 127 255 15 36 102 255
[TEMPERATURE-0.5] 91 121 185 255 73 96 147 255 46 61 92 255 36 48 73 255
[TEMPERATURE-0.8] 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
[TEMPERATURE-0.9] 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
[TEMPERATURE-0.95] 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
[TEMPERATURE-1.0] 143 39 36 255 114 31 28 255 71 20 18 255 57 16 14 255
+138 -63
View File
@@ -9,6 +9,7 @@ components:
allowwebchat: true
webchat-interval: 5
hidewebchatip: false
trustclientname: false
#- class: org.dynmap.JsonFileClientUpdateComponent
# writeinterval: 1
# sendhealth: true
@@ -60,6 +61,10 @@ components:
# strokeWeight: 3
# fillColor: "#FF0000"
# fillOpacity: 0.35
# # Optional setting to limit which regions to show, by name - if commented out, all regions are shown
# visibleregions:
# - homebase
# - miningsite
#- class: org.dynmap.TestComponent
# stuff: "This is some configuration-value"
@@ -69,15 +74,22 @@ display-whitelist: false
# How often a tile gets rendered (in seconds).
renderinterval: 1
# Zoom-out tile update period - how often to scan for and process tile updates into zoom-out tiles (in seconds)
zoomoutperiod: 60
# Tile hashing is used to minimize tile file updates when no changes have occurred - set to false to disable
enabletilehash: true
render-triggers:
# - chunkloaded
# - playermove
# - playerjoin
#- chunkloaded
#- playermove
#- playerjoin
- blockplaced
- blockbreak
- snowform
- leavesdecay
- blockburn
- chunkgenerated
# The path where the tile-files are placed.
tilespath: web/tiles
@@ -94,9 +106,15 @@ webserver-port: 8123
# Disables Webserver portion of Dynmap (Advanced users only)
disable-webserver: false
# Enable/disable having the web server allow symbolic links (true=compatible with existing code, false=more secure (default))
allow-symlinks: true
# Period between tile renders for fullrender, in seconds (non-zero to pace fullrenders, lessen CPU load)
timesliceinterval: 0.0
# Maximum chunk loads per server tick (1/20th of a second) - reducing this below 90 will impact render performance, but also will reduce server thread load
maxchunkspertick: 200
# Interval the browser should poll for updates.
updaterate: 2000
@@ -121,6 +139,10 @@ templates:
# Template for normal world
normal:
enabled: true
# # If bigworld set to true, use alternate directory layout better suited to large worlds
# bigworld: true
# # Number of extra zoom-out levels for world (each level is twice as big as the previous one)
# extrazoomout: 3
center:
x: 0
y: 64
@@ -131,19 +153,21 @@ templates:
title: "Flat"
prefix: flat
colorscheme: default
# To render a world as a "night view", set shadowstrength and ambientlight
# shadowstrength: 1.0
# ambientlight: 4
# To render both night and day versions of tiles (when ambientlight is set), set true
# night-and-day: true
# Option to turn on transparency support (off by default) - slows render
# transparency: true
# Background color for map during the day
# backgroundday: "#153E7E"
# Background color for map during the night
# backgroundnight: "#000000"
# Backgrounc color for map (independent of night/day)
# background: "#000000"
# The textured setting makes the flat render toning much more consistent with the other maps: set to 'none' for the original flat texture, 'smooth' for blended tile top colors, 'dither' for dither pattern
textured: smooth
# # To render a world as a "night view", set shadowstrength and ambientlight
# shadowstrength: 1.0
# ambientlight: 4
# # To render both night and day versions of tiles (when ambientlight is set), set true
# night-and-day: true
# # Option to turn on transparency support (off by default) - slows render
# transparency: true
# # Background color for map during the day
# backgroundday: "#153E7E"
# # Background color for map during the night
# backgroundnight: "#000000"
# # Background color for map (independent of night/day)
# background: "#000000"
- class: org.dynmap.kzedmap.KzedMap
renderers:
- class: org.dynmap.kzedmap.DefaultTileRenderer
@@ -152,30 +176,39 @@ templates:
prefix: t
maximumheight: 127
colorscheme: default
# Add shadows to world (based on top-down shadows from chunk data)
# shadowstrength: 1.0
# To render a world as a "night view", set shadowstrength and ambientlight
# ambientlight: 4
# To render both night and day versions of tiles (when ambientlight is set), set true
# night-and-day: true
# Option to turn off transparency support (on by default) - speeds render
# transparency: false
# Background color for map during the day
# backgroundday: "#153E7E"
# Background color for map during the night
# backgroundnight: "#000000"
# Backgrounc color for map (independent of night/day)
# background: "#000000"
# Sets the icon to 'images/block_custom.png'
# icon: custom
#- class: org.dynmap.kzedmap.HighlightTileRenderer
# prefix: ht
# maximumheight: 127
# colorscheme: default
# highlight: # For highlighting multiple block-types.
# - 56 # Highlight diamond-ore
# - 66 # Highlight minecart track
# highlight: 56 # For highlighting a single block-type.
# # Add shadows to world (based on top-down shadows from chunk data)
# shadowstrength: 1.0
# # To render a world as a "night view", set shadowstrength and ambientlight
# ambientlight: 4
# # To render both night and day versions of tiles (when ambientlight is set), set true
# night-and-day: true
# # Option to turn off transparency support (on by default) - speeds render
# transparency: false
# # Background color for map during the day
# backgroundday: "#153E7E"
# # Background color for map during the night
# backgroundnight: "#000000"
# # Background color for map (independent of night/day)
# background: "#000000"
# # Sets the icon to 'images/block_custom.png'
# icon: custom
# # Biome-based mapping
# - class: org.dynmap.kzedmap.DefaultTileRenderer
# name: biome
# title: "Biome"
# prefix: b
# maximumheight: 127
# colorscheme: default
# # Biome-based coloring : biome=biome type, temperature=biome-temperature, rainfall=biome-rainfall
# biomecolored: biome
# - class: org.dynmap.kzedmap.HighlightTileRenderer
# prefix: ht
# maximumheight: 127
# colorscheme: default
# highlight: # For highlighting multiple block-types.
# - 56 # Highlight diamond-ore
# - 66 # Highlight minecart track
# highlight: 56 # For highlighting a single block-type.
- class: org.dynmap.kzedmap.CaveTileRenderer
name: cave
title: "Cave"
@@ -184,6 +217,10 @@ templates:
# Nether world template
nether:
enabled: true
# # If bigworld set to true, use alternate directory layout better suited to large worlds
# bigworld: true
# # Number of extra zoom-out levels for world (each level is twice as big as the previous one)
# extrazoomout: 3
center:
x: 0
y: 64
@@ -196,6 +233,8 @@ templates:
colorscheme: default
# Map background color (day or night)
background: "#300806"
# The textured setting makes the flat render toning much more consistent with the other maps: set to 'none' for the original flat texture, 'smooth' for blended tile top colors, 'dither' for dither pattern
textured: smooth
- class: org.dynmap.kzedmap.KzedMap
renderers:
- class: org.dynmap.kzedmap.DefaultTileRenderer
@@ -209,6 +248,10 @@ templates:
# Skylands world template
skylands:
enabled: true
# # If bigworld set to true, use alternate directory layout better suited to large worlds
# bigworld: true
# # Number of extra zoom-out levels for world (each level is twice as big as the previous one)
# extrazoomout: 3
center:
x: 0
y: 64
@@ -223,6 +266,8 @@ templates:
backgroundday: "#153E7E"
# Background color for map during the night
backgroundnight: "#000000"
# The textured setting makes the flat render toning much more consistent with the other maps: set to 'none' for the original flat texture, 'smooth' for blended tile top colors, 'dither' for dither pattern
textured: smooth
- class: org.dynmap.kzedmap.KzedMap
renderers:
- class: org.dynmap.kzedmap.DefaultTileRenderer
@@ -260,6 +305,22 @@ worlds:
# - x: -15000
# y: 64
# z: -5000
# # Use visibilitylimits to restrict which areas of maps on your world to render (zero or more rectangles can be defined)
# visibilitylimits:
# - x0: -1000
# z0: -1000
# x1: 1000
# z1: 1000
# - x0: -2000
# z0: -1000
# x1: -1000
# z1: -500
# # Use hidestyle to control how hidden-but-existing chunks are to be rendered (air=empty air (same as ungenerated), stone=a flat stone plain, ocean=a flat ocean)
# hidestyle: stone
# # Use 'autogenerate-to-visibilitylimits: true' to choose to force the generation of ungenerated chunks while rendering maps on this world, for any chunks within the defined
# # visibilitylimits (limits must be set). The three options here are: none (default - no autogenerate), map-only (temporarily generate chunks for map, but don't save them (no world change),
# # permanent (generate and save chunks - this permanently adds the chunks to the world, as if a player had visited them - BE SURE THIS IS WHAT YOU WANT)
# autogenerate-to-visibilitylimits: map-only
# Use 'template: mycustomtemplate' to use the properties specified in the template 'mycustomtemplate' to this world. Default it is set to the environment-name (normal or nether).
# template: mycustomtemplate
# Rest of comes from template - uncomment to tailor for world specifically
@@ -267,25 +328,31 @@ worlds:
# x: 0
# y: 64
# z: 0
# # If bigworld set to true, use alternate directory layout better suited to large worlds
# bigworld: true
# # Number of extra zoom-out levels for world (each level is twice as big as the previous one)
# extrazoomout: 3
# maps:
# - class: org.dynmap.flat.FlatMap
# name: flat
# title: "Flat"
# prefix: flat
# colorscheme: default
# # The textured setting makes the flat render toning much more consistent with the other maps: set to 'none' for the original flat texture, 'smooth' for blended tile top colors, 'dither' for dither pattern
# textured: smooth
# # To render a world as a "night view", set shadowstrength and ambientlight
# # shadowstrength: 1.0
# # ambientlight: 4
# shadowstrength: 1.0
# ambientlight: 4
# # To render both night and day versions of tiles (when ambientlight is set), set true
# # night-and-day: true
# night-and-day: true
# # Option to turn on transparency support (off by default) - slows render
# # transparency: true
# transparency: true
# # Background color for map during the day
# # backgroundday: "#153E7E"
# backgroundday: "#153E7E"
# # Background color for map during the night
# # backgroundnight: "#000000"
# backgroundnight: "#000000"
# # Backgrounc color for map (independent of night/day)
# # background: "#000000"
# background: "#000000"
# - class: org.dynmap.kzedmap.KzedMap
# renderers:
# - class: org.dynmap.kzedmap.DefaultTileRenderer
@@ -295,29 +362,29 @@ worlds:
# maximumheight: 127
# colorscheme: default
# # Add shadows to world (based on top-down shadows from chunk data)
# # shadowstrength: 1.0
# shadowstrength: 1.0
# # To render a world as a "night view", set shadowstrength and ambientlight
# # ambientlight: 4
# ambientlight: 4
# # To render both night and day versions of tiles (when ambientlight is set), set true
# # night-and-day: true
# night-and-day: true
# # Option to turn off transparency support (on by default) - speeds render
# # transparency: false
# transparency: false
# # Background color for map during the day
# # backgroundday: "#153E7E"
# backgroundday: "#153E7E"
# # Background color for map during the night
# # backgroundnight: "#000000"
# backgroundnight: "#000000"
# # Backgrounc color for map (independent of night/day)
# # background: "#000000"
# background: "#000000"
# # Sets the icon to 'images/block_custom.png'
# # icon: custom
# #- class: org.dynmap.kzedmap.HighlightTileRenderer
# # prefix: ht
# # maximumheight: 127
# # colorscheme: default
# # highlight: # For highlighting multiple block-types.
# # - 56 # Highlight diamond-ore
# # - 66 # Highlight minecart track
# # highlight: 56 # For highlighting a single block-type.
# icon: custom
# - class: org.dynmap.kzedmap.HighlightTileRenderer
# prefix: ht
# maximumheight: 127
# colorscheme: default
# highlight: # For highlighting multiple block-types.
# - 56 # Highlight diamond-ore
# - 66 # Highlight minecart track
# highlight: 56 # For highlighting a single block-type.
# - class: org.dynmap.kzedmap.CaveTileRenderer
# name: cave
# title: "Cave"
@@ -334,12 +401,16 @@ worlds:
# x: 0
# y: 64
# z: 0
# # Number of extra zoom-out levels for world (each level is twice as big as the previous one)
# extrazoomout: 3
# maps:
# - class: org.dynmap.flat.FlatMap
# name: flat
# title: "Flat"
# prefix: flat
# colorscheme: default
# # The textured setting makes the flat render toning much more consistent with the other maps: set to 'none' for the original flat texture, 'smooth' for blended tile top colors, 'dither' for dither pattern
# textured: smooth
# - class: org.dynmap.kzedmap.KzedMap
# renderers:
# - class: org.dynmap.kzedmap.DefaultTileRenderer
@@ -349,6 +420,10 @@ worlds:
# maximumheight: 127
# colorscheme: default
# Set to true to enable verbose startup messages - can help with debugging map configuration problems
# Set to false for a much quieter startup log
verbose: true
# Enables debugging.
#debuggers:
# - class: org.dynmap.debug.LogDebugger
+1 -1
View File
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.dynmap</groupId>
<artifactId>dynmap</artifactId>
<version>0.18</version>
<version>0.19.2</version>
<name>dynmap</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+7 -1
View File
@@ -2,6 +2,7 @@ package org.dynmap;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.Material;
public class Armor {
/**
@@ -17,7 +18,12 @@ public class Armor {
double baseArmorPoints = 0;
ItemStack inventory[] = player.getInventory().getArmorContents();
for(int i=0;i<inventory.length;i++) {
final short maxDurability = inventory[i].getType().getMaxDurability();
if(inventory[i] == null)
continue;
Material m = inventory[i].getType();
if(m == null)
continue;
final short maxDurability = m.getMaxDurability();
if(maxDurability < 0)
continue;
final short durability = inventory[i].getDurability();
@@ -39,6 +39,7 @@ public class ClientComponent extends Component {
return o;
}
@SuppressWarnings("unchecked")
protected static final JSONArray convertList(List<?> l) {
JSONArray o = new JSONArray();
for(Object entry : l) {
@@ -47,6 +48,7 @@ public class ClientComponent extends Component {
return o;
}
@SuppressWarnings("unchecked")
protected static final Object convert(Object o) {
if (o instanceof Map<?, ?>) {
return convertMap((Map<String, ?>)o);
@@ -1,7 +1,6 @@
package org.dynmap;
import static org.dynmap.JSONUtils.a;
import static org.dynmap.JSONUtils.l;
import static org.dynmap.JSONUtils.s;
import org.dynmap.Event.Listener;
@@ -33,6 +32,8 @@ public class ClientConfigurationComponent extends Component {
s(wo, "center/x", wn.getFloat("center/x", 0.0f));
s(wo, "center/y", wn.getFloat("center/y", 64.0f));
s(wo, "center/z", wn.getFloat("center/z", 0.0f));
s(wo, "bigworld", world.bigworld);
s(wo, "extrazoomout", world.getExtraZoomOutLevels());
a(t, "worlds", wo);
for(MapType mt : world.maps) {
+128 -8
View File
@@ -8,19 +8,26 @@ import java.util.HashMap;
import java.util.Scanner;
import org.dynmap.debug.Debug;
import org.bukkit.block.Biome;
public class ColorScheme {
private static final HashMap<String, ColorScheme> cache = new HashMap<String, ColorScheme>();
public String name;
/* Switch to arrays - faster than map */
public Color[][] colors; /* [blk-type][step] */
public Color[][][] datacolors; /* [bkt-type][blk-dat][step] */
public final Color[][] colors; /* [blk-type][step] */
public final Color[][][] datacolors; /* [bkt-type][blk-dat][step] */
public final Color[][] biomecolors; /* [Biome.ordinal][step] */
public final Color[][] raincolors; /* [rain * 63][step] */
public final Color[][] tempcolors; /* [temp * 63][step] */
public ColorScheme(String name, Color[][] colors, Color[][][] datacolors) {
public ColorScheme(String name, Color[][] colors, Color[][][] datacolors, Color[][] biomecolors, Color[][] raincolors, Color[][] tempcolors) {
this.name = name;
this.colors = colors;
this.datacolors = datacolors;
this.biomecolors = biomecolors;
this.raincolors = raincolors;
this.tempcolors = tempcolors;
}
private static File getColorSchemeDirectory() {
@@ -42,6 +49,10 @@ public class ColorScheme {
File colorSchemeFile = new File(getColorSchemeDirectory(), name + ".txt");
Color[][] colors = new Color[256][];
Color[][][] datacolors = new Color[256][][];
Color[][] biomecolors = new Color[Biome.values().length][];
Color[][] raincolors = new Color[64][];
Color[][] tempcolors = new Color[64][];
InputStream stream;
try {
Debug.debug("Loading colors from '" + colorSchemeFile + "'...");
@@ -54,30 +65,86 @@ public class ColorScheme {
if (line.startsWith("#") || line.equals("")) {
continue;
}
String[] split = line.split("\t");
/* Make parser less pedantic - tabs or spaces should be fine */
String[] split = line.split("[\t ]");
int cnt = 0;
for(String s: split) { if(s.length() > 0) cnt++; }
String[] nsplit = new String[cnt];
cnt = 0;
for(String s: split) { if(s.length() > 0) { nsplit[cnt] = s; cnt++; } }
split = nsplit;
if (split.length < 17) {
continue;
}
Integer id;
Integer dat = null;
boolean isbiome = false;
boolean istemp = false;
boolean israin = false;
int idx = split[0].indexOf(':');
if(idx > 0) { /* ID:data - data color */
id = new Integer(split[0].substring(0, idx));
dat = new Integer(split[0].substring(idx+1));
}
else if(split[0].charAt(0) == '[') { /* Biome color data */
String bio = split[0].substring(1);
idx = bio.indexOf(']');
if(idx >= 0) bio = bio.substring(0, idx);
isbiome = true;
id = -1;
for(Biome b : Biome.values()) {
if(b.toString().equalsIgnoreCase(bio)) {
id = b.ordinal();
break;
}
}
if(id < 0) { /* Not biome - check for rain or temp */
if(bio.startsWith("RAINFALL-")) {
try {
double v = Double.parseDouble(bio.substring(9));
if((v >= 0) && (v <= 1.00)) {
id = (int)(v * 63.0);
israin = true;
}
} catch (NumberFormatException nfx) {
}
}
else if(bio.startsWith("TEMPERATURE-")) {
try {
double v = Double.parseDouble(bio.substring(12));
if((v >= 0) && (v <= 1.00)) {
id = (int)(v * 63.0);
istemp = true;
}
} catch (NumberFormatException nfx) {
}
}
}
}
else {
id = new Integer(split[0]);
}
Color[] c = new Color[4];
Color[] c = new Color[5];
/* 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]));
/* Blended color - for 'smooth' option on flat map */
c[4] = new Color((c[0].getRed()+c[2].getRed())/2, (c[0].getGreen()+c[2].getGreen())/2, (c[0].getBlue()+c[2].getBlue())/2, (c[0].getAlpha()+c[2].getAlpha())/2);
if(dat != null) {
if(isbiome) {
if(istemp) {
tempcolors[id] = c;
}
else if(israin) {
raincolors[id] = c;
}
else if((id >= 0) && (id < biomecolors.length))
biomecolors[id] = c;
}
else if(dat != null) {
Color[][] dcolor = datacolors[id]; /* Existing list? */
if(dcolor == null) {
dcolor = new Color[16][]; /* Make 16 index long list */
@@ -107,12 +174,65 @@ public class ColorScheme {
}
}
}
/* And interpolate any missing rain and temperature colors */
interpolateColorTable(tempcolors);
interpolateColorTable(raincolors);
} catch (RuntimeException e) {
Log.severe("Could not load colors '" + name + "' ('" + colorSchemeFile + "').", e);
return null;
} catch (FileNotFoundException e) {
Log.severe("Could not load colors '" + name + "' ('" + colorSchemeFile + "'): File not found.", e);
}
return new ColorScheme(name, colors, datacolors);
return new ColorScheme(name, colors, datacolors, biomecolors, raincolors, tempcolors);
}
public static void interpolateColorTable(Color[][] c) {
int idx = -1;
for(int k = 0; k < c.length; k++) {
if(c[k] == null) { /* Missing? */
if((idx >= 0) && (k == (c.length-1))) { /* We're last - so fill forward from last color */
for(int kk = idx+1; kk <= k; kk++) {
c[kk] = c[idx];
}
}
/* Skip - will backfill when we find next color */
}
else if(idx == -1) { /* No previous color, just backfill this color */
for(int kk = 0; kk < k; kk++) {
c[kk] = c[k];
}
idx = k; /* This is now last defined color */
}
else { /* Else, interpolate between last idx and this one */
int cnt = c[k].length;
for(int kk = idx+1; kk < k; kk++) {
double interp = (double)(kk-idx)/(double)(k-idx);
Color[] cc = new Color[cnt];
for(int jj = 0; jj < cnt; jj++) {
cc[jj] = new Color(
(int)((1.0-interp)*c[idx][jj].getRed() + interp*c[k][jj].getRed()),
(int)((1.0-interp)*c[idx][jj].getGreen() + interp*c[k][jj].getGreen()),
(int)((1.0-interp)*c[idx][jj].getBlue() + interp*c[k][jj].getBlue()),
(int)((1.0-interp)*c[idx][jj].getAlpha() + interp*c[k][jj].getAlpha()));
}
c[kk] = cc;
}
idx = k;
}
}
}
public Color[] getRainColor(double rain) {
int idx = (int)(rain * 63.0);
if((idx >= 0) && (idx < raincolors.length))
return raincolors[idx];
else
return null;
}
public Color[] getTempColor(double temp) {
int idx = (int)(temp * 63.0);
if((idx >= 0) && (idx < tempcolors.length))
return tempcolors[idx];
else
return null;
}
}
@@ -29,6 +29,7 @@ public class ConfigurationNode implements Map<String, Object> {
entries = map;
}
@SuppressWarnings("unchecked")
public Object getObject(String path) {
if (path.isEmpty())
return entries;
@@ -60,6 +61,7 @@ public class ConfigurationNode implements Map<String, Object> {
return o;
}
@SuppressWarnings("unchecked")
public <T> T getGeneric(String path, T def) {
Object o = getObject(path, def);
try {
@@ -112,6 +114,7 @@ public class ConfigurationNode implements Map<String, Object> {
return o.toString();
}
@SuppressWarnings("unchecked")
public <T> List<T> getList(String path) {
try {
List<T> list = (List<T>)getObject(path, null);
@@ -139,6 +142,7 @@ public class ConfigurationNode implements Map<String, Object> {
return new ConfigurationNode(v);
}
@SuppressWarnings("unchecked")
public List<ConfigurationNode> getNodes(String path) {
List<Object> o = getList(path);
@@ -165,6 +169,7 @@ public class ConfigurationNode implements Map<String, Object> {
extendMap(this, other);
}
@SuppressWarnings("unchecked")
private final static void extendMap(Map<String, Object> left, Map<String, Object> right) {
ConfigurationNode original = new ConfigurationNode(left);
for(Map.Entry<String, Object> entry : right.entrySet()) {
+95 -21
View File
@@ -18,8 +18,11 @@ import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockBurnEvent;
import org.bukkit.event.block.BlockListener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.LeavesDecayEvent;
import org.bukkit.event.block.SnowFormEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerMoveEvent;
@@ -49,6 +52,8 @@ public class DynmapPlugin extends JavaPlugin {
public Events events = new Events();
/* Flag to let code know that we're doing reload - make sure we don't double-register event handlers */
public boolean is_reload = false;
private boolean generate_only = false;
private static boolean ignore_chunk_loads = false; /* Flat to keep us from processing our own chunk loads */
public static File dataDirectory;
public static File tilesDirectory;
@@ -73,6 +78,8 @@ public class DynmapPlugin extends JavaPlugin {
bukkitConfiguration.load();
configuration = new ConfigurationNode(bukkitConfiguration);
Log.verbose = configuration.getBoolean("verbose", true);
loadDebuggers();
tilesDirectory = getFile(configuration.getString("tilespath", "web/tiles"));
@@ -101,7 +108,7 @@ public class DynmapPlugin extends JavaPlugin {
for(Component component : configuration.<Component>createInstances("components", new Class<?>[] { DynmapPlugin.class }, new Object[] { this })) {
componentManager.add(component);
}
Log.info("Loaded " + componentManager.components.size() + " components.");
Log.verboseinfo("Loaded " + componentManager.components.size() + " components.");
registerEvents();
@@ -129,10 +136,14 @@ public class DynmapPlugin extends JavaPlugin {
}
}
int port = configuration.getInteger("webserver-port", 8123);
boolean allow_symlinks = configuration.getBoolean("allow-symlinks", false);
if(allow_symlinks)
Log.verboseinfo("Web server is permitting symbolic links");
else
Log.verboseinfo("Web server is not permitting symbolic links");
webServer = new HttpServer(bindAddress, port);
webServer.handlers.put("/", new FilesystemHandler(getFile(configuration.getString("webpath", "web"))));
webServer.handlers.put("/tiles/", new FilesystemHandler(tilesDirectory));
webServer.handlers.put("/", new FilesystemHandler(getFile(configuration.getString("webpath", "web")), allow_symlinks));
webServer.handlers.put("/tiles/", new FilesystemHandler(tilesDirectory, allow_symlinks));
webServer.handlers.put("/up/configuration", new ClientConfigurationHandler(this));
}
@@ -180,11 +191,35 @@ public class DynmapPlugin extends JavaPlugin {
BlockListener renderTrigger = new BlockListener() {
@Override
public void onBlockPlace(BlockPlaceEvent event) {
if(event.isCancelled())
return;
mm.touch(event.getBlockPlaced().getLocation());
}
@Override
public void onBlockBreak(BlockBreakEvent event) {
if(event.isCancelled())
return;
mm.touch(event.getBlock().getLocation());
}
@Override
public void onSnowForm(SnowFormEvent event) {
if(event.isCancelled())
return;
mm.touch(event.getBlock().getLocation());
}
@Override
public void onLeavesDecay(LeavesDecayEvent event) {
if(event.isCancelled())
return;
mm.touch(event.getBlock().getLocation());
}
@Override
public void onBlockBurn(BlockBurnEvent event) {
if(event.isCancelled())
return;
mm.touch(event.getBlock().getLocation());
}
};
@@ -192,6 +227,12 @@ public class DynmapPlugin extends JavaPlugin {
pm.registerEvent(org.bukkit.event.Event.Type.BLOCK_PLACE, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
if (isTrigger("blockbreak"))
pm.registerEvent(org.bukkit.event.Event.Type.BLOCK_BREAK, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
if (isTrigger("snowform"))
pm.registerEvent(org.bukkit.event.Event.Type.SNOW_FORM, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
if (isTrigger("leavesdecay"))
pm.registerEvent(org.bukkit.event.Event.Type.LEAVES_DECAY, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
if (isTrigger("blockburn"))
pm.registerEvent(org.bukkit.event.Event.Type.BLOCK_BURN, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
}
{
PlayerListener renderTrigger = new PlayerListener() {
@@ -214,21 +255,46 @@ public class DynmapPlugin extends JavaPlugin {
WorldListener renderTrigger = new WorldListener() {
@Override
public void onChunkLoad(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(ignore_chunk_loads)
return;
if(generate_only) {
if(!isNewChunk(event))
return;
/* Touch extreme corners */
int x = event.getChunk().getX() * 16;
int z = event.getChunk().getZ() * 16;
mm.touch(new Location(event.getWorld(), x, 0, z));
mm.touch(new Location(event.getWorld(), x+15, 127, z));
mm.touch(new Location(event.getWorld(), x+15, 0, z+15));
mm.touch(new Location(event.getWorld(), x, 127, z+15));
}
else {
int x = event.getChunk().getX() * 16 + 8;
int z = event.getChunk().getZ() * 16 + 8;
mm.touch(new Location(event.getWorld(), x, 127, z));
}
}
private boolean isNewChunk(ChunkLoadEvent event) {
return event.isNewChunk();
}
/*
* @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"))
boolean ongenerate = isTrigger("chunkgenerated");
if(ongenerate) {
try { /* Test if new enough bukkit to allow this */
ChunkLoadEvent.class.getDeclaredMethod("isNewChunk", new Class[0]);
} catch (NoSuchMethodException nsmx) {
Log.info("Warning: CraftBukkit build does not support function needed for 'chunkgenerated' trigger - disabling");
ongenerate = false;
}
}
if(isTrigger("chunkloaded")) {
generate_only = false;
pm.registerEvent(org.bukkit.event.Event.Type.CHUNK_LOAD, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
//if (isTrigger("chunkgenerated")) pm.registerEvent(Event.Type.CHUNK_GENERATED, renderTrigger, Priority.Monitor, this);
}
else if(ongenerate) {
generate_only = true;
pm.registerEvent(org.bukkit.event.Event.Type.CHUNK_LOAD, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
}
}
// To link configuration to real loaded worlds.
@@ -330,14 +396,14 @@ public class DynmapPlugin extends JavaPlugin {
for (int i = 1; i < args.length; i++) {
World w = getServer().getWorld(args[i]);
if(w != null)
mapManager.renderFullWorld(new Location(w, 0, 0, 0));
mapManager.renderFullWorld(new Location(w, 0, 0, 0),sender);
else
sender.sendMessage("World '" + args[i] + "' not defined/loaded");
}
} else if (player != null) {
Location loc = player.getLocation();
if(loc != null)
mapManager.renderFullWorld(loc);
mapManager.renderFullWorld(loc, sender);
} else {
sender.sendMessage("World name is required");
}
@@ -396,9 +462,9 @@ public class DynmapPlugin extends JavaPlugin {
finalConfiguration.extend(templateConfiguration);
finalConfiguration.extend(worldConfiguration);
Log.info("Configuration of world " + world.getName());
Log.verboseinfo("Configuration of world " + world.getName());
for(Map.Entry<String, Object> e : finalConfiguration.entrySet()) {
Log.info(e.getKey() + ": " + e.getValue());
Log.verboseinfo(e.getKey() + ": " + e.getValue());
}
return finalConfiguration;
@@ -407,7 +473,7 @@ public class DynmapPlugin extends JavaPlugin {
private ConfigurationNode getDefaultTemplateConfigurationNode(World world) {
Environment environment = world.getEnvironment();
String environmentName = environment.name().toLowerCase();
Log.info("Using environment as template: " + environmentName);
Log.verboseinfo("Using environment as template: " + environmentName);
return getTemplateConfigurationNode(environmentName);
}
@@ -433,4 +499,12 @@ public class DynmapPlugin extends JavaPlugin {
pluginManager.disablePlugin(this);
pluginManager.enablePlugin(this);
}
public String getWebPath() {
return configuration.getString("webpath", "web");
}
public static void setIgnoreChunkLoads(boolean ignore) {
ignore_chunk_loads = ignore;
}
}
+345
View File
@@ -5,14 +5,359 @@ import java.util.List;
import org.bukkit.World;
import org.bukkit.Location;
import org.dynmap.debug.Debug;
import org.dynmap.kzedmap.KzedMap;
import org.dynmap.kzedmap.KzedMap.KzedBufferedImage;
import org.dynmap.utils.FileLockManager;
import org.dynmap.utils.MapChunkCache;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import javax.imageio.ImageIO;
public class DynmapWorld {
public enum AutoGenerateOption {
NONE,
FORMAPONLY,
PERMANENT
}
public World world;
public List<MapType> maps = new ArrayList<MapType>();
public UpdateQueue updates = new UpdateQueue();
public ConfigurationNode configuration;
public List<Location> seedloc;
public List<MapChunkCache.VisibilityLimit> visibility_limits;
public AutoGenerateOption do_autogenerate;
public MapChunkCache.HiddenChunkStyle hiddenchunkstyle;
public int servertime;
public boolean sendposition;
public boolean sendhealth;
public boolean bigworld; /* If true, deeper directory hierarchy */
private int extrazoomoutlevels; /* Number of additional zoom out levels to generate */
public File worldtilepath;
private Object lock = new Object();
private HashSet<String> zoomoutupdates[];
private boolean checkts = true; /* Check timestamps on first run with new configuration */
@SuppressWarnings("unchecked")
public void setExtraZoomOutLevels(int lvl) {
extrazoomoutlevels = lvl;
zoomoutupdates = new HashSet[lvl];
for(int i = 0; i < lvl; i++)
zoomoutupdates[i] = new HashSet<String>();
checkts = true;
}
public int getExtraZoomOutLevels() { return extrazoomoutlevels; }
public void enqueueZoomOutUpdate(File f) {
enqueueZoomOutUpdate(f, 0);
}
private void enqueueZoomOutUpdate(File f, int level) {
if(level >= extrazoomoutlevels)
return;
synchronized(lock) {
zoomoutupdates[level].add(f.getPath());
}
}
private boolean popQueuedUpdate(File f, int level) {
if(level >= extrazoomoutlevels)
return false;
synchronized(lock) {
return zoomoutupdates[level].remove(f.getPath());
}
}
private static class DirFilter implements FilenameFilter {
public boolean accept(File f, String n) {
if(!n.equals("..") && !n.equals(".")) {
File fn = new File(f, n);
return fn.isDirectory();
}
return false;
}
}
private static class PNGFileFilter implements FilenameFilter {
String prefix;
public PNGFileFilter(String pre) { prefix = pre; }
public boolean accept(File f, String n) {
if(n.endsWith(".png") && n.startsWith(prefix)) {
File fn = new File(f, n);
return fn.isFile();
}
return false;
}
}
public void freshenZoomOutFiles() {
for(int i = 0; i < extrazoomoutlevels; i++) {
freshenZoomOutFilesByLevel(i);
}
checkts = false; /* Just handle queued updates after first scan */
}
private static class PrefixData {
int stepsize;
int[] stepseq;
boolean neg_step_x;
String baseprefix;
int zoomlevel;
String zoomprefix;
String fnprefix;
String zfnprefix;
int bigworldshift;
}
public void freshenZoomOutFilesByLevel(int zoomlevel) {
int cnt = 0;
Debug.debug("freshenZoomOutFiles(" + world.getName() + "," + zoomlevel + ")");
if(worldtilepath.exists() == false) /* Quit if not found */
return;
HashMap<String, PrefixData> maptab = buildPrefixData(zoomlevel);
if(bigworld) { /* If big world, next directories are map name specific */
DirFilter df = new DirFilter();
for(String pfx : maptab.keySet()) { /* Walk through prefixes, as directories */
PrefixData pd = maptab.get(pfx);
File dname = new File(worldtilepath, pfx);
/* Now, go through subdirectories under this one, and process them */
String[] subdir = dname.list(df);
if(subdir == null) continue;
for(String s : subdir) {
File sdname = new File(dname, s);
cnt += processZoomDirectory(sdname, pd);
}
}
}
else { /* Else, classic file layout */
for(String pfx : maptab.keySet()) { /* Walk through prefixes, as directories */
cnt += processZoomDirectory(worldtilepath, maptab.get(pfx));
}
}
Debug.debug("freshenZoomOutFiles(" + world.getName() + "," + zoomlevel + ") - done (" + cnt + " updated files)");
}
private HashMap<String, PrefixData> buildPrefixData(int zoomlevel) {
HashMap<String, PrefixData> maptab = new HashMap<String, PrefixData>();
/* Build table of file prefixes and step sizes */
for(MapType mt : maps) {
List<String> pfx = mt.baseZoomFilePrefixes();
int stepsize = mt.baseZoomFileStepSize();
int bigworldshift = mt.getBigWorldShift();
boolean neg_step_x = false;
if(stepsize < 0) {
stepsize = -stepsize;
neg_step_x = true;
}
int[] stepseq = mt.zoomFileStepSequence();
for(String p : pfx) {
PrefixData pd = new PrefixData();
pd.stepsize = stepsize;
pd.neg_step_x = neg_step_x;
pd.stepseq = stepseq;
pd.baseprefix = p;
pd.zoomlevel = zoomlevel;
pd.zoomprefix = "zzzzzzzzzzzz".substring(0, zoomlevel);
pd.bigworldshift = bigworldshift;
if(bigworld) {
if(zoomlevel > 0) {
pd.zoomprefix += "_";
pd.zfnprefix = "z" + pd.zoomprefix;
}
else {
pd.zfnprefix = "z_";
}
pd.fnprefix = pd.zoomprefix;
}
else {
pd.fnprefix = pd.zoomprefix + pd.baseprefix;
pd.zfnprefix = "z" + pd.fnprefix;
}
maptab.put(p, pd);
}
}
return maptab;
}
private static class ProcessTileRec {
File zf;
String zfname;
int x, y;
}
private String makeFilePath(PrefixData pd, int x, int y, boolean zoomed) {
if(bigworld)
return pd.baseprefix + "/" + (x >> pd.bigworldshift) + "_" + (y >> pd.bigworldshift) + "/" + (zoomed?pd.zfnprefix:pd.fnprefix) + x + "_" + y + ".png";
else
return (zoomed?pd.zfnprefix:pd.fnprefix) + "_" + x + "_" + y + ".png";
}
private int processZoomDirectory(File dir, PrefixData pd) {
Debug.debug("processZoomDirectory(" + dir.getPath() + "," + pd.baseprefix + ")");
HashMap<String, ProcessTileRec> toprocess = new HashMap<String, ProcessTileRec>();
String[] files = dir.list(new PNGFileFilter(pd.fnprefix));
if(files == null)
return 0;
for(String fn : files) {
ProcessTileRec tr = processZoomFile(new File(dir, fn), pd);
if(tr != null) {
String zfpath = tr.zf.getPath();
if(!toprocess.containsKey(zfpath)) {
toprocess.put(zfpath, tr);
}
}
}
int cnt = 0;
/* Do processing */
for(ProcessTileRec s : toprocess.values()) {
processZoomTile(pd, dir, s.zf, s.zfname, s.x, s.y);
cnt++;
}
Debug.debug("processZoomDirectory(" + dir.getPath() + "," + pd.baseprefix + ") - done (" + cnt + " files)");
return cnt;
}
private ProcessTileRec processZoomFile(File f, PrefixData pd) {
/* If not checking timstamp, we're out if nothing queued for this file */
if(!checkts) {
if(!popQueuedUpdate(f, pd.zoomlevel))
return null;
}
int step = pd.stepsize << pd.zoomlevel;
String fn = f.getName();
/* Parse filename to predict zoomed out file */
fn = fn.substring(0, fn.lastIndexOf('.')); /* Strip off extension */
String[] tok = fn.split("_"); /* Split by underscores */
int x = 0;
int y = 0;
boolean parsed = false;
if(tok.length >= 2) {
try {
x = Integer.parseInt(tok[tok.length-2]);
y = Integer.parseInt(tok[tok.length-1]);
parsed = true;
} catch (NumberFormatException nfx) {
}
}
if(!parsed)
return null;
if(pd.neg_step_x) x = -x;
if(x >= 0)
x = x - (x % (2*step));
else
x = x + (x % (2*step));
if(pd.neg_step_x) x = -x;
if(y >= 0)
y = y - (y % (2*step));
else
y = y + (y % (2*step));
/* Make name of corresponding zoomed tile */
String zfname = makeFilePath(pd, x, y, true);
File zf = new File(worldtilepath, zfname);
if(checkts) { /* If checking timestamp, see if we need update based on enqueued update OR old file time */
/* If we're not updated, and zoom file exists and is older than our file, nothing to do */
if((!popQueuedUpdate(f, pd.zoomlevel)) && zf.exists() && (zf.lastModified() >= f.lastModified())) {
return null;
}
}
ProcessTileRec rec = new ProcessTileRec();
rec.zf = zf;
rec.x = x;
rec.y = y;
rec.zfname = zfname;
Debug.debug("Process " + zf.getPath() + " due to " + f.getPath());
return rec;
}
private void processZoomTile(PrefixData pd, File dir, File zf, String zfname, int tx, int ty) {
Debug.debug("processZoomFile(" + pd.baseprefix + "," + dir.getPath() + "," + zf.getPath() + "," + tx + "," + ty + ")");
int width = 128, height = 128;
BufferedImage zIm = null;
KzedBufferedImage kzIm = null;
int[] argb = new int[width*height];
int step = pd.stepsize << pd.zoomlevel;
int ztx = tx;
tx = tx - (pd.neg_step_x?step:0); /* Adjust for negative step */
/* create image buffer */
kzIm = KzedMap.allocateBufferedImage(width, height);
zIm = kzIm.buf_img;
for(int i = 0; i < 4; i++) {
File f = new File(worldtilepath, makeFilePath(pd, (tx + step*(1&pd.stepseq[i])), (ty + step*(pd.stepseq[i]>>1)), false));
if(f.exists()) {
BufferedImage im = null;
FileLockManager.getReadLock(f);
popQueuedUpdate(f, pd.zoomlevel);
try {
im = ImageIO.read(f);
} catch (IOException e) {
} catch (IndexOutOfBoundsException e) {
} finally {
FileLockManager.releaseReadLock(f);
}
if(im != null) {
im.getRGB(0, 0, width, height, argb, 0, width); /* Read data */
im.flush();
/* Do binlinear scale to 64x64 */
Color c1 = new Color();
for(int y = 0; y < height; y += 2) {
for(int x = 0; x < width; x += 2) {
int red = 0;
int green = 0;
int blue = 0;
int alpha = 0;
for(int yy = y; yy < y+2; yy++) {
for(int xx = x; xx < x+2; xx++) {
c1.setARGB(argb[(yy*width)+xx]);
red += c1.getRed();
green += c1.getGreen();
blue += c1.getBlue();
alpha += c1.getAlpha();
}
}
c1.setRGBA(red>>2, green>>2, blue>>2, alpha>>2);
argb[(y*width/2) + (x/2)] = c1.getARGB();
}
}
/* blit scaled rendered tile onto zoom-out tile */
zIm.setRGB(((i>>1) != 0)?0:width/2, (i & 1) * height/2, width/2, height/2, argb, 0, width);
}
}
}
FileLockManager.getWriteLock(zf);
try {
TileHashManager hashman = MapManager.mapman.hashman;
long crc = hashman.calculateTileHash(kzIm.argb_buf); /* Get hash of tile */
int tilex = ztx/step/2;
int tiley = ty/step/2;
String key = world.getName()+".z"+pd.zoomprefix+pd.baseprefix;
if((!zf.exists()) || (crc != MapManager.mapman.hashman.getImageHashCode(key, null, tilex, tiley))) {
try {
if(!zf.getParentFile().exists())
zf.getParentFile().mkdirs();
FileLockManager.imageIOWrite(zIm, "png", zf);
Debug.debug("Saved zoom-out tile at " + zf.getPath());
} catch (IOException e) {
Debug.error("Failed to save zoom-out tile: " + zf.getName(), e);
} catch (java.lang.NullPointerException e) {
Debug.error("Failed to save zoom-out tile (NullPointerException): " + zf.getName(), e);
}
hashman.updateHashCode(key, null, tilex, tiley, crc);
MapManager.mapman.pushUpdate(this.world, new Client.Tile(zfname));
enqueueZoomOutUpdate(zf, pd.zoomlevel+1);
}
} finally {
FileLockManager.releaseWriteLock(zf);
KzedMap.freeBufferedImage(kzIm);
}
}
}
+3
View File
@@ -5,6 +5,7 @@ import java.util.Map;
public class Events {
public Map<String, Event<?>> events = new HashMap<String, Event<?>>();
@SuppressWarnings("unchecked")
public <T> void addListener(String eventName, Event.Listener<T> listener) {
Event<?> genericEvent = events.get(eventName);
Event<T> event = null;
@@ -16,6 +17,7 @@ public class Events {
event.addListener(listener);
}
@SuppressWarnings("unchecked")
public <T> void removeListener(String eventName, Event.Listener<T> listener) {
Event<?> genericEvent = events.get(eventName);
Event<T> event = null;
@@ -25,6 +27,7 @@ public class Events {
}
}
@SuppressWarnings("unchecked")
public <T> void trigger(String eventName, T argument) {
Event<?> genericEvent = events.get(eventName);
if (genericEvent == null)
@@ -3,7 +3,6 @@ package org.dynmap;
import org.dynmap.Event.Listener;
import org.dynmap.web.handlers.ClientUpdateHandler;
import org.dynmap.web.handlers.SendMessageHandler;
import org.dynmap.web.handlers.SendMessageHandler.Message;
import org.json.simple.JSONObject;
import static org.dynmap.JSONUtils.*;
@@ -13,6 +12,7 @@ public class InternalClientUpdateComponent extends ClientUpdateComponent {
super(plugin, configuration);
final Boolean allowwebchat = configuration.getBoolean("allowwebchat", false);
final Boolean hidewebchatip = configuration.getBoolean("hidewebchatip", false);
final Boolean trust_client_name = configuration.getBoolean("trustclientname", false);
final float webchatInterval = configuration.getFloat("webchat-interval", 1);
final String spammessage = plugin.configuration.getString("spammessage", "You may only chat once every %interval% seconds.");
@@ -31,6 +31,7 @@ public class InternalClientUpdateComponent extends ClientUpdateComponent {
maximumMessageInterval = (int)(webchatInterval * 1000);
spamMessage = "\""+spammessage+"\"";
hideip = hidewebchatip;
this.trustclientname = trust_client_name;
onMessageReceived.addListener(new Listener<SendMessageHandler.Message>() {
@Override
public void triggered(Message t) {
+3
View File
@@ -25,6 +25,7 @@ public class JSONUtils {
}
// Sets a value on the specified path. If JSONObjects inside the path are missing, they'll be created.
@SuppressWarnings("unchecked")
public static void s(JSONObject o, String path, Object value) {
int index = path.indexOf('/');
if (index == -1) {
@@ -45,6 +46,7 @@ public class JSONUtils {
}
// Adds a value to the list at the specified path. If the list does not exist, it will be created.
@SuppressWarnings("unchecked")
public static void a(JSONObject o, String path, Object value) {
Object oo = g(o, path);
JSONArray array;
@@ -58,6 +60,7 @@ public class JSONUtils {
}
// Simply creates a JSONArray.
@SuppressWarnings("unchecked")
public static JSONArray l(Object... items) {
JSONArray arr = new JSONArray();
for(Object item : items) {
@@ -3,7 +3,6 @@ package org.dynmap;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.Reader;
@@ -13,9 +12,7 @@ import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.dynmap.web.Json;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
@@ -105,6 +102,7 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
}
}
@SuppressWarnings("unchecked")
protected void writeUpdates() {
File outputFile;
File outputTempFile;
+5
View File
@@ -6,9 +6,14 @@ import java.util.logging.Logger;
public class Log {
protected static final Logger log = Logger.getLogger("Minecraft");
protected static final String LOG_PREFIX = "[dynmap] ";
public static boolean verbose = false;
public static void info(String msg) {
log.log(Level.INFO, LOG_PREFIX + msg);
}
public static void verboseinfo(String msg) {
if(verbose)
log.log(Level.INFO, LOG_PREFIX + msg);
}
public static void severe(Exception e) {
log.log(Level.SEVERE, LOG_PREFIX + "Exception occured: ", e);
}
-297
View File
@@ -1,297 +0,0 @@
package org.dynmap;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.util.LinkedList;
import org.bukkit.World;
import org.bukkit.Chunk;
import org.bukkit.entity.Entity;
/**
* Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread
*/
public class MapChunkCache {
private World w;
private static Method getchunkdata = null;
private static Method gethandle = null;
private static Method poppreservedchunk = null;
private static Field heightmap = null;
private static boolean initialized = false;
private int x_min, x_max, z_min, z_max;
private int x_dim;
private ChunkSnapshot[] snaparray; /* Index = (x-x_min) + ((z-z_min)*x_dim) */
/**
* Iterator for traversing map chunk cache (base is for non-snapshot)
*/
public class MapIterator {
public int x, y, z;
private ChunkSnapshot snap;
MapIterator(int x0, int y0, int z0) {
initialize(x0, y0, z0);
}
public final void initialize(int x0, int y0, int z0) {
this.x = x0;
this.y = y0;
this.z = z0;
try {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
public final int getBlockTypeID() {
return snap.getBlockTypeId(x & 0xF, y, z & 0xF);
}
public final int getBlockData() {
return snap.getBlockData(x & 0xF, y, z & 0xF);
}
public final int getHighestBlockYAt() {
return snap.getHighestBlockYAt(x & 0xF, z & 0xF);
}
public final int getBlockSkyLight() {
return snap.getBlockSkyLight(x & 0xF, y, z & 0xF);
}
public final int getBlockEmittedLight() {
return snap.getBlockEmittedLight(x & 0xF, y, z & 0xF);
}
public final void incrementX() {
x++;
if((x & 0xF) == 0) { /* Next chunk? */
try {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
}
public final void decrementX() {
x--;
if((x & 0xF) == 15) { /* Next chunk? */
try {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
}
public final void incrementY() {
y++;
}
public final void decrementY() {
y--;
}
public final void incrementZ() {
z++;
if((z & 0xF) == 0) { /* Next chunk? */
try {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
}
public final void decrementZ() {
z--;
if((z & 0xF) == 15) { /* Next chunk? */
try {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
}
public final void setY(int y) {
this.y = y;
}
}
/**
* Chunk cache for representing unloaded chunk
*/
private static class EmptyChunk implements ChunkSnapshot {
public final int getBlockTypeId(int x, int y, int z) {
return 0;
}
public final int getBlockData(int x, int y, int z) {
return 0;
}
public final int getBlockSkyLight(int x, int y, int z) {
return 15;
}
public final int getBlockEmittedLight(int x, int y, int z) {
return 0;
}
public final int getHighestBlockYAt(int x, int z) {
return 1;
}
}
private static final EmptyChunk EMPTY = new EmptyChunk();
/**
* Create chunk cache container
* @param w - world
* @param x_min - minimum chunk x coordinate
* @param z_min - minimum chunk z coordinate
* @param x_max - maximum chunk x coordinate
* @param z_max - maximum chunk z coordinate
*/
@SuppressWarnings({ "unchecked" })
public MapChunkCache(World w, DynmapChunk[] chunks) {
/* Compute range */
if(chunks.length == 0) {
this.x_min = 0;
this.x_max = 0;
this.z_min = 0;
this.z_max = 0;
x_dim = 1;
}
else {
x_min = x_max = chunks[0].x;
z_min = z_max = chunks[0].z;
for(int i = 1; i < chunks.length; i++) {
if(chunks[i].x > x_max)
x_max = chunks[i].x;
if(chunks[i].x < x_min)
x_min = chunks[i].x;
if(chunks[i].z > z_max)
z_max = chunks[i].z;
if(chunks[i].z < z_min)
z_min = chunks[i].z;
}
x_dim = x_max - x_min + 1;
}
this.w = w;
if(!initialized) {
try {
Class c = Class.forName("net.minecraft.server.Chunk");
getchunkdata = c.getDeclaredMethod("a", new Class[] { byte[].class, int.class,
int.class, int.class, int.class, int.class, int.class, int.class });
heightmap = c.getDeclaredField("h");
c = Class.forName("org.bukkit.craftbukkit.CraftChunk");
gethandle = c.getDeclaredMethod("getHandle", new Class[0]);
} catch (ClassNotFoundException cnfx) {
} catch (NoSuchMethodException nsmx) {
} catch (NoSuchFieldException nsfx) {
}
/* Get CraftWorld.popPreservedChunk(x,z) - reduces memory bloat from map traversals (optional) */
try {
Class c = Class.forName("org.bukkit.craftbukkit.CraftWorld");
poppreservedchunk = c.getDeclaredMethod("popPreservedChunk", new Class[] { int.class, int.class });
} catch (ClassNotFoundException cnfx) {
} catch (NoSuchMethodException nsmx) {
}
initialized = true;
if(gethandle != null)
Log.info("Chunk snapshot support enabled");
else {
Log.severe("ERROR: Chunk snapshot support not found - rendering not functiona!l");
return;
}
}
snaparray = new ChunkSnapshot[x_dim * (z_max-z_min+1)];
if(gethandle != null) {
// Load the required chunks.
for (DynmapChunk chunk : chunks) {
boolean wasLoaded = w.isChunkLoaded(chunk.x, chunk.z);
boolean didload = w.loadChunk(chunk.x, chunk.z, false);
/* If it did load, make cache of it */
if(didload) {
Chunk c = w.getChunkAt(chunk.x, chunk.z);
try {
Object cc = gethandle.invoke(c);
byte[] buf = new byte[32768 + 16384 + 16384 + 16384]; /* Get big enough buffer for whole chunk */
getchunkdata.invoke(cc, buf, 0, 0, 0, 16, 128, 16, 0);
byte[] h = (byte[])heightmap.get(cc);
byte[] hmap = new byte[256];
System.arraycopy(h, 0, hmap, 0, 256);
CraftChunkSnapshot ss = new CraftChunkSnapshot(chunk.x, chunk.z, buf, hmap);
snaparray[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = ss;
} catch (Exception x) {
}
}
if ((!wasLoaded) && didload) {
/* It looks like bukkit "leaks" entities - they don't get removed from the world-level table
* when chunks are unloaded but not saved - removing them seems to do the trick */
Chunk cc = w.getChunkAt(chunk.x, chunk.z);
if(cc != null) {
for(Entity e: cc.getEntities())
e.remove();
}
/* Since we only remember ones we loaded, and we're synchronous, no player has
* moved, so it must be safe (also prevent chunk leak, which appears to happen
* because isChunkInUse defined "in use" as being within 256 blocks of a player,
* while the actual in-use chunk area for a player where the chunks are managed
* by the MC base server is 21x21 (or about a 160 block radius) */
w.unloadChunk(chunk.x, chunk.z, false, false);
/* And pop preserved chunk - this is a bad leak in Bukkit for map traversals like us */
try {
if(poppreservedchunk != null)
poppreservedchunk.invoke(w, chunk.x, chunk.z);
} catch (Exception x) {
Log.severe("Cannot pop preserved chunk - " + x.toString());
}
}
}
}
/* Fill missing chunks with empty dummy chunk */
for(int i = 0; i < snaparray.length; i++) {
if(snaparray[i] == null)
snaparray[i] = EMPTY;
}
}
/**
* Unload chunks
*/
public void unloadChunks() {
if(snaparray != null) {
for(int i = 0; i < snaparray.length; i++) {
snaparray[i] = null;
}
snaparray = null;
}
}
/**
* Get block ID at coordinates
*/
public int getBlockTypeID(int x, int y, int z) {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return ss.getBlockTypeId(x & 0xF, y, z & 0xF);
}
/**
* Get block data at coordiates
*/
public byte getBlockData(int x, int y, int z) {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return (byte)ss.getBlockData(x & 0xF, y, z & 0xF);
}
/* Get highest block Y
*
*/
public int getHighestBlockYAt(int x, int z) {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return ss.getHighestBlockYAt(x & 0xF, z & 0xF);
}
/* Get sky light level
*/
public int getBlockSkyLight(int x, int y, int z) {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return ss.getBlockSkyLight(x & 0xF, y, z & 0xF);
}
/* Get emitted light level
*/
public int getBlockEmittedLight(int x, int y, int z) {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return ss.getBlockEmittedLight(x & 0xF, y, z & 0xF);
}
/**
* Get cache iterator
*/
public MapIterator getIterator(int x, int y, int z) {
return new MapIterator(x, y, z);
}
}
+201 -37
View File
@@ -9,26 +9,39 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.command.CommandSender;
import org.dynmap.DynmapWorld.AutoGenerateOption;
import org.dynmap.debug.Debug;
import org.dynmap.utils.LegacyMapChunkCache;
import org.dynmap.utils.MapChunkCache;
import org.dynmap.utils.NewMapChunkCache;
public class MapManager {
public AsynchronousQueue<MapTile> tileQueue;
private static final int DEFAULT_CHUNKS_PER_TICK = 200;
private static final int DEFAULT_ZOOMOUT_PERIOD = 60;
public List<DynmapWorld> worlds = new ArrayList<DynmapWorld>();
public Map<String, DynmapWorld> worldsLookup = new HashMap<String, DynmapWorld>();
private BukkitScheduler scheduler;
private DynmapPlugin plug_in;
private long timeslice_int = 0; /* In milliseconds */
private int max_chunk_loads_per_tick = DEFAULT_CHUNKS_PER_TICK;
private int zoomout_period = DEFAULT_ZOOMOUT_PERIOD; /* Zoom-out tile processing period, in seconds */
/* Which fullrenders are active */
private HashMap<String, FullWorldRenderState> active_renders = new HashMap<String, FullWorldRenderState>();
/* List of MapChunkCache requests to be processed */
private ConcurrentLinkedQueue<MapChunkCache> chunkloads = new ConcurrentLinkedQueue<MapChunkCache>();
/* Tile hash manager */
public TileHashManager hashman;
/* lock for our data structures */
@@ -57,10 +70,22 @@ public class MapManager {
public Collection<DynmapWorld> getWorlds() {
return worlds;
}
private static class OurThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
t.setPriority(Thread.MIN_PRIORITY);
t.setName("Dynmap Render Thread");
return t;
}
}
private class DynmapScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
DynmapScheduledThreadPoolExecutor() {
super(POOL_SIZE);
this.setThreadFactory(new OurThreadFactory());
}
protected void afterExecute(Runnable r, Throwable x) {
@@ -72,6 +97,40 @@ public class MapManager {
x.printStackTrace();
}
}
@Override
public void execute(final Runnable r) {
final Runnable rr = r;
try {
super.execute(new Runnable() {
public void run() {
try {
r.run();
} catch (Exception x) {
Log.severe("Exception during render job: " + r);
x.printStackTrace();
}
}
});
} catch (RejectedExecutionException rxe) { /* Pool shutdown - nominal for reload or unload */
}
}
@Override
public ScheduledFuture<?> schedule(final Runnable command, long delay, TimeUnit unit) {
try {
return super.schedule(new Runnable() {
public void run() {
try {
command.run();
} catch (Exception x) {
Log.severe("Exception during render job: " + command);
x.printStackTrace();
}
}
}, delay, unit);
} catch (RejectedExecutionException rxe) {
return null; /* Pool shut down when we reload or unload */
}
}
}
/* This always runs on render pool threads - no bukkit calls from here */
private class FullWorldRenderState implements Runnable {
@@ -85,14 +144,17 @@ public class MapManager {
MapTile tile0 = null;
MapTile tile = null;
int rendercnt = 0;
CommandSender sender;
long timeaccum;
/* Full world, all maps render */
FullWorldRenderState(DynmapWorld dworld, Location l) {
FullWorldRenderState(DynmapWorld dworld, Location l, CommandSender sender) {
world = dworld;
loc = l;
found = new HashSet<MapTile>();
rendered = new HashSet<MapTile>();
renderQueue = new LinkedList<MapTile>();
this.sender = sender;
}
/* Single tile render - used for incremental renders */
@@ -119,15 +181,16 @@ public class MapManager {
/* If render queue is empty, start next map */
if(renderQueue.isEmpty()) {
if(map_index >= 0) { /* Finished a map? */
Log.info("Full render of map '" + world.maps.get(map_index).getClass().getSimpleName() + "' of world '" +
world.world.getName() + "' completed - " + rendercnt + " tiles rendered.");
double msecpertile = (double)timeaccum / (double)((rendercnt>0)?rendercnt:1);
sender.sendMessage("Full render of map '" + world.maps.get(map_index).getClass().getSimpleName() + "' of world '" +
world.world.getName() + "' completed - " + rendercnt + " tiles rendered (" + String.format("%.2f", msecpertile) + " msec/tile).");
}
found.clear();
rendered.clear();
rendercnt = 0;
map_index++; /* Next map */
if(map_index >= world.maps.size()) { /* Last one done? */
Log.info("Full render of '" + world.world.getName() + "' finished.");
sender.sendMessage("Full render of '" + world.world.getName() + "' finished.");
cleanup();
return;
}
@@ -158,17 +221,21 @@ public class MapManager {
}
World w = world.world;
/* Fetch chunk cache from server thread */
DynmapChunk[] requiredChunks = tile.getMap().getRequiredChunks(tile);
MapChunkCache cache = createMapChunkCache(w, requiredChunks);
MapType mt = tile.getMap();
List<DynmapChunk> requiredChunks = mt.getRequiredChunks(tile);
MapChunkCache cache = createMapChunkCache(world, requiredChunks, mt.isBlockTypeDataNeeded(),
mt.isHightestBlockYDataNeeded(), mt.isBiomeDataNeeded(),
mt.isRawBiomeDataNeeded());
if(cache == null) {
cleanup();
return; /* Cancelled/aborted */
}
if(tile0 != null) { /* Single tile? */
render(cache, tile); /* Just render */
if(cache.isEmpty() == false)
render(cache, tile); /* Just render */
}
else {
if (render(cache, tile)) {
if ((cache.isEmpty() == false) && render(cache, tile)) {
found.remove(tile);
rendered.add(tile);
for (MapTile adjTile : map.getAdjecentTiles(tile)) {
@@ -179,10 +246,14 @@ public class MapManager {
}
}
found.remove(tile);
rendercnt++;
if((rendercnt % 100) == 0) {
Log.info("Full render of map '" + world.maps.get(map_index).getClass().getSimpleName() + "' on world '" +
w.getName() + "' in progress - " + rendercnt + " tiles rendered, " + renderQueue.size() + " tiles pending.");
if(!cache.isEmpty()) {
rendercnt++;
timeaccum += System.currentTimeMillis() - tstart;
if((rendercnt % 100) == 0) {
double msecpertile = (double)timeaccum / (double)rendercnt;
sender.sendMessage("Full render of map '" + world.maps.get(map_index).getClass().getSimpleName() + "' on world '" +
w.getName() + "' in progress - " + rendercnt + " tiles rendered (" + String.format("%.2f", msecpertile) + " msec/tile).");
}
}
}
/* And unload what we loaded */
@@ -217,6 +288,36 @@ public class MapManager {
}
}
private class ProcessChunkLoads implements Runnable {
public void run() {
int cnt = max_chunk_loads_per_tick;
while(cnt > 0) {
MapChunkCache c = chunkloads.peek();
if(c == null)
return;
cnt = cnt - c.loadChunks(cnt);
if(c.isDoneLoading()) {
chunkloads.poll();
synchronized(c) {
c.notify();
}
}
}
}
}
private class DoZoomOutProcessing implements Runnable {
public void run() {
Debug.debug("DoZoomOutProcessing started");
for(DynmapWorld w : worlds) {
w.freshenZoomOutFiles();
}
renderpool.schedule(this, zoomout_period, TimeUnit.SECONDS);
Debug.debug("DoZoomOutProcessing finished");
}
}
public MapManager(DynmapPlugin plugin, ConfigurationNode configuration) {
plug_in = plugin;
mapman = this;
@@ -230,7 +331,12 @@ public class MapManager {
/* On dedicated thread, so default to no delays */
timeslice_int = (long)(configuration.getDouble("timesliceinterval", 0.0) * 1000);
max_chunk_loads_per_tick = configuration.getInteger("maxchunkspertick", DEFAULT_CHUNKS_PER_TICK);
if(max_chunk_loads_per_tick < 5) max_chunk_loads_per_tick = 5;
/* Get zoomout processing periond in seconds */
zoomout_period = configuration.getInteger("zoomoutperiod", DEFAULT_ZOOMOUT_PERIOD);
if(zoomout_period < 5) zoomout_period = 5;
scheduler = plugin.getServer().getScheduler();
hashman = new TileHashManager(DynmapPlugin.tilesDirectory, configuration.getBoolean("enabletilehash", true));
@@ -242,13 +348,14 @@ public class MapManager {
}
scheduler.scheduleSyncRepeatingTask(plugin, new CheckWorldTimes(), 5*20, 5*20); /* Check very 5 seconds */
scheduler.scheduleSyncRepeatingTask(plugin, new ProcessChunkLoads(), 1, 1); /* Chunk loader task */
}
void renderFullWorld(Location l) {
void renderFullWorld(Location l, CommandSender sender) {
DynmapWorld world = getWorld(l.getWorld().getName());
if (world == null) {
Log.severe("Could not render: world '" + l.getWorld().getName() + "' not defined in configuration.");
sender.sendMessage("Could not render: world '" + l.getWorld().getName() + "' not defined in configuration.");
return;
}
String wname = l.getWorld().getName();
@@ -256,15 +363,15 @@ public class MapManager {
synchronized(lock) {
rndr = active_renders.get(wname);
if(rndr != null) {
Log.info("Full world render of world '" + wname + "' already active.");
sender.sendMessage("Full world render of world '" + wname + "' already active.");
return;
}
rndr = new FullWorldRenderState(world,l); /* Make new activation record */
rndr = new FullWorldRenderState(world,l,sender); /* Make new activation record */
active_renders.put(wname, rndr); /* Add to active table */
}
/* Schedule first tile to be worked */
renderpool.execute(rndr);
Log.info("Full render starting on world '" + wname + "'...");
sender.sendMessage("Full render starting on world '" + wname + "'...");
}
public void activateWorld(World w) {
@@ -285,7 +392,7 @@ public class MapManager {
DynmapWorld dynmapWorld = new DynmapWorld();
dynmapWorld.world = w;
dynmapWorld.configuration = worldConfiguration;
Log.info("Loading maps of world '" + worldName + "'...");
Log.verboseinfo("Loading maps of world '" + worldName + "'...");
for(MapType map : worldConfiguration.<MapType>createInstances("maps", new Class<?>[0], new Object[0])) {
map.onTileInvalidated.addListener(invalitateListener);
dynmapWorld.maps.add(map);
@@ -297,12 +404,52 @@ public class MapManager {
dynmapWorld.servertime = (int)(w.getTime() % 24000);
dynmapWorld.sendposition = worldConfiguration.getBoolean("sendposition", true);
dynmapWorld.sendhealth = worldConfiguration.getBoolean("sendhealth", true);
dynmapWorld.bigworld = worldConfiguration.getBoolean("bigworld", false);
dynmapWorld.setExtraZoomOutLevels(worldConfiguration.getInteger("extrazoomout", 0));
dynmapWorld.worldtilepath = new File(plug_in.tilesDirectory, w.getName());
if(loclist != null) {
for(ConfigurationNode loc : loclist) {
Location lx = new Location(w, loc.getDouble("x", 0), loc.getDouble("y", 64), loc.getDouble("z", 0));
dynmapWorld.seedloc.add(lx);
}
}
/* Load visibility limits, if any are defined */
List<ConfigurationNode> vislimits = worldConfiguration.getNodes("visibilitylimits");
if(vislimits != null) {
dynmapWorld.visibility_limits = new ArrayList<MapChunkCache.VisibilityLimit>();
for(ConfigurationNode vis : vislimits) {
MapChunkCache.VisibilityLimit lim = new MapChunkCache.VisibilityLimit();
lim.x0 = vis.getInteger("x0", 0);
lim.x1 = vis.getInteger("x1", 0);
lim.z0 = vis.getInteger("z0", 0);
lim.z1 = vis.getInteger("z1", 0);
dynmapWorld.visibility_limits.add(lim);
/* Also, add a seed location for the middle of each visible area */
dynmapWorld.seedloc.add(new Location(w, (lim.x0+lim.x1)/2, 64, (lim.z0+lim.z1)/2));
}
}
String autogen = worldConfiguration.getString("autogenerate-to-visibilitylimits", "none");
if(autogen.equals("permanent")) {
dynmapWorld.do_autogenerate = AutoGenerateOption.PERMANENT;
}
else if(autogen.equals("map-only")) {
dynmapWorld.do_autogenerate = AutoGenerateOption.FORMAPONLY;
}
else {
dynmapWorld.do_autogenerate = AutoGenerateOption.NONE;
}
if((dynmapWorld.do_autogenerate != AutoGenerateOption.NONE) && (dynmapWorld.visibility_limits == null)) {
Log.info("Warning: Automatic world generation to visible limits option requires that visibitylimits be set - option disabled");
dynmapWorld.do_autogenerate = AutoGenerateOption.NONE;
}
String hiddenchunkstyle = worldConfiguration.getString("hidestyle", "stone");
if(hiddenchunkstyle.equals("air"))
dynmapWorld.hiddenchunkstyle = MapChunkCache.HiddenChunkStyle.FILL_AIR;
else if(hiddenchunkstyle.equals("ocean"))
dynmapWorld.hiddenchunkstyle = MapChunkCache.HiddenChunkStyle.FILL_OCEAN;
else
dynmapWorld.hiddenchunkstyle = MapChunkCache.HiddenChunkStyle.FILL_STONE_PLAIN;
// TODO: Make this less... weird...
// Insert the world on the same spot as in the configuration.
@@ -353,13 +500,11 @@ public class MapManager {
public void startRendering() {
tileQueue.start();
renderpool = new DynmapScheduledThreadPoolExecutor();
renderpool.schedule(new DoZoomOutProcessing(), 60000, TimeUnit.MILLISECONDS);
}
public void stopRendering() {
if(renderpool != null) {
renderpool.shutdown();
renderpool = null;
}
renderpool.shutdown();
tileQueue.stop();
}
@@ -406,22 +551,41 @@ public class MapManager {
return world.updates.getUpdatedObjects(since);
}
private static boolean use_legacy = false;
/**
* Render processor helper - used by code running on render threads to request chunk snapshot cache from server/sync thread
*/
public MapChunkCache createMapChunkCache(final World w, final DynmapChunk[] chunks) {
Callable<MapChunkCache> job = new Callable<MapChunkCache>() {
public MapChunkCache call() {
return new MapChunkCache(w, chunks);
}
};
Future<MapChunkCache> rslt = scheduler.callSyncMethod(plug_in, job);
public MapChunkCache createMapChunkCache(DynmapWorld w, List<DynmapChunk> chunks,
boolean blockdata, boolean highesty, boolean biome, boolean rawbiome) {
MapChunkCache c = null;
try {
return rslt.get();
} catch (Exception x) {
Log.info("createMapChunk - " + x);
return null;
if(!use_legacy)
c = new NewMapChunkCache();
} catch (NoClassDefFoundError ncdfe) {
use_legacy = true;
}
if(c == null)
c = new LegacyMapChunkCache();
if(w.visibility_limits != null) {
for(MapChunkCache.VisibilityLimit limit: w.visibility_limits) {
c.setVisibleRange(limit);
}
c.setHiddenFillStyle(w.hiddenchunkstyle);
c.setAutoGenerateVisbileRanges(w.do_autogenerate);
}
c.setChunks(w.world, chunks);
if(c.setChunkDataTypes(blockdata, biome, highesty, rawbiome) == false)
Log.severe("CraftBukkit build does not support biome APIs");
synchronized(c) {
chunkloads.add(c);
try {
c.wait();
} catch (InterruptedException ix) {
return null;
}
}
return c;
}
/**
* Update map tile statistics

Some files were not shown because too many files have changed in this diff Show More