mirror of
https://github.com/encounter/dynmap.git
synced 2026-03-30 11:08:39 -07:00
Compare commits
253 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5fc73b8d04 | |||
| 12d65b5ba9 | |||
| 7cf3834309 | |||
| b5e9e783a4 | |||
| ccc58ef00c | |||
| ace76fc426 | |||
| f91816cc39 | |||
| cf922e4121 | |||
| ebd024258b | |||
| 492b936683 | |||
| 1cb79e41cb | |||
| d95189a7c1 | |||
| 42c95012ef | |||
| 571c66a189 | |||
| 2f7e7ad87b | |||
| ba9e27f451 | |||
| 8d5233befd | |||
| c865ecb673 | |||
| bb2f21b44c | |||
| 132bfc539b | |||
| 852df86ad1 | |||
| 612cdf0c98 | |||
| d6388aab31 | |||
| bffc56dd20 | |||
| bb279d7e2f | |||
| 64bd846115 | |||
| db0fadc5de | |||
| 1d0b28c069 | |||
| e6e07bf421 | |||
| 091752aaae | |||
| 6d75c9ea44 | |||
| ee790f86ed | |||
| 4bf9f9a978 | |||
| 257b1c37f1 | |||
| 8cef3fb478 | |||
| 40e2b1eb4d | |||
| 49978e3ac5 | |||
| e08a2d4407 | |||
| b0a7a6b748 | |||
| 0bbcf6510e | |||
| 37c9d4b9cd | |||
| 9cc51e4cc0 | |||
| 17af53ee1f | |||
| f592f5a3bf | |||
| 2fa68b2992 | |||
| fdbd4ab2d1 | |||
| d845ed207d | |||
| 4d285b475a | |||
| 05f09f7bb4 | |||
| fea152a914 | |||
| 95c9520cc9 | |||
| e792bcc7a1 | |||
| 58df3a8441 | |||
| 98dee3b404 | |||
| 2ee49fd82e | |||
| c2fe0f772c | |||
| 65f20df60c | |||
| b4ce28fd9a | |||
| 5a39ba5d5a | |||
| 6c42b399f4 | |||
| f9958fbff8 | |||
| 29e42137c9 | |||
| 181e3dccbd | |||
| 95128df6b9 | |||
| 5bf8010bbb | |||
| 6259da4e0f | |||
| 47194defca | |||
| f8f1e77153 | |||
| 4824388c6b | |||
| ee0ad7c3d5 | |||
| 4622b42aed | |||
| bec6b0aec5 | |||
| 8957ab7c31 | |||
| b1272d18f8 | |||
| 832a79eb1f | |||
| 6d66d45d43 | |||
| 1a24217a98 | |||
| d483eb1e6f | |||
| f13b0b6c46 | |||
| 08192df906 | |||
| 5aa961388d | |||
| bea269e8df | |||
| 0abc944c6e | |||
| e90087390a | |||
| ce00242253 | |||
| 4f75bf691a | |||
| 9f19ccf50c | |||
| 2242c0643b | |||
| 31b849683a | |||
| 5a5fa147d3 | |||
| b944b3b729 | |||
| 90acf73976 | |||
| 51457464c2 | |||
| 369317ea45 | |||
| 0fb56c95bb | |||
| fd542d2b33 | |||
| 8ba8bcfc59 | |||
| 48683b972a | |||
| eaf6ecde26 | |||
| cce30da6be | |||
| fc3c5be36c | |||
| 8b40a9761b | |||
| 674b92003c | |||
| b9225b3ed3 | |||
| d862d1aa70 | |||
| 9005b68fdb | |||
| df9d3494c3 | |||
| 8bac8b0d23 | |||
| c135a669a8 | |||
| 1465795f97 | |||
| e1160f623f | |||
| 7e0124e849 | |||
| 096d2fe72e | |||
| ef59612dad | |||
| f9393d70ea | |||
| 5762340238 | |||
| beb3165bbe | |||
| 1e9cfe3bc7 | |||
| 5a9c28ae27 | |||
| aa29ddf141 | |||
| 641ce05767 | |||
| 42132328cd | |||
| 9e7e333cc5 | |||
| 23db0c62fc | |||
| cf08f243d0 | |||
| 31623a0676 | |||
| 737bcb98d9 | |||
| e0ddbcd27d | |||
| 3ddce85f89 | |||
| 4cacc3f92c | |||
| abd7c25d80 | |||
| 39a6bee3ca | |||
| 78f571a68b | |||
| a65fd601ac | |||
| 62b42aa302 | |||
| c7e176b56d | |||
| a07c03081d | |||
| 60f7773e76 | |||
| ddeded3e9c | |||
| e601a2c661 | |||
| 357e46280c | |||
| 9992aa7628 | |||
| 869d6a701f | |||
| 4be9ccb1b2 | |||
| 1c6ececd62 | |||
| d746102963 | |||
| 6e1768f544 | |||
| 9bb9012f9c | |||
| 0fba601063 | |||
| ec13742c85 | |||
| 2c1d078272 | |||
| e613fb14d7 | |||
| 0e6dfc1adf | |||
| 436fac707f | |||
| 0ee5c3db04 | |||
| 9c1a744431 | |||
| 5ad9d7bf90 | |||
| ce76cfd695 | |||
| a878ce7cd1 | |||
| 9197290910 | |||
| 559f251d50 | |||
| 43dba33db9 | |||
| 8c134edce3 | |||
| 2e96cf88e2 | |||
| da566cdecc | |||
| 1115963ab7 | |||
| ee3f07c6cd | |||
| edc97fe399 | |||
| b9882955af | |||
| bf4f8a84f0 | |||
| 2935080bdf | |||
| 4987ac3fe1 | |||
| a1536d03cd | |||
| 644c8d0213 | |||
| b277663705 | |||
| 913a92a010 | |||
| 976f8cd334 | |||
| 3ef3f6cb61 | |||
| b212908a13 | |||
| 537c6d3f25 | |||
| 06b7a5dd57 | |||
| f58092167f | |||
| 71a8195fc2 | |||
| 73825b4558 | |||
| 2c16c800e9 | |||
| 929a34656b | |||
| 910b963fcd | |||
| b51bb22b9e | |||
| 1adbe45c27 | |||
| ff07b6f343 | |||
| c74dd49f67 | |||
| 1862dc918c | |||
| d4ecd05af9 | |||
| 4e810fc9d8 | |||
| 4bc3030637 | |||
| 9133d03489 | |||
| d21d640eae | |||
| edac2e5cd9 | |||
| 0323c98938 | |||
| a91060dc95 | |||
| c958da0ae0 | |||
| 862c219d7d | |||
| 66ca5199e3 | |||
| eb87231926 | |||
| b4d7568e61 | |||
| e4edb91f3d | |||
| 281005f1f8 | |||
| c81c8cbaa6 | |||
| d764598bde | |||
| 9c1479b922 | |||
| bd69a69aff | |||
| 8df180313e | |||
| de2cdf5411 | |||
| 2db0d76950 | |||
| 57ea6aefd6 | |||
| 2cb8d9e3a1 | |||
| b72cc2063a | |||
| d8052d4196 | |||
| c5c699ae61 | |||
| 86e5b0c4f8 | |||
| 9faad7397b | |||
| 20028096c7 | |||
| 0f0fb22074 | |||
| b85e8f9151 | |||
| f4e9b8ffce | |||
| 88fde1fcd6 | |||
| e9c72e1cd9 | |||
| dcca317b2f | |||
| 874bf9da8d | |||
| 02329673b2 | |||
| 898f4a6740 | |||
| 02fa9384ac | |||
| a3c00a1026 | |||
| 69baafe597 | |||
| 7e5865a899 | |||
| 52f23f5e2d | |||
| ae190b3c57 | |||
| 137b6af6d5 | |||
| 56e5f6fbb3 | |||
| 4f73d2cbd6 | |||
| ee8718d083 | |||
| 225b348154 | |||
| 1f2722b249 | |||
| 9afe25b449 | |||
| f3f871df3c | |||
| 961eb17536 | |||
| e2244ddda5 | |||
| 4086291ce2 | |||
| 630759c87b | |||
| bf1f8a8f65 | |||
| 9942327531 | |||
| 9b9320f9c0 | |||
| e8aab6e257 |
@@ -22,6 +22,15 @@
|
||||
<jar jarfile="${dist}/${pluginname}.jar">
|
||||
<fileset dir="${bin}"/>
|
||||
<fileset file="${src}/main/resources/plugin.yml"/>
|
||||
<fileset file="${src}/main/resources/configuration.txt"/>
|
||||
<fileset file="${src}/main/resources/custom-lightings.txt"/>
|
||||
<fileset file="${src}/main/resources/custom-perspectives.txt"/>
|
||||
<fileset file="${src}/main/resources/custom-shaders.txt"/>
|
||||
<fileset file="${src}/main/resources/lightings.txt"/>
|
||||
<fileset file="${src}/main/resources/models.txt"/>
|
||||
<fileset file="${src}/main/resources/perspectives.txt"/>
|
||||
<fileset file="${src}/main/resources/texture.txt"/>
|
||||
<fileset file="${src}/main/resources/worlds.txt"/>
|
||||
<zipfileset file="${src}/main/resources/colors.txt"/>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
@@ -1,429 +0,0 @@
|
||||
# All paths in this configuration file are relative to Dynmap's data-folder: minecraft_server/plugins/dynmap/
|
||||
|
||||
components:
|
||||
- class: org.dynmap.ClientConfigurationComponent
|
||||
|
||||
- class: org.dynmap.InternalClientUpdateComponent
|
||||
sendhealth: true
|
||||
sendposition: true
|
||||
allowwebchat: true
|
||||
webchat-interval: 5
|
||||
hidewebchatip: false
|
||||
trustclientname: false
|
||||
#- class: org.dynmap.JsonFileClientUpdateComponent
|
||||
# writeinterval: 1
|
||||
# sendhealth: true
|
||||
# sendposition: true
|
||||
# allowwebchat: false
|
||||
# hidewebchatip: false
|
||||
|
||||
- class: org.dynmap.SimpleWebChatComponent
|
||||
allowchat: true
|
||||
#- class: org.dynmap.herochat.HeroWebChatComponent
|
||||
# # Control which HeroChat channel messages from web are directed to
|
||||
# herochatwebchannel: Global
|
||||
# # Control which channels are monitored and reported to the web
|
||||
# herochatchannels:
|
||||
# - Global
|
||||
# #- Trade
|
||||
# #- Haggle
|
||||
|
||||
- class: org.dynmap.ClientComponent
|
||||
type: chat
|
||||
- class: org.dynmap.ClientComponent
|
||||
type: chatballoon
|
||||
focuschatballoons: false
|
||||
- class: org.dynmap.ClientComponent
|
||||
type: chatbox
|
||||
showplayerfaces: true
|
||||
messagettl: 5
|
||||
- class: org.dynmap.ClientComponent
|
||||
type: playermarkers
|
||||
showplayerfaces: true
|
||||
showplayerhealth: true
|
||||
#- class: org.dynmap.ClientComponent
|
||||
# type: digitalclock
|
||||
- class: org.dynmap.ClientComponent
|
||||
type: timeofdayclock
|
||||
showdigitalclock: true
|
||||
#showweather: true
|
||||
#- class: org.dynmap.regions.RegionsComponent
|
||||
# type: regions
|
||||
# name: WorldGuard
|
||||
# useworldpath: true
|
||||
# filename: regions.yml
|
||||
# basenode: regions
|
||||
# use3dregions: true
|
||||
# infowindow: '<div class="infowindow"><span style="font-size:120%;">%regionname% - %priority% (%parent%)</span><br /> Owners <span style="font-weight:bold;">%playerowners% %groupowners%</span><br />Members <span style="font-weight:bold;">%playermembers% %groupmembers%</span><br />Flags<br /><span style="font-weight:bold;">%flags%</span></div>'
|
||||
# regionstyle:
|
||||
# strokeColor: "#FF0000"
|
||||
# strokeOpacity: 0.8
|
||||
# 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"
|
||||
|
||||
# Treat hiddenplayers.txt as a whitelist for players to be shown on the map? (Default false)
|
||||
display-whitelist: false
|
||||
|
||||
# How often a tile gets rendered (in seconds).
|
||||
renderinterval: 1
|
||||
|
||||
# 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
|
||||
- blockplaced
|
||||
- blockbreak
|
||||
- snowform
|
||||
- leavesdecay
|
||||
- blockburn
|
||||
- chunkgenerated
|
||||
|
||||
# The path where the tile-files are placed.
|
||||
tilespath: web/tiles
|
||||
|
||||
# The path where the web-files are located.
|
||||
webpath: web
|
||||
|
||||
# The network-interface the webserver will bind to (0.0.0.0 for all interfaces, 127.0.0.1 for only local access).
|
||||
webserver-bindaddress: 0.0.0.0
|
||||
|
||||
# The TCP-port the webserver will listen on.
|
||||
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
|
||||
|
||||
showplayerfacesinmenu: true
|
||||
|
||||
# Set sidebaropened: true to pin menu sidebar opened
|
||||
#sidebaropened: true
|
||||
|
||||
joinmessage: "%playername% joined"
|
||||
quitmessage: "%playername% quit"
|
||||
spammessage: "You may only chat once every %interval% seconds."
|
||||
webprefix: "§2[WEB] "
|
||||
websuffix: "§f"
|
||||
|
||||
defaultzoom: 0
|
||||
defaultworld: world
|
||||
|
||||
# template world - this is used for worlds that exist but aren't defined in the worlds section.
|
||||
# Also, it supplies the "maps" section for worlds lacking a maps section, and the "center"
|
||||
# for worlds lacking a "center" section.
|
||||
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
|
||||
z: 0
|
||||
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
|
||||
# # 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
|
||||
name: surface
|
||||
title: "Surface"
|
||||
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"
|
||||
# # 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"
|
||||
prefix: ct
|
||||
maximumheight: 127
|
||||
# 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
|
||||
z: 0
|
||||
maps:
|
||||
- class: org.dynmap.flat.FlatMap
|
||||
name: flat
|
||||
title: "Flat"
|
||||
prefix: flat
|
||||
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
|
||||
name: nether
|
||||
title: "Surface"
|
||||
prefix: nt
|
||||
maximumheight: 127
|
||||
colorscheme: default
|
||||
# Map background color (day or night)
|
||||
background: "#300806"
|
||||
# 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
|
||||
z: 0
|
||||
maps:
|
||||
- class: org.dynmap.flat.FlatMap
|
||||
name: flat
|
||||
title: "Flat"
|
||||
prefix: flat
|
||||
colorscheme: default
|
||||
# Background color for map during the day
|
||||
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
|
||||
name: skylands
|
||||
title: "Surface"
|
||||
prefix: st
|
||||
maximumheight: 127
|
||||
colorscheme: default
|
||||
# Background color for map during the day
|
||||
backgroundday: "#153E7E"
|
||||
# Background color for map during the night
|
||||
backgroundnight: "#000000"
|
||||
night-and-day: true
|
||||
shadowstrength: 1.0
|
||||
ambientlight: 4
|
||||
|
||||
# The maptypes Dynmap will use to render.
|
||||
worlds:
|
||||
# Worlds can be handled by templates, based on world type
|
||||
# You can override the properties of the template by specifying them in this section
|
||||
# for example 'Title: "My Awesome World"'
|
||||
#- name: world
|
||||
# title: "World"
|
||||
# Use 'enabled: false' to disable a certain world.
|
||||
# enabled: false
|
||||
# Use sendposition: false to prevent player positions from showing when on this world (if sendposition is globally enabled)
|
||||
# sendposition: false
|
||||
# Use sendhealth: false ot prevent player health from showing when on this world (if sendhealth is globally enabled)
|
||||
# sendhealth: false
|
||||
# # If world isn't contiguous chunks (due to teleporting, for example), fullrender needs to be given other locations to scan for tiles on each patch of chunks
|
||||
# fullrenderlocations:
|
||||
# - x: 10000
|
||||
# y: 64
|
||||
# z: 20000
|
||||
# - 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
|
||||
# center:
|
||||
# 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
|
||||
# # 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"
|
||||
# - class: org.dynmap.kzedmap.KzedMap
|
||||
# renderers:
|
||||
# - class: org.dynmap.kzedmap.DefaultTileRenderer
|
||||
# name: surface
|
||||
# title: "Surface"
|
||||
# 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.
|
||||
# - class: org.dynmap.kzedmap.CaveTileRenderer
|
||||
# name: cave
|
||||
# title: "Cave"
|
||||
# prefix: ct
|
||||
# maximumheight: 127
|
||||
#
|
||||
# To just label world, and inherit rest from template, just provide name and title
|
||||
#- name: world2
|
||||
# title: "Second World"
|
||||
#
|
||||
#- name: nether
|
||||
# title: "Nether"
|
||||
# center:
|
||||
# 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
|
||||
# name: nether
|
||||
# title: "Surface"
|
||||
# prefix: nt
|
||||
# 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
|
||||
@@ -2,7 +2,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.dynmap</groupId>
|
||||
<artifactId>dynmap</artifactId>
|
||||
<version>0.19.2</version>
|
||||
<version>0.20.1</version>
|
||||
<name>dynmap</name>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
@@ -24,10 +24,11 @@
|
||||
<outputDirectory>/dynmap/colorschemes</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.basedir}</directory>
|
||||
<outputDirectory>/dynmap/</outputDirectory>
|
||||
<includes>
|
||||
<include>configuration.txt</include></includes></fileSet>
|
||||
<directory>${project.basedir}/texturepacks</directory>
|
||||
<outputDirectory>/dynmap/texturepacks</outputDirectory></fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.basedir}/renderdata</directory>
|
||||
<outputDirectory>/dynmap/renderdata</outputDirectory></fileSet>
|
||||
</fileSets>
|
||||
<files>
|
||||
<file>
|
||||
|
||||
@@ -31,6 +31,6 @@ public class Armor {
|
||||
currentDurability += maxDurability - durability;
|
||||
baseArmorPoints += armorPoints[i];
|
||||
}
|
||||
return (int)(2*baseArmorPoints*currentDurability/baseDurability);
|
||||
return (int)Math.round(2*baseArmorPoints*currentDurability/baseDurability);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class Cache<K, V> {
|
||||
private final int size;
|
||||
private int len;
|
||||
|
||||
private CacheNode head;
|
||||
private CacheNode tail;
|
||||
|
||||
private class CacheNode {
|
||||
public CacheNode prev;
|
||||
public CacheNode next;
|
||||
public K key;
|
||||
public V value;
|
||||
|
||||
public CacheNode(K key, V value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
prev = null;
|
||||
next = null;
|
||||
}
|
||||
|
||||
public void unlink() {
|
||||
if (prev == null) {
|
||||
head = next;
|
||||
} else {
|
||||
prev.next = next;
|
||||
}
|
||||
|
||||
if (next == null) {
|
||||
tail = prev;
|
||||
} else {
|
||||
next.prev = prev;
|
||||
}
|
||||
|
||||
prev = null;
|
||||
next = null;
|
||||
|
||||
len--;
|
||||
}
|
||||
|
||||
public void append() {
|
||||
if (tail == null) {
|
||||
head = this;
|
||||
tail = this;
|
||||
} else {
|
||||
tail.next = this;
|
||||
prev = tail;
|
||||
tail = this;
|
||||
}
|
||||
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
private HashMap<K, CacheNode> map;
|
||||
|
||||
public Cache(int size) {
|
||||
this.size = size;
|
||||
len = 0;
|
||||
|
||||
head = null;
|
||||
tail = null;
|
||||
|
||||
map = new HashMap<K, CacheNode>();
|
||||
}
|
||||
|
||||
/*
|
||||
* returns value for key, if key exists in the cache otherwise null
|
||||
*/
|
||||
public V get(K key) {
|
||||
CacheNode n = map.get(key);
|
||||
if (n == null)
|
||||
return null;
|
||||
return n.value;
|
||||
}
|
||||
|
||||
/*
|
||||
* puts a new key-value pair in the cache if the key existed already, the
|
||||
* value is updated, and the old value is returned if the key didn't exist,
|
||||
* it is added; the oldest value (now pushed out of the cache) may be
|
||||
* returned, or null if the cache isn't yet full
|
||||
*/
|
||||
public V put(K key, V value) {
|
||||
CacheNode n = map.get(key);
|
||||
if (n == null) {
|
||||
V ret = null;
|
||||
|
||||
if (len >= size) {
|
||||
CacheNode first = head;
|
||||
first.unlink();
|
||||
map.remove(first.key);
|
||||
ret = first.value;
|
||||
}
|
||||
|
||||
CacheNode add = new CacheNode(key, value);
|
||||
add.append();
|
||||
map.put(key, add);
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
n.unlink();
|
||||
V old = n.value;
|
||||
n.value = value;
|
||||
n.append();
|
||||
return old;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,11 +18,12 @@ public class ClientConfigurationComponent extends Component {
|
||||
s(t, "joinmessage", c.getString("joinmessage", "%playername% joined"));
|
||||
s(t, "quitmessage", c.getString("quitmessage", "%playername% quit"));
|
||||
s(t, "spammessage", c.getString("spammessage", "You may only chat once every %interval% seconds."));
|
||||
s(t, "webprefix", c.getString("webprefix", "[WEB] "));
|
||||
s(t, "webprefix", unescapeString(c.getString("webprefix", "[WEB] ")));
|
||||
s(t, "defaultzoom", c.getInteger("defaultzoom", 0));
|
||||
s(t, "sidebaropened", c.getBoolean("sidebaropened", false));
|
||||
|
||||
DynmapWorld defaultWorld = null;
|
||||
String defmap = null;
|
||||
for(DynmapWorld world : plugin.mapManager.getWorlds()) {
|
||||
if (defaultWorld == null) defaultWorld = world;
|
||||
ConfigurationNode wn = world.configuration;
|
||||
@@ -37,10 +38,12 @@ public class ClientConfigurationComponent extends Component {
|
||||
a(t, "worlds", wo);
|
||||
|
||||
for(MapType mt : world.maps) {
|
||||
mt.buildClientConfiguration(wo);
|
||||
mt.buildClientConfiguration(wo, world);
|
||||
if(defmap == null) defmap = mt.getName();
|
||||
}
|
||||
}
|
||||
s(t, "defaultworld", c.getString("defaultworld", defaultWorld == null ? "world" : defaultWorld.world.getName()));
|
||||
s(t, "defaultmap", c.getString("defaultmap", defmap == null ? "surface" : defmap));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public class Color {
|
||||
return ((val >> 24) & 0xFF);
|
||||
}
|
||||
public final boolean isTransparent() {
|
||||
return (val == TRANSPARENT);
|
||||
return ((val & 0xFF000000) == TRANSPARENT);
|
||||
}
|
||||
public final void setTransparent() {
|
||||
val = TRANSPARENT;
|
||||
@@ -52,4 +52,23 @@ public class Color {
|
||||
public final int getComponent(int idx) {
|
||||
return 0xFF & (val >> ((3-idx)*8));
|
||||
}
|
||||
public final void setAlpha(int v) {
|
||||
val = (val & 0x00FFFFFF) | (v << 24);
|
||||
}
|
||||
/**
|
||||
* Scale each color component, based on the corresponding component
|
||||
*/
|
||||
public final void blendColor(Color c) {
|
||||
blendColor(c.val);
|
||||
}
|
||||
/**
|
||||
* Scale each color component, based on the corresponding component
|
||||
*/
|
||||
public final void blendColor(int argb) {
|
||||
int nval = (((((val >> 24) & 0xFF) * ((argb >> 24) & 0xFF)) / 255) << 24);
|
||||
nval = nval | (((((val >> 16) & 0xFF) * ((argb >> 16) & 0xFF)) / 255) << 16);
|
||||
nval = nval | (((((val >> 8) & 0xFF) * ((argb >> 8) & 0xFF)) / 255) << 8);
|
||||
nval = nval | (((val & 0xFF) * (argb & 0xFF)) / 255);
|
||||
val = nval;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ public class ColorScheme {
|
||||
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);
|
||||
c[4] = new Color((c[1].getRed()+c[3].getRed())/2, (c[1].getGreen()+c[3].getGreen())/2, (c[1].getBlue()+c[3].getBlue())/2, (c[1].getAlpha()+c[3].getAlpha())/2);
|
||||
|
||||
if(isbiome) {
|
||||
if(istemp) {
|
||||
@@ -235,4 +235,7 @@ public class ColorScheme {
|
||||
else
|
||||
return null;
|
||||
}
|
||||
public static void reset() {
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,4 +10,12 @@ public abstract class Component {
|
||||
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
/* Substitute proper values for escape sequences */
|
||||
public static String unescapeString(String v) {
|
||||
/* Replace color code &color; */
|
||||
v = v.replaceAll("&color;", "\u00A7");
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,19 +15,22 @@ public class DynmapPlayerChatListener extends PlayerListener {
|
||||
@Override
|
||||
public void onPlayerChat(PlayerChatEvent event) {
|
||||
if(event.isCancelled()) return;
|
||||
plugin.mapManager.pushUpdate(new Client.ChatMessage("player", "",
|
||||
if(plugin.mapManager != null)
|
||||
plugin.mapManager.pushUpdate(new Client.ChatMessage("player", "",
|
||||
event.getPlayer().getDisplayName(), event.getMessage(),
|
||||
event.getPlayer().getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
plugin.mapManager.pushUpdate(new Client.PlayerJoinMessage(event.getPlayer().getDisplayName(), event.getPlayer().getName()));
|
||||
if(plugin.mapManager != null)
|
||||
plugin.mapManager.pushUpdate(new Client.PlayerJoinMessage(event.getPlayer().getDisplayName(), event.getPlayer().getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
plugin.mapManager.pushUpdate(new Client.PlayerQuitMessage(event.getPlayer().getDisplayName(), event.getPlayer().getName()));
|
||||
if(plugin.mapManager != null)
|
||||
plugin.mapManager.pushUpdate(new Client.PlayerQuitMessage(event.getPlayer().getDisplayName(), event.getPlayer().getName()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
@@ -19,10 +24,12 @@ 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.BlockFadeEvent;
|
||||
import org.bukkit.event.block.BlockFormEvent;
|
||||
import org.bukkit.event.block.BlockListener;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.block.BlockSpreadEvent;
|
||||
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;
|
||||
@@ -34,6 +41,8 @@ import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.dynmap.debug.Debug;
|
||||
import org.dynmap.debug.Debugger;
|
||||
import org.dynmap.hdmap.HDBlockModels;
|
||||
import org.dynmap.hdmap.TexturePack;
|
||||
import org.dynmap.permissions.NijikokunPermissions;
|
||||
import org.dynmap.permissions.OpPermissions;
|
||||
import org.dynmap.permissions.PermissionProvider;
|
||||
@@ -50,10 +59,11 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
public PermissionProvider permissions;
|
||||
public ComponentManager componentManager = new ComponentManager();
|
||||
public Events events = new Events();
|
||||
public String deftemplatesuffix = "";
|
||||
/* 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 */
|
||||
private static boolean ignore_chunk_loads = false; /* Flag keep us from processing our own chunk loads */
|
||||
|
||||
public static File dataDirectory;
|
||||
public static File tilesDirectory;
|
||||
@@ -65,20 +75,149 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
public HttpServer getWebServer() {
|
||||
return webServer;
|
||||
}
|
||||
|
||||
/* Add/Replace branches in configuration tree with contribution from a separate file */
|
||||
@SuppressWarnings("unchecked")
|
||||
private void mergeConfigurationBranch(ConfigurationNode cfgnode, String branch, boolean replace_existing, boolean islist) {
|
||||
Object srcbranch = cfgnode.getObject(branch);
|
||||
if(srcbranch == null)
|
||||
return;
|
||||
/* See if top branch is in configuration - if not, just add whole thing */
|
||||
Object destbranch = configuration.getObject(branch);
|
||||
if(destbranch == null) { /* Not found */
|
||||
configuration.put(branch, srcbranch); /* Add new tree to configuration */
|
||||
return;
|
||||
}
|
||||
/* If list, merge by "name" attribute */
|
||||
if(islist) {
|
||||
List<ConfigurationNode> dest = configuration.getNodes(branch);
|
||||
List<ConfigurationNode> src = cfgnode.getNodes(branch);
|
||||
/* Go through new records : see what to do with each */
|
||||
for(ConfigurationNode node : src) {
|
||||
String name = node.getString("name", null);
|
||||
if(name == null) continue;
|
||||
/* Walk destination - see if match */
|
||||
boolean matched = false;
|
||||
for(ConfigurationNode dnode : dest) {
|
||||
String dname = dnode.getString("name", null);
|
||||
if(dname == null) continue;
|
||||
if(dname.equals(name)) { /* Match? */
|
||||
if(replace_existing) {
|
||||
dnode.clear();
|
||||
dnode.putAll(node);
|
||||
}
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* If no match, add to end */
|
||||
if(!matched) {
|
||||
dest.add(node);
|
||||
}
|
||||
}
|
||||
configuration.put(branch,dest);
|
||||
}
|
||||
/* If configuration node, merge by key */
|
||||
else {
|
||||
ConfigurationNode src = cfgnode.getNode(branch);
|
||||
ConfigurationNode dest = configuration.getNode(branch);
|
||||
for(String key : src.keySet()) { /* Check each contribution */
|
||||
if(dest.containsKey(key)) { /* Exists? */
|
||||
if(replace_existing) { /* If replacing, do so */
|
||||
dest.put(key, src.getObject(key));
|
||||
}
|
||||
}
|
||||
else { /* Else, always add if not there */
|
||||
dest.put(key, src.getObject(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Table of default templates - all are resources in dynmap.jar unnder templates/, and go in templates directory when needed */
|
||||
private static final String[] stdtemplates = { "normal.txt", "nether.txt", "skylands.txt", "normal-lowres.txt",
|
||||
"nether-lowres.txt", "skylands-lowres.txt", "normal-hires.txt", "nether-hires.txt", "skylands-hires.txt"
|
||||
};
|
||||
|
||||
private static final String CUSTOM_PREFIX = "custom-";
|
||||
/* Load templates from template folder */
|
||||
private void loadTemplates() {
|
||||
File templatedir = new File(dataDirectory, "templates");
|
||||
templatedir.mkdirs();
|
||||
/* First, prime the templates directory with default standard templates, if needed */
|
||||
for(String stdtemplate : stdtemplates) {
|
||||
File f = new File(templatedir, stdtemplate);
|
||||
createDefaultFileFromResource("/templates/" + stdtemplate, f);
|
||||
}
|
||||
/* Now process files */
|
||||
String[] templates = templatedir.list();
|
||||
/* Go through list - process all ones not starting with 'custom' first */
|
||||
for(String tname: templates) {
|
||||
/* If matches naming convention */
|
||||
if(tname.endsWith(".txt") && (!tname.startsWith(CUSTOM_PREFIX))) {
|
||||
File tf = new File(templatedir, tname);
|
||||
org.bukkit.util.config.Configuration cfg = new org.bukkit.util.config.Configuration(tf);
|
||||
cfg.load();
|
||||
ConfigurationNode cn = new ConfigurationNode(cfg);
|
||||
/* Supplement existing values (don't replace), since configuration.txt is more custom than these */
|
||||
mergeConfigurationBranch(cn, "templates", false, false);
|
||||
}
|
||||
}
|
||||
/* Go through list again - this time do custom- ones */
|
||||
for(String tname: templates) {
|
||||
/* If matches naming convention */
|
||||
if(tname.endsWith(".txt") && tname.startsWith(CUSTOM_PREFIX)) {
|
||||
File tf = new File(templatedir, tname);
|
||||
org.bukkit.util.config.Configuration cfg = new org.bukkit.util.config.Configuration(tf);
|
||||
cfg.load();
|
||||
ConfigurationNode cn = new ConfigurationNode(cfg);
|
||||
/* This are overrides - replace even configuration.txt content */
|
||||
mergeConfigurationBranch(cn, "templates", true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
/* Start with clean events */
|
||||
events = new Events();
|
||||
|
||||
permissions = NijikokunPermissions.create(getServer(), "dynmap");
|
||||
if (permissions == null)
|
||||
permissions = new OpPermissions(new String[] { "fullrender", "reload" });
|
||||
permissions = new OpPermissions(new String[] { "fullrender", "cancelrender", "radiusrender", "resetstats", "reload" });
|
||||
|
||||
dataDirectory = this.getDataFolder();
|
||||
|
||||
org.bukkit.util.config.Configuration bukkitConfiguration = new org.bukkit.util.config.Configuration(new File(this.getDataFolder(), "configuration.txt"));
|
||||
/* Load block models */
|
||||
HDBlockModels.loadModels(dataDirectory);
|
||||
/* Load texture mappings */
|
||||
TexturePack.loadTextureMapping(dataDirectory);
|
||||
|
||||
/* Initialize confguration.txt if needed */
|
||||
File f = new File(this.getDataFolder(), "configuration.txt");
|
||||
if(!createDefaultFileFromResource("/configuration.txt", f)) {
|
||||
this.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
/* Load configuration.txt */
|
||||
org.bukkit.util.config.Configuration bukkitConfiguration = new org.bukkit.util.config.Configuration(f);
|
||||
bukkitConfiguration.load();
|
||||
configuration = new ConfigurationNode(bukkitConfiguration);
|
||||
|
||||
|
||||
/* Now, process worlds.txt - merge it in as an override of existing values (since it is only user supplied values) */
|
||||
f = new File(this.getDataFolder(), "worlds.txt");
|
||||
if(!createDefaultFileFromResource("/worlds.txt", f)) {
|
||||
this.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
org.bukkit.util.config.Configuration cfg = new org.bukkit.util.config.Configuration(f);
|
||||
cfg.load();
|
||||
ConfigurationNode cn = new ConfigurationNode(cfg);
|
||||
mergeConfigurationBranch(cn, "worlds", true, true);
|
||||
|
||||
/* Now, process templates */
|
||||
loadTemplates();
|
||||
|
||||
Log.verbose = configuration.getBoolean("verbose", true);
|
||||
deftemplatesuffix = configuration.getString("deftemplatesuffix", "");
|
||||
|
||||
loadDebuggers();
|
||||
|
||||
@@ -137,11 +276,14 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
}
|
||||
int port = configuration.getInteger("webserver-port", 8123);
|
||||
boolean allow_symlinks = configuration.getBoolean("allow-symlinks", false);
|
||||
boolean checkbannedips = configuration.getBoolean("check-banned-ips", true);
|
||||
int maxconnections = configuration.getInteger("max-sessions", 30);
|
||||
if(maxconnections < 2) maxconnections = 2;
|
||||
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 = new HttpServer(bindAddress, port, checkbannedips, maxconnections);
|
||||
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));
|
||||
@@ -168,6 +310,7 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
|
||||
if (mapManager != null) {
|
||||
mapManager.stopRendering();
|
||||
mapManager = null;
|
||||
}
|
||||
|
||||
if (webServer != null) {
|
||||
@@ -182,6 +325,14 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
return enabledTriggers.contains(s);
|
||||
}
|
||||
|
||||
private boolean onplace;
|
||||
private boolean onbreak;
|
||||
private boolean onblockform;
|
||||
private boolean onblockfade;
|
||||
private boolean onblockspread;
|
||||
private boolean onleaves;
|
||||
private boolean onburn;
|
||||
|
||||
public void registerEvents() {
|
||||
final PluginManager pm = getServer().getPluginManager();
|
||||
final MapManager mm = mapManager;
|
||||
@@ -189,50 +340,102 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
// To trigger rendering.
|
||||
{
|
||||
BlockListener renderTrigger = new BlockListener() {
|
||||
|
||||
@Override
|
||||
public void onBlockPlace(BlockPlaceEvent event) {
|
||||
if(event.isCancelled())
|
||||
return;
|
||||
mm.touch(event.getBlockPlaced().getLocation());
|
||||
if(onplace)
|
||||
mm.touch(event.getBlockPlaced().getLocation());
|
||||
mm.sscache.invalidateSnapshot(event.getBlock().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());
|
||||
if(onbreak)
|
||||
mm.touch(event.getBlock().getLocation());
|
||||
mm.sscache.invalidateSnapshot(event.getBlock().getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLeavesDecay(LeavesDecayEvent event) {
|
||||
if(event.isCancelled())
|
||||
return;
|
||||
mm.touch(event.getBlock().getLocation());
|
||||
if(onleaves)
|
||||
mm.touch(event.getBlock().getLocation());
|
||||
mm.sscache.invalidateSnapshot(event.getBlock().getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockBurn(BlockBurnEvent event) {
|
||||
if(event.isCancelled())
|
||||
return;
|
||||
mm.touch(event.getBlock().getLocation());
|
||||
if(onburn)
|
||||
mm.touch(event.getBlock().getLocation());
|
||||
mm.sscache.invalidateSnapshot(event.getBlock().getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockForm(BlockFormEvent event) {
|
||||
if(event.isCancelled())
|
||||
return;
|
||||
if(onblockform)
|
||||
mm.touch(event.getBlock().getLocation());
|
||||
mm.sscache.invalidateSnapshot(event.getBlock().getLocation());
|
||||
}
|
||||
@Override
|
||||
public void onBlockFade(BlockFadeEvent event) {
|
||||
if(event.isCancelled())
|
||||
return;
|
||||
if(onblockfade)
|
||||
mm.touch(event.getBlock().getLocation());
|
||||
mm.sscache.invalidateSnapshot(event.getBlock().getLocation());
|
||||
}
|
||||
@Override
|
||||
public void onBlockSpread(BlockSpreadEvent event) {
|
||||
if(event.isCancelled())
|
||||
return;
|
||||
if(onblockspread)
|
||||
mm.touch(event.getBlock().getLocation());
|
||||
mm.sscache.invalidateSnapshot(event.getBlock().getLocation());
|
||||
}
|
||||
};
|
||||
if (isTrigger("blockplaced"))
|
||||
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);
|
||||
onplace = isTrigger("blockplaced");
|
||||
pm.registerEvent(org.bukkit.event.Event.Type.BLOCK_PLACE, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
||||
onbreak = isTrigger("blockbreak");
|
||||
pm.registerEvent(org.bukkit.event.Event.Type.BLOCK_BREAK, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
||||
if(isTrigger("snowform")) Log.info("The 'snowform' trigger has been deprecated due to Bukkit changes - use 'blockformed'");
|
||||
onleaves = isTrigger("leavesdecay");
|
||||
pm.registerEvent(org.bukkit.event.Event.Type.LEAVES_DECAY, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
||||
onburn = isTrigger("blockburn");
|
||||
pm.registerEvent(org.bukkit.event.Event.Type.BLOCK_BURN, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
||||
|
||||
onblockform = isTrigger("blockformed");
|
||||
try {
|
||||
Class.forName("org.bukkit.event.block.BlockFormEvent");
|
||||
pm.registerEvent(org.bukkit.event.Event.Type.BLOCK_FORM, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
||||
} catch (ClassNotFoundException cnfx) {
|
||||
if(onblockform)
|
||||
Log.info("BLOCK_FORM event not supported by this version of CraftBukkit - event disabled");
|
||||
}
|
||||
onblockfade = isTrigger("blockfaded");
|
||||
try {
|
||||
Class.forName("org.bukkit.event.block.BlockFadeEvent");
|
||||
pm.registerEvent(org.bukkit.event.Event.Type.BLOCK_FADE, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
||||
} catch (ClassNotFoundException cnfx) {
|
||||
if(onblockfade)
|
||||
Log.info("BLOCK_FADE event not supported by this version of CraftBukkit - event disabled");
|
||||
}
|
||||
onblockspread = isTrigger("blockspread");
|
||||
try {
|
||||
Class.forName("org.bukkit.event.block.BlockSpreadEvent");
|
||||
pm.registerEvent(org.bukkit.event.Event.Type.BLOCK_SPREAD, renderTrigger, org.bukkit.event.Event.Priority.Monitor, this);
|
||||
} catch (ClassNotFoundException cnfx) {
|
||||
if(onblockspread)
|
||||
Log.info("BLOCK_SPREAD event not supported by this version of CraftBukkit - event disabled");
|
||||
}
|
||||
}
|
||||
{
|
||||
PlayerListener renderTrigger = new PlayerListener() {
|
||||
@@ -343,6 +546,8 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
"hide",
|
||||
"show",
|
||||
"fullrender",
|
||||
"cancelrender",
|
||||
"radiusrender",
|
||||
"reload",
|
||||
"stats",
|
||||
"resetstats" }));
|
||||
@@ -364,8 +569,27 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
if (player != null) {
|
||||
int invalidates = mapManager.touch(player.getLocation());
|
||||
sender.sendMessage("Queued " + invalidates + " tiles" + (invalidates == 0
|
||||
? " (world is not loaded?)"
|
||||
: "..."));
|
||||
? " (world is not loaded?)"
|
||||
: "..."));
|
||||
}
|
||||
else {
|
||||
sender.sendMessage("Command can only be issued by player.");
|
||||
}
|
||||
}
|
||||
else if(c.equals("radiusrender") && checkPlayerPermission(sender,"radiusrender")) {
|
||||
if (player != null) {
|
||||
int radius = 0;
|
||||
if(args.length > 1) {
|
||||
radius = Integer.parseInt(args[1]); /* Parse radius */
|
||||
if(radius < 0)
|
||||
radius = 0;
|
||||
}
|
||||
Location loc = player.getLocation();
|
||||
if(loc != null)
|
||||
mapManager.renderWorldRadius(loc, sender, radius);
|
||||
}
|
||||
else {
|
||||
sender.sendMessage("Command can only be issued by player.");
|
||||
}
|
||||
} else if (c.equals("hide")) {
|
||||
if (args.length == 1) {
|
||||
@@ -407,6 +631,22 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
} else {
|
||||
sender.sendMessage("World name is required");
|
||||
}
|
||||
} else if (c.equals("cancelrender") && checkPlayerPermission(sender,"cancelrender")) {
|
||||
if (args.length > 1) {
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
World w = getServer().getWorld(args[i]);
|
||||
if(w != null)
|
||||
mapManager.cancelRender(w,sender);
|
||||
else
|
||||
sender.sendMessage("World '" + args[i] + "' not defined/loaded");
|
||||
}
|
||||
} else if (player != null) {
|
||||
Location loc = player.getLocation();
|
||||
if(loc != null)
|
||||
mapManager.cancelRender(loc.getWorld(), sender);
|
||||
} else {
|
||||
sender.sendMessage("World name is required");
|
||||
}
|
||||
} else if (c.equals("reload") && checkPlayerPermission(sender, "reload")) {
|
||||
sender.sendMessage("Reloading Dynmap...");
|
||||
reload();
|
||||
@@ -473,6 +713,9 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
private ConfigurationNode getDefaultTemplateConfigurationNode(World world) {
|
||||
Environment environment = world.getEnvironment();
|
||||
String environmentName = environment.name().toLowerCase();
|
||||
if(deftemplatesuffix.length() > 0) {
|
||||
environmentName += "-" + deftemplatesuffix;
|
||||
}
|
||||
Log.verboseinfo("Using environment as template: " + environmentName);
|
||||
return getTemplateConfigurationNode(environmentName);
|
||||
}
|
||||
@@ -507,4 +750,35 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
public static void setIgnoreChunkLoads(boolean ignore) {
|
||||
ignore_chunk_loads = ignore;
|
||||
}
|
||||
/* Uses resource to create default file, if file does not yet exist */
|
||||
public boolean createDefaultFileFromResource(String resourcename, File deffile) {
|
||||
if(deffile.canRead())
|
||||
return true;
|
||||
Log.info(deffile.getPath() + " not found - creating default");
|
||||
InputStream in = getClass().getResourceAsStream(resourcename);
|
||||
if(in == null) {
|
||||
Log.severe("Unable to find default resource - " + resourcename);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(deffile);
|
||||
byte[] buf = new byte[512];
|
||||
int len;
|
||||
while((len = in.read(buf)) > 0) {
|
||||
fos.write(buf, 0, len);
|
||||
}
|
||||
} catch (IOException iox) {
|
||||
Log.severe("ERROR creatomg default for " + deffile.getPath());
|
||||
return false;
|
||||
} finally {
|
||||
if(fos != null)
|
||||
try { fos.close(); } catch (IOException iox) {}
|
||||
if(in != null)
|
||||
try { in.close(); } catch (IOException iox) {}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.dynmap;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
|
||||
/**
|
||||
* Custom bukkit event, corresponding to the receiving of a web-chat message from a web UI user
|
||||
*/
|
||||
public class DynmapWebChatEvent extends Event implements Cancellable {
|
||||
private String source;
|
||||
private String name;
|
||||
private String message;
|
||||
private boolean cancelled;
|
||||
|
||||
public DynmapWebChatEvent(String source, String name, String message) {
|
||||
super("org.dynmap.DynmapWebChatEvent");
|
||||
this.source = source;
|
||||
this.name = name;
|
||||
this.message = message;
|
||||
this.cancelled = false;
|
||||
}
|
||||
public boolean isCancelled() { return cancelled; }
|
||||
|
||||
public void setCancelled(boolean cancel) { cancelled = cancel; }
|
||||
|
||||
public String getSource() { return source; }
|
||||
|
||||
public String getName() { return name; }
|
||||
|
||||
public String getMessage() { return message; }
|
||||
|
||||
}
|
||||
@@ -7,7 +7,7 @@ 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.DynmapBufferedImage;
|
||||
import org.dynmap.utils.FileLockManager;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
|
||||
@@ -41,8 +41,10 @@ public class DynmapWorld {
|
||||
private int extrazoomoutlevels; /* Number of additional zoom out levels to generate */
|
||||
public File worldtilepath;
|
||||
private Object lock = new Object();
|
||||
private HashSet<String> zoomoutupdates[];
|
||||
@SuppressWarnings("unchecked")
|
||||
private HashSet<String> zoomoutupdates[] = new HashSet[0];
|
||||
private boolean checkts = true; /* Check timestamps on first run with new configuration */
|
||||
private boolean cancelled;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setExtraZoomOutLevels(int lvl) {
|
||||
@@ -59,21 +61,39 @@ public class DynmapWorld {
|
||||
}
|
||||
|
||||
private void enqueueZoomOutUpdate(File f, int level) {
|
||||
if(level >= extrazoomoutlevels)
|
||||
return;
|
||||
synchronized(lock) {
|
||||
if(level >= zoomoutupdates.length) {
|
||||
@SuppressWarnings("unchecked")
|
||||
HashSet<String> new_zoomout[] = new HashSet[level+1];
|
||||
System.arraycopy(zoomoutupdates, 0, new_zoomout, 0, zoomoutupdates.length);
|
||||
for(int i = 0; i < new_zoomout.length; i++) {
|
||||
if(i < zoomoutupdates.length)
|
||||
new_zoomout[i] = zoomoutupdates[i];
|
||||
else
|
||||
new_zoomout[i] = new HashSet<String>();
|
||||
}
|
||||
zoomoutupdates = new_zoomout;
|
||||
}
|
||||
zoomoutupdates[level].add(f.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean popQueuedUpdate(File f, int level) {
|
||||
if(level >= extrazoomoutlevels)
|
||||
if(level >= zoomoutupdates.length)
|
||||
return false;
|
||||
synchronized(lock) {
|
||||
return zoomoutupdates[level].remove(f.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
private String[] peekQueuedUpdates(int level) {
|
||||
if(level >= zoomoutupdates.length)
|
||||
return new String[0];
|
||||
synchronized(lock) {
|
||||
return zoomoutupdates[level].toArray(new String[zoomoutupdates[level].size()]);
|
||||
}
|
||||
}
|
||||
|
||||
private static class DirFilter implements FilenameFilter {
|
||||
public boolean accept(File f, String n) {
|
||||
if(!n.equals("..") && !n.equals(".")) {
|
||||
@@ -97,76 +117,142 @@ public class DynmapWorld {
|
||||
}
|
||||
|
||||
public void freshenZoomOutFiles() {
|
||||
for(int i = 0; i < extrazoomoutlevels; i++) {
|
||||
freshenZoomOutFilesByLevel(i);
|
||||
boolean done = false;
|
||||
int last_done = 0;
|
||||
for(int i = 0; (!cancelled) && (!done); i++) {
|
||||
done = freshenZoomOutFilesByLevel(i);
|
||||
last_done = i;
|
||||
}
|
||||
/* Purge updates for levels above what any map needs */
|
||||
for(int i = last_done; i < zoomoutupdates.length; i++) {
|
||||
zoomoutupdates[i].clear();
|
||||
}
|
||||
checkts = false; /* Just handle queued updates after first scan */
|
||||
}
|
||||
|
||||
public void cancelZoomOutFreshen() {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
private static class PrefixData {
|
||||
int stepsize;
|
||||
int[] stepseq;
|
||||
boolean neg_step_x;
|
||||
boolean neg_step_y;
|
||||
String baseprefix;
|
||||
int zoomlevel;
|
||||
String zoomprefix;
|
||||
String fnprefix;
|
||||
String zfnprefix;
|
||||
int bigworldshift;
|
||||
boolean isbigmap;
|
||||
}
|
||||
|
||||
public void freshenZoomOutFilesByLevel(int zoomlevel) {
|
||||
public boolean freshenZoomOutFilesByLevel(int zoomlevel) {
|
||||
int cnt = 0;
|
||||
Debug.debug("freshenZoomOutFiles(" + world.getName() + "," + zoomlevel + ")");
|
||||
if(worldtilepath.exists() == false) /* Quit if not found */
|
||||
return;
|
||||
return true;
|
||||
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);
|
||||
if(checkts) { /* If doing timestamp based scan (initial) */
|
||||
DirFilter df = new DirFilter();
|
||||
for(String pfx : maptab.keySet()) { /* Walk through prefixes */
|
||||
if(cancelled) return true;
|
||||
PrefixData pd = maptab.get(pfx);
|
||||
if(pd.isbigmap) { /* If big world, next directories are map name specific */
|
||||
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) {
|
||||
if(cancelled) return true;
|
||||
File sdname = new File(dname, s);
|
||||
cnt += processZoomDirectory(sdname, pd);
|
||||
}
|
||||
}
|
||||
else { /* Else, classic file layout */
|
||||
cnt += processZoomDirectory(worldtilepath, maptab.get(pfx));
|
||||
}
|
||||
}
|
||||
Debug.debug("freshenZoomOutFiles(" + world.getName() + "," + zoomlevel + ") - done (" + cnt + " updated files)");
|
||||
}
|
||||
else { /* Else, only process updates */
|
||||
String[] paths = peekQueuedUpdates(zoomlevel); /* Get pending updates */
|
||||
HashMap<String, ProcessTileRec> toprocess = new HashMap<String, ProcessTileRec>();
|
||||
/* Accumulate zoomed tiles to be processed (combine triggering subtiles) */
|
||||
for(String p : paths) {
|
||||
if(cancelled) return true;
|
||||
File f = new File(p); /* Make file */
|
||||
/* Find matching prefix */
|
||||
for(PrefixData pd : maptab.values()) { /* Walk through prefixes */
|
||||
if(cancelled) return true;
|
||||
ProcessTileRec tr = null;
|
||||
/* If big map and matches name pattern */
|
||||
if(pd.isbigmap && f.getName().startsWith(pd.fnprefix) &&
|
||||
f.getParentFile().getParentFile().getName().equals(pd.baseprefix)) {
|
||||
tr = processZoomFile(f, pd);
|
||||
}
|
||||
/* If not big map and matches name pattern */
|
||||
else if((!pd.isbigmap) && f.getName().startsWith(pd.fnprefix)) {
|
||||
tr = processZoomFile(f, pd);
|
||||
}
|
||||
if(tr != null) {
|
||||
String zfpath = tr.zf.getPath();
|
||||
if(!toprocess.containsKey(zfpath)) {
|
||||
toprocess.put(zfpath, tr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* Else, classic file layout */
|
||||
for(String pfx : maptab.keySet()) { /* Walk through prefixes, as directories */
|
||||
cnt += processZoomDirectory(worldtilepath, maptab.get(pfx));
|
||||
/* Do processing */
|
||||
for(ProcessTileRec s : toprocess.values()) {
|
||||
if(cancelled) return true;
|
||||
processZoomTile(s.pd, s.zf, s.zfname, s.x, s.y);
|
||||
}
|
||||
}
|
||||
Debug.debug("freshenZoomOutFiles(" + world.getName() + "," + zoomlevel + ") - done (" + cnt + " updated files)");
|
||||
/* Return true when we have none left at the level */
|
||||
return (maptab.size() == 0);
|
||||
}
|
||||
|
||||
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) {
|
||||
/* If level is above top needed for this map, skip */
|
||||
if(zoomlevel > (this.extrazoomoutlevels + mt.getMapZoomOutLevels()))
|
||||
continue;
|
||||
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;
|
||||
boolean neg_step_y = false;
|
||||
switch(mt.zoomFileMapStep()) {
|
||||
case X_PLUS_Y_PLUS:
|
||||
break;
|
||||
case X_MINUS_Y_PLUS:
|
||||
neg_step_x = true;
|
||||
break;
|
||||
case X_PLUS_Y_MINUS:
|
||||
neg_step_y = true;
|
||||
break;
|
||||
case X_MINUS_Y_MINUS:
|
||||
neg_step_x = neg_step_y = true;
|
||||
break;
|
||||
}
|
||||
int[] stepseq = mt.zoomFileStepSequence();
|
||||
for(String p : pfx) {
|
||||
PrefixData pd = new PrefixData();
|
||||
pd.stepsize = stepsize;
|
||||
pd.neg_step_x = neg_step_x;
|
||||
pd.neg_step_y = neg_step_y;
|
||||
pd.stepseq = stepseq;
|
||||
pd.baseprefix = p;
|
||||
pd.zoomlevel = zoomlevel;
|
||||
pd.zoomprefix = "zzzzzzzzzzzz".substring(0, zoomlevel);
|
||||
pd.zoomprefix = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz".substring(0, zoomlevel);
|
||||
pd.bigworldshift = bigworldshift;
|
||||
if(bigworld) {
|
||||
pd.isbigmap = mt.isBigWorldMap(this);
|
||||
if(pd.isbigmap) {
|
||||
if(zoomlevel > 0) {
|
||||
pd.zoomprefix += "_";
|
||||
pd.zfnprefix = "z" + pd.zoomprefix;
|
||||
@@ -191,10 +277,11 @@ public class DynmapWorld {
|
||||
File zf;
|
||||
String zfname;
|
||||
int x, y;
|
||||
PrefixData pd;
|
||||
}
|
||||
|
||||
private String makeFilePath(PrefixData pd, int x, int y, boolean zoomed) {
|
||||
if(bigworld)
|
||||
if(pd.isbigmap)
|
||||
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";
|
||||
@@ -218,7 +305,7 @@ public class DynmapWorld {
|
||||
int cnt = 0;
|
||||
/* Do processing */
|
||||
for(ProcessTileRec s : toprocess.values()) {
|
||||
processZoomTile(pd, dir, s.zf, s.zfname, s.x, s.y);
|
||||
processZoomTile(s.pd, s.zf, s.zfname, s.x, s.y);
|
||||
cnt++;
|
||||
}
|
||||
Debug.debug("processZoomDirectory(" + dir.getPath() + "," + pd.baseprefix + ") - done (" + cnt + " files)");
|
||||
@@ -255,10 +342,12 @@ public class DynmapWorld {
|
||||
else
|
||||
x = x + (x % (2*step));
|
||||
if(pd.neg_step_x) x = -x;
|
||||
if(pd.neg_step_y) y = -y;
|
||||
if(y >= 0)
|
||||
y = y - (y % (2*step));
|
||||
else
|
||||
y = y + (y % (2*step));
|
||||
if(pd.neg_step_y) y = -y;
|
||||
/* Make name of corresponding zoomed tile */
|
||||
String zfname = makeFilePath(pd, x, y, true);
|
||||
File zf = new File(worldtilepath, zfname);
|
||||
@@ -273,22 +362,25 @@ public class DynmapWorld {
|
||||
rec.x = x;
|
||||
rec.y = y;
|
||||
rec.zfname = zfname;
|
||||
rec.pd = pd;
|
||||
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 + ")");
|
||||
private void processZoomTile(PrefixData pd, File zf, String zfname, int tx, int ty) {
|
||||
Debug.debug("processZoomFile(" + pd.baseprefix + "," + zf.getPath() + "," + tx + "," + ty + ")");
|
||||
int width = 128, height = 128;
|
||||
BufferedImage zIm = null;
|
||||
KzedBufferedImage kzIm = null;
|
||||
DynmapBufferedImage kzIm = null;
|
||||
int[] argb = new int[width*height];
|
||||
int step = pd.stepsize << pd.zoomlevel;
|
||||
int ztx = tx;
|
||||
int zty = ty;
|
||||
tx = tx - (pd.neg_step_x?step:0); /* Adjust for negative step */
|
||||
ty = ty - (pd.neg_step_y?step:0); /* Adjust for negative step */
|
||||
|
||||
/* create image buffer */
|
||||
kzIm = KzedMap.allocateBufferedImage(width, height);
|
||||
kzIm = DynmapBufferedImage.allocateBufferedImage(width, height);
|
||||
zIm = kzIm.buf_img;
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
@@ -308,24 +400,19 @@ public class DynmapWorld {
|
||||
im.getRGB(0, 0, width, height, argb, 0, width); /* Read data */
|
||||
im.flush();
|
||||
/* Do binlinear scale to 64x64 */
|
||||
Color c1 = new Color();
|
||||
int off = 0;
|
||||
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();
|
||||
off = y*width;
|
||||
for(int x = 0; x < width; x += 2, off += 2) {
|
||||
int p0 = argb[off];
|
||||
int p1 = argb[off+1];
|
||||
int p2 = argb[off+width];
|
||||
int p3 = argb[off+width+1];
|
||||
int alpha = ((p0 >> 24) & 0xFF) + ((p1 >> 24) & 0xFF) + ((p2 >> 24) & 0xFF) + ((p3 >> 24) & 0xFF);
|
||||
int red = ((p0 >> 16) & 0xFF) + ((p1 >> 16) & 0xFF) + ((p2 >> 16) & 0xFF) + ((p3 >> 16) & 0xFF);
|
||||
int green = ((p0 >> 8) & 0xFF) + ((p1 >> 8) & 0xFF) + ((p2 >> 8) & 0xFF) + ((p3 >> 8) & 0xFF);
|
||||
int blue = (p0 & 0xFF) + (p1 & 0xFF) + (p2 & 0xFF) + (p3 & 0xFF);
|
||||
argb[off>>1] = (((alpha>>2)&0xFF)<<24) | (((red>>2)&0xFF)<<16) | (((green>>2)&0xFF)<<8) | ((blue>>2)&0xFF);
|
||||
}
|
||||
}
|
||||
/* blit scaled rendered tile onto zoom-out tile */
|
||||
@@ -335,12 +422,15 @@ public class DynmapWorld {
|
||||
}
|
||||
FileLockManager.getWriteLock(zf);
|
||||
try {
|
||||
TileHashManager hashman = MapManager.mapman.hashman;
|
||||
MapManager mm = MapManager.mapman;
|
||||
if(mm == null)
|
||||
return;
|
||||
TileHashManager hashman = mm.hashman;
|
||||
long crc = hashman.calculateTileHash(kzIm.argb_buf); /* Get hash of tile */
|
||||
int tilex = ztx/step/2;
|
||||
int tiley = ty/step/2;
|
||||
int tiley = zty/step/2;
|
||||
String key = world.getName()+".z"+pd.zoomprefix+pd.baseprefix;
|
||||
if((!zf.exists()) || (crc != MapManager.mapman.hashman.getImageHashCode(key, null, tilex, tiley))) {
|
||||
if((!zf.exists()) || (crc != mm.hashman.getImageHashCode(key, null, tilex, tiley))) {
|
||||
try {
|
||||
if(!zf.getParentFile().exists())
|
||||
zf.getParentFile().mkdirs();
|
||||
@@ -357,7 +447,7 @@ public class DynmapWorld {
|
||||
}
|
||||
} finally {
|
||||
FileLockManager.releaseWriteLock(zf);
|
||||
KzedMap.freeBufferedImage(kzIm);
|
||||
DynmapBufferedImage.freeBufferedImage(kzIm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,31 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class Event<T> {
|
||||
private List<Listener<T>> listeners = new LinkedList<Listener<T>>();
|
||||
private Object lock = new Object();
|
||||
|
||||
public synchronized void addListener(Listener<T> l) {
|
||||
listeners.add(l);
|
||||
public void addListener(Listener<T> l) {
|
||||
synchronized(lock) {
|
||||
listeners.add(l);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void removeListener(Listener<T> l) {
|
||||
listeners.remove(l);
|
||||
public void removeListener(Listener<T> l) {
|
||||
synchronized(lock) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void trigger(T t) {
|
||||
for (Listener<T> l : listeners) {
|
||||
public void trigger(T t) {
|
||||
ArrayList<Listener<T>> iterlist;
|
||||
synchronized(lock) {
|
||||
iterlist = new ArrayList<Listener<T>>(listeners);
|
||||
}
|
||||
for (Listener<T> l : iterlist) {
|
||||
l.triggered(t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,9 +45,11 @@ public class InternalClientUpdateComponent extends ClientUpdateComponent {
|
||||
}
|
||||
|
||||
protected void webChat(String name, String message) {
|
||||
if(plugin.mapManager == null)
|
||||
return;
|
||||
// TODO: Change null to something meaningful.
|
||||
plugin.mapManager.pushUpdate(new Client.ChatMessage("web", null, name, message, null));
|
||||
Log.info(plugin.configuration.getString("webprefix", "\u00A72[WEB] ") + name + ": " + plugin.configuration.getString("websuffix", "\u00A7f") + message);
|
||||
Log.info(unescapeString(plugin.configuration.getString("webprefix", "\u00A72[WEB] ")) + name + ": " + unescapeString(plugin.configuration.getString("websuffix", "\u00A7f")) + message);
|
||||
ChatEvent event = new ChatEvent("web", name, message);
|
||||
plugin.events.trigger("webchat", event);
|
||||
}
|
||||
|
||||
@@ -22,8 +22,6 @@ import static org.dynmap.JSONUtils.*;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||
protected TimerTask task;
|
||||
protected Timer timer;
|
||||
protected long jsonInterval;
|
||||
protected long currentTimestamp = 0;
|
||||
protected long lastTimestamp = 0;
|
||||
@@ -39,7 +37,7 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||
final boolean allowwebchat = configuration.getBoolean("allowwebchat", false);
|
||||
jsonInterval = (long)(configuration.getFloat("writeinterval", 1) * 1000);
|
||||
hidewebchatip = configuration.getBoolean("hidewebchatip", false);
|
||||
task = new TimerTask() {
|
||||
MapManager.scheduleDelayedJob(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
currentTimestamp = System.currentTimeMillis();
|
||||
@@ -48,15 +46,17 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||
handleWebChat();
|
||||
}
|
||||
lastTimestamp = currentTimestamp;
|
||||
}
|
||||
};
|
||||
timer = new Timer();
|
||||
timer.scheduleAtFixedRate(task, jsonInterval, jsonInterval);
|
||||
MapManager.scheduleDelayedJob(this, jsonInterval);
|
||||
}}, jsonInterval);
|
||||
|
||||
plugin.events.addListener("buildclientconfiguration", new Event.Listener<JSONObject>() {
|
||||
@Override
|
||||
public void triggered(JSONObject t) {
|
||||
s(t, "jsonfile", true);
|
||||
s(t, "allowwebchat", allowwebchat);
|
||||
|
||||
// For 'sendmessage.php'
|
||||
s(t, "webchat-interval", configuration.getFloat("webchat-interval", 5.0f));
|
||||
}
|
||||
});
|
||||
plugin.events.addListener("initialized", new Event.Listener<Object>() {
|
||||
@@ -81,6 +81,7 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||
return new File(plugin.getDataFolder(), webpath.toString());
|
||||
}
|
||||
|
||||
private static final int RETRY_LIMIT = 5;
|
||||
protected void writeConfiguration() {
|
||||
File outputFile;
|
||||
File outputTempFile;
|
||||
@@ -88,17 +89,27 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||
plugin.events.trigger("buildclientconfiguration", clientConfiguration);
|
||||
outputFile = getStandaloneFile("dynmap_config.json");
|
||||
outputTempFile = getStandaloneFile("dynmap_config.json.new");
|
||||
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(outputTempFile);
|
||||
fos.write(clientConfiguration.toJSONString().getBytes("UTF-8"));
|
||||
fos.close();
|
||||
outputFile.delete();
|
||||
outputTempFile.renameTo(outputFile);
|
||||
} catch (FileNotFoundException ex) {
|
||||
Log.severe("Exception while writing JSON-configuration-file.", ex);
|
||||
} catch (IOException ioe) {
|
||||
Log.severe("Exception while writing JSON-configuration-file.", ioe);
|
||||
|
||||
int retrycnt = 0;
|
||||
boolean done = false;
|
||||
while(!done) {
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(outputTempFile);
|
||||
fos.write(clientConfiguration.toJSONString().getBytes("UTF-8"));
|
||||
fos.close();
|
||||
outputFile.delete();
|
||||
outputTempFile.renameTo(outputFile);
|
||||
done = true;
|
||||
} catch (IOException ioe) {
|
||||
if(retrycnt < RETRY_LIMIT) {
|
||||
try { Thread.sleep(20 * (1 << retrycnt)); } catch (InterruptedException ix) {}
|
||||
retrycnt++;
|
||||
}
|
||||
else {
|
||||
Log.severe("Exception while writing JSON-configuration-file.", ioe);
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,6 +117,7 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||
protected void writeUpdates() {
|
||||
File outputFile;
|
||||
File outputTempFile;
|
||||
if(plugin.mapManager == null) return;
|
||||
//Handles Updates
|
||||
for (DynmapWorld dynmapWorld : plugin.mapManager.getWorlds()) {
|
||||
World world = dynmapWorld.world;
|
||||
@@ -117,16 +129,26 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||
|
||||
outputFile = getStandaloneFile("dynmap_" + world.getName() + ".json");
|
||||
outputTempFile = getStandaloneFile("dynmap_" + world.getName() + ".json.new");
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(outputTempFile);
|
||||
fos.write(Json.stringifyJson(update).getBytes("UTF-8"));
|
||||
fos.close();
|
||||
outputFile.delete();
|
||||
outputTempFile.renameTo(outputFile);
|
||||
} catch (FileNotFoundException ex) {
|
||||
Log.severe("Exception while writing JSON-file.", ex);
|
||||
} catch (IOException ioe) {
|
||||
Log.severe("Exception while writing JSON-file.", ioe);
|
||||
int retrycnt = 0;
|
||||
boolean done = false;
|
||||
while(!done) {
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(outputTempFile);
|
||||
fos.write(Json.stringifyJson(update).getBytes("UTF-8"));
|
||||
fos.close();
|
||||
outputFile.delete();
|
||||
outputTempFile.renameTo(outputFile);
|
||||
done = true;
|
||||
} catch (IOException ioe) {
|
||||
if(retrycnt < RETRY_LIMIT) {
|
||||
try { Thread.sleep(20 * (1 << retrycnt)); } catch (InterruptedException ix) {}
|
||||
retrycnt++;
|
||||
}
|
||||
else {
|
||||
Log.severe("Exception while writing JSON-file.", ioe);
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
plugin.events.<ClientUpdateEvent>trigger("clientupdatewritten", clientUpdate);
|
||||
}
|
||||
@@ -174,9 +196,10 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||
}
|
||||
|
||||
protected void webChat(String name, String message) {
|
||||
if(plugin.mapManager == null) return;
|
||||
// TODO: Change null to something meaningful.
|
||||
plugin.mapManager.pushUpdate(new Client.ChatMessage("web", null, name, message, null));
|
||||
Log.info(plugin.configuration.getString("webprefix", "\u00A2[WEB] ") + name + ": " + plugin.configuration.getString("websuffix", "\u00A7f") + message);
|
||||
Log.info(unescapeString(plugin.configuration.getString("webprefix", "\u00A2[WEB] ")) + name + ": " + unescapeString(plugin.configuration.getString("websuffix", "\u00A7f")) + message);
|
||||
ChatEvent event = new ChatEvent("web", name, message);
|
||||
plugin.events.trigger("webchat", event);
|
||||
}
|
||||
@@ -184,6 +207,5 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
timer.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,18 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.dynmap.kzedmap.MapTileRenderer;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
|
||||
public abstract class MapTile {
|
||||
protected DynmapWorld world;
|
||||
private MapType map;
|
||||
|
||||
public abstract boolean render(MapChunkCache cache);
|
||||
public abstract List<DynmapChunk> getRequiredChunks();
|
||||
public abstract MapTile[] getAdjecentTiles();
|
||||
|
||||
public World getWorld() {
|
||||
return world.world;
|
||||
@@ -14,17 +22,12 @@ public abstract class MapTile {
|
||||
return world;
|
||||
}
|
||||
|
||||
public MapType getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public abstract String getFilename();
|
||||
|
||||
public abstract String getDayFilename();
|
||||
|
||||
public MapTile(DynmapWorld world, MapType map) {
|
||||
public MapTile(DynmapWorld world) {
|
||||
this.world = world;
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -41,7 +44,11 @@ public abstract class MapTile {
|
||||
return super.equals(obj);
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return world.world.getName() + "." + map.getName();
|
||||
}
|
||||
public abstract String getKey();
|
||||
|
||||
public abstract boolean isBiomeDataNeeded();
|
||||
public abstract boolean isHightestBlockYDataNeeded();
|
||||
public abstract boolean isRawBiomeDataNeeded();
|
||||
public abstract boolean isBlockTypeDataNeeded();
|
||||
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@ import org.dynmap.utils.MapChunkCache;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public abstract class MapType {
|
||||
public Event<MapTile> onTileInvalidated = new Event<MapTile>();
|
||||
|
||||
public abstract MapTile[] getTiles(Location l);
|
||||
|
||||
public abstract MapTile[] getAdjecentTiles(MapTile tile);
|
||||
@@ -18,21 +16,31 @@ public abstract class MapType {
|
||||
|
||||
public abstract boolean render(MapChunkCache cache, MapTile tile, File outputFile);
|
||||
|
||||
public void buildClientConfiguration(JSONObject worldObject) {
|
||||
public void buildClientConfiguration(JSONObject worldObject, DynmapWorld w) {
|
||||
}
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
/* Get maps rendered concurrently with this map in this world */
|
||||
public abstract List<MapType> getMapsSharingRender(DynmapWorld w);
|
||||
/* Get names of maps rendered concurrently with this map type in this world */
|
||||
public abstract List<String> getMapNamesSharingRender(DynmapWorld w);
|
||||
|
||||
public boolean isBiomeDataNeeded() { return false; }
|
||||
public boolean isHightestBlockYDataNeeded() { return false; }
|
||||
public boolean isRawBiomeDataNeeded() { return false; }
|
||||
public boolean isBlockTypeDataNeeded() { return true; }
|
||||
|
||||
public enum MapStep {
|
||||
X_PLUS_Y_PLUS,
|
||||
X_PLUS_Y_MINUS,
|
||||
X_MINUS_Y_PLUS,
|
||||
X_MINUS_Y_MINUS
|
||||
}
|
||||
public abstract MapStep zoomFileMapStep();
|
||||
public abstract List<String> baseZoomFilePrefixes();
|
||||
public abstract int baseZoomFileStepSize();
|
||||
/* How many bits of coordinate are shifted off to make big world directory name */
|
||||
public abstract int getBigWorldShift();
|
||||
|
||||
/* Returns true if big world file structure is in effect for this map */
|
||||
public abstract boolean isBigWorldMap(DynmapWorld w);
|
||||
/* Return number of zoom levels needed by this map (before extra levels from extrazoomout) */
|
||||
public int getMapZoomOutLevels() { return 0; }
|
||||
/**
|
||||
* Step sequence for creating zoomed file: first index is top-left, second top-right, third bottom-left, forth bottom-right
|
||||
* Values correspond to tile X,Y (0), X+step,Y (1), X,Y+step (2), X+step,Y+step (3)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user