mirror of
https://github.com/webbukkit/dynmap.git
synced 2024-11-28 05:05:16 +01:00
Finish split of dynmap and DynmapCore
This commit is contained in:
parent
aa5d73ea09
commit
fc319a2d32
60
build.xml
60
build.xml
@ -1,60 +0,0 @@
|
||||
<project name="dynmap" default="dist" basedir=".">
|
||||
<property name="bukkit.jar" location="C:\Users\Bob\Desktop\minecraft_server\bukkit-0.0.1-SNAPSHOT.jar"/>
|
||||
<property name="minecraft" location="C:\Users\Bob\Desktop\minecraft_server"/>
|
||||
<property name="plugins" location="${minecraft}/plugins/"/>
|
||||
<property name="http_root" location="/srv/http/dynmap/"/>
|
||||
<property name="pluginname" value="dynmap"/>
|
||||
|
||||
<property name="src" location="src"/>
|
||||
<property name="bin" location="bin"/>
|
||||
<property name="dist" location="dist"/>
|
||||
|
||||
<target name="init">
|
||||
<mkdir dir="${bin}"/>
|
||||
</target>
|
||||
|
||||
<target name="compile" depends="init">
|
||||
<javac srcdir="${src}/main/java" destdir="${bin}" classpath="${bukkit.jar}" debug="on" includeantruntime="false" />
|
||||
</target>
|
||||
|
||||
<target name="dist" depends="compile">
|
||||
<mkdir dir="${dist}"/>
|
||||
<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>
|
||||
|
||||
<target name="deploy" depends="dist">
|
||||
<copy file="${dist}/${pluginname}.jar" todir="${plugins}"/>
|
||||
<copy todir="${http_root}">
|
||||
<fileset dir="web"/>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="release" depends="dist">
|
||||
<delete file="${pluginname}.zip"/>
|
||||
<zip destfile="${pluginname}.zip">
|
||||
<zipfileset dir="." includes="README.md" fullpath="readme.txt"/>
|
||||
<zipfileset dir="." includes="build.xml"/>
|
||||
<zipfileset dir="${dist}" includes="*.jar"/>
|
||||
<zipfileset dir="${src}" includes="*.java" prefix="src/"/>
|
||||
<zipfileset dir="${web}" includes="**" prefix="web/"/>
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
<target name="clean">
|
||||
<delete dir="${bin}"/>
|
||||
<delete dir="${dist}"/>
|
||||
</target>
|
||||
</project>
|
@ -1,6 +0,0 @@
|
||||
<project name="dynmap_parameters" basedir=".">
|
||||
<property name="bukkit.jar" location="../../bukkit.jar"/>
|
||||
<property name="minecraft" location="../../"/>
|
||||
<property name="plugins" location="${minecraft}/plugins/"/>
|
||||
<property name="http_root" location="/srv/http/dynmap/"/>
|
||||
</project>
|
@ -1,340 +0,0 @@
|
||||
Stone
|
||||
1 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Grass
|
||||
2 117 176 73 255 93 140 58 255 58 88 36 255 46 70 29 255
|
||||
Dirt
|
||||
3 134 96 67 255 107 76 53 255 67 48 33 255 53 38 26 255
|
||||
Cobblestone
|
||||
4 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Wooden Plank
|
||||
5 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255
|
||||
Sapling
|
||||
6 120 120 120 0 96 96 96 0 60 60 60 0 48 48 48 0
|
||||
Bedrock
|
||||
7 84 84 84 255 67 67 67 255 42 42 42 255 33 33 33 255
|
||||
Water
|
||||
8 38 92 255 51 30 73 204 51 19 46 127 51 15 36 102 51
|
||||
Stationary Water
|
||||
9 38 92 255 51 30 73 204 51 19 46 127 51 15 36 102 51
|
||||
Lava
|
||||
10 255 90 0 255 204 72 0 255 127 45 0 255 102 36 0 255
|
||||
Stationary Lava
|
||||
11 255 90 0 255 204 72 0 255 127 45 0 255 102 36 0 255
|
||||
Sand
|
||||
12 218 210 158 255 174 168 126 255 109 105 79 255 87 84 63 255
|
||||
Gravel
|
||||
13 136 126 126 255 108 100 100 255 68 63 63 255 54 50 50 255
|
||||
Gold Ore
|
||||
14 143 140 125 255 114 112 100 255 71 70 62 255 57 56 50 255
|
||||
Iron Ore
|
||||
15 136 130 127 255 108 104 101 255 68 65 63 255 54 52 50 255
|
||||
Coal Ore
|
||||
16 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Wood - Normal
|
||||
17 102 81 51 255 125 102 63 255 78 64 39 255 40 32 20 255
|
||||
17:0 102 81 51 255 125 102 63 255 78 64 39 255 40 32 20 255
|
||||
Wood - Spruce (Red/dark wood)
|
||||
17:1 75 44 24 255 125 102 63 255 78 64 39 255 30 18 10 255
|
||||
Wood - Birch (light wood)
|
||||
17:2 191 191 191 255 125 102 63 255 78 64 39 255 76 76 76 255
|
||||
Leaves
|
||||
18 60 192 41 100 48 153 32 100 30 96 20 100 24 76 16 100
|
||||
Sponge
|
||||
19 193 193 65 255 174 174 47 255 97 97 5 255 76 76 20 255
|
||||
Glass
|
||||
20 255 255 255 64 204 204 204 64 127 127 127 64 102 102 102 64
|
||||
Lapis Lazuli Ore
|
||||
21 23 68 196 255 18 56 158 255 14 43 122 255 14 43 78 255
|
||||
Lapis Lazuli Block
|
||||
22 23 68 196 255 18 56 158 255 14 43 122 255 14 43 78 255
|
||||
Dispenser
|
||||
23 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255
|
||||
Sandstone
|
||||
24 218 210 158 255 174 168 126 255 109 105 79 255 87 84 63 255
|
||||
Note Block
|
||||
25 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
|
||||
Bed
|
||||
26 200 20 20 255 160 16 16 255 100 10 10 255 80 8 8 255
|
||||
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
|
||||
Wool - Orange
|
||||
35:1 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
|
||||
Wool - Magenta
|
||||
35:2 166 66 175 255 133 53 140 255 83 33 87 255 66 26 69 255
|
||||
Wool - Light Blue
|
||||
35:3 91 121 185 255 73 96 147 255 46 61 92 255 36 48 73 255
|
||||
Wool - Yellow
|
||||
35:4 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
|
||||
Wool - Light Green
|
||||
35:5 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
|
||||
Wool - Pink
|
||||
35:6 190 115 135 255 151 92 108 255 95 57 67 255 75 46 53 255
|
||||
Wool - Gray
|
||||
35:7 58 58 58 255 47 47 47 255 29 29 29 255 23 23 23 255
|
||||
Wool - Light Gray
|
||||
35:8 138 145 145 255 110 115 115 255 69 72 72 255 55 57 57 255
|
||||
Wool - Cyan
|
||||
35:9 34 102 131 255 27 81 104 255 17 51 65 255 13 40 52 255
|
||||
Wool - Purple
|
||||
35:10 113 47 171 255 90 37 136 255 57 24 85 255 45 19 68 255
|
||||
Wool - Blue
|
||||
35:11 34 44 134 255 27 35 107 255 17 22 67 255 13 18 53 255
|
||||
Wool - Brown
|
||||
35:12 75 44 24 255 60 35 19 255 37 22 12 255 30 18 10 255
|
||||
Wool - Dark Green
|
||||
35:13 49 67 21 255 39 53 17 255 24 34 10 255 19 27 8 255
|
||||
Wool - Red
|
||||
35:14 143 39 36 255 114 31 28 255 71 20 18 255 57 16 14 255
|
||||
Wool - Black
|
||||
35:15 24 20 20 255 19 16 16 255 12 10 10 255 9 8 8 255
|
||||
Yellow Flower
|
||||
37 255 255 0 255 204 204 0 255 127 127 0 255 102 102 0 255
|
||||
Red Rose
|
||||
38 255 0 0 255 204 0 0 255 127 0 0 255 102 0 0 255
|
||||
Brown Mushroom
|
||||
39 204 153 120 32 145 109 85 32 114 86 67 32 73 64 58 32
|
||||
Red Mushroom
|
||||
40 255 43 43 32 196 29 38 32 186 105 109 32 124 64 64 32
|
||||
Gold Block
|
||||
41 232 245 46 255 185 196 36 255 116 122 23 255 92 98 18 255
|
||||
Iron Block
|
||||
42 191 191 191 255 152 152 152 255 95 95 95 255 76 76 76 255
|
||||
Double Stone Slab
|
||||
43 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
43:0 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
43:6 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
Double Stone Slab - Sandstone
|
||||
43:1 218 210 158 255 174 168 126 255 109 105 79 255 87 84 63 255
|
||||
Double Stone Slab - Wood
|
||||
43:2 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255
|
||||
Double Stone Slab - Cobblestone
|
||||
43:3 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Double Stone Slab - Brick
|
||||
43:4 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255
|
||||
Double Stone Slab - Stone Brick
|
||||
43:5 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
Stone Slab
|
||||
44 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
44:0 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
44:6 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
Stone Slab - Sandstone
|
||||
44:1 218 210 158 255 174 168 126 255 109 105 79 255 87 84 63 255
|
||||
Stone Slab - Wood
|
||||
44:2 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255
|
||||
Stone Slab - Cobblestone
|
||||
44:3 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Stone Slab - Brick
|
||||
44:4 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255
|
||||
Stone Slab - Stone Brick
|
||||
44:5 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
Brick
|
||||
45 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255
|
||||
TNT
|
||||
46 160 83 65 255 128 66 52 255 80 41 32 255 64 33 26 255
|
||||
Bookshelf
|
||||
47 125 91 38 192 100 72 30 192 62 45 19 192 50 36 15 192
|
||||
Moss Stone
|
||||
48 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Obsidian
|
||||
49 26 11 43 255 20 8 34 255 13 5 21 255 10 4 17 255
|
||||
Torch
|
||||
50 159 127 80 255 98 88 20 0 245 220 50 255 196 176 40 0
|
||||
Fire
|
||||
51 255 170 30 200 204 136 24 200 127 85 15 200 102 68 12 200
|
||||
Monster Spawner
|
||||
52 0 150 110 196 0 150 130 196 0 150 110 196 0 150 130 196
|
||||
Wooden Stair
|
||||
53 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255
|
||||
53:4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
Chest
|
||||
54 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
|
||||
Redstone Wire
|
||||
55 240 30 30 64 160 20 20 64 120 15 15 64 100 12 12 64
|
||||
Diamond Ore
|
||||
56 129 140 143 255 103 112 114 255 64 70 71 255 51 56 57 255
|
||||
Diamond Block
|
||||
57 45 166 152 255 36 132 121 255 22 83 76 255 18 66 60 255
|
||||
Workbench
|
||||
58 114 88 56 255 91 70 44 255 57 44 28 255 45 35 22 255
|
||||
Crops
|
||||
59 146 192 0 255 116 153 0 255 73 96 0 255 58 76 0 255
|
||||
Farmland
|
||||
60 95 58 30 255 76 46 24 255 47 29 15 255 38 23 12 255
|
||||
Furnace
|
||||
61 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255
|
||||
Burning Furnace
|
||||
62 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255
|
||||
Sign Post
|
||||
63 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
|
||||
Wooden Door
|
||||
64 136 109 67 255 108 87 53 255 68 54 33 255 54 43 26 255
|
||||
Ladder
|
||||
65 181 140 64 32 144 112 51 32 90 70 32 32 72 56 25 32
|
||||
Minecart Tracks
|
||||
66 150 134 102 180 120 107 81 180 75 67 51 180 60 53 40 180
|
||||
Cobblestone Stairs
|
||||
67 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Wall Sign
|
||||
68 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
|
||||
Lever
|
||||
69 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
|
||||
Stone Pressure Plate
|
||||
70 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Iron Door
|
||||
71 191 191 191 255 152 152 152 255 95 95 95 255 76 76 76 255
|
||||
Wooden Pressure Plate
|
||||
72 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
|
||||
Redstone Ore
|
||||
73 131 107 107 255 104 85 85 255 65 53 53 255 52 42 42 255
|
||||
Glowing Redstone Ore
|
||||
74 131 107 107 255 104 85 85 255 65 53 53 255 52 42 42 255
|
||||
Redstone Torch off
|
||||
75 159 127 80 255 72 56 25 0 181 140 64 255 144 112 51 0
|
||||
Redstone Torch on
|
||||
76 159 127 80 255 102 0 0 0 255 0 0 255 204 0 0 0
|
||||
Stone Button
|
||||
77 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Snow
|
||||
78 255 255 255 255 204 204 204 255 127 127 127 255 102 102 102 255
|
||||
Ice
|
||||
79 83 113 163 51 66 90 130 51 41 56 81 51 33 45 65 51
|
||||
Snow Block
|
||||
80 250 250 250 255 200 200 200 255 125 125 125 255 100 100 100 255
|
||||
Cactus
|
||||
81 25 120 25 255 20 96 20 255 12 60 12 255 10 48 10 255
|
||||
Clay
|
||||
82 151 157 169 255 120 125 135 255 75 78 84 255 60 62 67 255
|
||||
Sugar Cane
|
||||
83 193 234 150 255 154 187 120 255 96 117 75 255 77 93 60 255
|
||||
Jukebox
|
||||
84 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
|
||||
Fence
|
||||
85 127 98 49 96 95 72 33 96 48 34 9 96 32 21 21 96
|
||||
Pumpkin
|
||||
86 255 115 0 200 204 92 0 200 126 57 0 200 102 46 0 200
|
||||
Netherrack
|
||||
87 166 89 89 255 141 80 62 255 135 15 15 255 96 6 6 255
|
||||
Soulsand
|
||||
88 133 109 94 255 121 97 82 255 90 70 57 255 79 59 46 255
|
||||
Glowstone
|
||||
89 249 212 156 255 255 188 94 255 192 143 70 255 122 91 44 255
|
||||
Portal
|
||||
90 140 0 196 128 120 0 196 128 140 0 196 128 120 0 196 128
|
||||
Jack-o-lantern
|
||||
91 255 115 0 255 204 92 0 255 126 57 0 255 102 46 0 255
|
||||
Cake Block
|
||||
92 234 234 234 255 210 210 210 255 203 203 203 255 190 190 190 255
|
||||
Redstone Repeater off
|
||||
93 159 127 80 255 72 56 25 0 181 140 64 255 144 112 51 0
|
||||
Redstone Repeater on
|
||||
94 159 127 80 255 102 0 0 0 255 0 0 255 204 0 0 0
|
||||
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
|
||||
Stone - Sliverfish
|
||||
97 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Stone Brick
|
||||
98 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Huge Brown Mushroom
|
||||
99 204 153 120 255 145 109 85 255 114 86 67 255 73 64 58 255
|
||||
Huge Red Mushroom
|
||||
100 255 43 43 255 196 29 38 255 186 105 109 255 124 64 64 255
|
||||
Iron Bars
|
||||
101 191 191 191 96 152 152 152 96 95 95 95 96 76 76 76 96
|
||||
Glass Pane
|
||||
102 255 255 255 64 204 204 204 64 127 127 127 64 102 102 102 64
|
||||
Melon
|
||||
103 193 193 65 255 174 174 47 255 97 97 5 255 76 76 20 255
|
||||
Pumpkin Stem
|
||||
104 146 192 0 255 116 153 0 255 73 96 0 255 58 76 0 255
|
||||
Melon Stem
|
||||
105 146 192 0 255 116 153 0 255 73 96 0 255 58 76 0 255
|
||||
Vines
|
||||
106 60 192 41 100 48 153 32 100 30 96 20 100 24 76 16 100
|
||||
Fence Gate
|
||||
107 127 98 49 96 95 72 33 96 48 34 9 96 32 21 21 96
|
||||
Brick Stairs
|
||||
108 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255
|
||||
Stone Stairs
|
||||
109 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Mycelium
|
||||
110 110 98 104 255 88 78 83 255 55 49 52 255 44 39 42 255
|
||||
Lilly pad
|
||||
111 117 176 73 255 93 140 58 255 58 88 36 255 46 70 29 255
|
||||
Nether brick
|
||||
112 166 89 89 255 141 80 62 255 135 15 15 255 96 6 6 255
|
||||
Nether brick fence
|
||||
113 166 89 89 96 141 80 62 96 135 15 15 96 96 6 6 96
|
||||
Nether brick stairs
|
||||
114 166 89 89 255 141 80 62 255 135 15 15 255 96 6 6 255
|
||||
Nether Wart
|
||||
115 142 19 21 96 113 15 17 96 71 10 10 96 57 7 8 96
|
||||
Enchantment table
|
||||
116 88 23 22 255 29 10 16 255 17 7 10 255 15 5 8 255
|
||||
Brewing stand
|
||||
117 114 114 114 96 91 91 91 96 67 67 67 96 46 46 46 96
|
||||
Cauldron
|
||||
118 74 74 74 255 59 59 59 255 37 37 37 255 30 30 30 255
|
||||
Air portal
|
||||
119 26 11 43 255 20 8 34 255 13 5 21 255 10 4 17 255
|
||||
Air portal frame
|
||||
120 113 133 104 255 90 106 83 255 56 66 52 255 45 54 42 255
|
||||
White stone
|
||||
121 224 226 169 255 179 180 135 255 112 113 85 255 90 90 66 255
|
||||
Dragon Egg
|
||||
122 26 11 43 255 20 8 34 255 13 5 21 255 10 4 17 255
|
||||
Biome Mapping
|
||||
[RAINFOREST] 49 67 21 255 39 54 17 255 25 34 11 255 20 27 8 255
|
||||
[SWAMPLAND] 64 128 0 255 51 102 0 255 32 64 0 255 26 51 0 255
|
||||
[SEASONAL_FOREST] 51 165 42 255 41 132 34 255 26 83 21 255 20 66 17 255
|
||||
[FOREST] 0 128 64 255 0 102 51 255 0 64 32 255 0 51 26 255
|
||||
[SAVANNA] 58 58 58 255 46 46 46 255 29 29 29 255 23 23 23 255
|
||||
[SHRUBLAND] 170 158 24 255 136 126 19 255 85 79 12 255 68 63 10 255
|
||||
[TAIGA] 204 255 102 255 163 204 82 255 102 128 51 255 82 102 41 255
|
||||
[DESERT] 255 255 102 255 204 204 82 255 128 128 51 255 102 102 41 255
|
||||
[PLAINS] 255 204 102 255 204 163 82 255 128 102 51 255 102 82 41 255
|
||||
[ICE_DESERT] 26 33 103 255 21 26 82 255 13 17 52 255 10 13 41 255
|
||||
[TUNDRA] 222 222 222 255 178 178 178 255 111 111 111 255 89 89 89 255
|
||||
[HELL] 255 0 0 255 204 0 0 255 128 0 0 255 102 0 0 255
|
||||
[SKY] 102 204 255 255 82 163 204 255 51 102 128 255 41 82 102 255
|
||||
[OCEAN] 0 0 255 255 0 0 204 255 0 0 128 255 0 0 102 255
|
||||
[RIVER] 0 128 255 255 0 102 204 255 0 64 128 255 0 51 102 255
|
||||
[EXTREME_HILLS] 128 64 0 255 102 51 0 255 64 32 0 255 51 26 0 255
|
||||
[FROZEN_OCEAN] 102 255 204 255 82 204 163 255 51 128 102 255 41 102 82 255
|
||||
[FROZEN_RIVER] 102 102 255 255 82 82 204 255 51 51 128 255 41 41 102 255
|
||||
[ICE_PLAINS] 102 255 255 255 82 204 204 255 51 128 128 255 41 102 102 255
|
||||
[ICE_MOUNTAINS] 255 255 255 255 204 204 204 255 128 128 128 255 102 102 102 255
|
||||
[MUSHROOM_ISLAND] 255 111 207 255 204 89 166 255 128 56 104 255 102 44 83 255
|
||||
[MUSHROOM_SHORE] 255 0 128 255 204 0 102 255 128 0 64 255 102 0 51 255
|
||||
[BEACH] 255 206 75 255 230 185 68 255 255 206 75 255 179 144 53 255
|
||||
[DESERT_HILLS] 255 146 51 255 230 131 46 255 255 146 51 255 179 102 36 255
|
||||
[FOREST_HILLS] 0 162 100 255 0 146 90 255 0 162 100 255 0 113 70 255
|
||||
[TAIGA_HILLS] 178 212 117 255 160 191 105 255 178 212 117 255 125 148 82 255
|
||||
[SMALL_MOUNTAINS] 184 103 33 255 166 93 30 255 184 103 33 255 129 72 23 255
|
||||
Rainfall/Temperature Mapping
|
||||
[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
|
@ -1,340 +0,0 @@
|
||||
Stone
|
||||
1 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Grass
|
||||
2 60 113 17 255 50 94 14 255 42 79 12 255 50 94 14 255
|
||||
Dirt
|
||||
3 134 96 67 255 107 76 53 255 67 48 33 255 53 38 26 255
|
||||
Cobblestone
|
||||
4 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Wooden Plank
|
||||
5 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255
|
||||
Sapling
|
||||
6 120 120 120 0 96 96 96 0 60 60 60 0 48 48 48 0
|
||||
Bedrock
|
||||
7 84 84 84 255 67 67 67 255 42 42 42 255 33 33 33 255
|
||||
Water
|
||||
8 38 92 255 51 30 73 204 51 19 46 127 51 15 36 102 51
|
||||
Stationary Water
|
||||
9 38 92 255 51 30 73 204 51 19 46 127 51 15 36 102 51
|
||||
Lava
|
||||
10 255 90 0 255 204 72 0 255 127 45 0 255 102 36 0 255
|
||||
Stationary Lava
|
||||
11 255 90 0 255 204 72 0 255 127 45 0 255 102 36 0 255
|
||||
Sand
|
||||
12 218 210 158 255 174 168 126 255 109 105 79 255 87 84 63 255
|
||||
Gravel
|
||||
13 136 126 126 255 108 100 100 255 68 63 63 255 54 50 50 255
|
||||
Gold Ore
|
||||
14 143 140 125 255 114 112 100 255 71 70 62 255 57 56 50 255
|
||||
Iron Ore
|
||||
15 136 130 127 255 108 104 101 255 68 65 63 255 54 52 50 255
|
||||
Coal Ore
|
||||
16 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Wood - Normal
|
||||
17 102 81 51 255 125 102 63 255 78 64 39 255 40 32 20 255
|
||||
17:0 102 81 51 255 125 102 63 255 78 64 39 255 40 32 20 255
|
||||
Wood - Spruce (Red/dark wood)
|
||||
17:1 75 44 24 255 125 102 63 255 78 64 39 255 30 18 10 255
|
||||
Wood - Birch (light wood)
|
||||
17:2 191 191 191 255 125 102 63 255 78 64 39 255 76 76 76 255
|
||||
Leaves
|
||||
18 27 69 37 180 22 57 31 180 19 48 25 180 22 57 31 180
|
||||
Sponge
|
||||
19 193 193 65 255 174 174 47 255 97 97 5 255 76 76 20 255
|
||||
Glass
|
||||
20 255 255 255 64 204 204 204 64 127 127 127 64 102 102 102 64
|
||||
Lapis Lazuli Ore
|
||||
21 23 68 196 255 18 56 158 255 14 43 122 255 14 43 78 255
|
||||
Lapis Lazuli Block
|
||||
22 23 68 196 255 18 56 158 255 14 43 122 255 14 43 78 255
|
||||
Dispenser
|
||||
23 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255
|
||||
Sandstone
|
||||
24 192 178 110 255 160 148 92 255 134 124 77 255 160 148 92 255
|
||||
Note Block
|
||||
25 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
|
||||
Bed
|
||||
26 200 20 20 255 160 16 16 255 100 10 10 255 80 8 8 255
|
||||
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
|
||||
Wool - Orange
|
||||
35:1 227 128 52 255 224 126 51 255 187 105 42 255 224 126 51 255
|
||||
Wool - Magenta
|
||||
35:2 185 76 188 255 183 75 186 255 153 63 155 255 183 75 186 255
|
||||
Wool - Light Blue
|
||||
35:3 102 139 199 255 100 137 196 255 84 114 164 255 100 137 196 255
|
||||
Wool - Yellow
|
||||
35:4 189 181 26 255 187 178 26 255 156 149 22 255 187 178 26 255
|
||||
Wool - Light Green
|
||||
35:5 57 189 45 255 56 186 44 255 47 156 37 255 56 186 44 255
|
||||
Wool - Pink
|
||||
35:6 211 132 145 255 209 130 143 255 174 109 120 255 209 130 143 255
|
||||
Wool - Gray
|
||||
35:7 65 67 63 255 64 66 62 255 54 55 52 255 64 66 62 255
|
||||
Wool - Light Gray
|
||||
35:8 154 166 156 255 152 163 154 255 127 137 128 255 152 163 154 255
|
||||
Wool - Cyan
|
||||
35:9 38 117 141 255 37 115 139 255 31 96 116 255 37 115 139 255
|
||||
Wool - Purple
|
||||
35:10 126 54 184 255 124 53 181 255 104 44 151 255 124 53 181 255
|
||||
Wool - Blue
|
||||
35:11 38 51 144 255 37 50 143 255 31 42 119 255 37 50 143 255
|
||||
Wool - Brown
|
||||
35:12 83 51 26 255 82 50 26 255 69 42 22 255 82 50 26 255
|
||||
Wool - Dark Green
|
||||
35:13 54 77 22 255 54 76 22 255 45 63 19 255 54 76 22 255
|
||||
Wool - Red
|
||||
35:14 159 45 38 255 157 44 38 255 131 37 32 255 157 44 38 255
|
||||
Wool - Black
|
||||
35:15 26 23 22 255 26 23 21 255 22 19 18 255 26 23 21 255
|
||||
Yellow Flower
|
||||
37 255 255 0 255 204 204 0 255 127 127 0 255 102 102 0 255
|
||||
Red Rose
|
||||
38 255 0 0 255 204 0 0 255 127 0 0 255 102 0 0 255
|
||||
Brown Mushroom
|
||||
39 204 153 120 32 145 109 85 32 114 86 67 32 73 64 58 32
|
||||
Red Mushroom
|
||||
40 255 43 43 32 196 29 38 32 186 105 109 32 124 64 64 32
|
||||
Gold Block
|
||||
41 232 245 46 255 185 196 36 255 116 122 23 255 92 98 18 255
|
||||
Iron Block
|
||||
42 191 191 191 255 152 152 152 255 95 95 95 255 76 76 76 255
|
||||
Double Stone Slab
|
||||
43 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
43:0 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
43:6 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
Double Stone Slab - Sandstone
|
||||
43:1 192 178 110 255 160 148 92 255 134 124 77 255 160 148 92 255
|
||||
Double Stone Slab - Wood
|
||||
43:2 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255
|
||||
Double Stone Slab - Cobblestone
|
||||
43:3 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Double Stone Slab - Brick
|
||||
43:4 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255
|
||||
Double Stone Slab - Stone Brick
|
||||
43:5 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
Stone Slab
|
||||
44 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
44:0 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
44:6 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
Stone Slab - Sandstone
|
||||
44:1 192 178 110 255 160 148 92 255 134 124 77 255 160 148 92 255
|
||||
Stone Slab - Wood
|
||||
44:2 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255
|
||||
Stone Slab - Cobblestone
|
||||
44:3 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Stone Slab - Brick
|
||||
44:4 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255
|
||||
Stone Slab - Stone Brick
|
||||
44:5 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
Brick
|
||||
45 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255
|
||||
TNT
|
||||
46 160 83 65 255 128 66 52 255 80 41 32 255 64 33 26 255
|
||||
Bookshelf
|
||||
47 125 91 38 192 100 72 30 192 62 45 19 192 50 36 15 192
|
||||
Moss Stone
|
||||
48 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Obsidian
|
||||
49 26 11 43 255 20 8 34 255 13 5 21 255 10 4 17 255
|
||||
Torch
|
||||
50 159 127 80 255 98 88 20 0 245 220 50 255 196 176 40 0
|
||||
Fire
|
||||
51 255 170 30 200 204 136 24 200 127 85 15 200 102 68 12 200
|
||||
Monster Spawner
|
||||
52 0 150 110 196 0 150 130 196 0 150 110 196 0 150 130 196
|
||||
Wooden Stair
|
||||
53 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255
|
||||
53:4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
Chest
|
||||
54 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
|
||||
Redstone Wire
|
||||
55 240 30 30 64 160 20 20 64 120 15 15 64 100 12 12 64
|
||||
Diamond Ore
|
||||
56 129 140 143 255 103 112 114 255 64 70 71 255 51 56 57 255
|
||||
Diamond Block
|
||||
57 45 166 152 255 36 132 121 255 22 83 76 255 18 66 60 255
|
||||
Workbench
|
||||
58 114 88 56 255 91 70 44 255 57 44 28 255 45 35 22 255
|
||||
Crops
|
||||
59 146 192 0 255 116 153 0 255 73 96 0 255 58 76 0 255
|
||||
Farmland
|
||||
60 95 58 30 255 76 46 24 255 47 29 15 255 38 23 12 255
|
||||
Furnace
|
||||
61 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255
|
||||
Burning Furnace
|
||||
62 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255
|
||||
Sign Post
|
||||
63 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
|
||||
Wooden Door
|
||||
64 136 109 67 255 108 87 53 255 68 54 33 255 54 43 26 255
|
||||
Ladder
|
||||
65 181 140 64 32 144 112 51 32 90 70 32 32 72 56 25 32
|
||||
Minecart Tracks
|
||||
66 150 134 102 180 120 107 81 180 75 67 51 180 60 53 40 180
|
||||
Cobblestone Stairs
|
||||
67 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Wall Sign
|
||||
68 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
|
||||
Lever
|
||||
69 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
|
||||
Stone Pressure Plate
|
||||
70 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Iron Door
|
||||
71 191 191 191 255 152 152 152 255 95 95 95 255 76 76 76 255
|
||||
Wooden Pressure Plate
|
||||
72 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
|
||||
Redstone Ore
|
||||
73 131 107 107 255 104 85 85 255 65 53 53 255 52 42 42 255
|
||||
Glowing Redstone Ore
|
||||
74 131 107 107 255 104 85 85 255 65 53 53 255 52 42 42 255
|
||||
Redstone Torch off
|
||||
75 159 127 80 255 72 56 25 0 181 140 64 255 144 112 51 0
|
||||
Redstone Torch on
|
||||
76 159 127 80 255 102 0 0 0 255 0 0 255 204 0 0 0
|
||||
Stone Button
|
||||
77 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Snow
|
||||
78 255 255 255 255 204 204 204 255 127 127 127 255 102 102 102 255
|
||||
Ice
|
||||
79 83 113 163 51 66 90 130 51 41 56 81 51 33 45 65 51
|
||||
Snow Block
|
||||
80 250 250 250 255 200 200 200 255 125 125 125 255 100 100 100 255
|
||||
Cactus
|
||||
81 25 120 25 255 20 96 20 255 12 60 12 255 10 48 10 255
|
||||
Clay
|
||||
82 151 157 169 255 120 125 135 255 75 78 84 255 60 62 67 255
|
||||
Sugar Cane
|
||||
83 193 234 150 255 154 187 120 255 96 117 75 255 77 93 60 255
|
||||
Jukebox
|
||||
84 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
|
||||
Fence
|
||||
85 127 98 49 96 95 72 33 96 48 34 9 96 32 21 21 96
|
||||
Pumpkin
|
||||
86 255 115 0 200 204 92 0 200 126 57 0 200 102 46 0 200
|
||||
Netherrack
|
||||
87 166 89 89 255 141 80 62 255 135 15 15 255 96 6 6 255
|
||||
Soulsand
|
||||
88 133 109 94 255 121 97 82 255 90 70 57 255 79 59 46 255
|
||||
Glowstone
|
||||
89 249 212 156 255 255 188 94 255 192 143 70 255 122 91 44 255
|
||||
Portal
|
||||
90 140 0 196 128 120 0 196 128 140 0 196 128 120 0 196 128
|
||||
Jack-o-lantern
|
||||
91 255 115 0 255 204 92 0 255 126 57 0 255 102 46 0 255
|
||||
Cake Block
|
||||
92 234 234 234 255 210 210 210 255 203 203 203 255 190 190 190 255
|
||||
Redstone Repeater off
|
||||
93 159 127 80 255 72 56 25 0 181 140 64 255 144 112 51 0
|
||||
Redstone Repeater on
|
||||
94 159 127 80 255 102 0 0 0 255 0 0 255 204 0 0 0
|
||||
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
|
||||
Stone - Sliverfish
|
||||
97 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Stone Brick
|
||||
98 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Huge Brown Mushroom
|
||||
99 204 153 120 255 145 109 85 255 114 86 67 255 73 64 58 255
|
||||
Huge Red Mushroom
|
||||
100 255 43 43 255 196 29 38 255 186 105 109 255 124 64 64 255
|
||||
Iron Bars
|
||||
101 191 191 191 96 152 152 152 96 95 95 95 96 76 76 76 96
|
||||
Glass Pane
|
||||
102 255 255 255 64 204 204 204 64 127 127 127 64 102 102 102 64
|
||||
Melon
|
||||
103 193 193 65 255 174 174 47 255 97 97 5 255 76 76 20 255
|
||||
Pumpkin Stem
|
||||
104 146 192 0 255 116 153 0 255 73 96 0 255 58 76 0 255
|
||||
Melon Stem
|
||||
105 146 192 0 255 116 153 0 255 73 96 0 255 58 76 0 255
|
||||
Vines
|
||||
106 60 192 41 100 48 153 32 100 30 96 20 100 24 76 16 100
|
||||
Fence Gate
|
||||
107 127 98 49 96 95 72 33 96 48 34 9 96 32 21 21 96
|
||||
Brick Stairs
|
||||
108 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255
|
||||
Stone Stairs
|
||||
109 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Mycelium
|
||||
110 110 98 104 255 88 78 83 255 55 49 52 255 44 39 42 255
|
||||
Lilly pad
|
||||
111 117 176 73 255 93 140 58 255 58 88 36 255 46 70 29 255
|
||||
Nether brick
|
||||
112 166 89 89 255 141 80 62 255 135 15 15 255 96 6 6 255
|
||||
Nether brick fence
|
||||
113 166 89 89 96 141 80 62 96 135 15 15 96 96 6 6 96
|
||||
Nether brick stairs
|
||||
114 166 89 89 255 141 80 62 255 135 15 15 255 96 6 6 255
|
||||
Nether Wart
|
||||
115 142 19 21 96 113 15 17 96 71 10 10 96 57 7 8 96
|
||||
Enchantment table
|
||||
116 88 23 22 255 29 10 16 255 17 7 10 255 15 5 8 255
|
||||
Brewing stand
|
||||
117 114 114 114 96 91 91 91 96 67 67 67 96 46 46 46 96
|
||||
Cauldron
|
||||
118 74 74 74 255 59 59 59 255 37 37 37 255 30 30 30 255
|
||||
Air portal
|
||||
119 26 11 43 255 20 8 34 255 13 5 21 255 10 4 17 255
|
||||
Air portal frame
|
||||
120 113 133 104 255 90 106 83 255 56 66 52 255 45 54 42 255
|
||||
White stone
|
||||
121 224 226 169 255 179 180 135 255 112 113 85 255 90 90 66 255
|
||||
Dragon Egg
|
||||
122 26 11 43 255 20 8 34 255 13 5 21 255 10 4 17 255
|
||||
Biome Mapping
|
||||
[RAINFOREST] 49 67 21 255 39 54 17 255 25 34 11 255 20 27 8 255
|
||||
[SWAMPLAND] 64 128 0 255 51 102 0 255 32 64 0 255 26 51 0 255
|
||||
[SEASONAL_FOREST] 51 165 42 255 41 132 34 255 26 83 21 255 20 66 17 255
|
||||
[FOREST] 0 128 64 255 0 102 51 255 0 64 32 255 0 51 26 255
|
||||
[SAVANNA] 58 58 58 255 46 46 46 255 29 29 29 255 23 23 23 255
|
||||
[SHRUBLAND] 170 158 24 255 136 126 19 255 85 79 12 255 68 63 10 255
|
||||
[TAIGA] 204 255 102 255 163 204 82 255 102 128 51 255 82 102 41 255
|
||||
[DESERT] 255 255 102 255 204 204 82 255 128 128 51 255 102 102 41 255
|
||||
[PLAINS] 255 204 102 255 204 163 82 255 128 102 51 255 102 82 41 255
|
||||
[ICE_DESERT] 26 33 103 255 21 26 82 255 13 17 52 255 10 13 41 255
|
||||
[TUNDRA] 222 222 222 255 178 178 178 255 111 111 111 255 89 89 89 255
|
||||
[HELL] 255 0 0 255 204 0 0 255 128 0 0 255 102 0 0 255
|
||||
[SKY] 102 204 255 255 82 163 204 255 51 102 128 255 41 82 102 255
|
||||
[OCEAN] 0 0 255 255 0 0 204 255 0 0 128 255 0 0 102 255
|
||||
[RIVER] 0 128 255 255 0 102 204 255 0 64 128 255 0 51 102 255
|
||||
[EXTREME_HILLS] 128 64 0 255 102 51 0 255 64 32 0 255 51 26 0 255
|
||||
[FROZEN_OCEAN] 102 255 204 255 82 204 163 255 51 128 102 255 41 102 82 255
|
||||
[FROZEN_RIVER] 102 102 255 255 82 82 204 255 51 51 128 255 41 41 102 255
|
||||
[ICE_PLAINS] 102 255 255 255 82 204 204 255 51 128 128 255 41 102 102 255
|
||||
[ICE_MOUNTAINS] 255 255 255 255 204 204 204 255 128 128 128 255 102 102 102 255
|
||||
[MUSHROOM_ISLAND] 255 111 207 255 204 89 166 255 128 56 104 255 102 44 83 255
|
||||
[MUSHROOM_SHORE] 255 0 128 255 204 0 102 255 128 0 64 255 102 0 51 255
|
||||
[BEACH] 255 206 75 255 230 185 68 255 255 206 75 255 179 144 53 255
|
||||
[DESERT_HILLS] 255 146 51 255 230 131 46 255 255 146 51 255 179 102 36 255
|
||||
[FOREST_HILLS] 0 162 100 255 0 146 90 255 0 162 100 255 0 113 70 255
|
||||
[TAIGA_HILLS] 178 212 117 255 160 191 105 255 178 212 117 255 125 148 82 255
|
||||
[SMALL_MOUNTAINS] 184 103 33 255 166 93 30 255 184 103 33 255 129 72 23 255
|
||||
Rainfall/Temperature Mapping
|
||||
[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
|
@ -1,340 +0,0 @@
|
||||
Stone
|
||||
1 149 145 138 255 125 122 116 255 114 111 105 255 88 85 81 255
|
||||
Grass
|
||||
2 111 185 79 255 86 158 53 255 65 131 40 255 57 105 21 255
|
||||
Dirt
|
||||
3 174 133 106 255 152 113 82 255 136 102 74 255 93 73 57 255
|
||||
Cobblestone
|
||||
4 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Wooden Plank
|
||||
5 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255
|
||||
Sappling
|
||||
6 120 120 120 0 96 96 96 0 60 60 60 0 48 48 48 0
|
||||
Bedrock
|
||||
7 84 84 84 255 67 67 67 255 42 42 42 255 33 33 33 255
|
||||
Water
|
||||
8 47 116 160 80 40 100 138 80 33 92 129 80 26 74 103 80
|
||||
Stationary Water
|
||||
9 47 116 160 80 40 100 138 80 33 92 129 80 26 74 103 80
|
||||
Lava
|
||||
10 255 90 0 255 204 72 0 255 127 45 0 255 102 36 0 255
|
||||
Stationary Lava
|
||||
11 255 90 0 255 204 72 0 255 127 45 0 255 102 36 0 255
|
||||
Sand
|
||||
12 251 240 193 255 251 223 157 255 237 202 135 255 200 168 107 255
|
||||
Gravel
|
||||
13 136 126 126 255 108 100 100 255 68 63 63 255 54 50 50 255
|
||||
Gold Ore
|
||||
14 143 140 125 255 114 112 100 255 71 70 62 255 57 56 50 255
|
||||
Iron Ore
|
||||
15 136 130 127 255 108 104 101 255 68 65 63 255 54 52 50 255
|
||||
Coal Ore
|
||||
16 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Wood - Normal
|
||||
17 102 81 51 255 125 102 63 255 78 64 39 255 40 32 20 255
|
||||
17:0 102 81 51 255 125 102 63 255 78 64 39 255 40 32 20 255
|
||||
Wood - Spruce (Red/dark wood)
|
||||
17:1 75 44 24 255 125 102 63 255 78 64 39 255 30 18 10 255
|
||||
Wood - Birch (light wood)
|
||||
17:2 191 191 191 255 125 102 63 255 78 64 39 255 76 76 76 255
|
||||
Leaves
|
||||
18 47 99 32 255 34 86 20 255 24 66 14 255 23 57 13 255
|
||||
Sponge
|
||||
19 193 193 65 255 174 174 47 255 97 97 5 255 76 76 20 255
|
||||
Glass
|
||||
20 255 255 255 64 204 204 204 64 127 127 127 64 102 102 102 64
|
||||
Lapis Lazuli Ore
|
||||
21 23 68 196 255 18 56 158 255 14 43 122 255 14 43 78 255
|
||||
Lapis Lazuli Block
|
||||
22 23 68 196 255 18 56 158 255 14 43 122 255 14 43 78 255
|
||||
Dispenser
|
||||
23 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255
|
||||
Sandstone
|
||||
24 251 240 193 255 251 223 157 255 237 202 135 255 200 168 107 255
|
||||
Note Block
|
||||
25 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
|
||||
Bed
|
||||
26 200 20 20 255 160 16 16 255 100 10 10 255 80 8 8 255
|
||||
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
|
||||
Wool - Orange
|
||||
35:1 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
|
||||
Wool - Magenta
|
||||
35:2 166 66 175 255 133 53 140 255 83 33 87 255 66 26 69 255
|
||||
Wool - Light Blue
|
||||
35:3 91 121 185 255 73 96 147 255 46 61 92 255 36 48 73 255
|
||||
Wool - Yellow
|
||||
35:4 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
|
||||
Wool - Light Green
|
||||
35:5 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
|
||||
Wool - Pink
|
||||
35:6 190 115 135 255 151 92 108 255 95 57 67 255 75 46 53 255
|
||||
Wool - Gray
|
||||
35:7 58 58 58 255 47 47 47 255 29 29 29 255 23 23 23 255
|
||||
Wool - Light Gray
|
||||
35:8 138 145 145 255 110 115 115 255 69 72 72 255 55 57 57 255
|
||||
Wool - Cyan
|
||||
35:9 34 102 131 255 27 81 104 255 17 51 65 255 13 40 52 255
|
||||
Wool - Purple
|
||||
35:10 113 47 171 255 90 37 136 255 57 24 85 255 45 19 68 255
|
||||
Wool - Blue
|
||||
35:11 34 44 134 255 27 35 107 255 17 22 67 255 13 18 53 255
|
||||
Wool - Brown
|
||||
35:12 75 44 24 255 60 35 19 255 37 22 12 255 30 18 10 255
|
||||
Wool - Dark Green
|
||||
35:13 49 67 21 255 39 53 17 255 24 34 10 255 19 27 8 255
|
||||
Wool - Red
|
||||
35:14 143 39 36 255 114 31 28 255 71 20 18 255 57 16 14 255
|
||||
Wool - Black
|
||||
35:15 24 20 20 255 19 16 16 255 12 10 10 255 9 8 8 255
|
||||
Yellow Flower
|
||||
37 255 255 0 255 204 204 0 255 127 127 0 255 102 102 0 255
|
||||
Red Rose
|
||||
38 255 0 0 255 204 0 0 255 127 0 0 255 102 0 0 255
|
||||
Brown Mushroom
|
||||
39 204 153 120 32 145 109 85 32 114 86 67 32 73 64 58 32
|
||||
Red Mushroom
|
||||
40 255 43 43 32 196 29 38 32 186 105 109 32 124 64 64 32
|
||||
Gold Block
|
||||
41 232 245 46 255 185 196 36 255 116 122 23 255 92 98 18 255
|
||||
Iron Block
|
||||
42 191 191 191 255 152 152 152 255 95 95 95 255 76 76 76 255
|
||||
Double Stone Slab
|
||||
43 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
43:0 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
43:6 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
Double Stone Slab - Sandstone
|
||||
43:1 218 210 158 255 174 168 126 255 109 105 79 255 87 84 63 255
|
||||
Double Stone Slab - Wood
|
||||
43:2 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255
|
||||
Double Stone Slab - Cobblestone
|
||||
43:3 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Double Stone Slab - Brick
|
||||
43:4 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255
|
||||
Double Stone Slab - Stone Brick
|
||||
43:5 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
Stone Slab
|
||||
44 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
44:0 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
44:6 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
Stone Slab - Sandstone
|
||||
44:1 218 210 158 255 174 168 126 255 109 105 79 255 87 84 63 255
|
||||
Stone Slab - Wood
|
||||
44:2 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255
|
||||
Stone Slab - Cobblestone
|
||||
44:3 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Stone Slab - Brick
|
||||
44:4 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255
|
||||
Stone Slab - Stone Brick
|
||||
44:5 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
Brick
|
||||
45 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255
|
||||
TNT
|
||||
46 160 83 65 255 128 66 52 255 80 41 32 255 64 33 26 255
|
||||
Bookshelf
|
||||
47 125 91 38 192 100 72 30 192 62 45 19 192 50 36 15 192
|
||||
Moss Stone
|
||||
48 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Obsidian
|
||||
49 26 11 43 255 20 8 34 255 13 5 21 255 10 4 17 255
|
||||
Torch
|
||||
50 103 80 45 255 98 88 20 0 255 249 79 255 196 176 40 0
|
||||
Fire
|
||||
51 255 170 30 200 204 136 24 200 127 85 15 200 102 68 12 200
|
||||
Monster Spawner
|
||||
52 0 150 110 196 0 150 130 196 0 150 110 196 0 150 130 196
|
||||
Wooden Stair
|
||||
53 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255
|
||||
53:4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
Chest
|
||||
54 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
|
||||
Redstone Wire
|
||||
55 240 30 30 64 160 20 20 64 120 15 15 64 100 12 12 64
|
||||
Diamond Ore
|
||||
56 129 140 143 255 103 112 114 255 64 70 71 255 51 56 57 255
|
||||
Diamond Block
|
||||
57 45 166 152 255 36 132 121 255 22 83 76 255 18 66 60 255
|
||||
Workbench
|
||||
58 114 88 56 255 91 70 44 255 57 44 28 255 45 35 22 255
|
||||
Crops
|
||||
59 146 192 0 255 116 153 0 255 73 96 0 255 58 76 0 255
|
||||
Farmland
|
||||
60 95 58 30 255 76 46 24 255 47 29 15 255 38 23 12 255
|
||||
Furnace
|
||||
61 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255
|
||||
Burning Furnace
|
||||
62 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255
|
||||
Sign Post
|
||||
63 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
|
||||
Wooden Door
|
||||
64 136 109 67 255 108 87 53 255 68 54 33 255 54 43 26 255
|
||||
Ladder
|
||||
65 181 140 64 32 144 112 51 32 90 70 32 32 72 56 25 32
|
||||
Minecart Tracks
|
||||
66 150 134 102 180 120 107 81 180 75 67 51 180 60 53 40 180
|
||||
Cobblestone Stairs
|
||||
67 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255
|
||||
Wall Sign
|
||||
68 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
|
||||
Lever
|
||||
69 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
|
||||
Stone Pressure Plate
|
||||
70 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Iron Door
|
||||
71 191 191 191 255 152 152 152 255 95 95 95 255 76 76 76 255
|
||||
Wooden Pressure Plate
|
||||
72 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
|
||||
Redstone Ore
|
||||
73 131 107 107 255 104 85 85 255 65 53 53 255 52 42 42 255
|
||||
Glowing Redstone Ore
|
||||
74 131 107 107 255 104 85 85 255 65 53 53 255 52 42 42 255
|
||||
Redstone Torch off
|
||||
75 159 127 80 255 72 56 25 0 181 140 64 255 144 112 51 0
|
||||
Redstone Torch on
|
||||
76 159 127 80 255 102 0 0 0 255 0 0 255 204 0 0 0
|
||||
Stone Button
|
||||
77 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Snow
|
||||
78 255 255 255 255 252 253 253 255 198 220 225 255 129 179 190 255
|
||||
Ice
|
||||
79 182 211 235 150 164 189 211 150 138 177 211 150 128 165 196 150
|
||||
Snow Block
|
||||
80 250 250 250 255 200 200 200 255 125 125 125 255 100 100 100 255
|
||||
Cactus
|
||||
81 25 120 25 255 20 96 20 255 12 60 12 255 10 48 10 255
|
||||
Clay
|
||||
82 151 157 169 255 120 125 135 255 75 78 84 255 60 62 67 255
|
||||
Sugar Cane
|
||||
83 193 234 150 255 154 187 120 255 96 117 75 255 77 93 60 255
|
||||
Jukebox
|
||||
84 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
|
||||
Fence
|
||||
85 127 98 49 96 95 72 33 96 48 34 9 96 32 21 21 96
|
||||
Pumpkin
|
||||
86 255 115 0 200 204 92 0 200 126 57 0 200 102 46 0 200
|
||||
Netherrack
|
||||
87 166 89 89 255 141 80 62 255 135 15 15 255 96 6 6 255
|
||||
Soulsand
|
||||
88 133 109 94 255 121 97 82 255 90 70 57 255 79 59 46 255
|
||||
Glowstone
|
||||
89 249 212 156 255 255 188 94 255 192 143 70 255 122 91 44 255
|
||||
Portal
|
||||
90 140 0 196 128 120 0 196 128 140 0 196 128 120 0 196 128
|
||||
Jack-o-lantern
|
||||
91 255 115 0 255 204 92 0 255 126 57 0 255 102 46 0 255
|
||||
Cake Block
|
||||
92 234 234 234 255 210 210 210 255 203 203 203 255 190 190 190 255
|
||||
Redstone Repeater off
|
||||
93 159 127 80 255 72 56 25 0 181 140 64 255 144 112 51 0
|
||||
Redstone Repeater on
|
||||
94 159 127 80 255 102 0 0 0 255 0 0 255 204 0 0 0
|
||||
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
|
||||
Stone - Sliverfish
|
||||
97 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Stone Brick
|
||||
98 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Huge Brown Mushroom
|
||||
99 204 153 120 255 145 109 85 255 114 86 67 255 73 64 58 255
|
||||
Huge Red Mushroom
|
||||
100 255 43 43 255 196 29 38 255 186 105 109 255 124 64 64 255
|
||||
Iron Bars
|
||||
101 191 191 191 96 152 152 152 96 95 95 95 96 76 76 76 96
|
||||
Glass Pane
|
||||
102 255 255 255 64 204 204 204 64 127 127 127 64 102 102 102 64
|
||||
Melon
|
||||
103 193 193 65 255 174 174 47 255 97 97 5 255 76 76 20 255
|
||||
Pumpkin Stem
|
||||
104 146 192 0 255 116 153 0 255 73 96 0 255 58 76 0 255
|
||||
Melon Stem
|
||||
105 146 192 0 255 116 153 0 255 73 96 0 255 58 76 0 255
|
||||
Vines
|
||||
106 60 192 41 100 48 153 32 100 30 96 20 100 24 76 16 100
|
||||
Fence Gate
|
||||
107 127 98 49 96 95 72 33 96 48 34 9 96 32 21 21 96
|
||||
Brick Stairs
|
||||
108 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255
|
||||
Stone Stairs
|
||||
109 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
Mycelium
|
||||
110 110 98 104 255 88 78 83 255 55 49 52 255 44 39 42 255
|
||||
Lilly pad
|
||||
111 117 176 73 255 93 140 58 255 58 88 36 255 46 70 29 255
|
||||
Nether brick
|
||||
112 166 89 89 255 141 80 62 255 135 15 15 255 96 6 6 255
|
||||
Nether brick fence
|
||||
113 166 89 89 96 141 80 62 96 135 15 15 96 96 6 6 96
|
||||
Nether brick stairs
|
||||
114 166 89 89 255 141 80 62 255 135 15 15 255 96 6 6 255
|
||||
Nether Wart
|
||||
115 142 19 21 96 113 15 17 96 71 10 10 96 57 7 8 96
|
||||
Enchantment table
|
||||
116 88 23 22 255 29 10 16 255 17 7 10 255 15 5 8 255
|
||||
Brewing stand
|
||||
117 114 114 114 96 91 91 91 96 67 67 67 96 46 46 46 96
|
||||
Cauldron
|
||||
118 74 74 74 255 59 59 59 255 37 37 37 255 30 30 30 255
|
||||
Air portal
|
||||
119 26 11 43 255 20 8 34 255 13 5 21 255 10 4 17 255
|
||||
Air portal frame
|
||||
120 113 133 104 255 90 106 83 255 56 66 52 255 45 54 42 255
|
||||
White stone
|
||||
121 224 226 169 255 179 180 135 255 112 113 85 255 90 90 66 255
|
||||
Dragon Egg
|
||||
122 26 11 43 255 20 8 34 255 13 5 21 255 10 4 17 255
|
||||
Biome Mapping
|
||||
[RAINFOREST] 49 67 21 255 39 54 17 255 25 34 11 255 20 27 8 255
|
||||
[SWAMPLAND] 64 128 0 255 51 102 0 255 32 64 0 255 26 51 0 255
|
||||
[SEASONAL_FOREST] 51 165 42 255 41 132 34 255 26 83 21 255 20 66 17 255
|
||||
[FOREST] 0 128 64 255 0 102 51 255 0 64 32 255 0 51 26 255
|
||||
[SAVANNA] 58 58 58 255 46 46 46 255 29 29 29 255 23 23 23 255
|
||||
[SHRUBLAND] 170 158 24 255 136 126 19 255 85 79 12 255 68 63 10 255
|
||||
[TAIGA] 204 255 102 255 163 204 82 255 102 128 51 255 82 102 41 255
|
||||
[DESERT] 255 255 102 255 204 204 82 255 128 128 51 255 102 102 41 255
|
||||
[PLAINS] 255 204 102 255 204 163 82 255 128 102 51 255 102 82 41 255
|
||||
[ICE_DESERT] 26 33 103 255 21 26 82 255 13 17 52 255 10 13 41 255
|
||||
[TUNDRA] 222 222 222 255 178 178 178 255 111 111 111 255 89 89 89 255
|
||||
[HELL] 255 0 0 255 204 0 0 255 128 0 0 255 102 0 0 255
|
||||
[SKY] 102 204 255 255 82 163 204 255 51 102 128 255 41 82 102 255
|
||||
[OCEAN] 0 0 255 255 0 0 204 255 0 0 128 255 0 0 102 255
|
||||
[RIVER] 0 128 255 255 0 102 204 255 0 64 128 255 0 51 102 255
|
||||
[EXTREME_HILLS] 128 64 0 255 102 51 0 255 64 32 0 255 51 26 0 255
|
||||
[FROZEN_OCEAN] 102 255 204 255 82 204 163 255 51 128 102 255 41 102 82 255
|
||||
[FROZEN_RIVER] 102 102 255 255 82 82 204 255 51 51 128 255 41 41 102 255
|
||||
[ICE_PLAINS] 102 255 255 255 82 204 204 255 51 128 128 255 41 102 102 255
|
||||
[ICE_MOUNTAINS] 255 255 255 255 204 204 204 255 128 128 128 255 102 102 102 255
|
||||
[MUSHROOM_ISLAND] 255 111 207 255 204 89 166 255 128 56 104 255 102 44 83 255
|
||||
[MUSHROOM_SHORE] 255 0 128 255 204 0 102 255 128 0 64 255 102 0 51 255
|
||||
[BEACH] 255 206 75 255 230 185 68 255 255 206 75 255 179 144 53 255
|
||||
[DESERT_HILLS] 255 146 51 255 230 131 46 255 255 146 51 255 179 102 36 255
|
||||
[FOREST_HILLS] 0 162 100 255 0 146 90 255 0 162 100 255 0 113 70 255
|
||||
[TAIGA_HILLS] 178 212 117 255 160 191 105 255 178 212 117 255 125 148 82 255
|
||||
[SMALL_MOUNTAINS] 184 103 33 255 166 93 30 255 184 103 33 255 129 72 23 255
|
||||
Rainfall/Temperature Mapping
|
||||
[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
|
@ -1,191 +0,0 @@
|
||||
1 133 129 118 255 111 108 98 255 93 90 82 255 111 108 98 255
|
||||
2 60 113 17 255 50 94 14 255 42 79 12 255 50 94 14 255
|
||||
3 103 83 51 255 86 69 43 255 72 58 36 255 86 69 43 255
|
||||
4 118 112 96 255 98 93 80 255 82 78 67 255 98 93 80 255
|
||||
5 109 80 60 255 91 67 50 255 76 56 41 255 91 67 50 255
|
||||
7 79 79 82 255 66 66 68 255 55 55 57 255 66 66 68 255
|
||||
8 94 170 255 51 82 148 223 51 69 124 186 51 82 148 223 51
|
||||
9 94 170 255 51 82 148 223 51 69 124 186 51 82 148 223 51
|
||||
10 255 164 41 255 255 164 41 255 212 137 34 255 255 164 41 255
|
||||
11 255 164 41 255 255 164 41 255 212 137 34 255 255 164 41 255
|
||||
12 192 178 110 255 160 148 92 255 134 124 77 255 160 148 92 255
|
||||
13 120 105 79 255 100 87 66 255 84 73 55 255 100 87 66 255
|
||||
14 255 181 38 255 255 181 38 255 212 151 31 255 255 181 38 255
|
||||
15 231 174 113 255 193 145 94 255 161 121 79 255 193 145 94 255
|
||||
16 56 60 70 255 46 50 58 255 39 42 49 255 46 50 58 255
|
||||
17 119 97 74 255 99 81 62 255 83 68 52 255 99 81 62 255
|
||||
17:0 119 97 74 255 99 81 62 255 83 68 52 255 99 81 62 255
|
||||
17:1 75 44 24 255 125 102 63 255 78 64 39 255 30 18 10 255
|
||||
17:2 191 191 191 255 125 102 63 255 78 64 39 255 76 76 76 255
|
||||
18 27 69 37 180 22 57 31 180 19 48 25 180 22 57 31 180
|
||||
19 193 193 65 255 174 174 47 255 97 97 5 255 76 76 20 255
|
||||
20 178 217 223 90 148 181 186 90 124 151 155 90 148 181 186 90
|
||||
21 23 68 196 255 18 56 158 255 14 43 122 255 14 43 78 255
|
||||
22 23 68 196 255 18 56 158 255 14 43 122 255 14 43 78 255
|
||||
23 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255
|
||||
24 192 178 110 255 160 148 92 255 134 124 77 255 160 148 92 255
|
||||
25 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
|
||||
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
|
||||
35:2 185 76 188 255 183 75 186 255 153 63 155 255 183 75 186 255
|
||||
35:3 102 139 199 255 100 137 196 255 84 114 164 255 100 137 196 255
|
||||
35:4 189 181 26 255 187 178 26 255 156 149 22 255 187 178 26 255
|
||||
35:5 57 189 45 255 56 186 44 255 47 156 37 255 56 186 44 255
|
||||
35:6 211 132 145 255 209 130 143 255 174 109 120 255 209 130 143 255
|
||||
35:7 65 67 63 255 64 66 62 255 54 55 52 255 64 66 62 255
|
||||
35:8 154 166 156 255 152 163 154 255 127 137 128 255 152 163 154 255
|
||||
35:9 38 117 141 255 37 115 139 255 31 96 116 255 37 115 139 255
|
||||
35:10 126 54 184 255 124 53 181 255 104 44 151 255 124 53 181 255
|
||||
35:11 38 51 144 255 37 50 143 255 31 42 119 255 37 50 143 255
|
||||
35:12 83 51 26 255 82 50 26 255 69 42 22 255 82 50 26 255
|
||||
35:13 54 77 22 255 54 76 22 255 45 63 19 255 54 76 22 255
|
||||
35:14 159 45 38 255 157 44 38 255 131 37 32 255 157 44 38 255
|
||||
35:15 26 23 22 255 26 23 21 255 22 19 18 255 26 23 21 255
|
||||
37 73 108 60 254 61 90 50 254 51 75 42 254 61 90 50 254
|
||||
38 84 139 187 254 70 116 155 254 59 97 130 254 70 116 155 254
|
||||
39 184 144 0 254 153 119 0 254 128 100 0 254 153 119 0 254
|
||||
40 201 17 17 254 168 14 14 254 140 12 12 254 168 14 14 254
|
||||
41 247 255 239 255 244 251 236 255 204 210 197 255 244 251 236 255
|
||||
42 249 249 249 255 207 207 207 255 173 173 173 255 207 207 207 255
|
||||
43 122 112 99 255 101 93 82 255 85 78 69 255 101 93 82 255
|
||||
43:0 122 112 99 255 101 93 82 255 85 78 69 255 101 93 82 255
|
||||
43:1 192 178 110 255 160 148 92 255 134 124 77 255 160 148 92 255
|
||||
43:2 109 80 60 255 91 67 50 255 76 56 41 255 91 67 50 255
|
||||
43:3 118 112 96 255 98 93 80 255 82 78 67 255 98 93 80 255
|
||||
43:4 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255
|
||||
43:5 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
43:6 122 112 99 255 101 93 82 255 85 78 69 255 101 93 82 255
|
||||
44 122 112 99 254 101 93 82 254 85 78 69 254 101 93 82 254
|
||||
44:0 122 112 99 254 101 93 82 254 85 78 69 254 101 93 82 254
|
||||
44:1 192 178 110 255 160 148 92 255 134 124 77 255 160 148 92 255
|
||||
44:2 109 80 60 255 91 67 50 255 76 56 41 255 91 67 50 255
|
||||
44:3 118 112 96 255 98 93 80 255 82 78 67 255 98 93 80 255
|
||||
44:4 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255
|
||||
44:5 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255
|
||||
44:6 122 112 99 254 101 93 82 254 85 78 69 254 101 93 82 254
|
||||
45 230 103 73 255 192 86 61 255 160 71 50 255 192 86 61 255
|
||||
46 255 79 30 255 231 72 27 255 193 60 22 255 231 72 27 255
|
||||
47 125 91 38 192 100 72 30 192 62 45 19 192 50 36 15 192
|
||||
48 96 108 70 255 80 90 58 255 67 75 49 255 80 90 58 255
|
||||
49 83 67 83 255 69 56 69 255 58 47 58 255 69 56 69 255
|
||||
50 255 203 58 200 255 203 58 200 212 169 48 200 255 203 58 200
|
||||
51 255 170 30 200 255 170 30 200 212 141 25 200 255 170 30 200
|
||||
52 255 228 52 255 255 228 52 255 212 190 43 255 255 228 52 255
|
||||
53 145 109 80 255 121 91 67 255 101 76 56 255 121 91 67 255
|
||||
53:4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
54 165 132 100 255 138 110 84 255 115 92 70 255 138 110 84 255
|
||||
55 116 21 21 255 97 18 18 255 81 15 15 255 97 18 18 255
|
||||
56 115 230 255 255 105 210 232 255 88 175 194 255 105 210 232 255
|
||||
57 164 217 237 255 136 181 198 255 114 151 165 255 136 181 198 255
|
||||
58 171 138 99 255 142 115 82 255 118 96 68 255 142 115 82 255
|
||||
59 136 152 21 255 114 127 17 255 95 106 14 255 114 127 17 255
|
||||
60 123 82 51 255 103 68 43 255 86 57 36 255 103 68 43 255
|
||||
61 158 128 73 255 132 106 61 255 110 89 51 255 132 106 61 255
|
||||
62 158 128 73 255 132 106 61 255 110 89 51 255 132 106 61 255
|
||||
63 60 112 17 255 50 93 14 255 42 78 12 255 50 93 14 255
|
||||
64 129 97 69 255 108 81 57 255 90 68 47 255 108 81 57 255
|
||||
65 144 128 99 32 120 106 82 32 100 89 69 32 120 106 82 32
|
||||
66 113 109 102 180 94 91 85 180 79 76 71 180 94 91 85 180
|
||||
67 115 107 93 255 96 89 78 255 80 75 65 255 96 89 78 255
|
||||
68 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
|
||||
69 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
|
||||
70 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
71 255 255 255 255 229 229 229 255 191 191 191 255 229 229 229 255
|
||||
72 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
|
||||
73 174 107 107 255 145 89 89 255 121 75 75 255 145 89 89 255
|
||||
74 174 107 107 255 145 89 89 255 121 75 75 255 145 89 89 255
|
||||
75 255 140 61 254 217 119 52 254 181 99 43 254 217 119 52 254
|
||||
76 255 0 0 254 255 0 0 254 212 0 0 254 255 0 0 254
|
||||
77 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
78 237 248 255 254 237 248 255 254 198 207 212 254 237 248 255 254
|
||||
79 166 222 255 55 166 222 255 55 139 185 212 55 166 222 255 55
|
||||
80 237 248 255 255 237 248 255 255 198 207 212 255 237 248 255 255
|
||||
81 116 167 80 255 97 139 67 255 81 116 56 255 97 139 67 255
|
||||
82 234 240 255 255 216 221 235 255 180 185 196 255 216 221 235 255
|
||||
83 136 167 74 255 114 139 62 255 95 116 52 255 114 139 62 255
|
||||
84 116 97 80 255 97 81 67 255 81 68 55 255 97 81 67 255
|
||||
85 115 99 63 255 96 82 52 255 80 69 44 255 96 82 52 255
|
||||
86 255 115 0 200 204 92 0 200 126 57 0 200 102 46 0 200
|
||||
87 166 89 89 255 141 80 62 255 135 15 15 255 96 6 6 255
|
||||
88 133 109 94 255 121 97 82 255 90 70 57 255 79 59 46 255
|
||||
89 249 212 156 255 255 188 94 255 192 143 70 255 122 91 44 255
|
||||
90 140 0 196 128 120 0 196 128 140 0 196 128 120 0 196 128
|
||||
91 255 115 0 255 204 92 0 255 126 57 0 255 102 46 0 255
|
||||
92 234 234 234 255 210 210 210 255 203 203 203 255 190 190 190 255
|
||||
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
|
||||
97 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
98 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
99 204 153 120 255 145 109 85 255 114 86 67 255 73 64 58 255
|
||||
100 255 43 43 255 196 29 38 255 186 105 109 255 124 64 64 255
|
||||
101 191 191 191 96 152 152 152 96 95 95 95 96 76 76 76 96
|
||||
102 255 255 255 64 204 204 204 64 127 127 127 64 102 102 102 64
|
||||
103 193 193 65 255 174 174 47 255 97 97 5 255 76 76 20 255
|
||||
104 146 192 0 255 116 153 0 255 73 96 0 255 58 76 0 255
|
||||
105 146 192 0 255 116 153 0 255 73 96 0 255 58 76 0 255
|
||||
106 60 192 41 100 48 153 32 100 30 96 20 100 24 76 16 100
|
||||
107 127 98 49 96 95 72 33 96 48 34 9 96 32 21 21 96
|
||||
108 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255
|
||||
109 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
|
||||
110 110 98 104 255 88 78 83 255 55 49 52 255 44 39 42 255
|
||||
111 117 176 73 255 93 140 58 255 58 88 36 255 46 70 29 255
|
||||
112 166 89 89 255 141 80 62 255 135 15 15 255 96 6 6 255
|
||||
113 166 89 89 96 141 80 62 96 135 15 15 96 96 6 6 96
|
||||
114 166 89 89 255 141 80 62 255 135 15 15 255 96 6 6 255
|
||||
115 142 19 21 96 113 15 17 96 71 10 10 96 57 7 8 96
|
||||
116 88 23 22 255 29 10 16 255 17 7 10 255 15 5 8 255
|
||||
117 114 114 114 96 91 91 91 96 67 67 67 96 46 46 46 96
|
||||
118 74 74 74 255 59 59 59 255 37 37 37 255 30 30 30 255
|
||||
119 26 11 43 255 20 8 34 255 13 5 21 255 10 4 17 255
|
||||
120 113 133 104 255 90 106 83 255 56 66 52 255 45 54 42 255
|
||||
121 224 226 169 255 179 180 135 255 112 113 85 255 90 90 66 255
|
||||
122 26 11 43 255 20 8 34 255 13 5 21 255 10 4 17 255
|
||||
Biome Mapping
|
||||
[RAINFOREST] 49 67 21 255 39 54 17 255 25 34 11 255 20 27 8 255
|
||||
[SWAMPLAND] 64 128 0 255 51 102 0 255 32 64 0 255 26 51 0 255
|
||||
[SEASONAL_FOREST] 51 165 42 255 41 132 34 255 26 83 21 255 20 66 17 255
|
||||
[FOREST] 0 128 64 255 0 102 51 255 0 64 32 255 0 51 26 255
|
||||
[SAVANNA] 58 58 58 255 46 46 46 255 29 29 29 255 23 23 23 255
|
||||
[SHRUBLAND] 170 158 24 255 136 126 19 255 85 79 12 255 68 63 10 255
|
||||
[TAIGA] 204 255 102 255 163 204 82 255 102 128 51 255 82 102 41 255
|
||||
[DESERT] 255 255 102 255 204 204 82 255 128 128 51 255 102 102 41 255
|
||||
[PLAINS] 255 204 102 255 204 163 82 255 128 102 51 255 102 82 41 255
|
||||
[ICE_DESERT] 26 33 103 255 21 26 82 255 13 17 52 255 10 13 41 255
|
||||
[TUNDRA] 222 222 222 255 178 178 178 255 111 111 111 255 89 89 89 255
|
||||
[HELL] 255 0 0 255 204 0 0 255 128 0 0 255 102 0 0 255
|
||||
[SKY] 102 204 255 255 82 163 204 255 51 102 128 255 41 82 102 255
|
||||
[OCEAN] 0 0 255 255 0 0 204 255 0 0 128 255 0 0 102 255
|
||||
[RIVER] 0 128 255 255 0 102 204 255 0 64 128 255 0 51 102 255
|
||||
[EXTREME_HILLS] 128 64 0 255 102 51 0 255 64 32 0 255 51 26 0 255
|
||||
[FROZEN_OCEAN] 102 255 204 255 82 204 163 255 51 128 102 255 41 102 82 255
|
||||
[FROZEN_RIVER] 102 102 255 255 82 82 204 255 51 51 128 255 41 41 102 255
|
||||
[ICE_PLAINS] 102 255 255 255 82 204 204 255 51 128 128 255 41 102 102 255
|
||||
[ICE_MOUNTAINS] 255 255 255 255 204 204 204 255 128 128 128 255 102 102 102 255
|
||||
[MUSHROOM_ISLAND] 255 111 207 255 204 89 166 255 128 56 104 255 102 44 83 255
|
||||
[MUSHROOM_SHORE] 255 0 128 255 204 0 102 255 128 0 64 255 102 0 51 255
|
||||
[BEACH] 255 206 75 255 230 185 68 255 255 206 75 255 179 144 53 255
|
||||
[DESERT_HILLS] 255 146 51 255 230 131 46 255 255 146 51 255 179 102 36 255
|
||||
[FOREST_HILLS] 0 162 100 255 0 146 90 255 0 162 100 255 0 113 70 255
|
||||
[TAIGA_HILLS] 178 212 117 255 160 191 105 255 178 212 117 255 125 148 82 255
|
||||
[SMALL_MOUNTAINS] 184 103 33 255 166 93 30 255 184 103 33 255 129 72 23 255
|
||||
Rainfall/Temperature Mapping
|
||||
[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
|
37
pom.xml
37
pom.xml
@ -43,6 +43,31 @@
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack</id>
|
||||
<phase>package</phase>
|
||||
<goals><goal>unpack</goal></goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.dynmap</groupId>
|
||||
<artifactId>DynmapCore</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>bin</classifier>
|
||||
<type>zip</type>
|
||||
<outputDirectory>${project.build.directory}/core</outputDirectory>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
@ -57,8 +82,7 @@
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>org.dynmap:dynmap-api:jar:*</include>
|
||||
<include>org.eclipse.jetty:jetty-*:jar:*</include>
|
||||
<include>javax.servlet:javax.servlet-api:jar:*</include>
|
||||
<include>org.dynmap:DynmapCore:jar:*</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
@ -106,7 +130,7 @@
|
||||
<dependency>
|
||||
<groupId>org.dynmap</groupId>
|
||||
<artifactId>dynmap-api</artifactId>
|
||||
<version>[0.25,)</version>
|
||||
<version>${version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
@ -126,5 +150,12 @@
|
||||
<version>8.0.1.v20110908</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dynmap</groupId>
|
||||
<artifactId>DynmapCore</artifactId>
|
||||
<version>${version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -1,257 +0,0 @@
|
||||
# BuildCraft Block mapping
|
||||
# define buildcraft-support: true in configuration.txt to enable
|
||||
enabled:buildcraft-support
|
||||
# Variables - can be altered in configuration.txt
|
||||
var:bc-autoWorkbench=152,bc-builder=157,bc-dockingStation=168,bc-drill=151
|
||||
var:bc-engine=161,bc-filler=155,bc-frame=160,bc-marker=154,bc-miningWell=150
|
||||
var:bc-oilMoving=162,bc-oilStill=163,bc-pipe=166,bc-pump=164,bc-quarry=153,bc-refinery=167
|
||||
var:bc-tank=165,bc-template=158
|
||||
# Pipe - set render alg
|
||||
linkmap:id=bc-pipe,linkalg=5,linkid=bc-pipe
|
||||
# Frame
|
||||
linkmap:id=bc-frame,linkalg=5,linkid=bc-frame
|
||||
# Pipe - (data is faked: 1=north,2=east,4=south,8=west)
|
||||
# Pipe - no neighbors
|
||||
# Frame
|
||||
block:id=bc-pipe,id=bc-frame,data=0,scale=4
|
||||
layer:1,2
|
||||
----
|
||||
-**-
|
||||
-**-
|
||||
----
|
||||
# Pipe - just north neighbor
|
||||
# Frame
|
||||
block:id=bc-pipe,id=bc-frame,data=1,scale=4
|
||||
layer:1,2
|
||||
-**-
|
||||
-**-
|
||||
-**-
|
||||
----
|
||||
# Pipe - just east neighbor
|
||||
# Frame
|
||||
block:id=bc-pipe,id=bc-frame,data=2,scale=4
|
||||
rotate:id=bc-pipe,data=1,rot=90
|
||||
# Pipe - just south neighbor
|
||||
# Frame
|
||||
block:id=bc-pipe,id=bc-frame,data=4,scale=4
|
||||
rotate:id=bc-pipe,data=1,rot=180
|
||||
# Pipe - just south neighbor
|
||||
# Frame
|
||||
block:id=bc-pipe,id=bc-frame,data=8,scale=4
|
||||
rotate:id=bc-pipe,data=1,rot=270
|
||||
# Pipe - north and east neighbor
|
||||
# Frame
|
||||
block:id=bc-pipe,id=bc-frame,data=3,scale=4
|
||||
layer:1,2
|
||||
-**-
|
||||
-***
|
||||
-***
|
||||
----
|
||||
# Pipe - east and south neighbor
|
||||
# Frame
|
||||
block:id=bc-pipe,id=bc-frame,data=6,scale=4
|
||||
rotate:id=bc-pipe,data=3,rot=90
|
||||
# Pipe - south and west neighbor
|
||||
# Frame
|
||||
block:id=bc-pipe,id=bc-frame,data=12,scale=4
|
||||
rotate:id=bc-pipe,data=3,rot=180
|
||||
# Pipe - west and north neighbor
|
||||
# Frame
|
||||
block:id=bc-pipe,id=bc-frame,data=9,scale=4
|
||||
rotate:id=bc-pipe,data=3,rot=270
|
||||
# Pipe - north and south neighbor
|
||||
# Frame
|
||||
block:id=bc-pipe,id=bc-frame,data=5,scale=4
|
||||
layer:1,2
|
||||
-**-
|
||||
-**-
|
||||
-**-
|
||||
-**-
|
||||
# Pipe - east and west neighbor
|
||||
# Frame
|
||||
block:id=bc-pipe,id=bc-frame,data=10,scale=4
|
||||
rotate:id=bc-pipe,data=5,rot=90
|
||||
# Pipe - north, east and south neighbor
|
||||
# Frame
|
||||
block:id=bc-pipe,id=bc-frame,data=7,scale=4
|
||||
layer:1,2
|
||||
-**-
|
||||
-***
|
||||
-***
|
||||
-**-
|
||||
# Pipe - east, south and west neighbor
|
||||
# Frame
|
||||
block:id=bc-pipe,id=bc-frame,data=14,scale=4
|
||||
rotate:id=bc-pipe,data=7,rot=90
|
||||
# Pipe - south, west and north neighbor
|
||||
# Frame
|
||||
block:id=bc-pipe,id=bc-frame,data=13,scale=4
|
||||
rotate:id=bc-pipe,data=7,rot=180
|
||||
# Pipe - west, north and east neighbor
|
||||
# Frame
|
||||
block:id=bc-pipe,id=bc-frame,data=11,scale=4
|
||||
rotate:id=bc-pipe,data=7,rot=270
|
||||
# Pipe - north, south, east, west neightbors
|
||||
# Frame
|
||||
block:id=bc-pipe,id=bc-frame,data=15,scale=4
|
||||
layer:1,2
|
||||
-**-
|
||||
****
|
||||
****
|
||||
-**-
|
||||
# Drill - set render alg
|
||||
linkmap:id=bc-drill,linkalg=5
|
||||
# Drill - (data is faked: 1=north,2=east,4=south,8=west)
|
||||
# Drill - no neighbors
|
||||
block:id=bc-drill,data=0,scale=4
|
||||
layer:0,1,2,3
|
||||
----
|
||||
-**-
|
||||
-**-
|
||||
----
|
||||
# Drill - just north neighbor
|
||||
block:id=bc-drill,data=1,scale=4
|
||||
layer:0,3
|
||||
----
|
||||
-**-
|
||||
-**-
|
||||
----
|
||||
layer:1,2
|
||||
-**-
|
||||
-**-
|
||||
-**-
|
||||
----
|
||||
# Drill - just east neighbor
|
||||
block:id=bc-drill,data=2,scale=4
|
||||
rotate:id=bc-drill,data=1,rot=90
|
||||
# Drill - just south neighbor
|
||||
block:id=bc-drill,data=4,scale=4
|
||||
rotate:id=bc-drill,data=1,rot=180
|
||||
# Drill - just south neighbor
|
||||
block:id=bc-drill,data=8,scale=4
|
||||
rotate:id=bc-drill,data=1,rot=270
|
||||
# Drill - north and east neighbor
|
||||
block:id=bc-drill,data=3,scale=4
|
||||
layer:0,3
|
||||
----
|
||||
-**-
|
||||
-**-
|
||||
----
|
||||
layer:1,2
|
||||
-**-
|
||||
-***
|
||||
-***
|
||||
----
|
||||
# Drill - east and south neighbor
|
||||
block:id=bc-drill,data=6,scale=4
|
||||
rotate:id=bc-drill,data=3,rot=90
|
||||
# Drill - south and west neighbor
|
||||
block:id=bc-drill,data=12,scale=4
|
||||
rotate:id=bc-drill,data=3,rot=180
|
||||
# Drill - west and north neighbor
|
||||
block:id=bc-drill,data=9,scale=4
|
||||
rotate:id=bc-drill,data=3,rot=270
|
||||
# Drill - north and south neighbor
|
||||
block:id=bc-drill,data=5,scale=4
|
||||
layer:0,3
|
||||
----
|
||||
-**-
|
||||
-**-
|
||||
----
|
||||
layer:1,2
|
||||
-**-
|
||||
-**-
|
||||
-**-
|
||||
-**-
|
||||
# Drill - east and west neighbor
|
||||
block:id=bc-drill,data=10,scale=4
|
||||
rotate:id=bc-drill,data=5,rot=90
|
||||
# Drill - north, east and south neighbor
|
||||
block:id=bc-drill,data=7,scale=4
|
||||
layer:0,3
|
||||
----
|
||||
-**-
|
||||
-**-
|
||||
----
|
||||
layer:1,2
|
||||
-**-
|
||||
-***
|
||||
-***
|
||||
-**-
|
||||
# Drill - east, south and west neighbor
|
||||
block:id=bc-drill,data=14,scale=4
|
||||
rotate:id=bc-drill,data=7,rot=90
|
||||
# Drill - south, west and north neighbor
|
||||
block:id=bc-drill,data=13,scale=4
|
||||
rotate:id=bc-drill,data=7,rot=180
|
||||
# Drill - west, north and east neighbor
|
||||
block:id=bc-drill,data=11,scale=4
|
||||
rotate:id=bc-drill,data=7,rot=270
|
||||
# Drill - north, south, east, west neightbors
|
||||
block:id=bc-drill,data=15,scale=4
|
||||
layer:0,3
|
||||
----
|
||||
-**-
|
||||
-**-
|
||||
----
|
||||
layer:1,2
|
||||
-**-
|
||||
****
|
||||
****
|
||||
-**-
|
||||
# Marker
|
||||
block:id=bc-marker,data=*,scale=8
|
||||
layer:0,1,2,3,4,5,6,7
|
||||
--------
|
||||
--------
|
||||
---**---
|
||||
--****--
|
||||
--****--
|
||||
---**---
|
||||
--------
|
||||
--------
|
||||
# Engine
|
||||
block:id=bc-engine,data=*,scale=8
|
||||
layer:2,3
|
||||
********
|
||||
********
|
||||
********
|
||||
********
|
||||
********
|
||||
********
|
||||
********
|
||||
********
|
||||
layer:4,5,6,7
|
||||
--------
|
||||
--------
|
||||
--****--
|
||||
--****--
|
||||
--****--
|
||||
--****--
|
||||
--------
|
||||
--------
|
||||
# Oil, flowing
|
||||
block:id=bc-oilMoving,data=*,scale=4
|
||||
layer:0
|
||||
****
|
||||
****
|
||||
****
|
||||
****
|
||||
# Oil
|
||||
block:id=bc-oilStill,data=*,scale=4
|
||||
layer:0,1
|
||||
****
|
||||
****
|
||||
****
|
||||
****
|
||||
# Tank
|
||||
block:id=bc-tank,data=*,scale=8
|
||||
layer:0,1,2,3,4,5,6,7
|
||||
--------
|
||||
-******-
|
||||
-******-
|
||||
-******-
|
||||
-******-
|
||||
-******-
|
||||
-******-
|
||||
--------
|
@ -1,60 +0,0 @@
|
||||
# BuildCraft Block mapping
|
||||
# define buildcraft-support: true in configuration.txt to enable
|
||||
enabled:buildcraft-support
|
||||
# Variables - can be altered in configuration.txt
|
||||
var:bc-autoWorkbench=152,bc-builder=157,bc-cobblestonePipe=159,bc-dockingStation=168,bc-drill=151
|
||||
var:bc-engine=161,bc-filler=155,bc-frame=160,bc-marker=154,bc-miningWell=150
|
||||
var:bc-oilMoving=162,bc-oilStill=163,bc-pipe=166,bc-pump=164,bc-quarry=153,bc-refinery=167
|
||||
var:bc-tank=165,bc-template=158
|
||||
# Files
|
||||
texturefile:id=blk,filename=buildcraft/block_textures.png,xcount=16,ycount=16
|
||||
texturefile:id=wood,filename=buildcraft/base_wood.png,xcount=4,ycount=2
|
||||
texturefile:id=iron,filename=buildcraft/base_iron.png,xcount=4,ycount=2
|
||||
texturefile:id=stone,filename=buildcraft/base_stone.png,xcount=4,ycount=2
|
||||
# MINING_WELL_ID = 150
|
||||
block:id=bc-miningWell,data=2,east=35,top=4036,north=37,south=37,west=38,bottom=38,txtid=blk
|
||||
block:id=bc-miningWell,data=3,west=35,top=4036,north=37,south=37,east=38,bottom=38,txtid=blk
|
||||
block:id=bc-miningWell,data=4,north=35,top=4036,east=37,west=37,south=38,bottom=38,txtid=blk
|
||||
block:id=bc-miningWell,data=5,south=35,top=4036,east=37,west=37,north=38,bottom=38,txtid=blk
|
||||
# DRILL_ID = 151
|
||||
block:id=bc-drill,data=*,allfaces=32,txtid=blk,transparency=TRANSPARENT
|
||||
# AUTO_WORKBENCH_ID = 152
|
||||
block:id=bc-autoWorkbench,data=*,allsides=44,topbottom=4043
|
||||
# QUARRY_ID = 153
|
||||
block:id=bc-quarry,data=2,east=39,top=4040,north=38,south=38,west=38,bottom=38,txtid=blk
|
||||
block:id=bc-quarry,data=3,west=39,top=4040,north=38,south=38,east=38,bottom=38,txtid=blk
|
||||
block:id=bc-quarry,data=4,north=39,top=4040,east=38,west=38,south=38,bottom=38,txtid=blk
|
||||
block:id=bc-quarry,data=5,south=39,top=4040,east=38,west=38,north=38,bottom=38,txtid=blk
|
||||
# MARKER_ID = 154
|
||||
block:id=bc-marker,data=*,allsides=57,txtid=blk,transparency=TRANSPARENT
|
||||
# FILLER_ID = 155
|
||||
block:id=bc-filler,data=*,allsides=66,topbottom=4065,txtid=blk
|
||||
# BUILDER_ID = 157
|
||||
block:id=bc-builder,data=2,east=55,top=4054,north=3,south=3,west=3,bottom=3,txtid=blk
|
||||
block:id=bc-builder,data=3,west=55,top=4054,north=3,south=3,east=3,bottom=3,txtid=blk
|
||||
block:id=bc-builder,data=4,north=55,top=4054,east=3,west=3,south=3,bottom=3,txtid=blk
|
||||
block:id=bc-builder,data=5,south=55,top=4054,east=3,west=3,north=3,bottom=3,txtid=blk
|
||||
# TEMPLATE_ID = 158
|
||||
block:id=bc-template,data=2,east=52,top=4050,north=48,south=48,west=48,bottom=48,txtid=blk
|
||||
block:id=bc-template,data=3,west=52,top=4050,north=48,south=48,east=48,bottom=48,txtid=blk
|
||||
block:id=bc-template,data=4,north=52,top=4050,east=48,west=48,south=48,bottom=48,txtid=blk
|
||||
block:id=bc-template,data=5,south=52,top=4050,east=48,west=48,north=48,bottom=48,txtid=blk
|
||||
# FRAME_ID = 160
|
||||
block:id=bc-frame,data=*,allfaces=34,txtid=blk,transparency=TRANSPARENT
|
||||
# ENGINE_ID = 161
|
||||
block:id=bc-engine,data=0,north=8004,east=8005,south=8006,west=8007,top=1,bottom=2,txtid=wood
|
||||
block:id=bc-engine,data=1,north=8004,east=8005,south=8006,west=8007,top=1,bottom=2,txtid=stone
|
||||
block:id=bc-engine,data=2,north=8004,east=8005,south=8006,west=8007,top=1,bottom=2,txtid=iron
|
||||
# OIL_MOVING_ID = 162
|
||||
block:id=bc-oilMoving,data=*,allfaces=223,txtid=blk
|
||||
# OIL_STILL_ID = 163
|
||||
block:id=bc-oilStill,data=*,allfaces=223,txtid=blk
|
||||
# PUMP_ID = 164
|
||||
block:id=bc-pump,data=*,allsides=99,top=4064,bottom=100,txtid=blk
|
||||
# TANK_ID = 165
|
||||
block:id=bc-tank,data=*,allsides=96,topbottom=98,txtid=blk,transparency=TRANSPARENT
|
||||
# GENERIC_PIPE_ID = 166 : entity data based, so we can't handle it yet: just map to one type (iron)
|
||||
block:id=bc-pipe,data=*,allfaces=18,txtid=blk,transparency=TRANSPARENT
|
||||
# REFINERY_ID = 167 - funky texture mapping - just do tank for now
|
||||
block:id=bc-refinery,data=*,allsides=96,topbottom=98,txtid=blk,transparency=TRANSPARENT
|
||||
# DOCKING_STATION_ID = 168
|
@ -1,203 +0,0 @@
|
||||
# Industrial Craft 2 Texture mapping
|
||||
# define ic2-support: true in configuration.txt to enable
|
||||
enabled:ic2-support
|
||||
# variables: set in configuration.txt to override
|
||||
var: ic2-blockCable=228,ic2-blockFenceIron=232,ic2-blockMachine2=223,ic2-blockPersonal=225,ic2-blockLuminator=226,ic2-blockElectric=227,ic2-blockReactorChamber=233,ic2-blockNuke=237,ic2-blockGenerator=246,ic2blockMachine=250
|
||||
# Wire - set render alg
|
||||
linkmap:id=ic2-blockCable,linkalg=5,linkid=ic2-blockMachine2,linkid=ic2-blockPersonal,linkid=ic2-blockLuminator,linkid=ic2-blockElectric,linkid=ic2-blockCable,linkid=ic2-blockReactorChamber,linkid=ic2-blockNuke,linkid=ic2-blockGenerator,linkid=ic2blockMachine
|
||||
# Wire - (data is faked: 1=north,2=east,4=south,8=west)
|
||||
# Wire - no neighbors
|
||||
block:id=ic2-blockCable,data=0,scale=16
|
||||
layer:5,6,7,8,9,10
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
# Wire - just north neighbor
|
||||
block:id=ic2-blockCable,data=1,scale=16
|
||||
layer:5,6,7,8,9,10
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
# Wire - just east neighbor
|
||||
block:id=ic2-blockCable,data=2,scale=16
|
||||
rotate:id=ic2-blockCable,data=1,rot=90
|
||||
# Wire - just south neighbor
|
||||
block:id=ic2-blockCable,id=113,data=4,scale=16
|
||||
rotate:id=ic2-blockCable,data=1,rot=180
|
||||
# Wire - just south neighbor
|
||||
block:id=ic2-blockCable,data=8,scale=16
|
||||
rotate:id=ic2-blockCable,data=1,rot=270
|
||||
# Wire - north and east neighbor
|
||||
block:id=ic2-blockCable,data=3,scale=16
|
||||
layer:5,6,7,8,9,10
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----***********
|
||||
-----***********
|
||||
-----***********
|
||||
-----***********
|
||||
-----***********
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
# Wire - east and south neighbor
|
||||
block:id=ic2-blockCable,data=6,scale=16
|
||||
rotate:id=ic2-blockCable,data=3,rot=90
|
||||
# Wire - south and west neighbor
|
||||
block:id=ic2-blockCable,data=12,scale=16
|
||||
rotate:id=ic2-blockCable,data=3,rot=180
|
||||
# Wire - west and north neighbor
|
||||
block:id=ic2-blockCable,data=9,scale=16
|
||||
rotate:id=ic2-blockCable,data=3,rot=270
|
||||
# Wire - north and south neighbor
|
||||
block:id=ic2-blockCable,data=5,scale=16
|
||||
layer:5,6,7,8,9,10
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
# Wire - east and west neighbor
|
||||
block:id=ic2-blockCable,data=10,scale=16
|
||||
rotate:id=ic2-blockCable,data=5,rot=90
|
||||
# Wire - north, east and south neighbor
|
||||
block:id=ic2-blockCable,data=7,scale=16
|
||||
layer:5,6,7,8,9,10
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----***********
|
||||
-----***********
|
||||
-----***********
|
||||
-----***********
|
||||
-----***********
|
||||
-----***********
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
# Wire - east, south and west neighbor
|
||||
block:id=ic2-blockCable,data=14,scale=16
|
||||
rotate:id=ic2-blockCable,data=7,rot=90
|
||||
# Wire - south, west and north neighbor
|
||||
block:id=ic2-blockCable,data=13,scale=16
|
||||
rotate:id=ic2-blockCable,data=7,rot=180
|
||||
# Wire - west, north and east neighbor
|
||||
block:id=ic2-blockCable,data=11,scale=16
|
||||
rotate:id=ic2-blockCable,data=7,rot=270
|
||||
# Wire - north, south, east, west neightbors
|
||||
block:id=ic2-blockCable,data=15,scale=16
|
||||
layer:5,6,7,8,9,10
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
-----******-----
|
||||
# Iron Fence - set render algorithm
|
||||
linkmap:id=ic2-blockFenceIron,linkalg=1
|
||||
# Iron Fence - (data is faked: 1=north,2=east,4=south,8=west)
|
||||
# Iron Fence - no neighbors
|
||||
block:id=ic2-blockFenceIron,data=0,scale=16
|
||||
rotate:id=85,data=0,rot=0
|
||||
# Iron Fence - just north neighbor
|
||||
block:id=ic2-blockFenceIron,data=1,scale=16
|
||||
rotate:id=85,data=1,rot=0
|
||||
# Iron Fence - just east neighbor
|
||||
block:id=ic2-blockFenceIron,data=2,scale=16
|
||||
rotate:id=ic2-blockFenceIron,data=1,rot=90
|
||||
# Iron Fence - just south neighbor
|
||||
block:id=ic2-blockFenceIron,data=4,scale=16
|
||||
rotate:id=ic2-blockFenceIron,data=1,rot=180
|
||||
# Iron Fence - just south neighbor
|
||||
block:id=ic2-blockFenceIron,data=8,scale=16
|
||||
rotate:id=ic2-blockFenceIron,data=1,rot=270
|
||||
# Iron Fence - north and east neighbor
|
||||
block:id=ic2-blockFenceIron,data=3,scale=16
|
||||
rotate:id=85,data=3,rot=0
|
||||
# Iron Fence - east and south neighbor
|
||||
block:id=ic2-blockFenceIron,data=6,scale=16
|
||||
rotate:id=ic2-blockFenceIron,data=3,rot=90
|
||||
# Iron Fence - south and west neighbor
|
||||
block:id=ic2-blockFenceIron,data=12,scale=16
|
||||
rotate:id=85,data=3,rot=180
|
||||
# Iron Fence - west and north neighbor
|
||||
block:id=ic2-blockFenceIron,data=9,scale=16
|
||||
rotate:id=85,data=3,rot=270
|
||||
# Iron Fence - north and south neighbor
|
||||
block:id=ic2-blockFenceIron,data=5,scale=16
|
||||
rotate:id=85,data=5,rot=0
|
||||
# Iron Fence - east and west neighbor
|
||||
block:id=ic2-blockFenceIron,id=113,data=10,scale=16
|
||||
rotate:id=ic2-blockFenceIron,data=5,rot=90
|
||||
# Iron Fence - north, east and south neighbor
|
||||
block:id=ic2-blockFenceIron,data=7,scale=16
|
||||
rotate:id=85,data=7,rot=0
|
||||
# Iron Fence - east, south and west neighbor
|
||||
block:id=ic2-blockFenceIron,data=14,scale=16
|
||||
rotate:id=ic2-blockFenceIron,data=7,rot=90
|
||||
# Iron Fence - south, west and north neighbor
|
||||
block:id=ic2-blockFenceIron,data=13,scale=16
|
||||
rotate:id=ic2-blockFenceIron,data=7,rot=180
|
||||
# Iron Fence - west, north and east neighbor
|
||||
block:id=ic2-blockFenceIron,data=11,scale=16
|
||||
rotate:id=ic2-blockFenceIron,data=7,rot=270
|
||||
# Iron Fence - north, south, east, west neightbors
|
||||
block:id=ic2-blockFenceIron,data=15,scale=16
|
||||
rotate:id=ic2-blockFenceIron,data=15,rot=0
|
@ -1,203 +0,0 @@
|
||||
# Industrial Craft 2 Block mapping
|
||||
# define ic2-support: true in configuration.txt to enable
|
||||
enabled:ic2-support
|
||||
# variables: set in configuration.txt to override
|
||||
var:ic2-blockScaffold=220,ic2-blockWall=221,ic2-blockFoam=222,ic2-blockMachine2=223,ic2-blockMetal=224,ic2-blockPersonal=225,ic2-blockLuminator=226,ic2-blockElectric=227
|
||||
var:ic2-blockCable=228,ic2-blockDoorAlloy=229,ic2-blockAlloyGlass=230,ic2-blockAlloy=231,ic2-blockFenceIron=232,ic2-blockReactorChamber=233
|
||||
var:ic2-blockRubber=234,ic2-blockDynamiteRemote=235,ic2-blockDynamite=236,ic2-blockNuke=237,ic2-blockITNT=239,ic2-blockHarz=240,ic2-blockRubSapling=241
|
||||
var:ic2-blockRubLeaves=242,ic2-blockRubWood=243,ic2-blockMiningTip=244,ic2-blockMiningPipe=245,ic2-blockGenerator=246
|
||||
var:ic2-blockOreUran=247,ic2-blockOreTin=248,ic2-blockOreCopper=249,ic2-blockMachine=250
|
||||
# Files
|
||||
texturefile:id=blk0,filename=ic2/sprites/block_0.png,xcount=16,ycount=16
|
||||
texturefile:id=cable,filename=ic2/sprites/block_cable.png,xcount=16,ycount=16
|
||||
texturefile:id=elec,filename=ic2/sprites/block_electric.png,xcount=16,ycount=16
|
||||
texturefile:id=gen,filename=ic2/sprites/block_generator.png,xcount=16,ycount=16
|
||||
texturefile:id=mach,filename=ic2/sprites/block_machine.png,xcount=16,ycount=16
|
||||
texturefile:id=mach2,filename=ic2/sprites/block_machine2.png,xcount=16,ycount=16
|
||||
texturefile:id=pers,filename=ic2/sprites/block_personal.png,xcount=16,ycount=16
|
||||
# Blocks
|
||||
# blockScaffold=220
|
||||
# data=*
|
||||
block:id=ic2-blockScaffold,data=*,allsides=116,topbottom=117,txtid=blk0
|
||||
# data=2
|
||||
block:id=ic2-blockScaffold,data=2,allfaces=118,txtid=blk0
|
||||
# blockWall=221
|
||||
# data=0
|
||||
block:id=ic2-blockWall,data=0,allfaces=96,txtid=blk0
|
||||
# data=1
|
||||
block:id=ic2-blockWall,data=1,allfaces=97,txtid=blk0
|
||||
# data=2
|
||||
block:id=ic2-blockWall,data=2,allfaces=98,txtid=blk0
|
||||
# data=3
|
||||
block:id=ic2-blockWall,data=3,allfaces=99,txtid=blk0
|
||||
# data=4
|
||||
block:id=ic2-blockWall,data=4,allfaces=100,txtid=blk0
|
||||
# data=5
|
||||
block:id=ic2-blockWall,data=5,allfaces=101,txtid=blk0
|
||||
# data=6
|
||||
block:id=ic2-blockWall,data=6,allfaces=102,txtid=blk0
|
||||
# data=7
|
||||
block:id=ic2-blockWall,data=7,allfaces=103,txtid=blk0
|
||||
# data=8
|
||||
block:id=ic2-blockWall,data=8,allfaces=104,txtid=blk0
|
||||
# data=9
|
||||
block:id=ic2-blockWall,data=9,allfaces=105,txtid=blk0
|
||||
# data=10
|
||||
block:id=ic2-blockWall,data=10,allfaces=106,txtid=blk0
|
||||
# data=11
|
||||
block:id=ic2-blockWall,data=11,allfaces=107,txtid=blk0
|
||||
# data=12
|
||||
block:id=ic2-blockWall,data=12,allfaces=108,txtid=blk0
|
||||
# data=13
|
||||
block:id=ic2-blockWall,data=13,allfaces=109,txtid=blk0
|
||||
# data=14
|
||||
block:id=ic2-blockWall,data=14,allfaces=110,txtid=blk0
|
||||
# data=15
|
||||
block:id=ic2-blockWall,data=15,allfaces=111,txtid=blk0
|
||||
# blockFoam=222
|
||||
block:id=ic2-blockFoam,data=*,allfaces=37
|
||||
# blockMachine2=223
|
||||
# data=0
|
||||
block:id=ic2-blockMachine2,data=0,top=0,bottom=16,north=32,south=48,east=64,west=80,txtid=mach2
|
||||
# data=1
|
||||
block:id=ic2-blockMachine2,data=1,top=1,bottom=17,north=33,south=49,east=65,west=81,txtid=mach2
|
||||
# blockMetal=224
|
||||
# data=0 (copper)
|
||||
block:id=ic2-blockMetal,data=0,allfaces=93,txtid=blk0
|
||||
# data=1 (tin)
|
||||
block:id=ic2-blockMetal,data=1,allfaces=94,txtid=blk0
|
||||
# data=2 (bronze)
|
||||
block:id=ic2-blockMetal,data=2,allfaces=78,txtid=blk0
|
||||
# data=3 (uranium)
|
||||
block:id=ic2-blockMetal,data=3,topbottom=79,allsides=95,txtid=blk0
|
||||
# blockPersonal=225
|
||||
# data=0
|
||||
block:id=ic2-blockPersonal,data=0,bottom=0,top=16,north=32,south=48,east=64,west=80,txtid=pers
|
||||
# data=1
|
||||
block:id=ic2-blockPersonal,data=1,bottom=1,top=17,north=33,south=49,east=65,west=81,txtid=pers
|
||||
# blockLuminator=226
|
||||
block:id=ic2-blockLuminator,data=*,allfaces=31,txtid=blk0
|
||||
# blockElectric=227
|
||||
# data=0
|
||||
block:id=ic2-blockElectric,data=0,bottom=0,top=16,north=32,south=48,east=64,west=80,txtid=elec
|
||||
# data=1
|
||||
block:id=ic2-blockElectric,data=1,bottom=1,top=17,north=33,south=49,east=65,west=81,txtid=elec
|
||||
# data=2
|
||||
block:id=ic2-blockElectric,data=2,bottom=2,top=18,north=34,south=50,east=66,west=82,txtid=elec
|
||||
# data=3
|
||||
block:id=ic2-blockElectric,data=3,bottom=3,top=19,north=35,south=51,east=67,west=83,txtid=elec
|
||||
# data=4
|
||||
block:id=ic2-blockElectric,data=4,bottom=4,top=20,north=36,south=52,east=68,west=84,txtid=elec
|
||||
# data=5
|
||||
block:id=ic2-blockElectric,data=5,bottom=5,top=21,north=37,south=53,east=69,west=85,txtid=elec
|
||||
# blockCable=228
|
||||
# data=0
|
||||
block:id=ic2-blockCable,data=0,allfaces=0,txtid=cable
|
||||
# data=1
|
||||
block:id=ic2-blockCable,data=1,allfaces=16,txtid=cable
|
||||
# data=2
|
||||
block:id=ic2-blockCable,data=2,allfaces=32,txtid=cable
|
||||
# data=3
|
||||
block:id=ic2-blockCable,data=3,allfaces=48,txtid=cable
|
||||
# data=4
|
||||
block:id=ic2-blockCable,data=4,allfaces=64,txtid=cable
|
||||
# data=5
|
||||
block:id=ic2-blockCable,data=5,allfaces=80,txtid=cable
|
||||
# data=6
|
||||
block:id=ic2-blockCable,data=6,allfaces=96,txtid=cable
|
||||
# data=7
|
||||
block:id=ic2-blockCable,data=7,allfaces=112,txtid=cable
|
||||
# data=8
|
||||
block:id=ic2-blockCable,data=8,allfaces=128,txtid=cable
|
||||
# data=9
|
||||
block:id=ic2-blockCable,data=9,allfaces=144,txtid=cable
|
||||
# data=10
|
||||
block:id=ic2-blockCable,data=10,allfaces=160,txtid=cable
|
||||
# blockDoorAlloy=229
|
||||
# data=0-7 (bottom)
|
||||
block:id=ic2-blockDoorAlloy,data=0,data=1,data=2,data=3,data=4,data=5,data=6,data=7,allsides=15,topbottom=12,transparency=TRANSPARENT,txtid=blk0
|
||||
# data=8-15 (top)
|
||||
block:id=ic2-blockDoorAlloy,data=8,data=9,data=10,data=11,data=12,data=13,data=14,data=15,allsides=14,topbottom=12,transparency=TRANSPARENT,txtid=blk0
|
||||
# blockAlloyGlass=230
|
||||
block:id=ic2-blockAlloyGlass,data=*,allfaces=13,txtid=blk0,transparency=TRANSPARENT
|
||||
# blockAlloy=231
|
||||
block:id=ic2-blockAlloy,data=*,allfaces=12,txtid=blk0
|
||||
# blockFenceIron=232
|
||||
block:id=ic2-blockFenceIron,data=*,allfaces=1,txtid=blk0,transparency=TRANSPARENT
|
||||
# blockReactorChamber=233
|
||||
block:id=ic2-blockReactorChamber,data=*,bottom=16,top=17,allsides=67,txtid=blk0
|
||||
# blockRubber=234
|
||||
block:id=ic2-blockRubber,data=*,allfaces=40,txtid=blk0
|
||||
# blockDynamiteRemote=235
|
||||
block:id=ic2-blockDynamiteRemote,data=*,allsides=56,txtid=blk0
|
||||
# blockDynamite=236
|
||||
block:id=ic2-blockDynamite,data=*,allsides=57,txtid=blk0
|
||||
# blockNuke=237
|
||||
block:id=ic2-blockNuke,data=*,bottom=61,top=62,allsides=63,txtid=blk0
|
||||
# ?=238
|
||||
# blockITNT=239
|
||||
block:id=ic2-blockITNT,data=*,bottom=58,top=59,allsides=60,txtid=blk0
|
||||
# blockHarz=240
|
||||
block:id=ic2-blockHarz,data=*,allfaces=43,txtid=blk0
|
||||
# blockRubSapling=241
|
||||
block:id=ic2-blockRubSapling,data=*,allsides=2038,transparency=TRANSPARENT,txtid=blk0
|
||||
# blockRubLeaves=242
|
||||
block:id=ic2-blockRubLeaves,data=*,allfaces=2040,transparency=TRANSPARENT,txtid=blk0
|
||||
# blockRubWood=243
|
||||
block:id=ic2-blockRubWood,data=*,topbottom=47,allsides=44,txtid=blk0
|
||||
# blockMiningTip=244
|
||||
block:id=ic2-blockMiningTip,data=*,allfaces=36,txtid=blk0
|
||||
# blockMiningPipe=245
|
||||
block:id=ic2-blockMiningPipe,data=*,allfaces=35,txtid=blk0
|
||||
# blockGenerator=246
|
||||
# data=0
|
||||
block:id=ic2-blockGenerator,data=0,bottom=0,top=16,north=32,south=48,east=64,west=80,txtid=gen
|
||||
# data=1
|
||||
block:id=ic2-blockGenerator,data=1,bottom=1,top=17,north=33,south=49,east=65,west=81,txtid=gen
|
||||
# data=2
|
||||
block:id=ic2-blockGenerator,data=2,bottom=2,top=18,north=34,south=50,east=66,west=82,txtid=gen
|
||||
# data=3
|
||||
block:id=ic2-blockGenerator,data=3,bottom=3,top=19,north=35,south=51,east=67,west=83,txtid=gen
|
||||
# data=4
|
||||
block:id=ic2-blockGenerator,data=4,bottom=4,top=20,north=36,south=52,east=68,west=84,txtid=gen
|
||||
# data=5
|
||||
block:id=ic2-blockGenerator,data=5,bottom=5,top=21,north=37,south=53,east=69,west=85,txtid=gen
|
||||
# blockOreUran=247
|
||||
block:id=ic2-blockOreUran,data=*,allfaces=34,txtid=blk0
|
||||
# blockOreTin=248
|
||||
block:id=ic2-blockOreTin,data=*,allfaces=33,txtid=blk0
|
||||
# blockOreCopper=249
|
||||
block:id=ic2-blockOreCopper,data=*,allfaces=32,txtid=blk0
|
||||
# blockMachine=250
|
||||
# data=0
|
||||
block:id=ic2-blockMachine,data=0,bottom=0,top=16,north=32,south=48,east=64,west=80,txtid=mach
|
||||
# data=1
|
||||
block:id=ic2-blockMachine,data=1,bottom=1,top=17,north=33,south=49,east=65,west=81,txtid=mach
|
||||
# data=2
|
||||
block:id=ic2-blockMachine,data=2,bottom=2,top=18,north=34,south=50,east=66,west=82,txtid=mach
|
||||
# data=3
|
||||
block:id=ic2-blockMachine,data=3,bottom=3,top=19,north=35,south=51,east=67,west=83,txtid=mach
|
||||
# data=4
|
||||
block:id=ic2-blockMachine,data=4,bottom=4,top=20,north=36,south=52,east=68,west=84,txtid=mach
|
||||
# data=5
|
||||
block:id=ic2-blockMachine,data=5,bottom=5,top=21,north=37,south=53,east=69,west=85,txtid=mach
|
||||
# data=6
|
||||
block:id=ic2-blockMachine,data=6,bottom=6,top=22,north=38,south=54,east=70,west=86,txtid=mach
|
||||
# data=7
|
||||
block:id=ic2-blockMachine,data=7,bottom=7,top=23,north=39,south=55,east=71,west=87,txtid=mach
|
||||
# data=8
|
||||
block:id=ic2-blockMachine,data=8,bottom=8,top=24,north=40,south=56,east=72,west=88,txtid=mach
|
||||
# data=9
|
||||
block:id=ic2-blockMachine,data=9,bottom=9,top=25,north=41,south=57,east=73,west=89,txtid=mach
|
||||
# data=10
|
||||
block:id=ic2-blockMachine,data=10,bottom=10,top=26,north=42,south=58,east=74,west=90,txtid=mach
|
||||
# data=11
|
||||
block:id=ic2-blockMachine,data=11,bottom=11,top=27,north=43,south=59,east=75,west=91,txtid=mach
|
||||
# data=12
|
||||
block:id=ic2-blockMachine,data=12,bottom=12,top=28,north=44,south=60,east=76,west=92,txtid=mach
|
||||
# data=13
|
||||
block:id=ic2-blockMachine,data=13,bottom=13,top=29,north=45,south=61,east=77,west=93,txtid=mach
|
||||
# data=14
|
||||
block:id=ic2-blockMachine,data=14,bottom=14,top=30,north=46,south=62,east=78,west=94,txtid=mach
|
||||
# data=15
|
||||
block:id=ic2-blockMachine,data=15,bottom=15,top=31,north=47,south=63,east=79,west=95,txtid=mach
|
@ -1,157 +0,0 @@
|
||||
# RedPower2 block mapping
|
||||
# define redpower2-support: true in configuration.txt to enable
|
||||
enabled:redpower2-support
|
||||
# Variables - can be altered in configuration.txt
|
||||
var:rp2-base-appliance=137,rp2-base-microblock=136
|
||||
var:rp2-world-plants=139,rp2-world-ores=140,rp2-world-leaves=141,rp2-world-stone=142,rp2-world-log=143,rp2-world-crops=144,rp2-world-storage=145
|
||||
var:rp2-logic-logic=138
|
||||
var:rp2-lighting-lampOn=146,rp2-lighting-lampOff=147
|
||||
var:rp2-sensor-sensor=148
|
||||
var:rp2-array-array=149
|
||||
var:rp2-machine-machine=150,rp2-machine-machinePanel=151,rp2-machine-frame=152
|
||||
# rp2-world-plants,*
|
||||
block:id=rp2-world-plants,data=*,scale=16
|
||||
layer:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
||||
*--------------*
|
||||
-*------------*-
|
||||
--*----------*--
|
||||
---*--------*---
|
||||
----*------*----
|
||||
-----*----*-----
|
||||
------*--*------
|
||||
-------**-------
|
||||
-------**-------
|
||||
------*--*------
|
||||
-----*----*-----
|
||||
----*------*----
|
||||
---*--------*---
|
||||
--*----------*--
|
||||
-*------------*-
|
||||
*--------------*
|
||||
# Crops
|
||||
block:id=rp2-world-crops,data=*,scale=16
|
||||
layer:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
||||
---*--------*---
|
||||
---*--------*---
|
||||
---*--------*---
|
||||
****************
|
||||
---*--------*---
|
||||
---*--------*---
|
||||
---*--------*---
|
||||
---*--------*---
|
||||
---*--------*---
|
||||
---*--------*---
|
||||
---*--------*---
|
||||
---*--------*---
|
||||
****************
|
||||
---*--------*---
|
||||
---*--------*---
|
||||
---*--------*---
|
||||
# Logic
|
||||
block:id=rp2-logic-logic,data=*,scale=8
|
||||
layer:0
|
||||
********
|
||||
********
|
||||
********
|
||||
********
|
||||
********
|
||||
********
|
||||
********
|
||||
********
|
||||
# Array (array.array.id,0)
|
||||
# Inv-Array (array.array.id,1)
|
||||
# Non-Inv-Array (array.array.id,2)
|
||||
block:id=rp2-array-array,data=0,data=1,data=2,scale=16
|
||||
layer:0,1
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
****************
|
||||
layer:2,3
|
||||
-------**-------
|
||||
-------**-------
|
||||
--*----**----*--
|
||||
-------**-------
|
||||
-------**-------
|
||||
-------**-------
|
||||
-------**-------
|
||||
**-----**-----**
|
||||
**-----**-----**
|
||||
-------**-------
|
||||
-------**-------
|
||||
-------**-------
|
||||
-------**-------
|
||||
--*----**----*--
|
||||
-------**-------
|
||||
-------**-------
|
||||
layer:4,5,6,7,8,9
|
||||
----------------
|
||||
----------------
|
||||
--*----------*--
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
**------------**
|
||||
**------------**
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
--*----------*--
|
||||
----------------
|
||||
----------------
|
||||
layer:10
|
||||
----------------
|
||||
----------------
|
||||
--*----------*--
|
||||
--*----------*--
|
||||
--*----------*--
|
||||
--*----------*--
|
||||
--*----------*--
|
||||
***----------***
|
||||
***----------***
|
||||
--*----------*--
|
||||
--*----------*--
|
||||
--*----------*--
|
||||
--*----------*--
|
||||
--*----------*--
|
||||
----------------
|
||||
----------------
|
||||
layer:11,12
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
****************
|
||||
****************
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
# Solar panel (machine.machinePanel.id,0)
|
||||
block:id=rp2-machine-machinePanel,data=0,scale=4
|
||||
layer:0
|
||||
****
|
||||
****
|
||||
****
|
||||
****
|
||||
|
@ -1,217 +0,0 @@
|
||||
# RedPower2 block mapping
|
||||
# define redpower2-support: true in configuration.txt to enable
|
||||
enabled:redpower2-support
|
||||
# Variables - can be altered in configuration.txt
|
||||
var:rp2-base-appliance=137,rp2-base-microblock=136
|
||||
var:rp2-world-plants=139,rp2-world-ores=140,rp2-world-leaves=141,rp2-world-stone=142,rp2-world-log=143,rp2-world-crops=144,rp2-world-storage=145
|
||||
var:rp2-logic-logic=138
|
||||
var:rp2-lighting-lampOn=146,rp2-lighting-lampOff=147
|
||||
var:rp2-sensor-sensor=148
|
||||
var:rp2-array-array=149
|
||||
var:rp2-machine-machine=150,rp2-machine-machinePanel=151,rp2-machine-frame=152
|
||||
# Files
|
||||
texturefile:id=base,filename=redpower2/base1.png,xcount=16,ycount=16
|
||||
texturefile:id=world,filename=redpower2/world1.png,xcount=16,ycount=16
|
||||
texturefile:id=worlditem,filename=redpower2/worlditems1.png,xcount=16,ycount=16
|
||||
texturefile:id=logic,filename=redpower2/logic1.png,xcount=16,ycount=16
|
||||
texturefile:id=lighting,filename=redpower2/lighting1.png,xcount=16,ycount=16
|
||||
texturefile:id=array,filename=redpower2/array1.png,xcount=16,ycount=16
|
||||
texturefile:id=machine,filename=redpower2/machine1.png,xcount=16,ycount=16
|
||||
############
|
||||
# Blocks from RedPowerCore-2
|
||||
############
|
||||
# Alloy Furnace (base.appliance.id, 0)
|
||||
block:id=rp2-base-appliance,data=0,topbottom=19,north=18,south=18,east=16,west=16,txtid=base
|
||||
# Microblocks (base.microblock.id, 0) - can't do this right yet, so just do it as cobblestone...
|
||||
block:id=rp2-base-microblock,data=0,allfaces=16
|
||||
############
|
||||
# Blocks from RedPowerWorld-2
|
||||
############
|
||||
# Flower (world.plants.id, 0), (world.plants.id,3+)
|
||||
block:id=rp2-world-plants,data=0,data=3,data=4,data=5,data=6,data=7,data=8,data=9,data=10,data=11,data=12,data=13,data=14,data=15,allsides=1,txtid=worlditem,transparency=TRANSPARENT
|
||||
# Flower (world.plants.id, 1), (world.plants.id, 2)
|
||||
block:id=rp2-world-plants,data=1,data=2,allsides=2,txtid=worlditem,transparency=TRANSPARENT
|
||||
# Flax (world.crops.id,0)
|
||||
block:id=rp2-world-crops,data=0,allsides=64,txtid=world,transparency=TRANSPARENT
|
||||
# Flax (world.crops.id,1)
|
||||
block:id=rp2-world-crops,data=1,allsides=65,txtid=world,transparency=TRANSPARENT
|
||||
# Flax (world.crops.id,2)
|
||||
block:id=rp2-world-crops,data=2,allsides=66,txtid=world,transparency=TRANSPARENT
|
||||
# Flax (world.crops.id,3)
|
||||
block:id=rp2-world-crops,data=3,allsides=67,txtid=world,transparency=TRANSPARENT
|
||||
# Flax (world.crops.id,4)
|
||||
block:id=rp2-world-crops,data=4,allsides=68,txtid=world,transparency=TRANSPARENT
|
||||
# Flax (world.crops.id,5+)
|
||||
block:id=rp2-world-crops,data=5,data=6,data=7,data=8,data=9,data=10,data=11,data=12,data13,data=14,data=15,allsides=69,txtid=world,transparency=TRANSPARENT
|
||||
# Marble (world.stone.id,0)
|
||||
block:id=rp2-world-stone,data=0,allfaces=16,txtid=world
|
||||
# Basalt (world.stone.id,1)
|
||||
block:id=rp2-world-stone,data=1,allfaces=17,txtid=world
|
||||
# Marble bricks (world.stone.id,2)
|
||||
block:id=rp2-world-stone,data=2,allfaces=18,txtid=world
|
||||
# Basalt cobblestone (world.stone.id,3)
|
||||
block:id=rp2-world-stone,data=3,allfaces=19,txtid=world
|
||||
# Basalt bricks (world.stone.id,4)
|
||||
block:id=rp2-world-stone,data=4,allfaces=20,txtid=world
|
||||
# Ruby Ore (world.ores.id,0)
|
||||
block:id=rp2-world-ores,data=0,allfaces=32,txtid=world
|
||||
# Emerald Ore (world.ores.id,1)
|
||||
block:id=rp2-world-ores,data=1,allfaces=33,txtid=world
|
||||
# Sapphire Ore (world.ores.id,2)
|
||||
block:id=rp2-world-ores,data=2,allfaces=34,txtid=world
|
||||
# Silver Ore (world.ores.id,3)
|
||||
block:id=rp2-world-ores,data=3,allfaces=35,txtid=world
|
||||
# Tin Ore (world.ores.id,4)
|
||||
block:id=rp2-world-ores,data=4,allfaces=36,txtid=world
|
||||
# Copper Ore (world.ores.id,5)
|
||||
block:id=rp2-world-ores,data=5,allfaces=37,txtid=world
|
||||
# Tungsten Ore (world.ores.id,6)
|
||||
block:id=rp2-world-ores,data=6,allfaces=38,txtid=world
|
||||
# Nikolite Ore (world.ores.id,7)
|
||||
block:id=rp2-world-ores,data=7,allfaces=39,txtid=world
|
||||
# Rubber tree leaves (world.leaves.id,*)
|
||||
block:id=rp2-world-leaves,data=*,allfaces=2049,txtid=world
|
||||
# Ruby Block (world.storage.id,0)
|
||||
block:id=rp2-world-storage,data=0,allfaces=80,txtid=world
|
||||
# Emerald Block (world.storage.id,1)
|
||||
block:id=rp2-world-storage,data=1,allfaces=81,txtid=world
|
||||
# Sapphire Block (world.storage.id,2)
|
||||
block:id=rp2-world-storage,data=2,allfaces=82,txtid=world
|
||||
# Rubber log (world.log.id,*)
|
||||
block:id=rp2-world-log,data=*,allsides=50,topbottom=51,txtid=world
|
||||
############
|
||||
# Blocks from RedPowerLogic-2
|
||||
############
|
||||
# Timer (logic.logic.id,0)
|
||||
block:id=rp2-logic-logic,data=0,allsides=0,top=8,bottom=0,txtid=logic,transparency=TRANSPARENT
|
||||
# Sequencer (logic.logic.id,1)
|
||||
block:id=rp2-logic-logic,data=1,allsides=0,top=1,bottom=0,txtid=logic,transparency=TRANSPARENT
|
||||
# Latch (logic.logic.id,2)
|
||||
block:id=rp2-logic-logic,data=2,allsides=0,top=2,bottom=0,txtid=logic,transparency=TRANSPARENT
|
||||
# Nor (logic.logic.id,3)
|
||||
block:id=rp2-logic-logic,data=3,allsides=0,top=32,bottom=0,txtid=logic,transparency=TRANSPARENT
|
||||
# Or (logic.logic.id,4)
|
||||
block:id=rp2-logic-logic,data=4,allsides=0,top=144,bottom=0,txtid=logic,transparency=TRANSPARENT
|
||||
# Nand (logic.logic.id,5)
|
||||
block:id=rp2-logic-logic,data=5,allsides=0,top=96,bottom=0,txtid=logic,transparency=TRANSPARENT
|
||||
# And (logic.logic.id,6)
|
||||
block:id=rp2-logic-logic,data=6,allsides=0,top=160,bottom=0,txtid=logic,transparency=TRANSPARENT
|
||||
# Xnor (logic.logic.id,7)
|
||||
block:id=rp2-logic-logic,data=7,allsides=0,top=20,bottom=0,txtid=logic,transparency=TRANSPARENT
|
||||
# Xor (logic.logic.id,8)
|
||||
block:id=rp2-logic-logic,data=8,allsides=0,top=24,bottom=0,txtid=logic,transparency=TRANSPARENT
|
||||
# Pulse (logic.logic.id,9)
|
||||
block:id=rp2-logic-logic,data=9,allsides=0,top=216,bottom=0,txtid=logic,transparency=TRANSPARENT
|
||||
# Toggle (logic.logic.id,10)
|
||||
block:id=rp2-logic-logic,data=10,allsides=0,top=16,bottom=0,txtid=logic,transparency=TRANSPARENT
|
||||
# Not (logic.logic.id,11)
|
||||
block:id=rp2-logic-logic,data=11,allsides=0,top=192,bottom=0,txtid=logic,transparency=TRANSPARENT
|
||||
# Buffer (logic.logic.id,12)
|
||||
block:id=rp2-logic-logic,data=12,allsides=0,top=208,bottom=0,txtid=logic,transparency=TRANSPARENT
|
||||
# Mux (logic.logic.id,13)
|
||||
block:id=rp2-logic-logic,data=13,allsides=0,top=5,bottom=0,txtid=logic,transparency=TRANSPARENT
|
||||
# Counter (logic.logic.id,14)
|
||||
block:id=rp2-logic-logic,data=14,allsides=0,top=16,bottom=0,txtid=logic,transparency=TRANSPARENT
|
||||
# Repeater (logic.logic.id,15)
|
||||
block:id=rp2-logic-logic,data=15,allsides=0,top=188,bottom=0,txtid=logic,transparency=TRANSPARENT
|
||||
############
|
||||
# Blocks from RedPowerLighting-2
|
||||
############
|
||||
# White Lamp on
|
||||
block:id=rp2-lighting-lampOn,data=0,allfaces=32,txtid=lighting
|
||||
# Orange Lamp on
|
||||
block:id=rp2-lighting-lampOn,data=1,allfaces=33,txtid=lighting
|
||||
# Magenta Lamp on
|
||||
block:id=rp2-lighting-lampOn,data=2,allfaces=34,txtid=lighting
|
||||
# Light Blue Lamp on
|
||||
block:id=rp2-lighting-lampOn,data=3,allfaces=35,txtid=lighting
|
||||
# Yellow Lamp on
|
||||
block:id=rp2-lighting-lampOn,data=4,allfaces=36,txtid=lighting
|
||||
# Lime Lamp on
|
||||
block:id=rp2-lighting-lampOn,data=5,allfaces=37,txtid=lighting
|
||||
# Pink Lamp on
|
||||
block:id=rp2-lighting-lampOn,data=6,allfaces=38,txtid=lighting
|
||||
# Gray Lamp on
|
||||
block:id=rp2-lighting-lampOn,data=7,allfaces=39,txtid=lighting
|
||||
# Light Gray Lamp on
|
||||
block:id=rp2-lighting-lampOn,data=8,allfaces=40,txtid=lighting
|
||||
# Cyan Lamp on
|
||||
block:id=rp2-lighting-lampOn,data=9,allfaces=41,txtid=lighting
|
||||
# Purple Lamp on
|
||||
block:id=rp2-lighting-lampOn,data=10,allfaces=42,txtid=lighting
|
||||
# Blue Lamp on
|
||||
block:id=rp2-lighting-lampOn,data=11,allfaces=43,txtid=lighting
|
||||
# Brown Lamp on
|
||||
block:id=rp2-lighting-lampOn,data=12,allfaces=44,txtid=lighting
|
||||
# Green Lamp on
|
||||
block:id=rp2-lighting-lampOn,data=13,allfaces=45,txtid=lighting
|
||||
# Red Lamp on
|
||||
block:id=rp2-lighting-lampOn,data=14,allfaces=46,txtid=lighting
|
||||
# Black Lamp on
|
||||
block:id=rp2-lighting-lampOn,data=15,allfaces=47,txtid=lighting
|
||||
# White Lamp off
|
||||
block:id=rp2-lighting-lampOff,data=0,allfaces=16,txtid=lighting
|
||||
# Orange Lamp off
|
||||
block:id=rp2-lighting-lampOff,data=1,allfaces=17,txtid=lighting
|
||||
# Magenta Lamp off
|
||||
block:id=rp2-lighting-lampOff,data=2,allfaces=18,txtid=lighting
|
||||
# Light Blue Lamp off
|
||||
block:id=rp2-lighting-lampOff,data=3,allfaces=19,txtid=lighting
|
||||
# Yellow Lamp off
|
||||
block:id=rp2-lighting-lampOff,data=4,allfaces=20,txtid=lighting
|
||||
# Lime Lamp off
|
||||
block:id=rp2-lighting-lampOff,data=5,allfaces=21,txtid=lighting
|
||||
# Pink Lamp off
|
||||
block:id=rp2-lighting-lampOff,data=6,allfaces=22,txtid=lighting
|
||||
# Gray Lamp off
|
||||
block:id=rp2-lighting-lampOff,data=7,allfaces=23,txtid=lighting
|
||||
# Light Gray Lamp off
|
||||
block:id=rp2-lighting-lampOff,data=8,allfaces=24,txtid=lighting
|
||||
# Cyan Lamp off
|
||||
block:id=rp2-lighting-lampOff,data=9,allfaces=25,txtid=lighting
|
||||
# Purple Lamp off
|
||||
block:id=rp2-lighting-lampOff,data=10,allfaces=26,txtid=lighting
|
||||
# Blue Lamp off
|
||||
block:id=rp2-lighting-lampOff,data=11,allfaces=27,txtid=lighting
|
||||
# Brown Lamp off
|
||||
block:id=rp2-lighting-lampOff,data=12,allfaces=28,txtid=lighting
|
||||
# Green Lamp off
|
||||
block:id=rp2-lighting-lampOff,data=13,allfaces=29,txtid=lighting
|
||||
# Red Lamp off
|
||||
block:id=rp2-lighting-lampOff,data=14,allfaces=30,txtid=lighting
|
||||
# Black Lamp off
|
||||
block:id=rp2-lighting-lampOff,data=15,allfaces=31,txtid=lighting
|
||||
############
|
||||
# Blocks from RedPowerArray-2
|
||||
############
|
||||
# Array (array.array.id,0)
|
||||
block:id=rp2-array-array,data=0,allsides=0,top=2,bottom=0,txtid=array,transparency=TRANSPARENT
|
||||
# Inv-Array (array.array.id,1)
|
||||
block:id=rp2-array-array,data=1,allsides=0,top=3,bottom=0,txtid=array,transparency=TRANSPARENT
|
||||
# Non-Inv-Array (array.array.id,2)
|
||||
block:id=rp2-array-array,data=2,allsides=0,top=5,bottom=0,txtid=array,transparency=TRANSPARENT
|
||||
############
|
||||
# Blocks from RedPowerMachine-2
|
||||
############
|
||||
# Deployer (machine.machine.id,0) - no orientation data yet - just face east
|
||||
block:id=rp2-machine-machine,data=0,east=53,west=48,top=6055,bottom=4055,north=4056,south=6056,txtid=machine
|
||||
# Breaker (machine.machine.id,1) - no orientation data yet - just face east
|
||||
block:id=rp2-machine-machine,data=1,east=49,west=58,top=6051,bottom=4051,north=4051,south=6051,txtid=machine
|
||||
# Transposer (machine.machine.id,2) - no orientation data yet - just face east
|
||||
block:id=rp2-machine-machine,data=2,east=57,west=58,top=6059,bottom=4059,north=4059,south=6059,txtid=machine
|
||||
# Filter (machine.machine.id,3) - no orientation data yet - just face east
|
||||
block:id=rp2-machine-machine,data=3,east=57,west=58,top=6061,bottom=4061,north=4061,south=6061,txtid=machine
|
||||
# Item Detector (machine.machine.id,4) - no orientation data yet - just face east
|
||||
block:id=rp2-machine-machine,data=4,east=103,west=102,top=6100,bottom=4101,north=4096,south=6097,txtid=machine
|
||||
# Sorter (machine.machine.id,5) - no orientation data yet - just face east
|
||||
block:id=rp2-machine-machine,data=5,east=112,west=113,top=6116,bottom=4116,north=4116,south=6116,txtid=machine
|
||||
# BatBox (machine.machine.id,6)
|
||||
block:id=rp2-machine-machine,data=6,allsides=134,topbottom=128,txtid=machine
|
||||
# Retriever (machine.machine.id,8) - no orientation data yet - just face east
|
||||
block:id=rp2-machine-machine,data=8,east=125,west=124,top=6123,bottom=4123,north=4123,south=6123,txtid=machine
|
||||
# Solar Panel (machine.machinePanel.id,0)
|
||||
block:id=rp2-machine-machinePanel,data=0,top=85,bottom=84,allsides=86,txtid=machine
|
||||
# Blue Furnace (base.appliance.id, 1) - no orientation data yet - just face east
|
||||
block:id=rp2-base-appliance,data=1,east=82,west=80,top=83,bottom=83,north=80,south=80,txtid=machine
|
||||
# Buffer (base.appliance.id, 2) - no orientation data yet - just face east
|
||||
block:id=rp2-base-appliance,data=2,east=89,west=88,top=6088,bottom=4088,north=4088,south=6088,txtid=machine
|
@ -6,40 +6,16 @@
|
||||
</formats>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>${project.basedir}</directory>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<includes>
|
||||
<include>README*</include>
|
||||
<include>LICENSE*</include>
|
||||
<include>NOTICE*</include>
|
||||
<include>CHANGELOG*</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
<directory>${project.build.directory}/core</directory>
|
||||
<outputDirectory>/dynmap</outputDirectory>
|
||||
<excludes>
|
||||
<exclude>web/version.js</exclude></excludes></fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.basedir}/web/</directory>
|
||||
<outputDirectory>/dynmap/web/</outputDirectory>
|
||||
<includes>
|
||||
<include>version.js</include>
|
||||
</includes>
|
||||
<filtered>true</filtered>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.basedir}/web</directory>
|
||||
<outputDirectory>/dynmap/web</outputDirectory>
|
||||
<excludes>
|
||||
<exclude>version.js</exclude>
|
||||
</excludes>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.basedir}/colorschemes</directory>
|
||||
<outputDirectory>/dynmap/colorschemes</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.basedir}/texturepacks</directory>
|
||||
<outputDirectory>/dynmap/texturepacks</outputDirectory></fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.basedir}/renderdata</directory>
|
||||
<outputDirectory>/dynmap/renderdata</outputDirectory></fileSet>
|
||||
<directory>${project.build.directory}/core/web</directory>
|
||||
<outputDirectory>/dynmap/web</outputDirectory>
|
||||
<includes>
|
||||
<include>version.js</include></includes>
|
||||
<filtered>true</filtered></fileSet>
|
||||
</fileSets>
|
||||
<files>
|
||||
<file>
|
||||
|
@ -1,161 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
public class AsynchronousQueue<T> {
|
||||
private Object lock = new Object();
|
||||
private Thread thread;
|
||||
private LinkedBlockingQueue<T> queue = new LinkedBlockingQueue<T>();
|
||||
private Set<T> set = new HashSet<T>();
|
||||
private Handler<T> handler;
|
||||
private int dequeueTime;
|
||||
private int accelDequeueTime;
|
||||
private int accelDequeueThresh;
|
||||
private int pendingcnt;
|
||||
private int pendinglimit;
|
||||
private boolean normalprio;
|
||||
|
||||
public AsynchronousQueue(Handler<T> handler, int dequeueTime, int accelDequeueThresh, int accelDequeueTime, int pendinglimit, boolean normalprio) {
|
||||
this.handler = handler;
|
||||
this.dequeueTime = dequeueTime;
|
||||
this.accelDequeueTime = accelDequeueTime;
|
||||
this.accelDequeueThresh = accelDequeueThresh;
|
||||
if(pendinglimit < 1) pendinglimit = 1;
|
||||
this.pendinglimit = pendinglimit;
|
||||
this.normalprio = normalprio;
|
||||
}
|
||||
|
||||
public boolean push(T t) {
|
||||
synchronized (lock) {
|
||||
if (!set.add(t)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
queue.offer(t);
|
||||
return true;
|
||||
}
|
||||
|
||||
private T pop() {
|
||||
try {
|
||||
T t = queue.take();
|
||||
synchronized (lock) {
|
||||
set.remove(t);
|
||||
}
|
||||
return t;
|
||||
} catch (InterruptedException ix) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean remove(T t) {
|
||||
synchronized (lock) {
|
||||
if (set.remove(t)) {
|
||||
queue.remove(t);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return set.size();
|
||||
}
|
||||
|
||||
public List<T> popAll() {
|
||||
List<T> s;
|
||||
synchronized(lock) {
|
||||
s = new ArrayList<T>(queue);
|
||||
queue.clear();
|
||||
set.clear();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
synchronized (lock) {
|
||||
thread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
running();
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
try {
|
||||
if(!normalprio)
|
||||
thread.setPriority(Thread.MIN_PRIORITY);
|
||||
} catch (SecurityException e) {
|
||||
Log.info("Failed to set minimum priority for worker thread!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
synchronized (lock) {
|
||||
if (thread == null)
|
||||
return;
|
||||
Thread oldThread = thread;
|
||||
thread = null;
|
||||
|
||||
Log.info("Stopping map renderer...");
|
||||
|
||||
oldThread.interrupt();
|
||||
try {
|
||||
oldThread.join(1000);
|
||||
} catch (InterruptedException e) {
|
||||
Log.info("Waiting for map renderer to stop is interrupted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void running() {
|
||||
try {
|
||||
while (Thread.currentThread() == thread) {
|
||||
synchronized(lock) {
|
||||
while(pendingcnt >= pendinglimit) {
|
||||
try {
|
||||
lock.wait(accelDequeueTime);
|
||||
} catch (InterruptedException ix) {
|
||||
if(Thread.currentThread() != thread)
|
||||
return;
|
||||
throw ix;
|
||||
}
|
||||
}
|
||||
}
|
||||
T t = pop();
|
||||
if (t != null) {
|
||||
synchronized(lock) {
|
||||
pendingcnt++;
|
||||
}
|
||||
handler.handle(t);
|
||||
}
|
||||
if(set.size() >= accelDequeueThresh)
|
||||
sleep(accelDequeueTime);
|
||||
else
|
||||
sleep(dequeueTime);
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
Log.severe("Exception on rendering-thread", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean sleep(int time) {
|
||||
try {
|
||||
Thread.sleep(time);
|
||||
} catch (InterruptedException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void done(T t) {
|
||||
synchronized (lock) {
|
||||
if(pendingcnt > 0) pendingcnt--;
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
public class ChatEvent {
|
||||
public String source;
|
||||
public String name;
|
||||
public String message;
|
||||
public ChatEvent(String source, String name, String message) {
|
||||
this.source = source;
|
||||
this.name = name;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
@ -1,160 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
import org.json.simple.JSONAware;
|
||||
import org.json.simple.JSONStreamAware;
|
||||
import org.dynmap.common.DynmapChatColor;
|
||||
|
||||
public class Client {
|
||||
public static class Update implements JSONAware, JSONStreamAware {
|
||||
public long timestamp = System.currentTimeMillis();
|
||||
|
||||
@Override
|
||||
public String toJSONString() {
|
||||
return org.dynmap.web.Json.stringifyJson(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeJSONString(Writer w) throws IOException {
|
||||
// TODO: This isn't the best...
|
||||
w.write(toJSONString());
|
||||
}
|
||||
}
|
||||
|
||||
public static class ChatMessage extends Update {
|
||||
public String type = "chat";
|
||||
public String source;
|
||||
public String playerName;
|
||||
public String message;
|
||||
public String account;
|
||||
public String channel;
|
||||
public ChatMessage(String source, String channel, String playerName, String message, String playeraccount) {
|
||||
this.source = source;
|
||||
this.playerName = Client.stripColor(playerName);
|
||||
this.message = DynmapChatColor.stripColor(message);
|
||||
this.account = playeraccount;
|
||||
this.channel = channel;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(o instanceof ChatMessage) {
|
||||
ChatMessage m = (ChatMessage)o;
|
||||
return m.source.equals(source) && m.playerName.equals(playerName) && m.message.equals(message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return source.hashCode() ^ playerName.hashCode() ^ message.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static class PlayerJoinMessage extends Update {
|
||||
public String type = "playerjoin";
|
||||
public String playerName;
|
||||
public String account;
|
||||
public PlayerJoinMessage(String playerName, String playeraccount) {
|
||||
this.playerName = Client.stripColor(playerName);
|
||||
this.account = playeraccount;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(o instanceof PlayerJoinMessage) {
|
||||
PlayerJoinMessage m = (PlayerJoinMessage)o;
|
||||
return m.playerName.equals(playerName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return playerName.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static class PlayerQuitMessage extends Update {
|
||||
public String type = "playerquit";
|
||||
public String playerName;
|
||||
public String account;
|
||||
public PlayerQuitMessage(String playerName, String playeraccount) {
|
||||
this.playerName = Client.stripColor(playerName);
|
||||
this.account = playeraccount;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(o instanceof PlayerQuitMessage) {
|
||||
PlayerQuitMessage m = (PlayerQuitMessage)o;
|
||||
return m.playerName.equals(playerName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return playerName.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Tile extends Update {
|
||||
public String type = "tile";
|
||||
public String name;
|
||||
|
||||
public Tile(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(o instanceof Tile) {
|
||||
Tile m = (Tile)o;
|
||||
return m.name.equals(name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static class DayNight extends Update {
|
||||
public String type = "daynight";
|
||||
public boolean isday;
|
||||
|
||||
public DayNight(boolean isday) {
|
||||
this.isday = isday;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(o instanceof DayNight) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 12345;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ComponentMessage extends Update {
|
||||
public String type = "component";
|
||||
/* Each subclass must provide 'ctype' string for component 'type' */
|
||||
}
|
||||
|
||||
public static String stripColor(String s) {
|
||||
s = DynmapChatColor.stripColor(s); /* Strip standard color encoding */
|
||||
/* Handle Essentials nickname encoding too */
|
||||
int idx = 0;
|
||||
while((idx = s.indexOf('&', idx)) >= 0) {
|
||||
char c = s.charAt(idx+1); /* Get next character */
|
||||
if(c == '&') { /* Another ampersand */
|
||||
s = s.substring(0, idx) + s.substring(idx+1);
|
||||
}
|
||||
else {
|
||||
s = s.substring(0, idx) + s.substring(idx+2);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import static org.dynmap.JSONUtils.a;
|
||||
import static org.dynmap.JSONUtils.s;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
public class ClientComponent extends Component {
|
||||
private boolean disabled;
|
||||
|
||||
public ClientComponent(final DynmapCore plugin, final ConfigurationNode configuration) {
|
||||
super(plugin, configuration);
|
||||
plugin.events.addListener("buildclientconfiguration", new Event.Listener<JSONObject>() {
|
||||
@Override
|
||||
public void triggered(JSONObject root) {
|
||||
if(!disabled)
|
||||
buildClientConfiguration(root);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void disableComponent() {
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
protected void buildClientConfiguration(JSONObject root) {
|
||||
JSONObject o = createClientConfiguration();
|
||||
a(root, "components", o);
|
||||
}
|
||||
|
||||
protected JSONObject createClientConfiguration() {
|
||||
JSONObject o = convertMap(configuration);
|
||||
o.remove("class");
|
||||
return o;
|
||||
}
|
||||
|
||||
protected static final JSONObject convertMap(Map<String, ?> m) {
|
||||
JSONObject o = new JSONObject();
|
||||
for(Map.Entry<String, ?> entry : m.entrySet()) {
|
||||
s(o, entry.getKey(), convert(entry.getValue()));
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static final JSONArray convertList(List<?> l) {
|
||||
JSONArray o = new JSONArray();
|
||||
for(Object entry : l) {
|
||||
o.add(convert(entry));
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static final Object convert(Object o) {
|
||||
if (o instanceof Map<?, ?>) {
|
||||
return convertMap((Map<String, ?>)o);
|
||||
} else if (o instanceof List<?>) {
|
||||
return convertList((List<?>)o);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import static org.dynmap.JSONUtils.a;
|
||||
import static org.dynmap.JSONUtils.s;
|
||||
|
||||
import org.dynmap.Event.Listener;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class ClientConfigurationComponent extends Component {
|
||||
public ClientConfigurationComponent(final DynmapCore core, ConfigurationNode configuration) {
|
||||
super(core, configuration);
|
||||
core.events.<JSONObject>addListener("buildclientconfiguration", new Listener<JSONObject>() {
|
||||
@Override
|
||||
public void triggered(JSONObject t) {
|
||||
ConfigurationNode c = core.configuration;
|
||||
s(t, "confighash", core.getConfigHashcode());
|
||||
s(t, "updaterate", c.getFloat("updaterate", 1.0f));
|
||||
s(t, "showplayerfacesinmenu", c.getBoolean("showplayerfacesinmenu", true));
|
||||
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", unescapeString(c.getString("webprefix", "[WEB] ")));
|
||||
s(t, "defaultzoom", c.getInteger("defaultzoom", 0));
|
||||
s(t, "sidebaropened", c.getString("sidebaropened", "false"));
|
||||
s(t, "dynmapversion", core.getDynmapCoreVersion());
|
||||
s(t, "cyrillic", c.getBoolean("cyrillic-support", false));
|
||||
s(t, "showlayercontrol", c.getString("showlayercontrol", "true"));
|
||||
s(t, "grayplayerswhenhidden", c.getBoolean("grayplayerswhenhidden", true));
|
||||
String sn = core.getServer().getServerName();
|
||||
if(sn.equals("Unknown Server"))
|
||||
sn = "Minecraft Dynamic Map";
|
||||
s(t, "title", c.getString("webpage-title", sn));
|
||||
s(t, "msg-maptypes", c.getString("msg/maptypes", "Map Types"));
|
||||
s(t, "msg-players", c.getString("msg/players", "Players"));
|
||||
|
||||
DynmapWorld defaultWorld = null;
|
||||
String defmap = null;
|
||||
for(DynmapWorld world : core.mapManager.getWorlds()) {
|
||||
if (defaultWorld == null) defaultWorld = world;
|
||||
ConfigurationNode wn = world.configuration;
|
||||
JSONObject wo = new JSONObject();
|
||||
s(wo, "name", wn.getString("name"));
|
||||
s(wo, "title", wn.getString("title"));
|
||||
DynmapLocation spawn = world.getSpawnLocation();
|
||||
s(wo, "center/x", wn.getDouble("center/x", spawn.x));
|
||||
s(wo, "center/y", wn.getDouble("center/y", spawn.y));
|
||||
s(wo, "center/z", wn.getDouble("center/z", spawn.z));
|
||||
s(wo, "bigworld", world.bigworld);
|
||||
s(wo, "extrazoomout", world.getExtraZoomOutLevels());
|
||||
a(t, "worlds", wo);
|
||||
|
||||
for(MapType mt : world.maps) {
|
||||
mt.buildClientConfiguration(wo, world);
|
||||
if(defmap == null) defmap = mt.getName();
|
||||
}
|
||||
}
|
||||
s(t, "defaultworld", c.getString("defaultworld", defaultWorld == null ? "world" : defaultWorld.getName()));
|
||||
s(t, "defaultmap", c.getString("defaultmap", defmap == null ? "surface" : defmap));
|
||||
if(c.getString("followmap", null) != null)
|
||||
s(t, "followmap", c.getString("followmap"));
|
||||
if(c.getInteger("followzoom",-1) >= 0)
|
||||
s(t, "followzoom", c.getInteger("followzoom", 0));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,118 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import static org.dynmap.JSONUtils.a;
|
||||
import static org.dynmap.JSONUtils.s;
|
||||
|
||||
import java.util.List;
|
||||
import org.dynmap.common.DynmapPlayer;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class ClientUpdateComponent extends Component {
|
||||
|
||||
public ClientUpdateComponent(final DynmapCore plugin, ConfigurationNode configuration) {
|
||||
super(plugin, configuration);
|
||||
plugin.events.addListener("buildclientupdate", new Event.Listener<ClientUpdateEvent>() {
|
||||
@Override
|
||||
public void triggered(ClientUpdateEvent e) {
|
||||
buildClientUpdate(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void buildClientUpdate(ClientUpdateEvent e) {
|
||||
DynmapWorld world = e.world;
|
||||
JSONObject u = e.update;
|
||||
long since = e.timestamp;
|
||||
String worldName = world.getName();
|
||||
int hideifshadow = configuration.getInteger("hideifshadow", 15);
|
||||
int hideifunder = configuration.getInteger("hideifundercover", 15);
|
||||
boolean hideifsneaking = configuration.getBoolean("hideifsneaking", false);
|
||||
|
||||
s(u, "confighash", core.getConfigHashcode());
|
||||
|
||||
s(u, "servertime", world.getTime() % 24000);
|
||||
s(u, "hasStorm", world.hasStorm());
|
||||
s(u, "isThundering", world.isThundering());
|
||||
|
||||
s(u, "players", new JSONArray());
|
||||
List<DynmapPlayer> players = core.playerList.getVisiblePlayers();
|
||||
for(DynmapPlayer p : players) {
|
||||
DynmapLocation pl = p.getLocation();
|
||||
DynmapWorld pw = core.getWorld(pl.world);
|
||||
if(pw == null)
|
||||
continue;
|
||||
JSONObject jp = new JSONObject();
|
||||
boolean hide = false;
|
||||
|
||||
s(jp, "type", "player");
|
||||
s(jp, "name", Client.stripColor(p.getDisplayName()));
|
||||
s(jp, "account", p.getName());
|
||||
if(hideifshadow < 15) {
|
||||
if(pw.getLightLevel((int)pl.x, (int)pl.y, (int)pl.z) <= hideifshadow)
|
||||
hide = true;
|
||||
}
|
||||
if(hideifunder < 15) {
|
||||
if(pw.canGetSkyLightLevel()) { /* If we can get real sky level */
|
||||
if(pw.getSkyLightLevel((int)pl.x, (int)pl.y, (int)pl.z) <= hideifunder)
|
||||
hide = true;
|
||||
}
|
||||
else {
|
||||
if(pw.getHighestBlockYAt((int)pl.x, (int)pl.z) > pl.y)
|
||||
hide = true;
|
||||
}
|
||||
}
|
||||
if(hideifsneaking && p.isSneaking())
|
||||
hide = true;
|
||||
|
||||
/* Don't leak player location for world not visible on maps, or if sendposition disbaled */
|
||||
DynmapWorld pworld = MapManager.mapman.worldsLookup.get(pl.world);
|
||||
/* Fix typo on 'sendpositon' to 'sendposition', keep bad one in case someone used it */
|
||||
if(configuration.getBoolean("sendposition", true) && configuration.getBoolean("sendpositon", true) &&
|
||||
(pworld != null) && pworld.sendposition && (!hide)) {
|
||||
s(jp, "world", pl.world);
|
||||
s(jp, "x", pl.x);
|
||||
s(jp, "y", pl.y);
|
||||
s(jp, "z", pl.z);
|
||||
}
|
||||
else {
|
||||
s(jp, "world", "-some-other-bogus-world-");
|
||||
s(jp, "x", 0.0);
|
||||
s(jp, "y", 64.0);
|
||||
s(jp, "z", 0.0);
|
||||
}
|
||||
/* Only send health if enabled AND we're on visible world */
|
||||
if (configuration.getBoolean("sendhealth", false) && (pworld != null) && pworld.sendhealth && (!hide)) {
|
||||
s(jp, "health", p.getHealth());
|
||||
s(jp, "armor", p.getArmorPoints());
|
||||
}
|
||||
else {
|
||||
s(jp, "health", 0);
|
||||
s(jp, "armor", 0);
|
||||
}
|
||||
a(u, "players", jp);
|
||||
}
|
||||
if(configuration.getBoolean("includehiddenplayers", false)) {
|
||||
List<DynmapPlayer> hidden = core.playerList.getHiddenPlayers();
|
||||
for(DynmapPlayer p : hidden) {
|
||||
JSONObject jp = new JSONObject();
|
||||
s(jp, "type", "player");
|
||||
s(jp, "name", Client.stripColor(p.getDisplayName()));
|
||||
s(jp, "account", p.getName());
|
||||
s(jp, "world", "-hidden-player-");
|
||||
s(jp, "x", 0.0);
|
||||
s(jp, "y", 64.0);
|
||||
s(jp, "z", 0.0);
|
||||
s(jp, "health", 0);
|
||||
s(jp, "armor", 0);
|
||||
a(u, "players", jp);
|
||||
}
|
||||
}
|
||||
|
||||
s(u, "updates", new JSONArray());
|
||||
for(Object update : core.mapManager.getWorldUpdates(worldName, since)) {
|
||||
a(u, "updates", (Client.Update)update);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class ClientUpdateEvent {
|
||||
public long timestamp;
|
||||
public DynmapWorld world;
|
||||
public JSONObject update;
|
||||
|
||||
public ClientUpdateEvent(long timestamp, DynmapWorld world, JSONObject update) {
|
||||
this.timestamp = timestamp;
|
||||
this.world = world;
|
||||
this.update = update;
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
/**
|
||||
* Simple replacement for java.awt.Color for dynmap - it's not an invariant, so we don't make millions
|
||||
* of them during rendering
|
||||
*/
|
||||
public class Color {
|
||||
/* ARGB value */
|
||||
private int val;
|
||||
|
||||
public static final int TRANSPARENT = 0;
|
||||
|
||||
public Color(int red, int green, int blue, int alpha) {
|
||||
setRGBA(red, green, blue, alpha);
|
||||
}
|
||||
public Color(int red, int green, int blue) {
|
||||
setRGBA(red, green, blue, 0xFF);
|
||||
}
|
||||
public Color() {
|
||||
setTransparent();
|
||||
}
|
||||
public final int getRed() {
|
||||
return (val >> 16) & 0xFF;
|
||||
}
|
||||
public final int getGreen() {
|
||||
return (val >> 8) & 0xFF;
|
||||
}
|
||||
public final int getBlue() {
|
||||
return val & 0xFF;
|
||||
}
|
||||
public final int getAlpha() {
|
||||
return ((val >> 24) & 0xFF);
|
||||
}
|
||||
public final boolean isTransparent() {
|
||||
return ((val & 0xFF000000) == TRANSPARENT);
|
||||
}
|
||||
public final void setTransparent() {
|
||||
val = TRANSPARENT;
|
||||
}
|
||||
public final void setColor(Color c) {
|
||||
val = c.val;
|
||||
}
|
||||
public final void setRGBA(int red, int green, int blue, int alpha) {
|
||||
val = ((alpha & 0xFF) << 24) | ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | (blue & 0xFF);
|
||||
}
|
||||
public final int getARGB() {
|
||||
return val;
|
||||
}
|
||||
public final void setARGB(int c) {
|
||||
val = c;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
@ -1,250 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Scanner;
|
||||
|
||||
import org.dynmap.common.BiomeMap;
|
||||
import org.dynmap.debug.Debug;
|
||||
|
||||
public class ColorScheme {
|
||||
private static final HashMap<String, ColorScheme> cache = new HashMap<String, ColorScheme>();
|
||||
|
||||
public String name;
|
||||
/* Switch to arrays - faster than map */
|
||||
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, Color[][] biomecolors, Color[][] raincolors, Color[][] tempcolors) {
|
||||
this.name = name;
|
||||
this.colors = colors;
|
||||
this.datacolors = datacolors;
|
||||
this.biomecolors = biomecolors;
|
||||
this.raincolors = raincolors;
|
||||
this.tempcolors = tempcolors;
|
||||
if(MapManager.mapman.getHideOres()) {
|
||||
for(int i = 0; i < colors.length; i++) {
|
||||
int id = MapManager.mapman.getBlockIDAlias(i);
|
||||
if(id != i) {
|
||||
this.colors[i] = this.colors[id];
|
||||
this.datacolors[i] = this.datacolors[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static File getColorSchemeDirectory(DynmapCore core) {
|
||||
return new File(core.getDataFolder(), "colorschemes");
|
||||
}
|
||||
|
||||
public static ColorScheme getScheme(DynmapCore core, String name) {
|
||||
if (name == null)
|
||||
name = "default";
|
||||
ColorScheme scheme = cache.get(name);
|
||||
if (scheme == null) {
|
||||
scheme = loadScheme(core, name);
|
||||
cache.put(name, scheme);
|
||||
}
|
||||
return scheme;
|
||||
}
|
||||
|
||||
public static ColorScheme loadScheme(DynmapCore core, String name) {
|
||||
File colorSchemeFile = new File(getColorSchemeDirectory(core), name + ".txt");
|
||||
Color[][] colors = new Color[256][];
|
||||
Color[][][] datacolors = new Color[256][][];
|
||||
Color[][] biomecolors = new Color[BiomeMap.values().length][];
|
||||
Color[][] raincolors = new Color[64][];
|
||||
Color[][] tempcolors = new Color[64][];
|
||||
|
||||
InputStream stream;
|
||||
try {
|
||||
Debug.debug("Loading colors from '" + colorSchemeFile + "'...");
|
||||
stream = new FileInputStream(colorSchemeFile);
|
||||
|
||||
Scanner scanner = new Scanner(stream);
|
||||
int nc = 0;
|
||||
while (scanner.hasNextLine()) {
|
||||
String line = scanner.nextLine();
|
||||
if (line.startsWith("#") || line.equals("")) {
|
||||
continue;
|
||||
}
|
||||
/* 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(BiomeMap b : BiomeMap.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[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[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) {
|
||||
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 */
|
||||
datacolors[id] = dcolor;
|
||||
}
|
||||
if((dat >= 0) && (dat < 16)) { /* Add color to list */
|
||||
dcolor[dat] = c;
|
||||
}
|
||||
if(dat == 0) { /* Index zero is base color too */
|
||||
colors[id] = c;
|
||||
}
|
||||
}
|
||||
else {
|
||||
colors[id] = c;
|
||||
}
|
||||
nc += 1;
|
||||
}
|
||||
scanner.close();
|
||||
/* Last, push base color into any open slots in data colors list */
|
||||
for(int k = 0; k < 256; k++) {
|
||||
Color[][] dc = datacolors[k]; /* see if data colors too */
|
||||
if(dc != null) {
|
||||
Color[] c = colors[k];
|
||||
for(int i = 0; i < 16; i++) {
|
||||
if(dc[i] == null)
|
||||
dc[i] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 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, 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;
|
||||
}
|
||||
public static void reset() {
|
||||
cache.clear();
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
public abstract class Component {
|
||||
protected DynmapCore core;
|
||||
protected ConfigurationNode configuration;
|
||||
public Component(DynmapCore core, ConfigurationNode configuration) {
|
||||
this.core = core;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
/* Substitute proper values for escape sequences */
|
||||
public static String unescapeString(String v) {
|
||||
/* Replace color code &color; */
|
||||
v = v.replace("&color;", "\u00A7");
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class ComponentManager {
|
||||
public Set<Component> components = new HashSet<Component>();
|
||||
public Map<String, List<Component>> componentLookup = new HashMap<String, List<Component>>();
|
||||
|
||||
public void add(Component c) {
|
||||
if (components.add(c)) {
|
||||
String key = c.getClass().toString();
|
||||
List<Component> clist = componentLookup.get(key);
|
||||
if (clist == null) {
|
||||
clist = new ArrayList<Component>();
|
||||
componentLookup.put(key, clist);
|
||||
}
|
||||
clist.add(c);
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(Component c) {
|
||||
if (components.remove(c)) {
|
||||
String key = c.getClass().toString();
|
||||
List<Component> clist = componentLookup.get(key);
|
||||
if (clist != null) {
|
||||
clist.remove(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
componentLookup.clear();
|
||||
components.clear();
|
||||
}
|
||||
|
||||
public Iterable<Component> getComponents(Class<Component> c) {
|
||||
List<Component> list = componentLookup.get(c.toString());
|
||||
if (list == null)
|
||||
return new ArrayList<Component>();
|
||||
return list;
|
||||
}
|
||||
}
|
@ -1,426 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import org.yaml.snakeyaml.constructor.SafeConstructor;
|
||||
import org.yaml.snakeyaml.introspector.Property;
|
||||
import org.yaml.snakeyaml.nodes.CollectionNode;
|
||||
import org.yaml.snakeyaml.nodes.MappingNode;
|
||||
import org.yaml.snakeyaml.nodes.Node;
|
||||
import org.yaml.snakeyaml.nodes.NodeTuple;
|
||||
import org.yaml.snakeyaml.nodes.SequenceNode;
|
||||
import org.yaml.snakeyaml.nodes.Tag;
|
||||
import org.yaml.snakeyaml.reader.UnicodeReader;
|
||||
import org.yaml.snakeyaml.representer.Represent;
|
||||
import org.yaml.snakeyaml.representer.Representer;
|
||||
|
||||
public class ConfigurationNode implements Map<String, Object> {
|
||||
public Map<String, Object> entries;
|
||||
private File f;
|
||||
private Yaml yaml;
|
||||
|
||||
public ConfigurationNode() {
|
||||
entries = new HashMap<String, Object>();
|
||||
}
|
||||
|
||||
private void initparse() {
|
||||
if(yaml == null) {
|
||||
DumperOptions options = new DumperOptions();
|
||||
|
||||
options.setIndent(4);
|
||||
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
|
||||
yaml = new Yaml(new SafeConstructor(), new EmptyNullRepresenter(), options);
|
||||
}
|
||||
}
|
||||
|
||||
public ConfigurationNode(File f) {
|
||||
this.f = f;
|
||||
entries = new HashMap<String, Object>();
|
||||
}
|
||||
|
||||
public ConfigurationNode(Map<String, Object> map) {
|
||||
if (map == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
entries = map;
|
||||
}
|
||||
|
||||
public ConfigurationNode(InputStream in) {
|
||||
load(in);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean load(InputStream in) {
|
||||
initparse();
|
||||
|
||||
Object o = yaml.load(new UnicodeReader(in));
|
||||
if((o != null) && (o instanceof Map))
|
||||
entries = (Map<String, Object>)o;
|
||||
return (entries != null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean load() {
|
||||
initparse();
|
||||
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
fis = new FileInputStream(f);
|
||||
Object o = yaml.load(new UnicodeReader(fis));
|
||||
if((o != null) && (o instanceof Map))
|
||||
entries = (Map<String, Object>)o;
|
||||
fis.close();
|
||||
} catch(IOException iox) {
|
||||
Log.severe("Error reading " + f.getPath());
|
||||
return false;
|
||||
} finally {
|
||||
if(fis != null) {
|
||||
try { fis.close(); } catch (IOException x) {}
|
||||
}
|
||||
}
|
||||
return (entries != null);
|
||||
}
|
||||
|
||||
public boolean save() {
|
||||
return save(f);
|
||||
}
|
||||
|
||||
public boolean save(File file) {
|
||||
initparse();
|
||||
|
||||
FileOutputStream stream = null;
|
||||
|
||||
File parent = file.getParentFile();
|
||||
|
||||
if (parent != null) {
|
||||
parent.mkdirs();
|
||||
}
|
||||
|
||||
try {
|
||||
stream = new FileOutputStream(file);
|
||||
OutputStreamWriter writer = new OutputStreamWriter(stream, "UTF-8");
|
||||
yaml.dump(entries, writer);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
} finally {
|
||||
try {
|
||||
if (stream != null) {
|
||||
stream.close();
|
||||
}
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getObject(String path) {
|
||||
if (path.isEmpty())
|
||||
return entries;
|
||||
int separator = path.indexOf('/');
|
||||
if (separator < 0)
|
||||
return get(path);
|
||||
String localKey = path.substring(0, separator);
|
||||
Object subvalue = get(localKey);
|
||||
if (subvalue == null)
|
||||
return null;
|
||||
if (!(subvalue instanceof Map<?, ?>))
|
||||
return null;
|
||||
Map<String, Object> submap;
|
||||
try {
|
||||
submap = (Map<String, Object>)subvalue;
|
||||
} catch (ClassCastException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String subpath = path.substring(separator + 1);
|
||||
return new ConfigurationNode(submap).getObject(subpath);
|
||||
|
||||
}
|
||||
|
||||
public Object getObject(String path, Object def) {
|
||||
Object o = getObject(path);
|
||||
if (o == null)
|
||||
return def;
|
||||
return o;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getGeneric(String path, T def) {
|
||||
Object o = getObject(path, def);
|
||||
try {
|
||||
return (T)o;
|
||||
} catch(ClassCastException e) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
public int getInteger(String path, int def) {
|
||||
return Integer.parseInt(getObject(path, def).toString());
|
||||
}
|
||||
|
||||
public double getLong(String path, long def) {
|
||||
return Long.parseLong(getObject(path, def).toString());
|
||||
}
|
||||
|
||||
public float getFloat(String path, float def) {
|
||||
return Float.parseFloat(getObject(path, def).toString());
|
||||
}
|
||||
|
||||
public double getDouble(String path, double def) {
|
||||
return Double.parseDouble(getObject(path, def).toString());
|
||||
}
|
||||
|
||||
public boolean getBoolean(String path, boolean def) {
|
||||
return Boolean.parseBoolean(getObject(path, def).toString());
|
||||
}
|
||||
|
||||
public String getString(String path) {
|
||||
return getString(path, null);
|
||||
}
|
||||
|
||||
public List<String> getStrings(String path, List<String> def) {
|
||||
Object o = getObject(path);
|
||||
if (!(o instanceof List<?>)) {
|
||||
return def;
|
||||
}
|
||||
ArrayList<String> strings = new ArrayList<String>();
|
||||
for(Object i : (List<?>)o) {
|
||||
strings.add(i.toString());
|
||||
}
|
||||
return strings;
|
||||
}
|
||||
|
||||
public String getString(String path, String def) {
|
||||
Object o = getObject(path, def);
|
||||
if (o == null)
|
||||
return null;
|
||||
return o.toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> List<T> getList(String path) {
|
||||
try {
|
||||
List<T> list = (List<T>)getObject(path, null);
|
||||
return list;
|
||||
} catch (ClassCastException e) {
|
||||
try {
|
||||
T o = (T)getObject(path, null);
|
||||
if (o == null) {
|
||||
return new ArrayList<T>();
|
||||
}
|
||||
ArrayList<T> al = new ArrayList<T>();
|
||||
al.add(o);
|
||||
return al;
|
||||
} catch (ClassCastException e2) {
|
||||
return new ArrayList<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Map<String,Object>> getMapList(String path) {
|
||||
return getList(path);
|
||||
}
|
||||
|
||||
public ConfigurationNode getNode(String path) {
|
||||
Map<String, Object> v = null;
|
||||
v = getGeneric(path, v);
|
||||
if (v == null)
|
||||
return null;
|
||||
return new ConfigurationNode(v);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<ConfigurationNode> getNodes(String path) {
|
||||
List<Object> o = getList(path);
|
||||
|
||||
if(o == null)
|
||||
return new ArrayList<ConfigurationNode>();
|
||||
|
||||
ArrayList<ConfigurationNode> nodes = new ArrayList<ConfigurationNode>();
|
||||
for(Object i : (List<?>)o) {
|
||||
if (i instanceof Map<?, ?>) {
|
||||
Map<String, Object> map;
|
||||
try {
|
||||
map = (Map<String, Object>)i;
|
||||
} catch(ClassCastException e) {
|
||||
continue;
|
||||
}
|
||||
nodes.add(new ConfigurationNode(map));
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
public void extend(Map<String, Object> other) {
|
||||
if (other != null)
|
||||
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()) {
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
if (value instanceof Map<?, ?>) {
|
||||
ConfigurationNode subnode = original.getNode(key);
|
||||
if (subnode == null) {
|
||||
original.put(key, subnode = new ConfigurationNode());
|
||||
}
|
||||
extendMap(subnode, (Map<String, Object>)value);
|
||||
} else {
|
||||
original.put(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T createInstance(Class<?>[] constructorParameters, Object[] constructorArguments) {
|
||||
String typeName = getString("class");
|
||||
try {
|
||||
Class<?> mapTypeClass = Class.forName(typeName);
|
||||
|
||||
Class<?>[] constructorParameterWithConfiguration = new Class<?>[constructorParameters.length+1];
|
||||
for(int i = 0; i < constructorParameters.length; i++) { constructorParameterWithConfiguration[i] = constructorParameters[i]; }
|
||||
constructorParameterWithConfiguration[constructorParameterWithConfiguration.length-1] = ConfigurationNode.class;
|
||||
|
||||
Object[] constructorArgumentsWithConfiguration = new Object[constructorArguments.length+1];
|
||||
for(int i = 0; i < constructorArguments.length; i++) { constructorArgumentsWithConfiguration[i] = constructorArguments[i]; }
|
||||
constructorArgumentsWithConfiguration[constructorArgumentsWithConfiguration.length-1] = this;
|
||||
Constructor<?> constructor = mapTypeClass.getConstructor(constructorParameterWithConfiguration);
|
||||
@SuppressWarnings("unchecked")
|
||||
T t = (T)constructor.newInstance(constructorArgumentsWithConfiguration);
|
||||
return t;
|
||||
} catch (Exception e) {
|
||||
// TODO: Remove reference to MapManager.
|
||||
Log.severe("Error loading maptype", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> List<T> createInstances(String path, Class<?>[] constructorParameters, Object[] constructorArguments) {
|
||||
List<ConfigurationNode> nodes = getNodes(path);
|
||||
List<T> instances = new ArrayList<T>();
|
||||
for(ConfigurationNode node : nodes) {
|
||||
T instance = node.<T>createInstance(constructorParameters, constructorArguments);
|
||||
if (instance != null) {
|
||||
instances.add(instance);
|
||||
}
|
||||
}
|
||||
return instances;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return entries.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return entries.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return entries.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
return entries.containsValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object key) {
|
||||
return entries.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object put(String key, Object value) {
|
||||
return entries.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object remove(Object key) {
|
||||
return entries.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends String, ? extends Object> m) {
|
||||
entries.putAll(m);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
entries.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> keySet() {
|
||||
return entries.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Object> values() {
|
||||
return entries.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<java.util.Map.Entry<String, Object>> entrySet() {
|
||||
return entries.entrySet();
|
||||
}
|
||||
|
||||
private class EmptyNullRepresenter extends Representer {
|
||||
|
||||
public EmptyNullRepresenter() {
|
||||
super();
|
||||
this.nullRepresenter = new EmptyRepresentNull();
|
||||
}
|
||||
|
||||
protected class EmptyRepresentNull implements Represent {
|
||||
public Node representData(Object data) {
|
||||
return representScalar(Tag.NULL, ""); // Changed "null" to "" so as to avoid writing nulls
|
||||
}
|
||||
}
|
||||
|
||||
// Code borrowed from snakeyaml (http://code.google.com/p/snakeyaml/source/browse/src/test/java/org/yaml/snakeyaml/issues/issue60/SkipBeanTest.java)
|
||||
@Override
|
||||
protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
|
||||
NodeTuple tuple = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
|
||||
Node valueNode = tuple.getValueNode();
|
||||
if (valueNode instanceof CollectionNode) {
|
||||
// Removed null check
|
||||
if (Tag.SEQ.equals(valueNode.getTag())) {
|
||||
SequenceNode seq = (SequenceNode) valueNode;
|
||||
if (seq.getValue().isEmpty()) {
|
||||
return null; // skip empty lists
|
||||
}
|
||||
}
|
||||
if (Tag.MAP.equals(valueNode.getTag())) {
|
||||
MappingNode seq = (MappingNode) valueNode;
|
||||
if (seq.getValue().isEmpty()) {
|
||||
return null; // skip empty maps
|
||||
}
|
||||
}
|
||||
}
|
||||
return tuple;
|
||||
}
|
||||
// End of borrowed code
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
public class DynmapChunk {
|
||||
public int x, z;
|
||||
|
||||
public DynmapChunk(int x, int z) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,16 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
/**
|
||||
* Generic block location
|
||||
*/
|
||||
public class DynmapLocation {
|
||||
public double x, y, z;
|
||||
public String world;
|
||||
|
||||
public DynmapLocation() {}
|
||||
|
||||
public DynmapLocation(String w, double x, double y, double z) {
|
||||
world = w;
|
||||
this.x = x; this.y = y; this.z = z;
|
||||
}
|
||||
}
|
@ -1,525 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.dynmap.debug.Debug;
|
||||
import org.dynmap.utils.DynmapBufferedImage;
|
||||
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 abstract class DynmapWorld {
|
||||
|
||||
public enum AutoGenerateOption {
|
||||
NONE,
|
||||
FORMAPONLY,
|
||||
PERMANENT
|
||||
}
|
||||
public List<MapType> maps = new ArrayList<MapType>();
|
||||
public UpdateQueue updates = new UpdateQueue();
|
||||
public ConfigurationNode configuration;
|
||||
public List<DynmapLocation> seedloc;
|
||||
public List<MapChunkCache.VisibilityLimit> visibility_limits;
|
||||
public List<MapChunkCache.VisibilityLimit> hidden_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();
|
||||
@SuppressWarnings("unchecked")
|
||||
private HashSet<String> zoomoutupdates[] = new HashSet[0];
|
||||
private boolean checkts = true; /* Check timestamps on first run with new configuration */
|
||||
private boolean cancelled;
|
||||
private String wname;
|
||||
|
||||
protected DynmapWorld(String wname) {
|
||||
this.wname = wname;
|
||||
}
|
||||
@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) {
|
||||
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 >= 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(".")) {
|
||||
File fn = new File(f, n);
|
||||
return fn.isDirectory();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static final String COORDSTART = "-0123456789";
|
||||
private static class PNGFileFilter implements FilenameFilter {
|
||||
String prefix;
|
||||
String suffix;
|
||||
public PNGFileFilter(String pre, MapType.ImageFormat fmt) {
|
||||
if((pre != null) && (pre.length() > 0))
|
||||
prefix = pre;
|
||||
suffix = "." + fmt.getFileExt();
|
||||
}
|
||||
public boolean accept(File f, String n) {
|
||||
if(n.endsWith(suffix)) {
|
||||
if((prefix != null) && (!n.startsWith(prefix)))
|
||||
return false;
|
||||
if((prefix == null) && (COORDSTART.indexOf(n.charAt(0)) < 0))
|
||||
return false;
|
||||
File fn = new File(f, n);
|
||||
return fn.isFile();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void freshenZoomOutFiles() {
|
||||
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;
|
||||
int background;
|
||||
String zoomprefix;
|
||||
String fnprefix;
|
||||
String zfnprefix;
|
||||
int bigworldshift;
|
||||
boolean isbigmap;
|
||||
MapType.ImageFormat fmt;
|
||||
}
|
||||
|
||||
public boolean freshenZoomOutFilesByLevel(int zoomlevel) {
|
||||
int cnt = 0;
|
||||
Debug.debug("freshenZoomOutFiles(" + wname + "," + zoomlevel + ")");
|
||||
if(worldtilepath.exists() == false) /* Quit if not found */
|
||||
return true;
|
||||
HashMap<String, PrefixData> maptab = buildPrefixData(zoomlevel);
|
||||
|
||||
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(" + wname + "," + 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Do processing */
|
||||
for(ProcessTileRec s : toprocess.values()) {
|
||||
if(cancelled) return true;
|
||||
processZoomTile(s.pd, s.zf, s.zfname, s.x, s.y);
|
||||
}
|
||||
}
|
||||
/* 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<MapType.ZoomInfo> pfx = mt.baseZoomFileInfo();
|
||||
int stepsize = mt.baseZoomFileStepSize();
|
||||
int bigworldshift = mt.getBigWorldShift();
|
||||
boolean neg_step_x = false;
|
||||
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(MapType.ZoomInfo 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.prefix;
|
||||
pd.background = p.background_argb;
|
||||
pd.zoomlevel = zoomlevel;
|
||||
pd.zoomprefix = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz".substring(0, zoomlevel);
|
||||
pd.bigworldshift = bigworldshift;
|
||||
pd.isbigmap = mt.isBigWorldMap(this);
|
||||
pd.fmt = mt.getImageFormat();
|
||||
if(pd.isbigmap) {
|
||||
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.prefix, pd);
|
||||
}
|
||||
}
|
||||
return maptab;
|
||||
}
|
||||
|
||||
private static class ProcessTileRec {
|
||||
File zf;
|
||||
String zfname;
|
||||
int x, y;
|
||||
PrefixData pd;
|
||||
}
|
||||
|
||||
private String makeFilePath(PrefixData pd, int x, int y, boolean zoomed) {
|
||||
if(pd.isbigmap)
|
||||
return pd.baseprefix + "/" + (x >> pd.bigworldshift) + "_" + (y >> pd.bigworldshift) + "/" + (zoomed?pd.zfnprefix:pd.fnprefix) + x + "_" + y + "." + pd.fmt.getFileExt();
|
||||
else
|
||||
return (zoomed?pd.zfnprefix:pd.fnprefix) + "_" + x + "_" + y + "." + pd.fmt.getFileExt();
|
||||
}
|
||||
|
||||
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, pd.fmt));
|
||||
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(s.pd, 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(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);
|
||||
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;
|
||||
rec.pd = pd;
|
||||
Debug.debug("Process " + zf.getPath() + " due to " + f.getPath());
|
||||
return rec;
|
||||
}
|
||||
|
||||
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;
|
||||
DynmapBufferedImage kzIm = null;
|
||||
boolean blank = true;
|
||||
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 = DynmapBufferedImage.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();
|
||||
blank = false;
|
||||
/* Do binlinear scale to 64x64 */
|
||||
int off = 0;
|
||||
for(int y = 0; y < height; y += 2) {
|
||||
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 */
|
||||
zIm.setRGB(((i>>1) != 0)?0:width/2, (i & 1) * height/2, width/2, height/2, argb, 0, width);
|
||||
}
|
||||
else {
|
||||
Arrays.fill(argb, pd.background);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Arrays.fill(argb, pd.background);
|
||||
}
|
||||
/* 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 {
|
||||
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 = zty/step/2;
|
||||
String key = wname+".z"+pd.zoomprefix+pd.baseprefix;
|
||||
if(blank) {
|
||||
if(zf.exists()) {
|
||||
zf.delete();
|
||||
hashman.updateHashCode(key, null, tilex, tiley, -1);
|
||||
MapManager.mapman.pushUpdate(this, new Client.Tile(zfname));
|
||||
enqueueZoomOutUpdate(zf, pd.zoomlevel+1);
|
||||
}
|
||||
}
|
||||
else if((!zf.exists()) || (crc != mm.hashman.getImageHashCode(key, null, tilex, tiley))) {
|
||||
try {
|
||||
if(!zf.getParentFile().exists())
|
||||
zf.getParentFile().mkdirs();
|
||||
FileLockManager.imageIOWrite(zIm, pd.fmt, 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, new Client.Tile(zfname));
|
||||
enqueueZoomOutUpdate(zf, pd.zoomlevel+1);
|
||||
}
|
||||
} finally {
|
||||
FileLockManager.releaseWriteLock(zf);
|
||||
DynmapBufferedImage.freeBufferedImage(kzIm);
|
||||
}
|
||||
}
|
||||
/* Get world name */
|
||||
public String getName() {
|
||||
return wname;
|
||||
}
|
||||
/* Test if world is nether */
|
||||
public abstract boolean isNether();
|
||||
/* Get world spawn location */
|
||||
public abstract DynmapLocation getSpawnLocation();
|
||||
|
||||
public int hashCode() {
|
||||
return wname.hashCode();
|
||||
}
|
||||
/* Get world time */
|
||||
public abstract long getTime();
|
||||
/* World is storming */
|
||||
public abstract boolean hasStorm();
|
||||
/* World is thundering */
|
||||
public abstract boolean isThundering();
|
||||
/* World is loaded */
|
||||
public abstract boolean isLoaded();
|
||||
/* Get light level of block */
|
||||
public abstract int getLightLevel(int x, int y, int z);
|
||||
/* Get highest Y coord of given location */
|
||||
public abstract int getHighestBlockYAt(int x, int z);
|
||||
/* Test if sky light level is requestable */
|
||||
public abstract boolean canGetSkyLightLevel();
|
||||
/* Return sky light level */
|
||||
public abstract int getSkyLightLevel(int x, int y, int z);
|
||||
/**
|
||||
* Get world environment ID (lower case - normal, the_end, nether)
|
||||
*/
|
||||
public abstract String getEnvironment();
|
||||
/**
|
||||
* Get map chunk cache for world
|
||||
*/
|
||||
public abstract MapChunkCache getChunkCache(List<DynmapChunk> chunks);
|
||||
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
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 void addListener(Listener<T> l) {
|
||||
synchronized(lock) {
|
||||
listeners.add(l);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeListener(Listener<T> l) {
|
||||
synchronized(lock) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public interface Listener<T> {
|
||||
void triggered(T t);
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package org.dynmap;
|
||||
import java.util.HashMap;
|
||||
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;
|
||||
if (genericEvent != null) {
|
||||
event = (Event<T>)genericEvent;
|
||||
} else {
|
||||
events.put(eventName, event = new Event<T>());
|
||||
}
|
||||
event.addListener(listener);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> void removeListener(String eventName, Event.Listener<T> listener) {
|
||||
Event<?> genericEvent = events.get(eventName);
|
||||
Event<T> event = null;
|
||||
if (genericEvent != null) {
|
||||
event = (Event<T>)genericEvent;
|
||||
event.removeListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> void trigger(String eventName, T argument) {
|
||||
Event<?> genericEvent = events.get(eventName);
|
||||
if (genericEvent == null)
|
||||
return;
|
||||
((Event<T>)genericEvent).trigger(argument);
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
public interface Handler<T> {
|
||||
void handle(T t);
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import org.dynmap.servlet.ClientUpdateServlet;
|
||||
import org.dynmap.servlet.SendMessageServlet;
|
||||
import org.json.simple.JSONObject;
|
||||
import static org.dynmap.JSONUtils.*;
|
||||
|
||||
public class InternalClientUpdateComponent extends ClientUpdateComponent {
|
||||
|
||||
public InternalClientUpdateComponent(final DynmapCore dcore, final ConfigurationNode configuration) {
|
||||
super(dcore, configuration);
|
||||
dcore.addServlet("/up/world/*", new ClientUpdateServlet(dcore));
|
||||
|
||||
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 = dcore.configuration.getString("spammessage", "You may only chat once every %interval% seconds.");
|
||||
final Boolean use_player_ip = configuration.getBoolean("use-player-login-ip", true);
|
||||
final Boolean req_player_ip = configuration.getBoolean("require-player-login-ip", false);
|
||||
final Boolean block_banned_player_chat = configuration.getBoolean("block-banned-player-chat", false);
|
||||
|
||||
dcore.events.addListener("buildclientconfiguration", new Event.Listener<JSONObject>() {
|
||||
@Override
|
||||
public void triggered(JSONObject t) {
|
||||
s(t, "allowwebchat", allowwebchat);
|
||||
s(t, "webchat-interval", webchatInterval);
|
||||
}
|
||||
});
|
||||
|
||||
if (allowwebchat) {
|
||||
@SuppressWarnings("serial")
|
||||
SendMessageServlet messageHandler = new SendMessageServlet() {{
|
||||
maximumMessageInterval = (int)(webchatInterval * 1000);
|
||||
spamMessage = "\""+spammessage+"\"";
|
||||
hideip = hidewebchatip;
|
||||
this.trustclientname = trust_client_name;
|
||||
this.use_player_login_ip = use_player_ip;
|
||||
this.require_player_login_ip = req_player_ip;
|
||||
this.check_user_ban = block_banned_player_chat;
|
||||
this.core = dcore;
|
||||
|
||||
onMessageReceived.addListener(new Event.Listener<Message> () {
|
||||
@Override
|
||||
public void triggered(Message t) {
|
||||
webChat(t.name, t.message);
|
||||
}
|
||||
});
|
||||
}};
|
||||
dcore.addServlet("/up/sendmessage", messageHandler);
|
||||
}
|
||||
}
|
||||
|
||||
protected void webChat(String name, String message) {
|
||||
if(core.mapManager == null)
|
||||
return;
|
||||
// TODO: Change null to something meaningful.
|
||||
core.mapManager.pushUpdate(new Client.ChatMessage("web", null, name, message, null));
|
||||
Log.info(unescapeString(core.configuration.getString("webprefix", "\u00A72[WEB] ")) + name + ": " + unescapeString(core.configuration.getString("websuffix", "\u00A7f")) + message);
|
||||
ChatEvent event = new ChatEvent("web", name, message);
|
||||
core.events.trigger("webchat", event);
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class JSONUtils {
|
||||
|
||||
// Gets a value at the specified path.
|
||||
public static Object g(JSONObject o, String path) {
|
||||
int index = path.indexOf('/');
|
||||
if (index == -1) {
|
||||
return o.get(path);
|
||||
} else {
|
||||
String key = path.substring(0, index);
|
||||
String subpath = path.substring(index+1);
|
||||
Object oo = o.get(key);
|
||||
JSONObject subobject;
|
||||
if (oo == null) {
|
||||
return null;
|
||||
} else /*if (oo instanceof JSONObject)*/ {
|
||||
subobject = (JSONObject)o;
|
||||
}
|
||||
return g(subobject, subpath);
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
o.put(path, value);
|
||||
} else {
|
||||
String key = path.substring(0, index);
|
||||
String subpath = path.substring(index+1);
|
||||
Object oo = o.get(key);
|
||||
JSONObject subobject;
|
||||
if (oo == null) {
|
||||
subobject = new JSONObject();
|
||||
o.put(key, subobject);
|
||||
} else /*if (oo instanceof JSONObject)*/ {
|
||||
subobject = (JSONObject)oo;
|
||||
}
|
||||
s(subobject, subpath, value);
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
if (oo == null) {
|
||||
array =new JSONArray();
|
||||
s(o, path, array);
|
||||
} else {
|
||||
array = (JSONArray)oo;
|
||||
}
|
||||
array.add(value);
|
||||
}
|
||||
|
||||
// Simply creates a JSONArray.
|
||||
@SuppressWarnings("unchecked")
|
||||
public static JSONArray l(Object... items) {
|
||||
JSONArray arr = new JSONArray();
|
||||
for(Object item : items) {
|
||||
arr.add(item);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
}
|
@ -1,271 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.dynmap.web.Json;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
import static org.dynmap.JSONUtils.*;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||
protected long jsonInterval;
|
||||
protected long currentTimestamp = 0;
|
||||
protected long lastTimestamp = 0;
|
||||
protected JSONParser parser = new JSONParser();
|
||||
private boolean hidewebchatip;
|
||||
private boolean useplayerloginip;
|
||||
private boolean requireplayerloginip;
|
||||
private boolean trust_client_name;
|
||||
private boolean checkuserban;
|
||||
|
||||
private HashMap<String,String> useralias = new HashMap<String,String>();
|
||||
private int aliasindex = 1;
|
||||
private long last_confighash;
|
||||
|
||||
private Charset cs_utf8 = Charset.forName("UTF-8");
|
||||
public JsonFileClientUpdateComponent(final DynmapCore plugin, final ConfigurationNode configuration) {
|
||||
super(plugin, configuration);
|
||||
final boolean allowwebchat = configuration.getBoolean("allowwebchat", false);
|
||||
jsonInterval = (long)(configuration.getFloat("writeinterval", 1) * 1000);
|
||||
hidewebchatip = configuration.getBoolean("hidewebchatip", false);
|
||||
useplayerloginip = configuration.getBoolean("use-player-login-ip", true);
|
||||
requireplayerloginip = configuration.getBoolean("require-player-login-ip", false);
|
||||
trust_client_name = configuration.getBoolean("trustclientname", false);
|
||||
checkuserban = configuration.getBoolean("block-banned-player-chat", true);
|
||||
|
||||
MapManager.scheduleDelayedJob(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
currentTimestamp = System.currentTimeMillis();
|
||||
if(last_confighash != plugin.getConfigHashcode())
|
||||
writeConfiguration();
|
||||
writeUpdates();
|
||||
if (allowwebchat) {
|
||||
handleWebChat();
|
||||
}
|
||||
lastTimestamp = currentTimestamp;
|
||||
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>() {
|
||||
@Override
|
||||
public void triggered(Object t) {
|
||||
writeConfiguration();
|
||||
}
|
||||
});
|
||||
plugin.events.addListener("worldactivated", new Event.Listener<DynmapWorld>() {
|
||||
@Override
|
||||
public void triggered(DynmapWorld t) {
|
||||
writeConfiguration();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected File getStandaloneFile(String filename) {
|
||||
File webpath = new File(core.configuration.getString("webpath", "web"), "standalone/" + filename);
|
||||
if (webpath.isAbsolute())
|
||||
return webpath;
|
||||
else
|
||||
return new File(core.getDataFolder(), webpath.toString());
|
||||
}
|
||||
|
||||
private static final int RETRY_LIMIT = 5;
|
||||
protected void writeConfiguration() {
|
||||
File outputFile;
|
||||
File outputTempFile;
|
||||
JSONObject clientConfiguration = new JSONObject();
|
||||
core.events.trigger("buildclientconfiguration", clientConfiguration);
|
||||
outputFile = getStandaloneFile("dynmap_config.json");
|
||||
outputTempFile = getStandaloneFile("dynmap_config.json.new");
|
||||
last_confighash = core.getConfigHashcode();
|
||||
|
||||
int retrycnt = 0;
|
||||
boolean done = false;
|
||||
while(!done) {
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(outputTempFile);
|
||||
fos.write(clientConfiguration.toJSONString().getBytes("UTF-8"));
|
||||
fos.close();
|
||||
fos = null;
|
||||
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;
|
||||
}
|
||||
} finally {
|
||||
if(fos != null) {
|
||||
try {
|
||||
fos.close();
|
||||
} catch (IOException iox) {
|
||||
}
|
||||
fos = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void writeUpdates() {
|
||||
File outputFile;
|
||||
File outputTempFile;
|
||||
if(core.mapManager == null) return;
|
||||
//Handles Updates
|
||||
for (DynmapWorld dynmapWorld : core.mapManager.getWorlds()) {
|
||||
JSONObject update = new JSONObject();
|
||||
update.put("timestamp", currentTimestamp);
|
||||
ClientUpdateEvent clientUpdate = new ClientUpdateEvent(currentTimestamp - 30000, dynmapWorld, update);
|
||||
core.events.trigger("buildclientupdate", clientUpdate);
|
||||
|
||||
outputFile = getStandaloneFile("dynmap_" + dynmapWorld.getName() + ".json");
|
||||
outputTempFile = getStandaloneFile("dynmap_" + dynmapWorld.getName() + ".json.new");
|
||||
int retrycnt = 0;
|
||||
boolean done = false;
|
||||
while(!done) {
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(outputTempFile);
|
||||
fos.write(Json.stringifyJson(update).getBytes("UTF-8"));
|
||||
fos.close();
|
||||
fos = null;
|
||||
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;
|
||||
}
|
||||
} finally {
|
||||
if(fos != null) {
|
||||
try {
|
||||
fos.close();
|
||||
} catch (IOException iox) {
|
||||
}
|
||||
fos = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
core.events.<ClientUpdateEvent>trigger("clientupdatewritten", clientUpdate);
|
||||
}
|
||||
|
||||
core.events.<Object>trigger("clientupdateswritten", null);
|
||||
}
|
||||
|
||||
protected void handleWebChat() {
|
||||
File webchatFile = getStandaloneFile("dynmap_webchat.json");
|
||||
if (webchatFile.exists() && lastTimestamp != 0) {
|
||||
JSONArray jsonMsgs = null;
|
||||
Reader inputFileReader = null;
|
||||
try {
|
||||
inputFileReader = new InputStreamReader(new FileInputStream(webchatFile), cs_utf8);
|
||||
jsonMsgs = (JSONArray) parser.parse(inputFileReader);
|
||||
} catch (IOException ex) {
|
||||
Log.severe("Exception while reading JSON-file.", ex);
|
||||
} catch (ParseException ex) {
|
||||
Log.severe("Exception while parsing JSON-file.", ex);
|
||||
} finally {
|
||||
if(inputFileReader != null) {
|
||||
try {
|
||||
inputFileReader.close();
|
||||
} catch (IOException iox) {
|
||||
|
||||
}
|
||||
inputFileReader = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (jsonMsgs != null) {
|
||||
Iterator<?> iter = jsonMsgs.iterator();
|
||||
while (iter.hasNext()) {
|
||||
JSONObject o = (JSONObject) iter.next();
|
||||
String ts = String.valueOf(o.get("timestamp"));
|
||||
if(ts.equals("null")) ts = "0";
|
||||
if (Long.parseLong(ts) >= (lastTimestamp)) {
|
||||
String name = String.valueOf(o.get("name"));
|
||||
String ip = String.valueOf(o.get("ip"));
|
||||
boolean isip = true;
|
||||
if((!trust_client_name) || (name == null) || (name.equals(""))) {
|
||||
if(ip != null)
|
||||
name = ip;
|
||||
}
|
||||
if(useplayerloginip) { /* Try to match using IPs of player logins */
|
||||
List<String> ids = core.getIDsForIP(name);
|
||||
if(ids != null) {
|
||||
name = ids.get(0);
|
||||
isip = false;
|
||||
if(checkuserban) {
|
||||
if(core.getServer().isPlayerBanned(name)) {
|
||||
Log.info("Ignore message from '" + ip + "' - banned player (" + name + ")");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(requireplayerloginip) {
|
||||
Log.info("Ignore message from '" + name + "' - no matching player login recorded");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(hidewebchatip && isip) {
|
||||
String n = useralias.get(name);
|
||||
if(n == null) { /* Make ID */
|
||||
n = String.format("web-%03d", aliasindex);
|
||||
aliasindex++;
|
||||
useralias.put(name, n);
|
||||
}
|
||||
name = n;
|
||||
}
|
||||
String message = String.valueOf(o.get("message"));
|
||||
webChat(name, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void webChat(String name, String message) {
|
||||
if(core.mapManager == null) return;
|
||||
// TODO: Change null to something meaningful.
|
||||
core.mapManager.pushUpdate(new Client.ChatMessage("web", null, name, message, null));
|
||||
Log.info(unescapeString(core.configuration.getString("webprefix", "\u00A2[WEB] ")) + name + ": " + unescapeString(core.configuration.getString("websuffix", "\u00A7f")) + message);
|
||||
ChatEvent event = new ChatEvent("web", name, message);
|
||||
core.events.trigger("webchat", event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.util.logging.Level;
|
||||
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);
|
||||
}
|
||||
public static void severe(String msg) {
|
||||
log.log(Level.SEVERE, LOG_PREFIX + msg);
|
||||
}
|
||||
public static void severe(String msg, Exception e) {
|
||||
log.log(Level.SEVERE, LOG_PREFIX + msg, e);
|
||||
}
|
||||
public static void warning(String msg) {
|
||||
log.log(Level.WARNING, LOG_PREFIX + msg);
|
||||
}
|
||||
public static void warning(String msg, Exception e) {
|
||||
log.log(Level.WARNING, LOG_PREFIX + msg, e);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,71 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
|
||||
public abstract class MapTile {
|
||||
protected DynmapWorld world;
|
||||
|
||||
public abstract boolean render(MapChunkCache cache, String mapname);
|
||||
public abstract List<DynmapChunk> getRequiredChunks();
|
||||
public abstract MapTile[] getAdjecentTiles();
|
||||
|
||||
public DynmapWorld getDynmapWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public abstract String getFilename();
|
||||
|
||||
public abstract String getDayFilename();
|
||||
|
||||
public MapTile(DynmapWorld world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getFilename().hashCode() ^ world.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract boolean equals(Object obj);
|
||||
|
||||
public abstract String getKey(String prefix);
|
||||
|
||||
public abstract boolean isBiomeDataNeeded();
|
||||
public abstract boolean isHightestBlockYDataNeeded();
|
||||
public abstract boolean isRawBiomeDataNeeded();
|
||||
public abstract boolean isBlockTypeDataNeeded();
|
||||
|
||||
public abstract int tileOrdinalX();
|
||||
public abstract int tileOrdinalY();
|
||||
|
||||
public ConfigurationNode saveTile() {
|
||||
ConfigurationNode cn = new ConfigurationNode();
|
||||
cn.put("class", this.getClass().getName());
|
||||
cn.put("data", saveTileData());
|
||||
return cn;
|
||||
}
|
||||
|
||||
protected abstract String saveTileData();
|
||||
|
||||
public static MapTile restoreTile(DynmapWorld w, ConfigurationNode node) {
|
||||
String cn = node.getString("class");
|
||||
String dat = node.getString("data");
|
||||
if((cn == null) || (dat == null)) return null;
|
||||
try {
|
||||
Class<?> cls = Class.forName(cn);
|
||||
Constructor<?> con = cls.getConstructor(DynmapWorld.class, String.class);
|
||||
return (MapTile)con.newInstance(w, dat);
|
||||
} catch (ClassNotFoundException cnfx) {
|
||||
} catch (NoSuchMethodException nsmx) {
|
||||
} catch (InvocationTargetException itx) {
|
||||
} catch (IllegalAccessException iax) {
|
||||
} catch (InstantiationException ix) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.dynmap.utils.TileFlags;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public abstract class MapType {
|
||||
public enum ImageFormat {
|
||||
FORMAT_PNG("png", "png", 0.0f),
|
||||
FORMAT_JPG75("jpg-q75", "jpg", 0.75f),
|
||||
FORMAT_JPG80("jpg-q80", "jpg", 0.80f),
|
||||
FORMAT_JPG85("jpg-q85", "jpg", 0.85f),
|
||||
FORMAT_JPG("jpg", "jpg", 0.85f),
|
||||
FORMAT_JPG90("jpg-q90", "jpg", 0.90f),
|
||||
FORMAT_JPG95("jpg-q95", "jpg", 0.95f),
|
||||
FORMAT_JPG100("jpg-q100", "jpg", 1.00f);
|
||||
String id;
|
||||
String ext;
|
||||
float qual;
|
||||
|
||||
ImageFormat(String id, String ext, float quality) {
|
||||
this.id = id;
|
||||
this.ext = ext;
|
||||
this.qual = quality;
|
||||
}
|
||||
public String getID() { return id; }
|
||||
public String getFileExt() { return ext; }
|
||||
public float getQuality() { return qual; }
|
||||
};
|
||||
|
||||
public static class ZoomInfo {
|
||||
public String prefix;
|
||||
public int background_argb;
|
||||
public ZoomInfo(String pre, int bg) { prefix = pre; background_argb = bg; }
|
||||
}
|
||||
|
||||
public abstract MapTile[] getTiles(DynmapWorld w, int x, int y, int z);
|
||||
|
||||
public abstract MapTile[] getTiles(DynmapWorld w, int minx, int miny, int minz, int maxx, int maxy, int maxz);
|
||||
|
||||
public abstract MapTile[] getAdjecentTiles(MapTile tile);
|
||||
|
||||
public abstract List<DynmapChunk> getRequiredChunks(MapTile tile);
|
||||
|
||||
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 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<ZoomInfo> baseZoomFileInfo();
|
||||
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; }
|
||||
|
||||
public ImageFormat getImageFormat() { return ImageFormat.FORMAT_PNG; }
|
||||
|
||||
public int getBackgroundARGBNight() { return 0; }
|
||||
|
||||
public int getBackgroundARGBDay() { 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)
|
||||
*/
|
||||
public abstract int[] zoomFileStepSequence();
|
||||
|
||||
public void purgeOldTiles(DynmapWorld world, TileFlags rendered) { }
|
||||
|
||||
public interface FileCallback {
|
||||
public void fileFound(File f, File parent, boolean day);
|
||||
}
|
||||
|
||||
protected void walkMapTree(File root, FileCallback cb, boolean day) {
|
||||
LinkedList<File> dirs = new LinkedList<File>();
|
||||
String ext = "." + getImageFormat().getFileExt();
|
||||
dirs.add(root);
|
||||
while(dirs.isEmpty() == false) {
|
||||
File dir = dirs.pop();
|
||||
String[] lst = dir.list();
|
||||
for(String fn : lst) {
|
||||
if(fn.equals(".") || fn.equals(".."))
|
||||
continue;
|
||||
File f = new File(dir, fn);
|
||||
if(f.isDirectory()) { /* If directory, add to list to process */
|
||||
dirs.add(f);
|
||||
}
|
||||
else if(fn.endsWith(ext)) { /* Else, if matches suffix */
|
||||
cb.fileFound(f, dir, day);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,207 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import org.dynmap.common.DynmapListenerManager.EventType;
|
||||
import org.dynmap.common.DynmapListenerManager.WorldEventListener;
|
||||
import org.dynmap.common.DynmapListenerManager.PlayerEventListener;
|
||||
import org.dynmap.common.DynmapPlayer;
|
||||
import org.dynmap.markers.Marker;
|
||||
import org.dynmap.markers.MarkerIcon;
|
||||
import org.dynmap.markers.MarkerSet;
|
||||
import org.dynmap.markers.impl.MarkerAPIImpl;
|
||||
import org.dynmap.markers.impl.MarkerSignManager;
|
||||
|
||||
/**
|
||||
* Markers component - ties in the component system, both on the server and client
|
||||
*/
|
||||
public class MarkersComponent extends ClientComponent {
|
||||
private MarkerAPIImpl api;
|
||||
private MarkerSignManager signmgr;
|
||||
private MarkerIcon spawnicon;
|
||||
private String spawnlbl;
|
||||
private MarkerSet offlineset;
|
||||
private MarkerIcon offlineicon;
|
||||
private MarkerSet spawnbedset;
|
||||
private MarkerIcon spawnbedicon;
|
||||
private String spawnbedformat;
|
||||
private static final String OFFLINE_PLAYERS_SETID = "offline_players";
|
||||
private static final String PLAYER_SPAWN_BED_SETID = "spawn_beds";
|
||||
|
||||
public MarkersComponent(final DynmapCore core, ConfigurationNode configuration) {
|
||||
super(core, configuration);
|
||||
/* Register API with plugin, if needed */
|
||||
if(core.markerAPIInitialized()) {
|
||||
api = (MarkerAPIImpl)core.getMarkerAPI();
|
||||
}
|
||||
else {
|
||||
api = MarkerAPIImpl.initializeMarkerAPI(core);
|
||||
core.registerMarkerAPI(api);
|
||||
}
|
||||
/* If configuration has enabled sign support, prime it too */
|
||||
if(configuration.getBoolean("enablesigns", false)) {
|
||||
signmgr = MarkerSignManager.initializeSignManager(core);
|
||||
}
|
||||
/* If we're posting spawn point markers, initialize and add world listener */
|
||||
if(configuration.getBoolean("showspawn", false)) {
|
||||
String ico = configuration.getString("spawnicon", MarkerIcon.WORLD);
|
||||
spawnlbl = configuration.getString("spawnlabel", "Spawn");
|
||||
spawnicon = api.getMarkerIcon(ico); /* Load it */
|
||||
if(spawnicon == null) {
|
||||
spawnicon = api.getMarkerIcon(MarkerIcon.WORLD);
|
||||
}
|
||||
/* Add listener for world loads */
|
||||
WorldEventListener wel = new WorldEventListener() {
|
||||
@Override
|
||||
public void worldEvent(DynmapWorld w) {
|
||||
DynmapLocation loc = w.getSpawnLocation(); /* Get location of spawn */
|
||||
if(loc != null)
|
||||
addUpdateWorld(w, loc);
|
||||
}
|
||||
};
|
||||
core.listenerManager.addListener(EventType.WORLD_LOAD, wel);
|
||||
/* Add listener for spawn changes */
|
||||
core.listenerManager.addListener(EventType.WORLD_SPAWN_CHANGE, wel);
|
||||
|
||||
/* Initialize already loaded worlds */
|
||||
for(DynmapWorld w : core.getMapManager().getWorlds()) {
|
||||
DynmapLocation loc = w.getSpawnLocation();
|
||||
if(loc != null)
|
||||
addUpdateWorld(w, loc);
|
||||
}
|
||||
}
|
||||
/* If showing offline players as markers */
|
||||
if(configuration.getBoolean("showofflineplayers", false)) {
|
||||
/* Make set, if needed */
|
||||
offlineset = api.getMarkerSet(OFFLINE_PLAYERS_SETID);
|
||||
if(offlineset == null) {
|
||||
offlineset = api.createMarkerSet(OFFLINE_PLAYERS_SETID, configuration.getString("offlinelabel", "Offline"), null, true);
|
||||
}
|
||||
offlineset.setHideByDefault(configuration.getBoolean("offlinehidebydefault", true));
|
||||
offlineset.setMinZoom(configuration.getInteger("offlineminzoom", 0));
|
||||
|
||||
offlineicon = api.getMarkerIcon(configuration.getString("offlineicon", "offlineuser"));
|
||||
|
||||
/* Add listener for players coming and going */
|
||||
core.listenerManager.addListener(EventType.PLAYER_JOIN, new PlayerEventListener() {
|
||||
@Override
|
||||
public void playerEvent(DynmapPlayer p) {
|
||||
Marker m = offlineset.findMarker(p.getName());
|
||||
if(m != null) {
|
||||
m.deleteMarker();
|
||||
}
|
||||
}
|
||||
});
|
||||
core.listenerManager.addListener(EventType.PLAYER_QUIT, new PlayerEventListener() {
|
||||
@Override
|
||||
public void playerEvent(DynmapPlayer p) {
|
||||
String pname = p.getName();
|
||||
Marker m = offlineset.findMarker(pname);
|
||||
if(m != null) {
|
||||
m.deleteMarker();
|
||||
}
|
||||
if(core.playerList.isVisiblePlayer(pname)) {
|
||||
DynmapLocation loc = p.getLocation();
|
||||
m = offlineset.createMarker(p.getName(), core.getServer().stripChatColor(p.getDisplayName()), false,
|
||||
loc.world, loc.x, loc.y, loc.z, offlineicon, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
/* Make set, if needed */
|
||||
offlineset = api.getMarkerSet(OFFLINE_PLAYERS_SETID);
|
||||
if(offlineset != null) {
|
||||
offlineset.deleteMarkerSet();
|
||||
}
|
||||
}
|
||||
/* If showing player spawn bed locations as markers */
|
||||
if(configuration.getBoolean("showspawnbeds", false)) {
|
||||
/* Make set, if needed */
|
||||
spawnbedset = api.getMarkerSet(PLAYER_SPAWN_BED_SETID);
|
||||
if(spawnbedset == null) {
|
||||
spawnbedset = api.createMarkerSet(PLAYER_SPAWN_BED_SETID, configuration.getString("spawnbedlabel", "Spawn Beds"), null, true);
|
||||
}
|
||||
spawnbedset.setHideByDefault(configuration.getBoolean("spawnbedhidebydefault", true));
|
||||
spawnbedset.setMinZoom(configuration.getInteger("spawnbedminzoom", 0));
|
||||
|
||||
spawnbedicon = api.getMarkerIcon(configuration.getString("spawnbedicon", "bed"));
|
||||
spawnbedformat = configuration.getString("spawnbedformat", "%name%'s bed");
|
||||
|
||||
/* Add listener for players coming and going */
|
||||
core.listenerManager.addListener(EventType.PLAYER_JOIN, new PlayerEventListener() {
|
||||
@Override
|
||||
public void playerEvent(DynmapPlayer p) {
|
||||
updatePlayer(p);
|
||||
}
|
||||
});
|
||||
core.listenerManager.addListener(EventType.PLAYER_QUIT, new PlayerEventListener() {
|
||||
@Override
|
||||
public void playerEvent(DynmapPlayer p) {
|
||||
Marker m = spawnbedset.findMarker(p.getName()+"_bed");
|
||||
if(m != null) {
|
||||
m.deleteMarker();
|
||||
}
|
||||
}
|
||||
});
|
||||
core.listenerManager.addListener(EventType.PLAYER_BED_LEAVE, new PlayerEventListener() {
|
||||
@Override
|
||||
public void playerEvent(final DynmapPlayer p) {
|
||||
core.getServer().scheduleServerTask(new Runnable() {
|
||||
public void run() {
|
||||
updatePlayer(p);
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
/* Make set, if needed */
|
||||
spawnbedset = api.getMarkerSet(PLAYER_SPAWN_BED_SETID);
|
||||
if(spawnbedset != null) {
|
||||
spawnbedset.deleteMarkerSet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePlayer(DynmapPlayer p) {
|
||||
DynmapLocation bl = p.getBedSpawnLocation();
|
||||
Marker m = spawnbedset.findMarker(p.getName()+"_bed");
|
||||
if(bl == null) { /* No bed location */
|
||||
if(m != null) {
|
||||
m.deleteMarker();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(m != null)
|
||||
m.setLocation(bl.world, bl.x, bl.y, bl.z);
|
||||
else
|
||||
m = spawnbedset.createMarker(p.getName()+"_bed", spawnbedformat.replace("%name%", core.getServer().stripChatColor(p.getDisplayName())), false,
|
||||
bl.world, bl.x, bl.y, bl.z,
|
||||
spawnbedicon, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void addUpdateWorld(DynmapWorld w, DynmapLocation loc) {
|
||||
MarkerSet ms = api.getMarkerSet(MarkerSet.DEFAULT);
|
||||
if(ms != null) {
|
||||
String spawnid = "_spawn_" + w.getName();
|
||||
Marker m = ms.findMarker(spawnid); /* See if defined */
|
||||
if(m == null) { /* Not defined yet, add it */
|
||||
ms.createMarker(spawnid, spawnlbl, w.getName(), loc.x, loc.y, loc.z,
|
||||
spawnicon, false);
|
||||
}
|
||||
else {
|
||||
m.setLocation(w.getName(), loc.z, loc.y, loc.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if(signmgr != null) {
|
||||
MarkerSignManager.terminateSignManager(this.core);
|
||||
signmgr = null;
|
||||
}
|
||||
/* Don't unregister API - other plugins might be using it, and we want to keep non-persistent markers */
|
||||
}
|
||||
}
|
@ -1,160 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.dynmap.MapType.ImageFormat;
|
||||
import org.dynmap.common.DynmapListenerManager.EventType;
|
||||
import org.dynmap.common.DynmapListenerManager.PlayerEventListener;
|
||||
import org.dynmap.common.DynmapPlayer;
|
||||
import org.dynmap.debug.Debug;
|
||||
import org.dynmap.utils.DynmapBufferedImage;
|
||||
import org.dynmap.utils.FileLockManager;
|
||||
|
||||
/**
|
||||
* Listen for player logins, and process player faces by fetching skins *
|
||||
*/
|
||||
public class PlayerFaces {
|
||||
private File facesdir;
|
||||
private File faces8x8dir;
|
||||
private File faces16x16dir;
|
||||
private File faces32x32dir;
|
||||
private boolean fetchskins;
|
||||
private boolean refreshskins;
|
||||
|
||||
private class LoadPlayerImages implements Runnable {
|
||||
public String playername;
|
||||
public LoadPlayerImages(String playername) {
|
||||
this.playername = playername;
|
||||
}
|
||||
public void run() {
|
||||
File img_8x8 = new File(faces8x8dir, playername + ".png");
|
||||
File img_16x16 = new File(faces16x16dir, playername + ".png");
|
||||
File img_32x32 = new File(faces32x32dir, playername + ".png");
|
||||
boolean has_8x8 = img_8x8.exists();
|
||||
boolean has_16x16 = img_16x16.exists();
|
||||
boolean has_32x32 = img_32x32.exists();
|
||||
boolean missing_any = !(has_8x8 && has_16x16 && has_32x32);
|
||||
|
||||
BufferedImage img = null;
|
||||
try {
|
||||
if(fetchskins && (refreshskins || missing_any)) {
|
||||
URL url = new URL("http://s3.amazonaws.com/MinecraftSkins/" + playername + ".png");
|
||||
img = ImageIO.read(url); /* Load skin for player */
|
||||
}
|
||||
} catch (IOException iox) {
|
||||
Debug.debug("Error loading skin for '" + playername + "' - " + iox);
|
||||
}
|
||||
if(img == null) {
|
||||
try {
|
||||
InputStream in = getClass().getResourceAsStream("/char.png");
|
||||
img = ImageIO.read(in); /* Load generic skin for player */
|
||||
in.close();
|
||||
} catch (IOException iox) {
|
||||
Debug.debug("Error loading default skin for '" + playername + "' - " + iox);
|
||||
}
|
||||
}
|
||||
if(img == null) { /* No image to process? Quit */
|
||||
return;
|
||||
}
|
||||
int[] faceaccessory = new int[64]; /* 8x8 of face accessory */
|
||||
/* Get buffered image for face at 8x8 */
|
||||
DynmapBufferedImage face8x8 = DynmapBufferedImage.allocateBufferedImage(8, 8);
|
||||
img.getRGB(8, 8, 8, 8, face8x8.argb_buf, 0, 8); /* Read face from image */
|
||||
img.getRGB(40, 8, 8, 8, faceaccessory, 0, 8); /* Read face accessory from image */
|
||||
/* Apply accessory to face: see if anything is transparent (if so, apply accessory */
|
||||
boolean transp = false;
|
||||
for(int i = 0; i < 64; i++) {
|
||||
if((faceaccessory[i] & 0xFF000000) == 0) {
|
||||
transp = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(transp) {
|
||||
for(int i = 0; i < 64; i++) {
|
||||
if((faceaccessory[i] & 0xFF000000) != 0)
|
||||
face8x8.argb_buf[i] = faceaccessory[i];
|
||||
}
|
||||
}
|
||||
/* Write 8x8 file */
|
||||
if(refreshskins || (!has_8x8)) {
|
||||
FileLockManager.getWriteLock(img_8x8);
|
||||
try {
|
||||
FileLockManager.imageIOWrite(face8x8.buf_img, ImageFormat.FORMAT_PNG, img_8x8);
|
||||
} catch (IOException iox) {
|
||||
Log.severe("Cannot write player icon " + img_8x8.getPath());
|
||||
}
|
||||
FileLockManager.releaseWriteLock(img_8x8);
|
||||
}
|
||||
/* Write 16x16 file */
|
||||
if(refreshskins || (!has_16x16)) {
|
||||
/* Make 16x16 version */
|
||||
DynmapBufferedImage face16x16 = DynmapBufferedImage.allocateBufferedImage(16, 16);
|
||||
for(int i = 0; i < 16; i++) {
|
||||
for(int j = 0; j < 16; j++) {
|
||||
face16x16.argb_buf[i*16+j] = face8x8.argb_buf[(i/2)*8 + (j/2)];
|
||||
}
|
||||
}
|
||||
FileLockManager.getWriteLock(img_16x16);
|
||||
try {
|
||||
FileLockManager.imageIOWrite(face16x16.buf_img, ImageFormat.FORMAT_PNG, img_16x16);
|
||||
} catch (IOException iox) {
|
||||
Log.severe("Cannot write player icon " + img_16x16.getPath());
|
||||
}
|
||||
FileLockManager.releaseWriteLock(img_16x16);
|
||||
DynmapBufferedImage.freeBufferedImage(face16x16);
|
||||
}
|
||||
|
||||
/* Write 32x32 file */
|
||||
if(refreshskins || (!has_32x32)) {
|
||||
/* Make 32x32 version */
|
||||
DynmapBufferedImage face32x32 = DynmapBufferedImage.allocateBufferedImage(32, 32);
|
||||
for(int i = 0; i < 32; i++) {
|
||||
for(int j = 0; j < 32; j++) {
|
||||
face32x32.argb_buf[i*32+j] = face8x8.argb_buf[(i/4)*8 + (j/4)];
|
||||
}
|
||||
}
|
||||
FileLockManager.getWriteLock(img_32x32);
|
||||
try {
|
||||
FileLockManager.imageIOWrite(face32x32.buf_img, ImageFormat.FORMAT_PNG, img_32x32);
|
||||
} catch (IOException iox) {
|
||||
Log.severe("Cannot write player icon " + img_32x32.getPath());
|
||||
}
|
||||
FileLockManager.releaseWriteLock(img_32x32);
|
||||
DynmapBufferedImage.freeBufferedImage(face32x32);
|
||||
}
|
||||
|
||||
DynmapBufferedImage.freeBufferedImage(face8x8);
|
||||
/* TODO: signal update for player icon to client */
|
||||
}
|
||||
}
|
||||
public PlayerFaces(DynmapCore core) {
|
||||
fetchskins = core.configuration.getBoolean("fetchskins", true); /* Control whether to fetch skins */
|
||||
refreshskins = core.configuration.getBoolean("refreshskins", true); /* Control whether to update existing fetched skins or faces */
|
||||
|
||||
core.listenerManager.addListener(EventType.PLAYER_JOIN, new PlayerEventListener() {
|
||||
@Override
|
||||
public void playerEvent(DynmapPlayer p) {
|
||||
Runnable job = new LoadPlayerImages(p.getName());
|
||||
if(fetchskins)
|
||||
MapManager.scheduleDelayedJob(job, 0);
|
||||
else
|
||||
job.run();
|
||||
}
|
||||
});
|
||||
facesdir = new File(core.getTilesFolder(), "faces");
|
||||
|
||||
facesdir.mkdirs(); /* Make sure directory exists */
|
||||
faces8x8dir = new File(facesdir, "8x8");
|
||||
faces8x8dir.mkdirs();
|
||||
faces16x16dir = new File(facesdir, "16x16");
|
||||
faces16x16dir.mkdirs();
|
||||
faces32x32dir = new File(facesdir, "32x32");
|
||||
faces32x32dir.mkdirs();
|
||||
}
|
||||
}
|
@ -1,130 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
import org.dynmap.common.DynmapPlayer;
|
||||
import org.dynmap.common.DynmapServerInterface;
|
||||
|
||||
public class PlayerList {
|
||||
private DynmapServerInterface server;
|
||||
private HashSet<String> hiddenPlayerNames = new HashSet<String>();
|
||||
private File hiddenPlayersFile;
|
||||
private ConfigurationNode configuration;
|
||||
private DynmapPlayer[] online;
|
||||
|
||||
public PlayerList(DynmapServerInterface server, File hiddenPlayersFile, ConfigurationNode configuration) {
|
||||
this.server = server;
|
||||
this.hiddenPlayersFile = hiddenPlayersFile;
|
||||
this.configuration = configuration;
|
||||
updateOnlinePlayers(null);
|
||||
}
|
||||
|
||||
public void save() {
|
||||
OutputStream stream;
|
||||
try {
|
||||
stream = new FileOutputStream(hiddenPlayersFile);
|
||||
OutputStreamWriter writer = new OutputStreamWriter(stream);
|
||||
for (String player : hiddenPlayerNames) {
|
||||
writer.write(player);
|
||||
writer.write("\n");
|
||||
}
|
||||
writer.close();
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void load() {
|
||||
try {
|
||||
Scanner scanner = new Scanner(hiddenPlayersFile);
|
||||
while (scanner.hasNextLine()) {
|
||||
String line = scanner.nextLine();
|
||||
hiddenPlayerNames.add(line);
|
||||
}
|
||||
scanner.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void hide(String playerName) {
|
||||
hiddenPlayerNames.add(playerName.toLowerCase());
|
||||
save();
|
||||
}
|
||||
|
||||
public void show(String playerName) {
|
||||
hiddenPlayerNames.remove(playerName.toLowerCase());
|
||||
save();
|
||||
}
|
||||
|
||||
public void setVisible(String playerName, boolean visible) {
|
||||
if (visible ^ configuration.getBoolean("display-whitelist", false))
|
||||
show(playerName);
|
||||
else
|
||||
hide(playerName);
|
||||
}
|
||||
|
||||
public List<DynmapPlayer> getVisiblePlayers(String worldName) {
|
||||
ArrayList<DynmapPlayer> visiblePlayers = new ArrayList<DynmapPlayer>();
|
||||
DynmapPlayer[] onlinePlayers = online; /* Use copied list - we don't call from server thread */
|
||||
boolean useWhitelist = configuration.getBoolean("display-whitelist", false);
|
||||
for (int i = 0; i < onlinePlayers.length; i++) {
|
||||
DynmapPlayer p = onlinePlayers[i];
|
||||
if(p == null) continue;
|
||||
if((worldName != null) && (p.getWorld().equals(worldName) == false)) continue;
|
||||
|
||||
if (!(useWhitelist ^ hiddenPlayerNames.contains(p.getName().toLowerCase()))) {
|
||||
visiblePlayers.add(p);
|
||||
}
|
||||
}
|
||||
return visiblePlayers;
|
||||
}
|
||||
|
||||
public List<DynmapPlayer> getVisiblePlayers() {
|
||||
return getVisiblePlayers(null);
|
||||
}
|
||||
|
||||
public List<DynmapPlayer> getHiddenPlayers() {
|
||||
ArrayList<DynmapPlayer> hidden = new ArrayList<DynmapPlayer>();
|
||||
DynmapPlayer[] onlinePlayers = online; /* Use copied list - we don't call from server thread */
|
||||
boolean useWhitelist = configuration.getBoolean("display-whitelist", false);
|
||||
for (int i = 0; i < onlinePlayers.length; i++) {
|
||||
DynmapPlayer p = onlinePlayers[i];
|
||||
if(p == null) continue;
|
||||
if (useWhitelist ^ hiddenPlayerNames.contains(p.getName().toLowerCase())) {
|
||||
hidden.add(p);
|
||||
}
|
||||
}
|
||||
return hidden;
|
||||
}
|
||||
|
||||
public boolean isVisiblePlayer(String p) {
|
||||
boolean useWhitelist = configuration.getBoolean("display-whitelist", false);
|
||||
return (!(useWhitelist ^ hiddenPlayerNames.contains(p.toLowerCase())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this from server thread to update player list safely
|
||||
*/
|
||||
void updateOnlinePlayers(String skipone) {
|
||||
DynmapPlayer[] players = server.getOnlinePlayers();
|
||||
DynmapPlayer[] pl = new DynmapPlayer[players.length];
|
||||
System.arraycopy(players, 0, pl, 0, pl.length);
|
||||
if(skipone != null) {
|
||||
for(int i = 0; i < pl.length; i++)
|
||||
if(pl[i].getName().equals(skipone))
|
||||
pl[i] = null;
|
||||
}
|
||||
online = pl;
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import static org.dynmap.JSONUtils.s;
|
||||
|
||||
import org.dynmap.common.DynmapListenerManager;
|
||||
import org.dynmap.common.DynmapListenerManager.ChatEventListener;
|
||||
import org.dynmap.common.DynmapListenerManager.EventType;
|
||||
import org.dynmap.common.DynmapPlayer;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class SimpleWebChatComponent extends Component {
|
||||
|
||||
public SimpleWebChatComponent(final DynmapCore plugin, final ConfigurationNode configuration) {
|
||||
super(plugin, configuration);
|
||||
plugin.events.addListener("webchat", new Event.Listener<ChatEvent>() {
|
||||
@Override
|
||||
public void triggered(ChatEvent t) {
|
||||
if(plugin.getServer().sendWebChatEvent(t.source, t.name, t.message)) {
|
||||
String msg;
|
||||
String msgfmt = plugin.configuration.getString("webmsgformat", null);
|
||||
if(msgfmt != null) {
|
||||
msgfmt = unescapeString(msgfmt);
|
||||
msg = msgfmt.replace("%playername%", t.name).replace("%message%", t.message);
|
||||
}
|
||||
else {
|
||||
msg = unescapeString(plugin.configuration.getString("webprefix", "\u00A72[WEB] ")) + t.name + ": " + unescapeString(plugin.configuration.getString("websuffix", "\u00A7f")) + t.message;
|
||||
}
|
||||
plugin.getServer().broadcastMessage(msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
plugin.events.addListener("buildclientconfiguration", new Event.Listener<JSONObject>() {
|
||||
@Override
|
||||
public void triggered(JSONObject t) {
|
||||
s(t, "allowchat", configuration.getBoolean("allowchat", false));
|
||||
}
|
||||
});
|
||||
|
||||
if (configuration.getBoolean("allowchat", false)) {
|
||||
plugin.listenerManager.addListener(EventType.PLAYER_CHAT, new ChatEventListener() {
|
||||
@Override
|
||||
public void chatEvent(DynmapPlayer p, String msg) {
|
||||
if(core.mapManager != null)
|
||||
core.mapManager.pushUpdate(new Client.ChatMessage("player", "", p.getDisplayName(), msg, p.getName()));
|
||||
}
|
||||
});
|
||||
plugin.listenerManager.addListener(EventType.PLAYER_JOIN, new DynmapListenerManager.PlayerEventListener() {
|
||||
@Override
|
||||
public void playerEvent(DynmapPlayer p) {
|
||||
if((core.mapManager != null) && (core.playerList != null) && (core.playerList.isVisiblePlayer(p.getName()))) {
|
||||
core.mapManager.pushUpdate(new Client.PlayerJoinMessage(p.getDisplayName(), p.getName()));
|
||||
}
|
||||
}
|
||||
});
|
||||
plugin.listenerManager.addListener(EventType.PLAYER_QUIT, new DynmapListenerManager.PlayerEventListener() {
|
||||
@Override
|
||||
public void playerEvent(DynmapPlayer p) {
|
||||
if((core.mapManager != null) && (core.playerList != null) && (core.playerList.isVisiblePlayer(p.getName()))) {
|
||||
core.mapManager.pushUpdate(new Client.PlayerQuitMessage(p.getDisplayName(), p.getName()));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
public class TestComponent extends Component {
|
||||
|
||||
public TestComponent(DynmapCore plugin, ConfigurationNode configuration) {
|
||||
super(plugin, configuration);
|
||||
Log.info("Hello! I'm a component that does stuff! Like saying what is in my configuration: " + configuration.getString("stuff"));
|
||||
}
|
||||
|
||||
}
|
@ -1,195 +0,0 @@
|
||||
package org.dynmap;
|
||||
import java.io.File;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import org.dynmap.utils.LRULinkedHashMap;
|
||||
|
||||
/**
|
||||
* Image hash code manager - used to reduce compression and notification of updated tiles that do not actually yield new content
|
||||
*
|
||||
*/
|
||||
public class TileHashManager {
|
||||
private File tiledir; /* Base tile directory */
|
||||
private boolean enabled;
|
||||
|
||||
/**
|
||||
* Each tile hash file is a 32x32 tile grid, with each file having a CRC32 hash code generated from its pre-compression frame buffer
|
||||
*/
|
||||
private static class TileHashFile {
|
||||
final String key;
|
||||
final String subtype;
|
||||
final int x; /* minimum tile coordinate / 32 */
|
||||
final int y; /* minimum tile coordinate / 32 */
|
||||
private File hf;
|
||||
TileHashFile(String key, String subtype, int x, int y) {
|
||||
this.key = key;
|
||||
if(subtype != null)
|
||||
this.subtype = subtype;
|
||||
else
|
||||
this.subtype = "";
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(!(o instanceof TileHashFile))
|
||||
return false;
|
||||
TileHashFile fo = (TileHashFile)o;
|
||||
return (x == fo.x) && (y == fo.y) && key.equals(fo.key) && (subtype.equals(fo.subtype));
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return key.hashCode() ^ subtype.hashCode() ^ (x << 16) ^ y;
|
||||
}
|
||||
|
||||
public File getHashFile(File tiledir) {
|
||||
if(hf == null) {
|
||||
String k;
|
||||
int idx = key.lastIndexOf('.'); /* Find last '.' - world name split (allows dots in world name) */
|
||||
if(idx > 0)
|
||||
k = key.substring(0, idx) + File.separatorChar + key.substring(idx+1);
|
||||
else
|
||||
k = key;
|
||||
hf = new File(tiledir, k + (subtype.equals("")?"":("." + subtype)) + "_" + x + "_" + y + ".hash");
|
||||
}
|
||||
return hf;
|
||||
}
|
||||
/* Write to file */
|
||||
public void writeToFile(File tiledir, byte[] crcbuf) {
|
||||
RandomAccessFile fd = null;
|
||||
try {
|
||||
fd = new RandomAccessFile(getHashFile(tiledir), "rw");
|
||||
fd.seek(0);
|
||||
fd.write(crcbuf);
|
||||
} catch (IOException iox) {
|
||||
Log.severe("Error writing hash file - " + getHashFile(tiledir).getPath());
|
||||
} finally {
|
||||
if(fd != null) {
|
||||
try { fd.close(); } catch (IOException iox) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Read from file */
|
||||
public void readFromFile(File tiledir, byte[] crcbuf) {
|
||||
RandomAccessFile fd = null;
|
||||
try {
|
||||
fd = new RandomAccessFile(getHashFile(tiledir), "r");
|
||||
fd.seek(0);
|
||||
fd.read(crcbuf);
|
||||
} catch (IOException iox) {
|
||||
Arrays.fill(crcbuf, (byte)0xFF);
|
||||
writeToFile(tiledir, crcbuf);
|
||||
} finally {
|
||||
if(fd != null) {
|
||||
try { fd.close(); } catch (IOException iox) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Read CRC */
|
||||
public long getCRC(int tx, int ty, byte[] crcbuf) {
|
||||
int off = (128 * (ty & 0x1F)) + (4 * (tx & 0x1F));
|
||||
long crc = 0;
|
||||
for(int i = 0; i < 4; i++)
|
||||
crc = (crc << 8) + (0xFF & (int)crcbuf[off+i]);
|
||||
return crc;
|
||||
}
|
||||
/* Set CRC */
|
||||
public void setCRC(int tx, int ty, byte[] crcbuf, long crc) {
|
||||
int off = (128 * (ty & 0x1F)) + (4 * (tx & 0x1F));
|
||||
for(int i = 0; i < 4; i++)
|
||||
crcbuf[off+i] = (byte)((crc >> ((3-i)*8)) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
private static final int MAX_CACHED_TILEHASHFILES = 25;
|
||||
private Object lock = new Object();
|
||||
private LRULinkedHashMap<TileHashFile, byte[]> tilehash = new LRULinkedHashMap<TileHashFile, byte[]>(MAX_CACHED_TILEHASHFILES);
|
||||
private LinkedList<byte[]> crcworkbufs = new LinkedList<byte[]>();
|
||||
private LinkedList<CRC32> crcs = new LinkedList<CRC32>();
|
||||
|
||||
public TileHashManager(File tileroot, boolean enabled) {
|
||||
tiledir = tileroot;
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
/* Read cached hashcode for given tile */
|
||||
public long getImageHashCode(String key, String subtype, int tx, int ty) {
|
||||
if(!enabled) {
|
||||
return -1; /* Return value that never matches */
|
||||
}
|
||||
TileHashFile thf = new TileHashFile(key, subtype, tx >> 5, ty >> 5);
|
||||
synchronized(lock) {
|
||||
byte[] crcbuf = tilehash.get(thf); /* See if we have it cached */
|
||||
if(crcbuf == null) { /* If not in cache, load it */
|
||||
crcbuf = new byte[32*32*4]; /* Get our space */
|
||||
Arrays.fill(crcbuf, (byte)0xFF); /* Fill with -1 */
|
||||
tilehash.put(thf, crcbuf); /* Add to cache */
|
||||
thf.readFromFile(tiledir, crcbuf);
|
||||
}
|
||||
return thf.getCRC(tx & 0x1F, ty & 0x1F, crcbuf);
|
||||
}
|
||||
}
|
||||
/* Calculate hash code for given buffer */
|
||||
public long calculateTileHash(int[] newbuf) {
|
||||
if(!enabled) {
|
||||
return 0; /* Return value that doesn't match */
|
||||
}
|
||||
CRC32 crc32;
|
||||
byte[] crcworkbuf;
|
||||
synchronized(lock) {
|
||||
if(crcworkbufs.isEmpty()) {
|
||||
crcworkbuf = new byte[4*newbuf.length];
|
||||
}
|
||||
else {
|
||||
crcworkbuf = crcworkbufs.removeFirst();
|
||||
}
|
||||
if(crcs.isEmpty()) {
|
||||
crc32 = new CRC32();
|
||||
}
|
||||
else {
|
||||
crc32 = crcs.removeFirst();
|
||||
crc32.reset();
|
||||
}
|
||||
}
|
||||
if(crcworkbuf.length < (4*newbuf.length)){
|
||||
crcworkbuf = new byte[4*newbuf.length];
|
||||
}
|
||||
for(int i = 0, off = 0; i < newbuf.length; i++) {
|
||||
int v = newbuf[i];
|
||||
crcworkbuf[off++] = (byte)v;
|
||||
crcworkbuf[off++] = (byte)(v>>8);
|
||||
crcworkbuf[off++] = (byte)(v>>16);
|
||||
crcworkbuf[off++] = (byte)(v>>24);
|
||||
}
|
||||
/* Calculate CRC-32 for buffer */
|
||||
crc32.update(crcworkbuf, 0, 4*newbuf.length);
|
||||
long v = crc32.getValue();
|
||||
synchronized(lock) {
|
||||
crcworkbufs.addFirst(crcworkbuf);
|
||||
crcs.addFirst(crc32);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
/* Update hashcode for given tile */
|
||||
public void updateHashCode(String key, String subtype, int tx, int ty, long newcrc) {
|
||||
if(!enabled)
|
||||
return;
|
||||
synchronized(lock) {
|
||||
/* Now, find and check existing value */
|
||||
TileHashFile thf = new TileHashFile(key, subtype, tx >> 5, ty >> 5);
|
||||
byte[] crcbuf = tilehash.get(thf); /* See if we have it cached */
|
||||
if(crcbuf == null) { /* If not in cache, load it */
|
||||
crcbuf = new byte[32*32*4]; /* Get our space */
|
||||
tilehash.put(thf, crcbuf); /* Add to cache */
|
||||
thf.readFromFile(tiledir, crcbuf);
|
||||
}
|
||||
thf.setCRC(tx & 0x1F, ty & 0x1F, crcbuf, newcrc); /* Update field */
|
||||
thf.writeToFile(tiledir, crcbuf); /* And write it out */
|
||||
}
|
||||
}
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class UpdateQueue {
|
||||
public Object lock = new Object();
|
||||
private HashMap<UpdateRec,UpdateRec> updateSet = new HashMap<UpdateRec,UpdateRec>();
|
||||
private UpdateRec orderedlist = null; /* Oldest to youngest */
|
||||
private static final long maxUpdateAge = 120000;
|
||||
private static final long ageOutPeriod = 5000;
|
||||
private long lastageout = 0;
|
||||
|
||||
private static class UpdateRec {
|
||||
Client.Update u;
|
||||
UpdateRec next;
|
||||
UpdateRec prev;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(o instanceof UpdateRec)
|
||||
return u.equals(((UpdateRec)o).u);
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return u.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
private void doAgeOut(long now) {
|
||||
/* If we're due */
|
||||
if((now < lastageout) || (now > (lastageout + ageOutPeriod))) {
|
||||
lastageout = now;
|
||||
long deadline = now - maxUpdateAge;
|
||||
while((orderedlist != null) && (orderedlist.u.timestamp < deadline)) {
|
||||
UpdateRec r = orderedlist;
|
||||
|
||||
updateSet.remove(r); /* Remove record from set */
|
||||
if(r.next == r) {
|
||||
orderedlist = null;
|
||||
}
|
||||
else {
|
||||
orderedlist = r.next;
|
||||
r.next.prev = r.prev;
|
||||
r.prev.next = r.next;
|
||||
}
|
||||
r.next = r.prev = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void pushUpdate(Client.Update obj) {
|
||||
synchronized (lock) {
|
||||
/* Do inside lock - prevent delay between time and actual work */
|
||||
long now = System.currentTimeMillis();
|
||||
doAgeOut(now); /* Consider age out */
|
||||
UpdateRec r = new UpdateRec();
|
||||
r.u = obj;
|
||||
UpdateRec oldr = updateSet.remove(r); /* Try to remove redundant event */
|
||||
if(oldr != null) { /* If found, remove from ordered list too */
|
||||
if(oldr.next == oldr) { /* Only one? */
|
||||
orderedlist = null;
|
||||
}
|
||||
else {
|
||||
if(orderedlist == oldr) { /* We're oldest? */
|
||||
orderedlist = oldr.next;
|
||||
}
|
||||
oldr.next.prev = oldr.prev;
|
||||
oldr.prev.next = oldr.next;
|
||||
}
|
||||
oldr.next = oldr.prev = null;
|
||||
}
|
||||
updateSet.put(r, r);
|
||||
/* Add to end of ordered list */
|
||||
if(orderedlist == null) {
|
||||
orderedlist = r;
|
||||
r.next = r.prev = r;
|
||||
}
|
||||
else {
|
||||
r.next = orderedlist;
|
||||
r.prev = orderedlist.prev;
|
||||
r.next.prev = r.prev.next = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<Client.Update> tmpupdates = new ArrayList<Client.Update>();
|
||||
|
||||
public Client.Update[] getUpdatedObjects(long since) {
|
||||
Client.Update[] updates;
|
||||
synchronized (lock) {
|
||||
long now = System.currentTimeMillis();
|
||||
doAgeOut(now); /* Consider age out */
|
||||
|
||||
tmpupdates.clear();
|
||||
if(orderedlist != null) {
|
||||
UpdateRec r = orderedlist.prev; /* Get newest */
|
||||
while(r != null) {
|
||||
if(r.u.timestamp >= since) {
|
||||
tmpupdates.add(r.u);
|
||||
if(r == orderedlist)
|
||||
r = null;
|
||||
else
|
||||
r = r.prev;
|
||||
}
|
||||
else {
|
||||
r = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Reverse output.
|
||||
updates = new Client.Update[tmpupdates.size()];
|
||||
for (int i = 0; i < updates.length; i++) {
|
||||
updates[i] = tmpupdates.get(updates.length-1-i);
|
||||
}
|
||||
}
|
||||
return updates;
|
||||
}
|
||||
}
|
@ -73,6 +73,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
private PermissionProvider permissions;
|
||||
private String version;
|
||||
public BukkitEventProcessor bep;
|
||||
public SnapshotCache sscache;
|
||||
|
||||
private MapManager mapManager;
|
||||
public static DynmapPlugin plugin;
|
||||
@ -227,7 +228,14 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
bname[i] = b[i].toString();
|
||||
return bname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCacheHitRate() {
|
||||
return sscache.getHitRate();
|
||||
}
|
||||
@Override
|
||||
public void resetCacheStats() {
|
||||
sscache.resetStats();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Player access abstraction class
|
||||
@ -365,6 +373,8 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
this.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
sscache = new SnapshotCache(core.getSnapShotCacheSize());
|
||||
|
||||
/* Get map manager from core */
|
||||
mapManager = core.getMapManager();
|
||||
/* Initialized the currently loaded worlds */
|
||||
@ -384,7 +394,13 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
bep.cleanup();
|
||||
/* Disable core */
|
||||
core.disableCore();
|
||||
|
||||
if(sscache != null) {
|
||||
sscache.cleanup();
|
||||
sscache = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
|
||||
DynmapCommandSender dsender;
|
||||
@ -548,7 +564,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
return;
|
||||
Location loc = event.getBlock().getLocation();
|
||||
String wn = loc.getWorld().getName();
|
||||
mapManager.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
if(onplace) {
|
||||
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockplace");
|
||||
}
|
||||
@ -560,7 +576,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
return;
|
||||
Location loc = event.getBlock().getLocation();
|
||||
String wn = loc.getWorld().getName();
|
||||
mapManager.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
if(onbreak) {
|
||||
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockbreak");
|
||||
}
|
||||
@ -572,7 +588,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
return;
|
||||
Location loc = event.getBlock().getLocation();
|
||||
String wn = loc.getWorld().getName();
|
||||
mapManager.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
if(onleaves) {
|
||||
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "leavesdecay");
|
||||
}
|
||||
@ -584,7 +600,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
return;
|
||||
Location loc = event.getBlock().getLocation();
|
||||
String wn = loc.getWorld().getName();
|
||||
mapManager.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
if(onburn) {
|
||||
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockburn");
|
||||
}
|
||||
@ -596,7 +612,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
return;
|
||||
Location loc = event.getBlock().getLocation();
|
||||
String wn = loc.getWorld().getName();
|
||||
mapManager.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
if(onblockform) {
|
||||
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockform");
|
||||
}
|
||||
@ -608,7 +624,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
return;
|
||||
Location loc = event.getBlock().getLocation();
|
||||
String wn = loc.getWorld().getName();
|
||||
mapManager.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
if(onblockfade) {
|
||||
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockfade");
|
||||
}
|
||||
@ -620,7 +636,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
return;
|
||||
Location loc = event.getBlock().getLocation();
|
||||
String wn = loc.getWorld().getName();
|
||||
mapManager.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
if(onblockspread) {
|
||||
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockspread");
|
||||
}
|
||||
@ -632,12 +648,12 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
return;
|
||||
Location loc = event.getToBlock().getLocation();
|
||||
String wn = loc.getWorld().getName();
|
||||
mapManager.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
if(onblockfromto)
|
||||
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockfromto");
|
||||
loc = event.getBlock().getLocation();
|
||||
wn = loc.getWorld().getName();
|
||||
mapManager.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
if(onblockfromto)
|
||||
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockfromto");
|
||||
}
|
||||
@ -648,7 +664,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
return;
|
||||
Location loc = event.getBlock().getLocation();
|
||||
String wn = loc.getWorld().getName();
|
||||
mapManager.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
if(onblockphysics) {
|
||||
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockphysics");
|
||||
}
|
||||
@ -668,14 +684,14 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
}
|
||||
String wn = loc.getWorld().getName();
|
||||
int x = loc.getBlockX(), y = loc.getBlockY(), z = loc.getBlockZ();
|
||||
mapManager.sscache.invalidateSnapshot(wn, x, y, z);
|
||||
sscache.invalidateSnapshot(wn, x, y, z);
|
||||
if(onpiston)
|
||||
mapManager.touch(wn, x, y, z, "pistonretract");
|
||||
for(int i = 0; i < 2; i++) {
|
||||
x += dir.getModX();
|
||||
y += dir.getModY();
|
||||
z += dir.getModZ();
|
||||
mapManager.sscache.invalidateSnapshot(wn, x, y, z);
|
||||
sscache.invalidateSnapshot(wn, x, y, z);
|
||||
if(onpiston)
|
||||
mapManager.touch(wn, x, y, z, "pistonretract");
|
||||
}
|
||||
@ -694,14 +710,14 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
}
|
||||
String wn = loc.getWorld().getName();
|
||||
int x = loc.getBlockX(), y = loc.getBlockY(), z = loc.getBlockZ();
|
||||
mapManager.sscache.invalidateSnapshot(wn, x, y, z);
|
||||
sscache.invalidateSnapshot(wn, x, y, z);
|
||||
if(onpiston)
|
||||
mapManager.touch(wn, x, y, z, "pistonretract");
|
||||
for(int i = 0; i < 1+event.getLength(); i++) {
|
||||
x += dir.getModX();
|
||||
y += dir.getModY();
|
||||
z += dir.getModZ();
|
||||
mapManager.sscache.invalidateSnapshot(wn, x, y, z);
|
||||
sscache.invalidateSnapshot(wn, x, y, z);
|
||||
if(onpiston)
|
||||
mapManager.touch(wn, x, y, z, "pistonretract");
|
||||
}
|
||||
@ -794,7 +810,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
if(z < minz) minz = z;
|
||||
if(z > maxz) maxz = z;
|
||||
}
|
||||
mapManager.sscache.invalidateSnapshot(wname, minx, miny, minz, maxx, maxy, maxz);
|
||||
sscache.invalidateSnapshot(wname, minx, miny, minz, maxx, maxy, maxz);
|
||||
if(onexplosion) {
|
||||
mapManager.touchVolume(wname, minx, miny, minz, maxx, maxy, maxz, "entityexplode");
|
||||
}
|
||||
|
@ -481,7 +481,7 @@ public class NewMapChunkCache implements MapChunkCache {
|
||||
}
|
||||
}
|
||||
/* Check if cached chunk snapshot found */
|
||||
ChunkSnapshot ss = MapManager.mapman.sscache.getSnapshot(w.getName(), chunk.x, chunk.z, blockdata, biome, biomeraw, highesty);
|
||||
ChunkSnapshot ss = DynmapPlugin.plugin.sscache.getSnapshot(w.getName(), chunk.x, chunk.z, blockdata, biome, biomeraw, highesty);
|
||||
if(ss != null) {
|
||||
if(!vis) {
|
||||
if(hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN)
|
||||
@ -518,7 +518,7 @@ public class NewMapChunkCache implements MapChunkCache {
|
||||
else
|
||||
ss = w.getEmptyChunkSnapshot(chunk.x, chunk.z, biome, biomeraw);
|
||||
if(ss != null) {
|
||||
MapManager.mapman.sscache.putSnapshot(w.getName(), chunk.x, chunk.z, ss, blockdata, biome, biomeraw, highesty);
|
||||
DynmapPlugin.plugin.sscache.putSnapshot(w.getName(), chunk.x, chunk.z, ss, blockdata, biome, biomeraw, highesty);
|
||||
}
|
||||
}
|
||||
snaparray[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = ss;
|
||||
|
@ -1,33 +0,0 @@
|
||||
package org.dynmap.common;
|
||||
|
||||
/* Generic biome mapping */
|
||||
public enum BiomeMap {
|
||||
NULL,
|
||||
RAINFOREST,
|
||||
SWAMPLAND,
|
||||
SEASONAL_FOREST,
|
||||
FOREST,
|
||||
SAVANNA,
|
||||
SHRUBLAND,
|
||||
TAIGA,
|
||||
DESERT,
|
||||
PLAINS,
|
||||
ICE_DESERT,
|
||||
TUNDRA,
|
||||
HELL,
|
||||
SKY,
|
||||
OCEAN,
|
||||
RIVER,
|
||||
EXTREME_HILLS,
|
||||
FROZEN_OCEAN,
|
||||
FROZEN_RIVER,
|
||||
ICE_PLAINS,
|
||||
ICE_MOUNTAINS,
|
||||
MUSHROOM_ISLAND,
|
||||
MUSHROOM_SHORE,
|
||||
BEACH,
|
||||
DESERT_HILLS,
|
||||
FOREST_HILLS,
|
||||
TAIGA_HILLS,
|
||||
SMALL_MOUNTAINS
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package org.dynmap.common;
|
||||
|
||||
|
||||
public enum DynmapChatColor {
|
||||
BLACK(0x0),
|
||||
DARK_BLUE(0x1),
|
||||
DARK_GREEN(0x2),
|
||||
DARK_AQUA(0x3),
|
||||
DARK_RED(0x4),
|
||||
DARK_PURPLE(0x5),
|
||||
GOLD(0x6),
|
||||
GRAY(0x7),
|
||||
DARK_GRAY(0x8),
|
||||
BLUE(0x9),
|
||||
GREEN(0xA),
|
||||
AQUA(0xB),
|
||||
RED(0xC),
|
||||
LIGHT_PURPLE(0xD),
|
||||
YELLOW(0xE),
|
||||
WHITE(0xF);
|
||||
|
||||
private final String str;
|
||||
|
||||
private DynmapChatColor(final int code) {
|
||||
this.str = String.format("\u00A7%x", code);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return str;
|
||||
}
|
||||
public static String stripColor(final String input) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
return input.replaceAll("(?i)\u00A7[0-9A-F]", "");
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package org.dynmap.common;
|
||||
|
||||
public interface DynmapCommandSender {
|
||||
/**
|
||||
* Does command sender have given security privilege
|
||||
* @param privid - privilege ID
|
||||
* @return true if it does, false if it doesn't
|
||||
*/
|
||||
public boolean hasPrivilege(String privid);
|
||||
/**
|
||||
* Send given message to command sender
|
||||
* @param msg - message to be sent (with color codes marked &0 to &F)
|
||||
*/
|
||||
public void sendMessage(String msg);
|
||||
/**
|
||||
* Test if command sender is still connected/online
|
||||
* @return true if connected, false if not
|
||||
*/
|
||||
public boolean isConnected();
|
||||
/**
|
||||
* Is operator privilege
|
||||
*/
|
||||
public boolean isOp();
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
package org.dynmap.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.DynmapWorld;
|
||||
|
||||
/**
|
||||
* Simple handler for managing event listeners and dispatch in a neutral fashion
|
||||
*
|
||||
*/
|
||||
public class DynmapListenerManager {
|
||||
private DynmapCore core;
|
||||
|
||||
public DynmapListenerManager(DynmapCore core) {
|
||||
this.core = core;
|
||||
}
|
||||
public interface EventListener {
|
||||
}
|
||||
public interface WorldEventListener extends EventListener {
|
||||
public void worldEvent(DynmapWorld w);
|
||||
}
|
||||
public interface PlayerEventListener extends EventListener {
|
||||
public void playerEvent(DynmapPlayer p);
|
||||
}
|
||||
public interface ChatEventListener extends EventListener {
|
||||
public void chatEvent(DynmapPlayer p, String msg);
|
||||
}
|
||||
public interface BlockEventListener extends EventListener {
|
||||
public void blockEvent(int blkid, String w, int x, int y, int z);
|
||||
}
|
||||
public interface SignChangeEventListener extends EventListener {
|
||||
public void signChangeEvent(int blkid, String w, int x, int y, int z, String[] lines, DynmapPlayer p);
|
||||
}
|
||||
public enum EventType {
|
||||
WORLD_LOAD,
|
||||
WORLD_UNLOAD,
|
||||
WORLD_SPAWN_CHANGE,
|
||||
PLAYER_JOIN,
|
||||
PLAYER_QUIT,
|
||||
PLAYER_BED_LEAVE,
|
||||
PLAYER_CHAT,
|
||||
BLOCK_BREAK,
|
||||
SIGN_CHANGE
|
||||
}
|
||||
private Map<EventType, ArrayList<EventListener>> listeners = new EnumMap<EventType, ArrayList<EventListener>>(EventType.class);
|
||||
|
||||
public void addListener(EventType type, EventListener listener) {
|
||||
ArrayList<EventListener> lst = listeners.get(type);
|
||||
if(lst == null) {
|
||||
lst = new ArrayList<EventListener>();
|
||||
listeners.put(type, lst);
|
||||
core.getServer().requestEventNotification(type);
|
||||
}
|
||||
lst.add(listener);
|
||||
}
|
||||
|
||||
public void processWorldEvent(EventType type, DynmapWorld w) {
|
||||
ArrayList<EventListener> lst = listeners.get(type);
|
||||
if(lst == null) return;
|
||||
int sz = lst.size();
|
||||
for(int i = 0; i < sz; i++) {
|
||||
EventListener el = lst.get(i);
|
||||
if(el instanceof WorldEventListener) {
|
||||
((WorldEventListener)el).worldEvent(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void processPlayerEvent(EventType type, DynmapPlayer p) {
|
||||
ArrayList<EventListener> lst = listeners.get(type);
|
||||
if(lst == null) return;
|
||||
int sz = lst.size();
|
||||
for(int i = 0; i < sz; i++) {
|
||||
EventListener el = lst.get(i);
|
||||
if(el instanceof PlayerEventListener) {
|
||||
((PlayerEventListener)el).playerEvent(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void processChatEvent(EventType type, DynmapPlayer p, String msg) {
|
||||
ArrayList<EventListener> lst = listeners.get(type);
|
||||
if(lst == null) return;
|
||||
int sz = lst.size();
|
||||
for(int i = 0; i < sz; i++) {
|
||||
EventListener el = lst.get(i);
|
||||
if(el instanceof ChatEventListener) {
|
||||
((ChatEventListener)el).chatEvent(p, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void processBlockEvent(EventType type, int blkid, String world, int x, int y, int z)
|
||||
{
|
||||
ArrayList<EventListener> lst = listeners.get(type);
|
||||
if(lst == null) return;
|
||||
int sz = lst.size();
|
||||
for(int i = 0; i < sz; i++) {
|
||||
EventListener el = lst.get(i);
|
||||
if(el instanceof BlockEventListener) {
|
||||
((BlockEventListener)el).blockEvent(blkid, world, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void processSignChangeEvent(EventType type, int blkid, String world, int x, int y, int z, String[] lines, DynmapPlayer p)
|
||||
{
|
||||
ArrayList<EventListener> lst = listeners.get(type);
|
||||
if(lst == null) return;
|
||||
int sz = lst.size();
|
||||
for(int i = 0; i < sz; i++) {
|
||||
EventListener el = lst.get(i);
|
||||
if(el instanceof SignChangeEventListener) {
|
||||
((SignChangeEventListener)el).signChangeEvent(blkid, world, x, y, z, lines, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Clean up registered listeners */
|
||||
public void cleanup() {
|
||||
for(ArrayList<EventListener> l : listeners.values())
|
||||
l.clear();
|
||||
listeners.clear();
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package org.dynmap.common;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import org.dynmap.DynmapLocation;
|
||||
|
||||
/**
|
||||
* Player (server neutral) - represents online or offline player
|
||||
*/
|
||||
public interface DynmapPlayer extends DynmapCommandSender {
|
||||
/**
|
||||
* Get player ID
|
||||
* @return ID (case insensitive)
|
||||
*/
|
||||
public String getName();
|
||||
/**
|
||||
* Get player display name
|
||||
* @return display name
|
||||
*/
|
||||
public String getDisplayName();
|
||||
/**
|
||||
* Is player online?
|
||||
* @return true if online
|
||||
*/
|
||||
public boolean isOnline();
|
||||
/**
|
||||
* Get current location of player
|
||||
* @return location
|
||||
*/
|
||||
public DynmapLocation getLocation();
|
||||
/**
|
||||
* Get world ID of player
|
||||
* @return id
|
||||
*/
|
||||
public String getWorld();
|
||||
/**
|
||||
* Get connected address for player
|
||||
*/
|
||||
public InetSocketAddress getAddress();
|
||||
/**
|
||||
* Check if player is sneaking
|
||||
*/
|
||||
public boolean isSneaking();
|
||||
/**
|
||||
* Get health
|
||||
*/
|
||||
public int getHealth();
|
||||
/**
|
||||
* Get armor points
|
||||
*/
|
||||
public int getArmorPoints();
|
||||
/**
|
||||
* Get spawn bed location
|
||||
*/
|
||||
public DynmapLocation getBedSpawnLocation();
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
package org.dynmap.common;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.dynmap.common.DynmapListenerManager.EventType;
|
||||
|
||||
/**
|
||||
* This interface defines a server-neutral interface for the DynmapCore and other neutral components to use to access server provided
|
||||
* services. Platform-specific plugin must supply DynmapCore with an instance of an object implementing this interface.
|
||||
*/
|
||||
public interface DynmapServerInterface {
|
||||
/**
|
||||
* Schedule task to run on server-safe thread (one suitable for other server API calls)
|
||||
* @param run - runnable method
|
||||
* @param delay - delay in server ticks (50msec)
|
||||
*/
|
||||
public void scheduleServerTask(Runnable run, long delay);
|
||||
/**
|
||||
* Call method on server-safe thread
|
||||
* @param call - Callable method
|
||||
* @return future for completion of call
|
||||
*/
|
||||
public <T> Future<T> callSyncMethod(Callable<T> task);
|
||||
/**
|
||||
* Get list of online players
|
||||
* @return list of online players
|
||||
*/
|
||||
public DynmapPlayer[] getOnlinePlayers();
|
||||
/**
|
||||
* Request reload of plugin
|
||||
*/
|
||||
public void reload();
|
||||
/**
|
||||
* Get active player
|
||||
* @param name - player name
|
||||
* @return player
|
||||
*/
|
||||
public DynmapPlayer getPlayer(String name);
|
||||
/**
|
||||
* Get banned IPs
|
||||
*/
|
||||
public Set<String> getIPBans();
|
||||
/**
|
||||
* Get server name
|
||||
*/
|
||||
public String getServerName();
|
||||
/**
|
||||
* Test if player ID is banned
|
||||
*/
|
||||
public boolean isPlayerBanned(String pid);
|
||||
/**
|
||||
* Strip out chat color
|
||||
*/
|
||||
public String stripChatColor(String s);
|
||||
/**
|
||||
* Request notificiation for given events (used by DynmapListenerManager)
|
||||
*/
|
||||
public boolean requestEventNotification(EventType type);
|
||||
/**
|
||||
* Send notification of web chat message
|
||||
* @param source - source
|
||||
* @param name - name
|
||||
* @param msg - message text
|
||||
* @return true if not cancelled
|
||||
*/
|
||||
public boolean sendWebChatEvent(String source, String name, String msg);
|
||||
/**
|
||||
* Broadcast message to players
|
||||
* @param msg
|
||||
*/
|
||||
public void broadcastMessage(String msg);
|
||||
/**
|
||||
* Get Biome ID list
|
||||
*/
|
||||
public String[] getBiomeIDs();
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package org.dynmap.debug;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Debug {
|
||||
private static ArrayList<Debugger> debuggers = new ArrayList<Debugger>();
|
||||
|
||||
public synchronized static void addDebugger(Debugger d) {
|
||||
debuggers.add(d);
|
||||
}
|
||||
|
||||
public synchronized static void removeDebugger(Debugger d) {
|
||||
debuggers.remove(d);
|
||||
}
|
||||
|
||||
public synchronized static void clearDebuggers() {
|
||||
debuggers.clear();
|
||||
}
|
||||
|
||||
public synchronized static void debug(String message) {
|
||||
for(int i = 0; i < debuggers.size(); i++) debuggers.get(i).debug(message);
|
||||
}
|
||||
|
||||
public synchronized static void error(String message) {
|
||||
for(int i = 0; i < debuggers.size(); i++) debuggers.get(i).error(message);
|
||||
}
|
||||
|
||||
public synchronized static void error(String message, Throwable thrown) {
|
||||
for(int i = 0; i < debuggers.size(); i++) debuggers.get(i).error(message, thrown);
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package org.dynmap.debug;
|
||||
|
||||
public interface Debugger {
|
||||
void debug(String message);
|
||||
|
||||
void error(String message);
|
||||
|
||||
void error(String message, Throwable thrown);
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package org.dynmap.debug;
|
||||
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.Log;
|
||||
|
||||
public class LogDebugger implements Debugger {
|
||||
public LogDebugger(DynmapCore core, ConfigurationNode configuration) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String message) {
|
||||
Log.info(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message) {
|
||||
Log.severe(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message, Throwable thrown) {
|
||||
Log.severe(message);
|
||||
thrown.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
package org.dynmap.debug;
|
||||
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.DynmapCore;
|
||||
|
||||
public class NullDebugger implements Debugger {
|
||||
public static final NullDebugger instance = new NullDebugger(null, null);
|
||||
|
||||
public NullDebugger(DynmapCore core, ConfigurationNode configuration) {
|
||||
}
|
||||
|
||||
public void debug(String message) {
|
||||
}
|
||||
|
||||
public void error(String message) {
|
||||
}
|
||||
|
||||
public void error(String message, Throwable thrown) {
|
||||
}
|
||||
|
||||
}
|
@ -1,592 +0,0 @@
|
||||
package org.dynmap.flat;
|
||||
|
||||
import org.dynmap.DynmapWorld;
|
||||
import static org.dynmap.JSONUtils.a;
|
||||
import static org.dynmap.JSONUtils.s;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.dynmap.Client;
|
||||
import org.dynmap.Color;
|
||||
import org.dynmap.ColorScheme;
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.DynmapChunk;
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.DynmapCore.CompassMode;
|
||||
import org.dynmap.MapManager;
|
||||
import org.dynmap.TileHashManager;
|
||||
import org.dynmap.MapTile;
|
||||
import org.dynmap.MapType;
|
||||
import org.dynmap.debug.Debug;
|
||||
import org.dynmap.utils.DynmapBufferedImage;
|
||||
import org.dynmap.utils.FileLockManager;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
import org.dynmap.utils.MapIterator;
|
||||
import org.dynmap.utils.MapIterator.BlockStep;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class FlatMap extends MapType {
|
||||
private ConfigurationNode configuration;
|
||||
private String prefix;
|
||||
private String name;
|
||||
private ColorScheme colorScheme;
|
||||
private int maximumHeight = 127;
|
||||
private int ambientlight = 15;;
|
||||
private int shadowscale[] = null;
|
||||
private boolean night_and_day; /* If true, render both day (prefix+'-day') and night (prefix) tiles */
|
||||
protected boolean transparency;
|
||||
private enum Texture { NONE, SMOOTH, DITHER };
|
||||
private Texture textured = Texture.NONE;
|
||||
private boolean isbigmap;
|
||||
|
||||
public FlatMap(DynmapCore core, ConfigurationNode configuration) {
|
||||
this.configuration = configuration;
|
||||
name = configuration.getString("name", null);
|
||||
prefix = configuration.getString("prefix", name);
|
||||
colorScheme = ColorScheme.getScheme(core, (String) configuration.get("colorscheme"));
|
||||
Object o = configuration.get("maximumheight");
|
||||
if (o != null) {
|
||||
maximumHeight = Integer.parseInt(String.valueOf(o));
|
||||
if (maximumHeight > 127)
|
||||
maximumHeight = 127;
|
||||
}
|
||||
o = configuration.get("shadowstrength");
|
||||
if(o != null) {
|
||||
double shadowweight = Double.parseDouble(String.valueOf(o));
|
||||
if(shadowweight > 0.0) {
|
||||
shadowscale = new int[16];
|
||||
shadowscale[15] = 256;
|
||||
/* Normal brightness weight in MC is a 20% relative dropoff per step */
|
||||
for(int i = 14; i >= 0; i--) {
|
||||
double v = shadowscale[i+1] * (1.0 - (0.2 * shadowweight));
|
||||
shadowscale[i] = (int)v;
|
||||
if(shadowscale[i] > 256) shadowscale[i] = 256;
|
||||
if(shadowscale[i] < 0) shadowscale[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
o = configuration.get("ambientlight");
|
||||
if(o != null) {
|
||||
ambientlight = Integer.parseInt(String.valueOf(o));
|
||||
}
|
||||
night_and_day = configuration.getBoolean("night-and-day", false);
|
||||
transparency = configuration.getBoolean("transparency", false); /* Default off */
|
||||
String tex = configuration.getString("textured", "none");
|
||||
if(tex.equals("none"))
|
||||
textured = Texture.NONE;
|
||||
else if(tex.equals("dither"))
|
||||
textured = Texture.DITHER;
|
||||
else
|
||||
textured = Texture.SMOOTH;
|
||||
isbigmap = configuration.getBoolean("isbigmap", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapTile[] getTiles(DynmapWorld w, int x, int y, int z) {
|
||||
return new MapTile[] { new FlatMapTile(w, this, x>>7, z>>7, 128) };
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapTile[] getTiles(DynmapWorld w, int xmin, int ymin, int zmin, int xmax, int ymax, int zmax) {
|
||||
ArrayList<MapTile> rslt = new ArrayList<MapTile>();
|
||||
for(int i = xmin; i <= xmax; i++) {
|
||||
for(int j = zmin; j < zmax; j++) {
|
||||
rslt.add(new FlatMapTile(w, this, i, j, 128));
|
||||
}
|
||||
}
|
||||
return rslt.toArray(new MapTile[rslt.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapTile[] getAdjecentTiles(MapTile tile) {
|
||||
FlatMapTile t = (FlatMapTile) tile;
|
||||
DynmapWorld w = t.getDynmapWorld();
|
||||
int x = t.x;
|
||||
int y = t.y;
|
||||
int s = t.size;
|
||||
return new MapTile[] {
|
||||
new FlatMapTile(w, this, x, y - 1, s),
|
||||
new FlatMapTile(w, this, x + 1, y, s),
|
||||
new FlatMapTile(w, this, x, y + 1, s),
|
||||
new FlatMapTile(w, this, x - 1, y, s) };
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DynmapChunk> getRequiredChunks(MapTile tile) {
|
||||
FlatMapTile t = (FlatMapTile) tile;
|
||||
int chunksPerTile = t.size / 16;
|
||||
int sx = t.x * chunksPerTile;
|
||||
int sz = t.y * chunksPerTile;
|
||||
|
||||
ArrayList<DynmapChunk> result = new ArrayList<DynmapChunk>(chunksPerTile * chunksPerTile);
|
||||
for (int x = 0; x < chunksPerTile; x++)
|
||||
for (int z = 0; z < chunksPerTile; z++) {
|
||||
result.add(new DynmapChunk(sx + x, sz + z));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean render(MapChunkCache cache, MapTile tile, File outputFile) {
|
||||
FlatMapTile t = (FlatMapTile) tile;
|
||||
boolean isnether = t.getDynmapWorld().isNether() && (maximumHeight == 127);
|
||||
|
||||
boolean didwrite = false;
|
||||
Color rslt = new Color();
|
||||
int[] pixel = new int[4];
|
||||
int[] pixel_day = null;
|
||||
DynmapBufferedImage im = DynmapBufferedImage.allocateBufferedImage(t.size, t.size);
|
||||
int[] argb_buf = im.argb_buf;
|
||||
DynmapBufferedImage im_day = null;
|
||||
int[] argb_buf_day = null;
|
||||
if(night_and_day) {
|
||||
im_day = DynmapBufferedImage.allocateBufferedImage(t.size, t.size);
|
||||
argb_buf_day = im_day.argb_buf;
|
||||
pixel_day = new int[4];
|
||||
}
|
||||
MapIterator mapiter = cache.getIterator(t.x * t.size, 127, t.y * t.size);
|
||||
for (int x = 0; x < t.size; x++) {
|
||||
mapiter.initialize(t.x * t.size + x, 127, t.y * t.size);
|
||||
for (int y = 0; y < t.size; y++, mapiter.stepPosition(BlockStep.Z_PLUS)) {
|
||||
int blockType;
|
||||
mapiter.setY(127);
|
||||
if(isnether) {
|
||||
while((blockType = mapiter.getBlockTypeID()) != 0) {
|
||||
mapiter.stepPosition(BlockStep.Y_MINUS);
|
||||
if(mapiter.getY() < 0) { /* Solid - use top */
|
||||
mapiter.setY(127);
|
||||
blockType = mapiter.getBlockTypeID();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(blockType == 0) { /* Hit air - now find non-air */
|
||||
while((blockType = mapiter.getBlockTypeID()) == 0) {
|
||||
mapiter.stepPosition(BlockStep.Y_MINUS);
|
||||
if(mapiter.getY() < 0) {
|
||||
mapiter.setY(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
int my = mapiter.getHighestBlockYAt();
|
||||
if(my > maximumHeight) my = maximumHeight;
|
||||
mapiter.setY(my);
|
||||
blockType = mapiter.getBlockTypeID();
|
||||
if(blockType == 0) { /* If air, go down one - fixes ice */
|
||||
my--;
|
||||
if(my < 0)
|
||||
continue;
|
||||
mapiter.setY(my);
|
||||
blockType = mapiter.getBlockTypeID();
|
||||
}
|
||||
}
|
||||
int data = 0;
|
||||
Color[] colors = colorScheme.colors[blockType];
|
||||
if(colorScheme.datacolors[blockType] != null) {
|
||||
data = mapiter.getBlockData();
|
||||
colors = colorScheme.datacolors[blockType][data];
|
||||
}
|
||||
if (colors == null)
|
||||
continue;
|
||||
Color c;
|
||||
if(textured == Texture.SMOOTH)
|
||||
c = colors[4];
|
||||
else if((textured == Texture.DITHER) && (((x+y) & 0x01) == 1)) {
|
||||
c = colors[2];
|
||||
}
|
||||
else {
|
||||
c = colors[0];
|
||||
}
|
||||
if (c == null)
|
||||
continue;
|
||||
|
||||
pixel[0] = c.getRed();
|
||||
pixel[1] = c.getGreen();
|
||||
pixel[2] = c.getBlue();
|
||||
pixel[3] = c.getAlpha();
|
||||
|
||||
/* If transparency needed, process it */
|
||||
if(transparency && (pixel[3] < 255)) {
|
||||
process_transparent(pixel, pixel_day, mapiter);
|
||||
}
|
||||
/* If ambient light less than 15, do scaling */
|
||||
else if((shadowscale != null) && (ambientlight < 15)) {
|
||||
if(mapiter.getY() < 127)
|
||||
mapiter.stepPosition(BlockStep.Y_PLUS);
|
||||
if(night_and_day) { /* Use unscaled color for day (no shadows from above) */
|
||||
pixel_day[0] = pixel[0];
|
||||
pixel_day[1] = pixel[1];
|
||||
pixel_day[2] = pixel[2];
|
||||
pixel_day[3] = 255;
|
||||
}
|
||||
int light = Math.max(ambientlight, mapiter.getBlockEmittedLight());
|
||||
pixel[0] = (pixel[0] * shadowscale[light]) >> 8;
|
||||
pixel[1] = (pixel[1] * shadowscale[light]) >> 8;
|
||||
pixel[2] = (pixel[2] * shadowscale[light]) >> 8;
|
||||
pixel[3] = 255;
|
||||
}
|
||||
else { /* Only do height keying if we're not messing with ambient light */
|
||||
boolean below = mapiter.getY() < 64;
|
||||
|
||||
// Make height range from 0 - 1 (1 - 0 for below and 0 - 1 above)
|
||||
float height = (below ? 64 - mapiter.getY() : mapiter.getY() - 64) / 64.0f;
|
||||
|
||||
// Defines the 'step' in coloring.
|
||||
float step = 10 / 128.0f;
|
||||
|
||||
// The step applied to height.
|
||||
float scale = ((int)(height/step))*step;
|
||||
|
||||
// Make the smaller values change the color (slightly) more than the higher values.
|
||||
scale = (float)Math.pow(scale, 1.1f);
|
||||
|
||||
// Don't let the color go fully white or fully black.
|
||||
scale *= 0.8f;
|
||||
|
||||
if (below) {
|
||||
pixel[0] -= pixel[0] * scale;
|
||||
pixel[1] -= pixel[1] * scale;
|
||||
pixel[2] -= pixel[2] * scale;
|
||||
pixel[3] = 255;
|
||||
} else {
|
||||
pixel[0] += (255-pixel[0]) * scale;
|
||||
pixel[1] += (255-pixel[1]) * scale;
|
||||
pixel[2] += (255-pixel[2]) * scale;
|
||||
pixel[3] = 255;
|
||||
}
|
||||
if(night_and_day) {
|
||||
pixel_day[0] = pixel[0];
|
||||
pixel_day[1] = pixel[1];
|
||||
pixel_day[2] = pixel[2];
|
||||
pixel_day[3] = 255;
|
||||
}
|
||||
|
||||
}
|
||||
rslt.setRGBA(pixel[0], pixel[1], pixel[2], pixel[3]);
|
||||
argb_buf[(t.size-y-1) + (x*t.size)] = rslt.getARGB();
|
||||
if(night_and_day) {
|
||||
rslt.setRGBA(pixel_day[0], pixel_day[1], pixel_day[2], pixel[3]);
|
||||
argb_buf_day[(t.size-y-1) + (x*t.size)] = rslt.getARGB();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Test to see if we're unchanged from older tile */
|
||||
TileHashManager hashman = MapManager.mapman.hashman;
|
||||
long crc = hashman.calculateTileHash(argb_buf);
|
||||
boolean tile_update = false;
|
||||
FileLockManager.getWriteLock(outputFile);
|
||||
try {
|
||||
if((!outputFile.exists()) || (crc != hashman.getImageHashCode(tile.getKey(prefix), null, t.x, t.y))) {
|
||||
/* Wrap buffer as buffered image */
|
||||
Debug.debug("saving image " + outputFile.getPath());
|
||||
if(!outputFile.getParentFile().exists())
|
||||
outputFile.getParentFile().mkdirs();
|
||||
try {
|
||||
FileLockManager.imageIOWrite(im.buf_img, ImageFormat.FORMAT_PNG, outputFile);
|
||||
} catch (IOException e) {
|
||||
Debug.error("Failed to save image: " + outputFile.getPath(), e);
|
||||
} catch (java.lang.NullPointerException e) {
|
||||
Debug.error("Failed to save image (NullPointerException): " + outputFile.getPath(), e);
|
||||
}
|
||||
MapManager.mapman.pushUpdate(tile.getDynmapWorld(), new Client.Tile(tile.getFilename()));
|
||||
hashman.updateHashCode(tile.getKey(prefix), null, t.x, t.y, crc);
|
||||
tile.getDynmapWorld().enqueueZoomOutUpdate(outputFile);
|
||||
tile_update = true;
|
||||
didwrite = true;
|
||||
}
|
||||
else {
|
||||
Debug.debug("skipping image " + outputFile.getPath() + " - hash match");
|
||||
}
|
||||
} finally {
|
||||
FileLockManager.releaseWriteLock(outputFile);
|
||||
DynmapBufferedImage.freeBufferedImage(im);
|
||||
}
|
||||
MapManager.mapman.updateStatistics(tile, prefix, true, tile_update, true);
|
||||
|
||||
/* If day too, handle it */
|
||||
if(night_and_day) {
|
||||
File dayfile = new File(tile.getDynmapWorld().worldtilepath, tile.getDayFilename());
|
||||
crc = hashman.calculateTileHash(argb_buf_day);
|
||||
FileLockManager.getWriteLock(dayfile);
|
||||
try {
|
||||
if((!dayfile.exists()) || (crc != hashman.getImageHashCode(tile.getKey(prefix), "day", t.x, t.y))) {
|
||||
Debug.debug("saving image " + dayfile.getPath());
|
||||
if(!dayfile.getParentFile().exists())
|
||||
dayfile.getParentFile().mkdirs();
|
||||
try {
|
||||
FileLockManager.imageIOWrite(im_day.buf_img, ImageFormat.FORMAT_PNG, dayfile);
|
||||
} catch (IOException e) {
|
||||
Debug.error("Failed to save image: " + dayfile.getPath(), e);
|
||||
} catch (java.lang.NullPointerException e) {
|
||||
Debug.error("Failed to save image (NullPointerException): " + dayfile.getPath(), e);
|
||||
}
|
||||
MapManager.mapman.pushUpdate(tile.getDynmapWorld(), new Client.Tile(tile.getDayFilename()));
|
||||
hashman.updateHashCode(tile.getKey(prefix), "day", t.x, t.y, crc);
|
||||
tile.getDynmapWorld().enqueueZoomOutUpdate(dayfile);
|
||||
tile_update = true;
|
||||
didwrite = true;
|
||||
}
|
||||
else {
|
||||
Debug.debug("skipping image " + dayfile.getPath() + " - hash match");
|
||||
tile_update = false;
|
||||
}
|
||||
} finally {
|
||||
FileLockManager.releaseWriteLock(dayfile);
|
||||
DynmapBufferedImage.freeBufferedImage(im_day);
|
||||
}
|
||||
MapManager.mapman.updateStatistics(tile, prefix+"_day", true, tile_update, true);
|
||||
}
|
||||
|
||||
return didwrite;
|
||||
}
|
||||
private void process_transparent(int[] pixel, int[] pixel_day, MapIterator mapiter) {
|
||||
int r = pixel[0], g = pixel[1], b = pixel[2], a = pixel[3];
|
||||
int r_day = 0, g_day = 0, b_day = 0, a_day = 0;
|
||||
if(pixel_day != null) {
|
||||
r_day = pixel[0]; g_day = pixel[1]; b_day = pixel[2]; a_day = pixel[3];
|
||||
}
|
||||
/* Scale alpha to be proportional to iso view (where we go through 4 blocks to go sqrt(6) or 2.45 units of distance */
|
||||
if(a < 255)
|
||||
a = a_day = 255 - ((255-a)*(255-a) >> 8);
|
||||
/* Handle lighting on cube */
|
||||
if((shadowscale != null) && (ambientlight < 15)) {
|
||||
boolean did_inc = false;
|
||||
if(mapiter.getY() < 127) {
|
||||
mapiter.stepPosition(BlockStep.Y_PLUS);
|
||||
did_inc = true;
|
||||
}
|
||||
if(night_and_day) { /* Use unscaled color for day (no shadows from above) */
|
||||
r_day = r; g_day = g; b_day = b; a_day = a;
|
||||
}
|
||||
int light = Math.max(ambientlight, mapiter.getBlockEmittedLight());
|
||||
r = (r * shadowscale[light]) >> 8;
|
||||
g = (g * shadowscale[light]) >> 8;
|
||||
b = (b * shadowscale[light]) >> 8;
|
||||
if(did_inc)
|
||||
mapiter.stepPosition(BlockStep.Y_MINUS);
|
||||
}
|
||||
if(a < 255) { /* If not opaque */
|
||||
pixel[0] = pixel[1] = pixel[2] = pixel[3] = 0;
|
||||
if(pixel_day != null)
|
||||
pixel_day[0] = pixel_day[1] = pixel_day[2] = pixel_day[3] = 0;
|
||||
mapiter.stepPosition(BlockStep.Y_MINUS);
|
||||
if(mapiter.getY() >= 0) {
|
||||
int blockType = mapiter.getBlockTypeID();
|
||||
int data = 0;
|
||||
Color[] colors = colorScheme.colors[blockType];
|
||||
if(colorScheme.datacolors[blockType] != null) {
|
||||
data = mapiter.getBlockData();
|
||||
colors = colorScheme.datacolors[blockType][data];
|
||||
}
|
||||
if (colors != null) {
|
||||
Color c = colors[0];
|
||||
if (c != null) {
|
||||
pixel[0] = c.getRed();
|
||||
pixel[1] = c.getGreen();
|
||||
pixel[2] = c.getBlue();
|
||||
pixel[3] = c.getAlpha();
|
||||
}
|
||||
}
|
||||
/* Recurse to resolve color here */
|
||||
process_transparent(pixel, pixel_day, mapiter);
|
||||
}
|
||||
}
|
||||
/* Blend colors from behind block and block, based on alpha */
|
||||
r *= a;
|
||||
g *= a;
|
||||
b *= a;
|
||||
int na = 255 - a;
|
||||
pixel[0] = (pixel[0] * na + r) >> 8;
|
||||
pixel[1] = (pixel[1] * na + g) >> 8;
|
||||
pixel[2] = (pixel[2] * na + b) >> 8;
|
||||
pixel[3] = 255;
|
||||
if(pixel_day != null) {
|
||||
r_day *= a_day;
|
||||
g_day *= a_day;
|
||||
b_day *= a_day;
|
||||
na = 255 - a_day;
|
||||
pixel_day[0] = (pixel_day[0] * na + r_day) >> 8;
|
||||
pixel_day[1] = (pixel_day[1] * na + g_day) >> 8;
|
||||
pixel_day[2] = (pixel_day[2] * na + b_day) >> 8;
|
||||
pixel_day[3] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/* Get maps rendered concurrently with this map in this world */
|
||||
public List<MapType> getMapsSharingRender(DynmapWorld w) {
|
||||
return Collections.singletonList((MapType)this);
|
||||
}
|
||||
|
||||
/* Get names of maps rendered concurrently with this map type in this world */
|
||||
public List<String> getMapNamesSharingRender(DynmapWorld w) {
|
||||
return Collections.singletonList(name);
|
||||
}
|
||||
|
||||
public List<ZoomInfo> baseZoomFileInfo() {
|
||||
ArrayList<ZoomInfo> s = new ArrayList<ZoomInfo>();
|
||||
s.add(new ZoomInfo(getPrefix() + "_128", 0));
|
||||
if(night_and_day)
|
||||
s.add(new ZoomInfo(getPrefix()+"_day_128", 0));
|
||||
return s;
|
||||
}
|
||||
|
||||
public int baseZoomFileStepSize() { return 1; }
|
||||
|
||||
private static final int[] stepseq = { 1, 3, 0, 2 };
|
||||
|
||||
public MapStep zoomFileMapStep() { return MapStep.X_PLUS_Y_PLUS; }
|
||||
|
||||
public int[] zoomFileStepSequence() { return stepseq; }
|
||||
|
||||
/* How many bits of coordinate are shifted off to make big world directory name */
|
||||
public int getBigWorldShift() { return 5; }
|
||||
|
||||
/* Returns true if big world file structure is in effect for this map */
|
||||
@Override
|
||||
public boolean isBigWorldMap(DynmapWorld w) {
|
||||
return w.bigworld || isbigmap;
|
||||
}
|
||||
|
||||
public static class FlatMapTile extends MapTile {
|
||||
FlatMap map;
|
||||
public int x;
|
||||
public int y;
|
||||
public int size;
|
||||
private String fname;
|
||||
private String fname_day;
|
||||
|
||||
public FlatMapTile(DynmapWorld world, FlatMap map, int x, int y, int size) {
|
||||
super(world);
|
||||
this.map = map;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public FlatMapTile(DynmapWorld world, String parm) throws Exception {
|
||||
super(world);
|
||||
|
||||
String[] parms = parm.split(",");
|
||||
if(parms.length < 4) throw new Exception("wrong parameter count");
|
||||
this.x = Integer.parseInt(parms[0]);
|
||||
this.y = Integer.parseInt(parms[1]);
|
||||
this.size = Integer.parseInt(parms[2]);
|
||||
for(MapType t : world.maps) {
|
||||
if(t.getName().equals(parms[3]) && (t instanceof FlatMap)) {
|
||||
this.map = (FlatMap)t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(this.map == null) throw new Exception("invalid map");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String saveTileData() {
|
||||
return String.format("%d,%d,%d,%s", x, y, size, map.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilename() {
|
||||
if(fname == null) {
|
||||
if(world.bigworld)
|
||||
fname = map.prefix + "_" + size + "/" + ((-(y+1))>>5) + "_" + (x>>5) + "/" + -(y+1) + "_" + x + ".png";
|
||||
else
|
||||
fname = map.prefix + "_" + size + "_" + -(y+1) + "_" + x + ".png";
|
||||
}
|
||||
return fname;
|
||||
}
|
||||
@Override
|
||||
public String getDayFilename() {
|
||||
if(fname_day == null) {
|
||||
if(world.bigworld)
|
||||
fname_day = map.prefix + "_day_" + size + "/" + ((-(y+1))>>5) + "_" + (x>>5) + "/" + -(y+1) + "_" + x + ".png";
|
||||
else
|
||||
fname_day = map.prefix + "_day_" + size + "_" + -(y+1) + "_" + x + ".png";
|
||||
}
|
||||
return fname_day;
|
||||
}
|
||||
public String toString() {
|
||||
return world.getName() + ":" + getFilename();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean render(MapChunkCache cache, String mapname) {
|
||||
return map.render(cache, this, MapManager.mapman.getTileFile(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DynmapChunk> getRequiredChunks() {
|
||||
return map.getRequiredChunks(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapTile[] getAdjecentTiles() {
|
||||
return map.getAdjecentTiles(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return x ^ y ^ size ^ map.getName().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object x) {
|
||||
if(x instanceof FlatMapTile) {
|
||||
return equals((FlatMapTile)x);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean equals(FlatMapTile o) {
|
||||
return (o.x == x) && (o.y == y) && (o.map == map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey(String prefix) {
|
||||
return world.getName() + "." + map.getPrefix();
|
||||
}
|
||||
|
||||
public boolean isHightestBlockYDataNeeded() { return true; }
|
||||
public boolean isBiomeDataNeeded() { return false; }
|
||||
public boolean isRawBiomeDataNeeded() { return false; }
|
||||
public boolean isBlockTypeDataNeeded() { return true; }
|
||||
public int tileOrdinalX() { return x; }
|
||||
public int tileOrdinalY() { return y; }
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildClientConfiguration(JSONObject worldObject, DynmapWorld world) {
|
||||
ConfigurationNode c = configuration;
|
||||
JSONObject o = new JSONObject();
|
||||
s(o, "type", "FlatMapType");
|
||||
s(o, "name", c.getString("name"));
|
||||
s(o, "title", c.getString("title"));
|
||||
s(o, "icon", c.getString("icon"));
|
||||
s(o, "prefix", c.getString("prefix"));
|
||||
s(o, "background", c.getString("background"));
|
||||
s(o, "nightandday", c.getBoolean("night-and-day",false));
|
||||
s(o, "backgroundday", c.getString("backgroundday"));
|
||||
s(o, "backgroundnight", c.getString("backgroundnight"));
|
||||
s(o, "bigmap", this.isBigWorldMap(world));
|
||||
s(o, "mapzoomin", c.getInteger("mapzoomin", 3));
|
||||
s(o, "mapzoomout", world.getExtraZoomOutLevels());
|
||||
if(MapManager.mapman.getCompassMode() != CompassMode.PRE19)
|
||||
s(o, "compassview", "E"); /* Always from east */
|
||||
else
|
||||
s(o, "compassview", "S"); /* Always from south */
|
||||
s(o, "image-format", ImageFormat.FORMAT_PNG.getFileExt());
|
||||
a(worldObject, "maps", o);
|
||||
}
|
||||
}
|
@ -1,191 +0,0 @@
|
||||
package org.dynmap.hdmap;
|
||||
|
||||
import static org.dynmap.JSONUtils.s;
|
||||
import org.dynmap.Color;
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
import org.dynmap.utils.MapIterator;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class CaveHDShader implements HDShader {
|
||||
private String name;
|
||||
private boolean iflit;
|
||||
|
||||
|
||||
public CaveHDShader(DynmapCore core, ConfigurationNode configuration) {
|
||||
name = (String) configuration.get("name");
|
||||
iflit = configuration.getBoolean("onlyiflit", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBiomeDataNeeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRawBiomeDataNeeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHightestBlockYDataNeeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBlockTypeDataNeeded() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSkyLightLevelNeeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmittedLightLevelNeeded() {
|
||||
return iflit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
private class OurShaderState implements HDShaderState {
|
||||
private Color color;
|
||||
protected MapIterator mapiter;
|
||||
protected HDMap map;
|
||||
private boolean air;
|
||||
|
||||
private OurShaderState(MapIterator mapiter, HDMap map) {
|
||||
this.mapiter = mapiter;
|
||||
this.map = map;
|
||||
this.color = new Color();
|
||||
}
|
||||
/**
|
||||
* Get our shader
|
||||
*/
|
||||
public HDShader getShader() {
|
||||
return CaveHDShader.this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get our map
|
||||
*/
|
||||
public HDMap getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get our lighting
|
||||
*/
|
||||
public HDLighting getLighting() {
|
||||
return map.getLighting();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset renderer state for new ray
|
||||
*/
|
||||
public void reset(HDPerspectiveState ps) {
|
||||
color.setTransparent();
|
||||
air = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process next ray step - called for each block on route
|
||||
* @return true if ray is done, false if ray needs to continue
|
||||
*/
|
||||
public boolean processBlock(HDPerspectiveState ps) {
|
||||
int blocktype = ps.getBlockTypeID();
|
||||
switch (blocktype) {
|
||||
case 0:
|
||||
case 17:
|
||||
case 18:
|
||||
case 20:
|
||||
case 64:
|
||||
case 71:
|
||||
case 78:
|
||||
case 79:
|
||||
blocktype = 0;
|
||||
break;
|
||||
default:
|
||||
air = false;
|
||||
return false;
|
||||
}
|
||||
if ((blocktype == 0) && !air) {
|
||||
if(iflit && (ps.getMapIterator().getBlockEmittedLight() == 0)) {
|
||||
return false;
|
||||
}
|
||||
int cr, cg, cb;
|
||||
int mult = 256;
|
||||
|
||||
if (mapiter.getY() < 64) {
|
||||
cr = 0;
|
||||
cg = 64 + mapiter.getY() * 3;
|
||||
cb = 255 - mapiter.getY() * 4;
|
||||
} else {
|
||||
cr = (mapiter.getY() - 64) * 4;
|
||||
cg = 255;
|
||||
cb = 0;
|
||||
}
|
||||
/* Figure out which color to use */
|
||||
switch(ps.getLastBlockStep()) {
|
||||
case X_PLUS:
|
||||
case X_MINUS:
|
||||
mult = 224;
|
||||
break;
|
||||
case Z_PLUS:
|
||||
case Z_MINUS:
|
||||
mult = 256;
|
||||
break;
|
||||
default:
|
||||
mult = 160;
|
||||
break;
|
||||
}
|
||||
cr = cr * mult / 256;
|
||||
cg = cg * mult / 256;
|
||||
cb = cb * mult / 256;
|
||||
|
||||
color.setRGBA(cr, cg, cb, 255);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Ray ended - used to report that ray has exited map (called if renderer has not reported complete)
|
||||
*/
|
||||
public void rayFinished(HDPerspectiveState ps) {
|
||||
}
|
||||
/**
|
||||
* Get result color - get resulting color for ray
|
||||
* @param c - object to store color value in
|
||||
* @param index - index of color to request (renderer specific - 0=default, 1=day for night/day renderer
|
||||
*/
|
||||
public void getRayColor(Color c, int index) {
|
||||
c.setColor(color);
|
||||
}
|
||||
/**
|
||||
* Clean up state object - called after last ray completed
|
||||
*/
|
||||
public void cleanup() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get renderer state object for use rendering a tile
|
||||
* @param map - map being rendered
|
||||
* @param cache - chunk cache containing data for tile to be rendered
|
||||
* @param mapiter - iterator used when traversing rays in tile
|
||||
* @return state object to use for all rays in tile
|
||||
*/
|
||||
public HDShaderState getStateInstance(HDMap map, MapChunkCache cache, MapIterator mapiter) {
|
||||
return new OurShaderState(mapiter, map);
|
||||
}
|
||||
|
||||
/* Add shader's contributions to JSON for map object */
|
||||
public void addClientConfiguration(JSONObject mapObject) {
|
||||
s(mapObject, "shader", name);
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package org.dynmap.hdmap;
|
||||
|
||||
import org.dynmap.Color;
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.json.simple.JSONObject;
|
||||
import static org.dynmap.JSONUtils.s;
|
||||
|
||||
public class DefaultHDLighting implements HDLighting {
|
||||
private String name;
|
||||
|
||||
public DefaultHDLighting(DynmapCore core, ConfigurationNode configuration) {
|
||||
name = (String) configuration.get("name");
|
||||
}
|
||||
|
||||
/* Get lighting name */
|
||||
public String getName() { return name; }
|
||||
|
||||
/* Apply lighting to given pixel colors (1 outcolor if normal, 2 if night/day) */
|
||||
public void applyLighting(HDPerspectiveState ps, HDShaderState ss, Color incolor, Color[] outcolor) {
|
||||
for(int i = 0; i < outcolor.length; i++)
|
||||
outcolor[i].setColor(incolor);
|
||||
}
|
||||
|
||||
/* Test if Biome Data is needed for this renderer */
|
||||
public boolean isBiomeDataNeeded() { return false; }
|
||||
|
||||
/* Test if raw biome temperature/rainfall data is needed */
|
||||
public boolean isRawBiomeDataNeeded() { return false; }
|
||||
|
||||
/* Test if highest block Y data is needed */
|
||||
public boolean isHightestBlockYDataNeeded() { return false; }
|
||||
|
||||
/* Tet if block type data needed */
|
||||
public boolean isBlockTypeDataNeeded() { return false; }
|
||||
|
||||
/* Test if night/day is enabled for this renderer */
|
||||
public boolean isNightAndDayEnabled() { return false; }
|
||||
|
||||
/* Test if sky light level needed */
|
||||
public boolean isSkyLightLevelNeeded() { return false; }
|
||||
|
||||
/* Test if emitted light level needed */
|
||||
public boolean isEmittedLightLevelNeeded() { return false; }
|
||||
|
||||
/* Add shader's contributions to JSON for map object */
|
||||
public void addClientConfiguration(JSONObject mapObject) {
|
||||
s(mapObject, "lighting", name);
|
||||
s(mapObject, "nightandday", isNightAndDayEnabled());
|
||||
}
|
||||
}
|
@ -1,277 +0,0 @@
|
||||
package org.dynmap.hdmap;
|
||||
|
||||
import static org.dynmap.JSONUtils.s;
|
||||
import org.dynmap.Color;
|
||||
import org.dynmap.ColorScheme;
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.common.BiomeMap;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
import org.dynmap.utils.MapIterator;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class DefaultHDShader implements HDShader {
|
||||
private String name;
|
||||
protected ColorScheme colorScheme;
|
||||
|
||||
protected boolean transparency; /* Is transparency support active? */
|
||||
public enum BiomeColorOption {
|
||||
NONE, BIOME, TEMPERATURE, RAINFALL
|
||||
}
|
||||
protected BiomeColorOption biomecolored = BiomeColorOption.NONE; /* Use biome for coloring */
|
||||
|
||||
public DefaultHDShader(DynmapCore core, ConfigurationNode configuration) {
|
||||
name = (String) configuration.get("name");
|
||||
colorScheme = ColorScheme.getScheme(core, configuration.getString("colorscheme", "default"));
|
||||
transparency = configuration.getBoolean("transparency", true); /* Default on */
|
||||
String biomeopt = configuration.getString("biomecolored", "none");
|
||||
if(biomeopt.equals("biome")) {
|
||||
biomecolored = BiomeColorOption.BIOME;
|
||||
}
|
||||
else if(biomeopt.equals("temperature")) {
|
||||
biomecolored = BiomeColorOption.TEMPERATURE;
|
||||
}
|
||||
else if(biomeopt.equals("rainfall")) {
|
||||
biomecolored = BiomeColorOption.RAINFALL;
|
||||
}
|
||||
else {
|
||||
biomecolored = BiomeColorOption.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBiomeDataNeeded() {
|
||||
return biomecolored == BiomeColorOption.BIOME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRawBiomeDataNeeded() {
|
||||
return (biomecolored == BiomeColorOption.RAINFALL) || (biomecolored == BiomeColorOption.TEMPERATURE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHightestBlockYDataNeeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBlockTypeDataNeeded() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSkyLightLevelNeeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmittedLightLevelNeeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
private class OurShaderState implements HDShaderState {
|
||||
private Color color[];
|
||||
protected MapIterator mapiter;
|
||||
protected HDMap map;
|
||||
private Color tmpcolor[];
|
||||
private int pixelodd;
|
||||
private HDLighting lighting;
|
||||
|
||||
private OurShaderState(MapIterator mapiter, HDMap map) {
|
||||
this.mapiter = mapiter;
|
||||
this.map = map;
|
||||
this.lighting = map.getLighting();
|
||||
if(lighting.isNightAndDayEnabled()) {
|
||||
color = new Color[] { new Color(), new Color() };
|
||||
tmpcolor = new Color[] { new Color(), new Color() };
|
||||
}
|
||||
else {
|
||||
color = new Color[] { new Color() };
|
||||
tmpcolor = new Color[] { new Color() };
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get our shader
|
||||
*/
|
||||
public HDShader getShader() {
|
||||
return DefaultHDShader.this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get our map
|
||||
*/
|
||||
public HDMap getMap() {
|
||||
return map;
|
||||
}
|
||||
/**
|
||||
* Get our lighting
|
||||
*/
|
||||
public HDLighting getLighting() {
|
||||
return lighting;
|
||||
}
|
||||
/**
|
||||
* Reset renderer state for new ray
|
||||
*/
|
||||
public void reset(HDPerspectiveState ps) {
|
||||
for(int i = 0; i < color.length; i++)
|
||||
color[i].setTransparent();
|
||||
pixelodd = (ps.getPixelX() & 0x3) + (ps.getPixelY()<<1);
|
||||
}
|
||||
|
||||
protected Color[] getBlockColors(int blocktype, int blockdata) {
|
||||
if((blockdata != 0) && (colorScheme.datacolors[blocktype] != null))
|
||||
return colorScheme.datacolors[blocktype][blockdata];
|
||||
else
|
||||
return colorScheme.colors[blocktype];
|
||||
}
|
||||
|
||||
/**
|
||||
* Process next ray step - called for each block on route
|
||||
* @return true if ray is done, false if ray needs to continue
|
||||
*/
|
||||
public boolean processBlock(HDPerspectiveState ps) {
|
||||
int i;
|
||||
int blocktype = ps.getBlockTypeID();
|
||||
if(blocktype == 0)
|
||||
return false;
|
||||
Color[] colors = getBlockColors(blocktype, ps.getBlockData());
|
||||
|
||||
if (colors != null) {
|
||||
int seq;
|
||||
int subalpha = ps.getSubmodelAlpha();
|
||||
/* Figure out which color to use */
|
||||
switch(ps.getLastBlockStep()) {
|
||||
case X_PLUS:
|
||||
case X_MINUS:
|
||||
seq = 2;
|
||||
break;
|
||||
case Z_PLUS:
|
||||
case Z_MINUS:
|
||||
seq = 0;
|
||||
break;
|
||||
default:
|
||||
//if(subalpha >= 0) /* We hit a block in a model */
|
||||
// seq = 4; /* Use smooth top */
|
||||
//else
|
||||
if(((pixelodd + mapiter.getY()) & 0x03) == 0)
|
||||
seq = 3;
|
||||
else
|
||||
seq = 1;
|
||||
break;
|
||||
}
|
||||
Color c = colors[seq];
|
||||
if (c.getAlpha() > 0) {
|
||||
/* Handle light level, if needed */
|
||||
lighting.applyLighting(ps, this, c, tmpcolor);
|
||||
/* If we got alpha from subblock model, use it instead */
|
||||
if(subalpha >= 0) {
|
||||
for(int j = 0; j < tmpcolor.length; j++)
|
||||
tmpcolor[j].setAlpha(Math.max(subalpha,tmpcolor[j].getAlpha()));
|
||||
}
|
||||
/* Blend color with accumulated color (weighted by alpha) */
|
||||
if(!transparency) { /* No transparency support */
|
||||
for(i = 0; i < color.length; i++)
|
||||
color[i].setARGB(tmpcolor[i].getARGB() | 0xFF000000);
|
||||
return true; /* We're done */
|
||||
}
|
||||
/* If no previous color contribution, use new color */
|
||||
else if(color[0].isTransparent()) {
|
||||
for(i = 0; i < color.length; i++)
|
||||
color[i].setColor(tmpcolor[i]);
|
||||
return (color[0].getAlpha() == 255);
|
||||
}
|
||||
/* Else, blend and generate new alpha */
|
||||
else {
|
||||
int alpha = color[0].getAlpha();
|
||||
int alpha2 = tmpcolor[0].getAlpha() * (255-alpha) / 255;
|
||||
int talpha = alpha + alpha2;
|
||||
for(i = 0; i < color.length; i++)
|
||||
color[i].setRGBA((tmpcolor[i].getRed()*alpha2 + color[i].getRed()*alpha) / talpha,
|
||||
(tmpcolor[i].getGreen()*alpha2 + color[i].getGreen()*alpha) / talpha,
|
||||
(tmpcolor[i].getBlue()*alpha2 + color[i].getBlue()*alpha) / talpha, talpha);
|
||||
return (talpha >= 254); /* If only one short, no meaningful contribution left */
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Ray ended - used to report that ray has exited map (called if renderer has not reported complete)
|
||||
*/
|
||||
public void rayFinished(HDPerspectiveState ps) {
|
||||
}
|
||||
/**
|
||||
* Get result color - get resulting color for ray
|
||||
* @param c - object to store color value in
|
||||
* @param index - index of color to request (renderer specific - 0=default, 1=day for night/day renderer
|
||||
*/
|
||||
public void getRayColor(Color c, int index) {
|
||||
c.setColor(color[index]);
|
||||
}
|
||||
/**
|
||||
* Clean up state object - called after last ray completed
|
||||
*/
|
||||
public void cleanup() {
|
||||
}
|
||||
}
|
||||
|
||||
private class OurBiomeShaderState extends OurShaderState {
|
||||
private OurBiomeShaderState(MapIterator mapiter, HDMap map) {
|
||||
super(mapiter, map);
|
||||
}
|
||||
protected Color[] getBlockColors(int blocktype, int blockdata) {
|
||||
BiomeMap bio = mapiter.getBiome();
|
||||
if(bio != null)
|
||||
return colorScheme.biomecolors[bio.ordinal()];
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class OurBiomeRainfallShaderState extends OurShaderState {
|
||||
private OurBiomeRainfallShaderState(MapIterator mapiter, HDMap map) {
|
||||
super(mapiter, map);
|
||||
}
|
||||
protected Color[] getBlockColors(int blocktype, int blockdata) {
|
||||
return colorScheme.getRainColor(mapiter.getRawBiomeRainfall());
|
||||
}
|
||||
}
|
||||
|
||||
private class OurBiomeTempShaderState extends OurShaderState {
|
||||
private OurBiomeTempShaderState(MapIterator mapiter, HDMap map) {
|
||||
super(mapiter, map);
|
||||
}
|
||||
protected Color[] getBlockColors(int blocktype, int blockdata) {
|
||||
return colorScheme.getTempColor(mapiter.getRawBiomeTemperature());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get renderer state object for use rendering a tile
|
||||
* @param map - map being rendered
|
||||
* @param cache - chunk cache containing data for tile to be rendered
|
||||
* @param mapiter - iterator used when traversing rays in tile
|
||||
* @return state object to use for all rays in tile
|
||||
*/
|
||||
public HDShaderState getStateInstance(HDMap map, MapChunkCache cache, MapIterator mapiter) {
|
||||
switch(biomecolored) {
|
||||
case NONE:
|
||||
return new OurShaderState(mapiter, map);
|
||||
case BIOME:
|
||||
return new OurBiomeShaderState(mapiter, map);
|
||||
case RAINFALL:
|
||||
return new OurBiomeRainfallShaderState(mapiter, map);
|
||||
case TEMPERATURE:
|
||||
return new OurBiomeTempShaderState(mapiter, map);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/* Add shader's contributions to JSON for map object */
|
||||
public void addClientConfiguration(JSONObject mapObject) {
|
||||
s(mapObject, "shader", name);
|
||||
}
|
||||
}
|
@ -1,518 +0,0 @@
|
||||
package org.dynmap.hdmap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.Log;
|
||||
|
||||
/**
|
||||
* Custom block models - used for non-cube blocks to represent the physical volume associated with the block
|
||||
* Used by perspectives to determine if rays have intersected a block that doesn't occupy its whole block
|
||||
*/
|
||||
public class HDBlockModels {
|
||||
private int blockid;
|
||||
private int databits;
|
||||
private long blockflags[];
|
||||
private int nativeres;
|
||||
private HashMap<Integer, short[]> scaledblocks;
|
||||
private static int linkalg[] = new int[256];
|
||||
private static int linkmap[][] = new int[256][];
|
||||
|
||||
private static HashMap<Integer, HDBlockModels> models_by_id_data = new HashMap<Integer, HDBlockModels>();
|
||||
|
||||
public static class HDScaledBlockModels {
|
||||
private short[][][] modelvectors;
|
||||
|
||||
public final short[] getScaledModel(int blocktype, int blockdata, int blockrenderdata) {
|
||||
if(modelvectors[blocktype] == null) {
|
||||
return null;
|
||||
}
|
||||
return modelvectors[blocktype][(blockrenderdata>=0)?blockrenderdata:blockdata];
|
||||
}
|
||||
}
|
||||
|
||||
private static HashMap<Integer, HDScaledBlockModels> scaled_models_by_scale = new HashMap<Integer, HDScaledBlockModels>();
|
||||
|
||||
/**
|
||||
* Block definition - positions correspond to Bukkit coordinates (+X is south, +Y is up, +Z is west)
|
||||
* @param blockid - block ID
|
||||
* @param databits - bitmap of block data bits matching this model (bit N is set if data=N would match)
|
||||
* @param nativeres - native subblocks per edge of cube (up to 64)
|
||||
* @param blockflags - array of native^2 long integers representing volume of block (bit X of element (nativeres*Y+Z) is set if that subblock is filled)
|
||||
* if array is short, other elements area are assumed to be zero (fills from bottom of block up)
|
||||
*/
|
||||
public HDBlockModels(int blockid, int databits, int nativeres, long[] blockflags) {
|
||||
this.blockid = blockid;
|
||||
this.databits = databits;
|
||||
this.nativeres = nativeres;
|
||||
this.blockflags = new long[nativeres * nativeres];
|
||||
System.arraycopy(blockflags, 0, this.blockflags, 0, blockflags.length);
|
||||
for(int i = 0; i < 16; i++) {
|
||||
if((databits & (1<<i)) != 0) {
|
||||
models_by_id_data.put((blockid<<4)+i, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Test if given native block is filled
|
||||
*/
|
||||
public final boolean isSubblockSet(int x, int y, int z) {
|
||||
return ((blockflags[nativeres*y+z] & (1 << x)) != 0);
|
||||
}
|
||||
/**
|
||||
* Set subblock value
|
||||
*/
|
||||
public final void setSubblock(int x, int y, int z, boolean isset) {
|
||||
if(isset)
|
||||
blockflags[nativeres*y+z] |= (1 << x);
|
||||
else
|
||||
blockflags[nativeres*y+z] &= ~(1 << x);
|
||||
}
|
||||
/**
|
||||
* Get link algorithm
|
||||
* @param blkid - block ID
|
||||
* @return 0=no link alg
|
||||
*/
|
||||
public static final int getLinkAlgID(int blkid) {
|
||||
return linkalg[blkid];
|
||||
}
|
||||
/**
|
||||
* Get link block IDs
|
||||
* @param blkid - block ID
|
||||
* @return array of block IDs to link with
|
||||
*/
|
||||
public static final int[] getLinkIDs(int blkid) {
|
||||
return linkmap[blkid];
|
||||
}
|
||||
/**
|
||||
* Get scaled map of block: will return array of alpha levels, corresponding to how much of the
|
||||
* scaled subblocks are occupied by the original blocks (indexed by Y*res*res + Z*res + X)
|
||||
* @param res - requested scale (res subblocks per edge of block)
|
||||
* @return array of alpha values (0-255), corresponding to resXresXres subcubes of block
|
||||
*/
|
||||
public short[] getScaledMap(int res) {
|
||||
if(scaledblocks == null) { scaledblocks = new HashMap<Integer, short[]>(); }
|
||||
short[] map = scaledblocks.get(Integer.valueOf(res));
|
||||
if(map == null) {
|
||||
map = new short[res*res*res];
|
||||
if(res == nativeres) {
|
||||
for(int i = 0; i < blockflags.length; i++) {
|
||||
for(int j = 0; j < nativeres; j++) {
|
||||
if((blockflags[i] & (1 << j)) != 0)
|
||||
map[res*i+j] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If scaling from smaller sub-blocks to larger, each subblock contributes to 1-2 blocks
|
||||
* on each axis: need to calculate crossovers for each, and iterate through smaller
|
||||
* blocks to accumulate contributions
|
||||
*/
|
||||
else if(res > nativeres) {
|
||||
int weights[] = new int[res];
|
||||
int offsets[] = new int[res];
|
||||
/* LCM of resolutions is used as length of line (res * nativeres)
|
||||
* Each native block is (res) long, each scaled block is (nativeres) long
|
||||
* Each scaled block overlaps 1 or 2 native blocks: starting with native block 'offsets[]' with
|
||||
* 'weights[]' of its (res) width in the first, and the rest in the second
|
||||
*/
|
||||
for(int v = 0, idx = 0; v < res*nativeres; v += nativeres, idx++) {
|
||||
offsets[idx] = (v/res); /* Get index of the first native block we draw from */
|
||||
if((v+nativeres-1)/res == offsets[idx]) { /* If scaled block ends in same native block */
|
||||
weights[idx] = nativeres;
|
||||
}
|
||||
else { /* Else, see how much is in first one */
|
||||
weights[idx] = (offsets[idx] + res) - v;
|
||||
weights[idx] = (offsets[idx]*res + res) - v;
|
||||
}
|
||||
}
|
||||
/* Now, use weights and indices to fill in scaled map */
|
||||
for(int y = 0, off = 0; y < res; y++) {
|
||||
int ind_y = offsets[y];
|
||||
int wgt_y = weights[y];
|
||||
for(int z = 0; z < res; z++) {
|
||||
int ind_z = offsets[z];
|
||||
int wgt_z = weights[z];
|
||||
for(int x = 0; x < res; x++, off++) {
|
||||
int ind_x = offsets[x];
|
||||
int wgt_x = weights[x];
|
||||
int raw_w = 0;
|
||||
for(int xx = 0; xx < 2; xx++) {
|
||||
int wx = (xx==0)?wgt_x:(nativeres-wgt_x);
|
||||
if(wx == 0) continue;
|
||||
for(int yy = 0; yy < 2; yy++) {
|
||||
int wy = (yy==0)?wgt_y:(nativeres-wgt_y);
|
||||
if(wy == 0) continue;
|
||||
for(int zz = 0; zz < 2; zz++) {
|
||||
int wz = (zz==0)?wgt_z:(nativeres-wgt_z);
|
||||
if(wz == 0) continue;
|
||||
if(isSubblockSet(ind_x+xx, ind_y+yy, ind_z+zz)) {
|
||||
raw_w += wx*wy*wz;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
map[off] = (short)((255*raw_w) / (nativeres*nativeres*nativeres));
|
||||
if(map[off] > 255) map[off] = 255;
|
||||
if(map[off] < 0) map[off] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* nativeres > res */
|
||||
int weights[] = new int[nativeres];
|
||||
int offsets[] = new int[nativeres];
|
||||
/* LCM of resolutions is used as length of line (res * nativeres)
|
||||
* Each native block is (res) long, each scaled block is (nativeres) long
|
||||
* Each native block overlaps 1 or 2 scaled blocks: starting with scaled block 'offsets[]' with
|
||||
* 'weights[]' of its (res) width in the first, and the rest in the second
|
||||
*/
|
||||
for(int v = 0, idx = 0; v < res*nativeres; v += res, idx++) {
|
||||
offsets[idx] = (v/nativeres); /* Get index of the first scaled block we draw to */
|
||||
if((v+res-1)/nativeres == offsets[idx]) { /* If native block ends in same scaled block */
|
||||
weights[idx] = res;
|
||||
}
|
||||
else { /* Else, see how much is in first one */
|
||||
weights[idx] = (offsets[idx]*nativeres + nativeres) - v;
|
||||
}
|
||||
}
|
||||
/* Now, use weights and indices to fill in scaled map */
|
||||
long accum[] = new long[map.length];
|
||||
for(int y = 0; y < nativeres; y++) {
|
||||
int ind_y = offsets[y];
|
||||
int wgt_y = weights[y];
|
||||
for(int z = 0; z < nativeres; z++) {
|
||||
int ind_z = offsets[z];
|
||||
int wgt_z = weights[z];
|
||||
for(int x = 0; x < nativeres; x++) {
|
||||
if(isSubblockSet(x, y, z)) {
|
||||
int ind_x = offsets[x];
|
||||
int wgt_x = weights[x];
|
||||
for(int xx = 0; xx < 2; xx++) {
|
||||
int wx = (xx==0)?wgt_x:(res-wgt_x);
|
||||
if(wx == 0) continue;
|
||||
for(int yy = 0; yy < 2; yy++) {
|
||||
int wy = (yy==0)?wgt_y:(res-wgt_y);
|
||||
if(wy == 0) continue;
|
||||
for(int zz = 0; zz < 2; zz++) {
|
||||
int wz = (zz==0)?wgt_z:(res-wgt_z);
|
||||
if(wz == 0) continue;
|
||||
accum[(ind_y+yy)*res*res + (ind_z+zz)*res + (ind_x+xx)] +=
|
||||
wx*wy*wz;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < map.length; i++) {
|
||||
map[i] = (short)(accum[i]*255/nativeres/nativeres/nativeres);
|
||||
if(map[i] > 255) map[i] = 255;
|
||||
if(map[i] < 0) map[i] = 0;
|
||||
}
|
||||
}
|
||||
scaledblocks.put(Integer.valueOf(res), map);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scaled set of models for all modelled blocks
|
||||
* @param scale
|
||||
* @return
|
||||
*/
|
||||
public static HDScaledBlockModels getModelsForScale(int scale) {
|
||||
HDScaledBlockModels model = scaled_models_by_scale.get(Integer.valueOf(scale));
|
||||
if(model == null) {
|
||||
model = new HDScaledBlockModels();
|
||||
short[][][] blockmodels = new short[256][][];
|
||||
for(HDBlockModels m : models_by_id_data.values()) {
|
||||
short[][] row = blockmodels[m.blockid];
|
||||
if(row == null) {
|
||||
row = new short[16][];
|
||||
blockmodels[m.blockid] = row;
|
||||
}
|
||||
short[] smod = m.getScaledMap(scale);
|
||||
/* See if scaled model is full block : much faster to not use it if it is */
|
||||
if(smod != null) {
|
||||
boolean keep = false;
|
||||
for(int i = 0; (!keep) && (i < smod.length); i++) {
|
||||
if(smod[i] == 0) keep = true;
|
||||
}
|
||||
if(keep) {
|
||||
for(int i = 0; i < 16; i++) {
|
||||
if((m.databits & (1 << i)) != 0) {
|
||||
row[i] = smod;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
model.modelvectors = blockmodels;
|
||||
scaled_models_by_scale.put(scale, model);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
/**
|
||||
* Load models
|
||||
*/
|
||||
public static void loadModels(File datadir, ConfigurationNode config) {
|
||||
/* Reset models-by-ID-Data cache */
|
||||
models_by_id_data.clear();
|
||||
/* Reset scaled models by scale cache */
|
||||
scaled_models_by_scale.clear();
|
||||
|
||||
/* Load block models */
|
||||
InputStream in = TexturePack.class.getResourceAsStream("/models.txt");
|
||||
if(in != null) {
|
||||
loadModelFile(in, "models.txt", config);
|
||||
try { in.close(); } catch (IOException iox) {} in = null;
|
||||
}
|
||||
File customdir = new File(datadir, "renderdata");
|
||||
String[] files = customdir.list();
|
||||
if(files != null) {
|
||||
for(String fn : files) {
|
||||
if(fn.endsWith("-models.txt") == false)
|
||||
continue;
|
||||
File custom = new File(customdir, fn);
|
||||
if(custom.canRead()) {
|
||||
try {
|
||||
in = new FileInputStream(custom);
|
||||
loadModelFile(in, custom.getPath(), config);
|
||||
} catch (IOException iox) {
|
||||
Log.severe("Error loading " + custom.getPath());
|
||||
} finally {
|
||||
if(in != null) {
|
||||
try { in.close(); } catch (IOException iox) {}
|
||||
in = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private static Integer getIntValue(Map<String,Integer> vars, String val) throws NumberFormatException {
|
||||
if(Character.isLetter(val.charAt(0))) {
|
||||
Integer v = vars.get(val);
|
||||
if(v == null)
|
||||
throw new NumberFormatException("invalid ID - " + val);
|
||||
return v;
|
||||
}
|
||||
else {
|
||||
return Integer.valueOf(val);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Load models from file
|
||||
*/
|
||||
private static void loadModelFile(InputStream in, String fname, ConfigurationNode config) {
|
||||
LineNumberReader rdr = null;
|
||||
int cnt = 0;
|
||||
try {
|
||||
String line;
|
||||
ArrayList<HDBlockModels> modlist = new ArrayList<HDBlockModels>();
|
||||
HashMap<String,Integer> varvals = new HashMap<String,Integer>();
|
||||
int layerbits = 0;
|
||||
int rownum = 0;
|
||||
int scale = 0;
|
||||
rdr = new LineNumberReader(new InputStreamReader(in));
|
||||
while((line = rdr.readLine()) != null) {
|
||||
if(line.startsWith("block:")) {
|
||||
ArrayList<Integer> blkids = new ArrayList<Integer>();
|
||||
int databits = 0;
|
||||
scale = 0;
|
||||
line = line.substring(6);
|
||||
String[] args = line.split(",");
|
||||
for(String a : args) {
|
||||
String[] av = a.split("=");
|
||||
if(av.length < 2) continue;
|
||||
if(av[0].equals("id")) {
|
||||
blkids.add(getIntValue(varvals,av[1]));
|
||||
}
|
||||
else if(av[0].equals("data")) {
|
||||
if(av[1].equals("*"))
|
||||
databits = 0xFFFF;
|
||||
else
|
||||
databits |= (1 << getIntValue(varvals,av[1]));
|
||||
}
|
||||
else if(av[0].equals("scale")) {
|
||||
scale = Integer.parseInt(av[1]);
|
||||
}
|
||||
}
|
||||
/* If we have everything, build block */
|
||||
if((blkids.size() > 0) && (databits != 0) && (scale > 0)) {
|
||||
modlist.clear();
|
||||
for(Integer id : blkids) {
|
||||
modlist.add(new HDBlockModels(id.intValue(), databits, scale, new long[0]));
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Log.severe("Block model missing required parameters = line " + rdr.getLineNumber() + " of " + fname);
|
||||
}
|
||||
layerbits = 0;
|
||||
}
|
||||
else if(line.startsWith("layer:")) {
|
||||
line = line.substring(6);
|
||||
String args[] = line.split(",");
|
||||
layerbits = 0;
|
||||
rownum = 0;
|
||||
for(String a: args) {
|
||||
layerbits |= (1 << Integer.parseInt(a));
|
||||
}
|
||||
}
|
||||
else if(line.startsWith("rotate:")) {
|
||||
line = line.substring(7);
|
||||
String args[] = line.split(",");
|
||||
int id = -1;
|
||||
int data = -1;
|
||||
int rot = -1;
|
||||
for(String a : args) {
|
||||
String[] av = a.split("=");
|
||||
if(av.length < 2) continue;
|
||||
if(av[0].equals("id")) { id = getIntValue(varvals,av[1]); }
|
||||
if(av[0].equals("data")) { data = getIntValue(varvals,av[1]); }
|
||||
if(av[0].equals("rot")) { rot = Integer.parseInt(av[1]); }
|
||||
}
|
||||
/* get old model to be rotated */
|
||||
HDBlockModels mod = models_by_id_data.get((id<<4)+data);
|
||||
if((mod != null) && ((rot%90) == 0)) {
|
||||
for(int x = 0; x < scale; x++) {
|
||||
for(int y = 0; y < scale; y++) {
|
||||
for(int z = 0; z < scale; z++) {
|
||||
if(mod.isSubblockSet(x, y, z) == false) continue;
|
||||
switch(rot) {
|
||||
case 0:
|
||||
for(HDBlockModels bm : modlist)
|
||||
bm.setSubblock(x, y, z, true);
|
||||
break;
|
||||
case 90:
|
||||
for(HDBlockModels bm : modlist)
|
||||
bm.setSubblock(scale-z-1, y, x, true);
|
||||
break;
|
||||
case 180:
|
||||
for(HDBlockModels bm : modlist)
|
||||
bm.setSubblock(scale-x-1, y, scale-z-1, true);
|
||||
break;
|
||||
case 270:
|
||||
for(HDBlockModels bm : modlist)
|
||||
bm.setSubblock(z, y, scale-x-1, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(line.startsWith("linkmap:")) {
|
||||
ArrayList<Integer> blkids = new ArrayList<Integer>();
|
||||
line = line.substring(8);
|
||||
String[] args = line.split(",");
|
||||
List<Integer> map = new ArrayList<Integer>();
|
||||
int linktype = 0;
|
||||
for(String a : args) {
|
||||
String[] av = a.split("=");
|
||||
if(av.length < 2) continue;
|
||||
if(av[0].equals("id")) {
|
||||
blkids.add(getIntValue(varvals,av[1]));
|
||||
}
|
||||
else if(av[0].equals("linkalg")) {
|
||||
linktype = Integer.parseInt(av[1]);
|
||||
}
|
||||
else if(av[0].equals("linkid")) {
|
||||
map.add(getIntValue(varvals,av[1]));
|
||||
}
|
||||
}
|
||||
if(linktype > 0) {
|
||||
int[] mapids = new int[map.size()];
|
||||
for(int i = 0; i < mapids.length; i++)
|
||||
mapids[i] = map.get(i);
|
||||
for(Integer bid : blkids) {
|
||||
linkalg[bid] = linktype;
|
||||
linkmap[bid] = mapids;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(line.startsWith("#") || line.startsWith(";")) {
|
||||
}
|
||||
else if(line.startsWith("enabled:")) { /* Test if texture file is enabled */
|
||||
line = line.substring(8).trim();
|
||||
if(line.startsWith("true")) { /* We're enabled? */
|
||||
/* Nothing to do - keep processing */
|
||||
}
|
||||
else if(line.startsWith("false")) { /* Disabled */
|
||||
return; /* Quit */
|
||||
}
|
||||
/* If setting is not defined or false, quit */
|
||||
else if(config.getBoolean(line, false) == false) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
Log.info(line + " models enabled");
|
||||
}
|
||||
}
|
||||
else if(line.startsWith("var:")) { /* Test if variable declaration */
|
||||
line = line.substring(4).trim();
|
||||
String args[] = line.split(",");
|
||||
for(int i = 0; i < args.length; i++) {
|
||||
String[] v = args[i].split("=");
|
||||
if(v.length < 2) {
|
||||
Log.severe("Format error - line " + rdr.getLineNumber() + " of " + fname);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int val = Integer.valueOf(v[1]); /* Parse default value */
|
||||
int parmval = config.getInteger(v[0], val); /* Read value, with applied default */
|
||||
varvals.put(v[0], parmval); /* And save value */
|
||||
} catch (NumberFormatException nfx) {
|
||||
Log.severe("Format error - line " + rdr.getLineNumber() + " of " + fname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(layerbits != 0) { /* If we're working pattern lines */
|
||||
/* Layerbits determine Y, rows count from North to South (X=0 to X=N-1), columns Z are West to East (N-1 to 0) */
|
||||
for(int i = 0; (i < scale) && (i < line.length()); i++) {
|
||||
if(line.charAt(i) == '*') { /* If an asterix, set flag */
|
||||
for(int y = 0; y < scale; y++) {
|
||||
if((layerbits & (1<<y)) != 0) {
|
||||
for(HDBlockModels mod : modlist) {
|
||||
mod.setSubblock(rownum, y, scale-i-1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* See if we're done with layer */
|
||||
rownum++;
|
||||
if(rownum >= scale) {
|
||||
rownum = 0;
|
||||
layerbits = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.verboseinfo("Loaded " + cnt + " block models from " + fname);
|
||||
} catch (IOException iox) {
|
||||
Log.severe("Error reading models.txt - " + iox.toString());
|
||||
} catch (NumberFormatException nfx) {
|
||||
Log.severe("Format error - line " + rdr.getLineNumber() + " of " + fname);
|
||||
} finally {
|
||||
if(rdr != null) {
|
||||
try {
|
||||
rdr.close();
|
||||
rdr = null;
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package org.dynmap.hdmap;
|
||||
|
||||
import org.dynmap.Color;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public interface HDLighting {
|
||||
/* Get lighting name */
|
||||
String getName();
|
||||
/* Apply lighting to given pixel colors (1 outcolor if normal, 2 if night/day) */
|
||||
void applyLighting(HDPerspectiveState ps, HDShaderState ss, Color incolor, Color[] outcolor);
|
||||
/* Test if Biome Data is needed for this renderer */
|
||||
boolean isBiomeDataNeeded();
|
||||
/* Test if raw biome temperature/rainfall data is needed */
|
||||
boolean isRawBiomeDataNeeded();
|
||||
/* Test if highest block Y data is needed */
|
||||
boolean isHightestBlockYDataNeeded();
|
||||
/* Tet if block type data needed */
|
||||
boolean isBlockTypeDataNeeded();
|
||||
/* Test if night/day is enabled for this renderer */
|
||||
boolean isNightAndDayEnabled();
|
||||
/* Test if sky light level needed */
|
||||
boolean isSkyLightLevelNeeded();
|
||||
/* Test if emitted light level needed */
|
||||
boolean isEmittedLightLevelNeeded();
|
||||
/* Add shader's contributions to JSON for map object */
|
||||
void addClientConfiguration(JSONObject mapObject);
|
||||
}
|
@ -1,335 +0,0 @@
|
||||
package org.dynmap.hdmap;
|
||||
|
||||
import static org.dynmap.JSONUtils.a;
|
||||
import static org.dynmap.JSONUtils.s;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.dynmap.Client;
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.DynmapChunk;
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.DynmapWorld;
|
||||
import org.dynmap.Log;
|
||||
import org.dynmap.MapManager;
|
||||
import org.dynmap.MapTile;
|
||||
import org.dynmap.MapType;
|
||||
import org.dynmap.debug.Debug;
|
||||
import org.dynmap.utils.TileFlags;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class HDMap extends MapType {
|
||||
|
||||
private String name;
|
||||
private String prefix;
|
||||
private HDPerspective perspective;
|
||||
private HDShader shader;
|
||||
private HDLighting lighting;
|
||||
private ConfigurationNode configuration;
|
||||
private int mapzoomout;
|
||||
private MapType.ImageFormat imgformat;
|
||||
private int bgcolornight;
|
||||
private int bgcolorday;
|
||||
|
||||
public static final String IMGFORMAT_PNG = "png";
|
||||
public static final String IMGFORMAT_JPG = "jpg";
|
||||
|
||||
|
||||
public HDMap(DynmapCore core, ConfigurationNode configuration) {
|
||||
name = configuration.getString("name", null);
|
||||
if(name == null) {
|
||||
Log.severe("HDMap missing required attribute 'name' - disabled");
|
||||
return;
|
||||
}
|
||||
String perspectiveid = configuration.getString("perspective", "default");
|
||||
perspective = MapManager.mapman.hdmapman.perspectives.get(perspectiveid);
|
||||
if(perspective == null) {
|
||||
/* Try to use default */
|
||||
perspective = MapManager.mapman.hdmapman.perspectives.get("default");
|
||||
if(perspective == null) {
|
||||
Log.severe("HDMap '"+name+"' loaded invalid perspective '" + perspectiveid + "' - map disabled");
|
||||
name = null;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
Log.severe("HDMap '"+name+"' loaded invalid perspective '" + perspectiveid + "' - using 'default' perspective");
|
||||
}
|
||||
}
|
||||
String shaderid = configuration.getString("shader", "default");
|
||||
shader = MapManager.mapman.hdmapman.shaders.get(shaderid);
|
||||
if(shader == null) {
|
||||
shader = MapManager.mapman.hdmapman.shaders.get("default");
|
||||
if(shader == null) {
|
||||
Log.severe("HDMap '"+name+"' loading invalid shader '" + shaderid + "' - map disabled");
|
||||
name = null;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
Log.severe("HDMap '"+name+"' loading invalid shader '" + shaderid + "' - using 'default' shader");
|
||||
}
|
||||
}
|
||||
String lightingid = configuration.getString("lighting", "default");
|
||||
lighting = MapManager.mapman.hdmapman.lightings.get(lightingid);
|
||||
if(lighting == null) {
|
||||
lighting = MapManager.mapman.hdmapman.lightings.get("default");
|
||||
if(lighting == null) {
|
||||
Log.severe("HDMap '"+name+"' loading invalid lighting '" + lighting + "' - map disabled");
|
||||
name = null;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
Log.severe("HDMap '"+name+"' loading invalid lighting '" + lighting + "' - using 'default' lighting");
|
||||
}
|
||||
}
|
||||
prefix = configuration.getString("prefix", name);
|
||||
this.configuration = configuration;
|
||||
|
||||
/* Compute extra zoom outs needed for this map */
|
||||
double scale = perspective.getScale();
|
||||
mapzoomout = 0;
|
||||
while(scale >= 1.0) {
|
||||
mapzoomout++;
|
||||
scale = scale / 2.0;
|
||||
}
|
||||
String fmt = configuration.getString("image-format", "png");
|
||||
/* Only allow png or jpg */
|
||||
for(ImageFormat f : ImageFormat.values()) {
|
||||
if(fmt.equals(f.getID())) {
|
||||
imgformat = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(imgformat == null) {
|
||||
Log.severe("HDMap '"+name+"' set invalid image-format: " + fmt);
|
||||
imgformat = ImageFormat.FORMAT_PNG;
|
||||
}
|
||||
/* Get color info */
|
||||
String c = configuration.getString("background");
|
||||
if(c != null) {
|
||||
bgcolorday = bgcolornight = parseColor(c);
|
||||
}
|
||||
c = configuration.getString("backgroundday");
|
||||
if(c != null) {
|
||||
bgcolorday = parseColor(c);
|
||||
}
|
||||
c = configuration.getString("backgroundnight");
|
||||
if(c != null) {
|
||||
bgcolornight = parseColor(c);
|
||||
}
|
||||
if(imgformat != ImageFormat.FORMAT_PNG) { /* If JPG, set background color opacity */
|
||||
bgcolorday |= 0xFF000000;
|
||||
bgcolornight |= 0xFF000000;
|
||||
}
|
||||
}
|
||||
|
||||
public HDShader getShader() { return shader; }
|
||||
public HDPerspective getPerspective() { return perspective; }
|
||||
public HDLighting getLighting() { return lighting; }
|
||||
|
||||
@Override
|
||||
public MapTile[] getTiles(DynmapWorld w, int x, int y, int z) {
|
||||
return perspective.getTiles(w, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapTile[] getTiles(DynmapWorld w, int minx, int miny, int minz, int maxx, int maxy, int maxz) {
|
||||
return perspective.getTiles(w, minx, miny, minz, maxx, maxy, maxz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapTile[] getAdjecentTiles(MapTile tile) {
|
||||
return perspective.getAdjecentTiles(tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DynmapChunk> getRequiredChunks(MapTile tile) {
|
||||
return perspective.getRequiredChunks(tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ZoomInfo> baseZoomFileInfo() {
|
||||
ArrayList<ZoomInfo> s = new ArrayList<ZoomInfo>();
|
||||
s.add(new ZoomInfo(prefix, getBackgroundARGBNight()));
|
||||
if(lighting.isNightAndDayEnabled())
|
||||
s.add(new ZoomInfo(prefix + "_day", getBackgroundARGBDay()));
|
||||
return s;
|
||||
}
|
||||
|
||||
public int baseZoomFileStepSize() { return 1; }
|
||||
|
||||
private static final int[] stepseq = { 3, 1, 2, 0 };
|
||||
|
||||
public MapStep zoomFileMapStep() { return MapStep.X_PLUS_Y_MINUS; }
|
||||
|
||||
public int[] zoomFileStepSequence() { return stepseq; }
|
||||
|
||||
/* How many bits of coordinate are shifted off to make big world directory name */
|
||||
public int getBigWorldShift() { return 5; }
|
||||
|
||||
/* Returns true if big world file structure is in effect for this map */
|
||||
@Override
|
||||
public boolean isBigWorldMap(DynmapWorld w) { return true; } /* We always use it on these maps */
|
||||
|
||||
/* Return number of zoom levels needed by this map (before extra levels from extrazoomout) */
|
||||
public int getMapZoomOutLevels() {
|
||||
return mapzoomout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/* Get maps rendered concurrently with this map in this world */
|
||||
public List<MapType> getMapsSharingRender(DynmapWorld w) {
|
||||
ArrayList<MapType> maps = new ArrayList<MapType>();
|
||||
for(MapType mt : w.maps) {
|
||||
if(mt instanceof HDMap) {
|
||||
HDMap hdmt = (HDMap)mt;
|
||||
if(hdmt.perspective == this.perspective) { /* Same perspective */
|
||||
maps.add(hdmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
return maps;
|
||||
}
|
||||
|
||||
/* Get names of maps rendered concurrently with this map type in this world */
|
||||
public List<String> getMapNamesSharingRender(DynmapWorld w) {
|
||||
ArrayList<String> lst = new ArrayList<String>();
|
||||
for(MapType mt : w.maps) {
|
||||
if(mt instanceof HDMap) {
|
||||
HDMap hdmt = (HDMap)mt;
|
||||
if(hdmt.perspective == this.perspective) { /* Same perspective */
|
||||
if(hdmt.lighting.isNightAndDayEnabled())
|
||||
lst.add(hdmt.getName() + "(night/day)");
|
||||
else
|
||||
lst.add(hdmt.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
return lst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getImageFormat() { return imgformat; }
|
||||
|
||||
@Override
|
||||
public void buildClientConfiguration(JSONObject worldObject, DynmapWorld world) {
|
||||
ConfigurationNode c = configuration;
|
||||
JSONObject o = new JSONObject();
|
||||
s(o, "type", "HDMapType");
|
||||
s(o, "name", name);
|
||||
s(o, "title", c.getString("title"));
|
||||
s(o, "icon", c.getString("icon"));
|
||||
s(o, "prefix", prefix);
|
||||
s(o, "background", c.getString("background"));
|
||||
s(o, "backgroundday", c.getString("backgroundday"));
|
||||
s(o, "backgroundnight", c.getString("backgroundnight"));
|
||||
s(o, "bigmap", true);
|
||||
s(o, "mapzoomout", (world.getExtraZoomOutLevels()+mapzoomout));
|
||||
s(o, "mapzoomin", c.getInteger("mapzoomin", 2));
|
||||
s(o, "image-format", imgformat.getFileExt());
|
||||
perspective.addClientConfiguration(o);
|
||||
shader.addClientConfiguration(o);
|
||||
lighting.addClientConfiguration(o);
|
||||
|
||||
a(worldObject, "maps", o);
|
||||
|
||||
}
|
||||
|
||||
private static int parseColor(String c) {
|
||||
int v = 0;
|
||||
if(c.startsWith("#")) {
|
||||
c = c.substring(1);
|
||||
if(c.length() == 3) { /* #rgb */
|
||||
try {
|
||||
v = Integer.valueOf(c, 16);
|
||||
} catch (NumberFormatException nfx) {
|
||||
return 0;
|
||||
}
|
||||
v = 0xFF000000 | ((v & 0xF00) << 12) | ((v & 0x0F0) << 8) | ((v & 0x00F) << 4);
|
||||
}
|
||||
else if(c.length() == 6) { /* #rrggbb */
|
||||
try {
|
||||
v = Integer.valueOf(c, 16);
|
||||
} catch (NumberFormatException nfx) {
|
||||
return 0;
|
||||
}
|
||||
v = 0xFF000000 | (v & 0xFFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public int getBackgroundARGBDay() {
|
||||
return bgcolorday;
|
||||
}
|
||||
|
||||
public int getBackgroundARGBNight() {
|
||||
return bgcolornight;
|
||||
}
|
||||
|
||||
private HDMapTile fileToTile(DynmapWorld world, File f) {
|
||||
String n = f.getName();
|
||||
n = n.substring(0, n.lastIndexOf('.'));
|
||||
if(n == null) return null;
|
||||
String[] nt = n.split("_");
|
||||
if(nt.length != 2) return null;
|
||||
int xx, zz;
|
||||
try {
|
||||
xx = Integer.parseInt(nt[0]);
|
||||
zz = Integer.parseInt(nt[1]);
|
||||
} catch (NumberFormatException nfx) {
|
||||
return null;
|
||||
}
|
||||
return new HDMapTile(world, perspective, xx, zz);
|
||||
}
|
||||
|
||||
public void purgeOldTiles(final DynmapWorld world, final TileFlags rendered) {
|
||||
File basedir = new File(world.worldtilepath, prefix); /* Get base directory for map */
|
||||
FileCallback cb = new FileCallback() {
|
||||
public void fileFound(File f, File parent, boolean day) {
|
||||
String n = f.getName();
|
||||
if(n.startsWith("z")) { /* If zoom file */
|
||||
if(n.startsWith("z_")) { /* First tier of zoom? */
|
||||
File ff = new File(parent, n.substring(2)); /* Make file for render tier, and drive update */
|
||||
HDMapTile tile = fileToTile(world, ff); /* Parse it */
|
||||
if(tile == null) return;
|
||||
if(rendered.getFlag(tile.tx, tile.ty) || rendered.getFlag(tile.tx+1, tile.ty) ||
|
||||
rendered.getFlag(tile.tx, tile.ty-1) || rendered.getFlag(tile.tx+1, tile.ty-1))
|
||||
return;
|
||||
world.enqueueZoomOutUpdate(ff);
|
||||
}
|
||||
return;
|
||||
}
|
||||
HDMapTile tile = fileToTile(world, f);
|
||||
if(tile == null) return;
|
||||
|
||||
if(rendered.getFlag(tile.tx, tile.ty)) { /* If we rendered this tile, its good */
|
||||
return;
|
||||
}
|
||||
Debug.debug("clean up " + f.getPath());
|
||||
/* Otherwise, delete tile */
|
||||
f.delete();
|
||||
/* Push updates, clear hash code, and signal zoom tile update */
|
||||
MapManager.mapman.pushUpdate(world,
|
||||
new Client.Tile(day?tile.getDayFilename(prefix, getImageFormat()):tile.getFilename(prefix, getImageFormat())));
|
||||
MapManager.mapman.hashman.updateHashCode(tile.getKey(prefix), day?"day":null, tile.tx, tile.ty, -1);
|
||||
world.enqueueZoomOutUpdate(f);
|
||||
}
|
||||
|
||||
};
|
||||
walkMapTree(basedir, cb, false);
|
||||
if(lighting.isNightAndDayEnabled()) {
|
||||
basedir = new File(world.worldtilepath, prefix+"_day");
|
||||
walkMapTree(basedir, cb, true);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,181 +0,0 @@
|
||||
package org.dynmap.hdmap;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.DynmapWorld;
|
||||
import org.dynmap.Log;
|
||||
import org.dynmap.MapManager;
|
||||
import org.dynmap.MapType;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
import org.dynmap.utils.MapIterator;
|
||||
|
||||
public class HDMapManager {
|
||||
public HashMap<String, HDShader> shaders = new HashMap<String, HDShader>();
|
||||
public HashMap<String, HDPerspective> perspectives = new HashMap<String, HDPerspective>();
|
||||
public HashMap<String, HDLighting> lightings = new HashMap<String, HDLighting>();
|
||||
public HashSet<HDMap> maps = new HashSet<HDMap>();
|
||||
public HashMap<String, ArrayList<HDMap>> maps_by_world_perspective = new HashMap<String, ArrayList<HDMap>>();
|
||||
|
||||
public static boolean usegeneratedtextures;
|
||||
public static boolean waterlightingfix;
|
||||
public static boolean biomeshadingfix;
|
||||
|
||||
public void loadHDShaders(DynmapCore core) {
|
||||
Log.verboseinfo("Loading shaders...");
|
||||
|
||||
File f = new File(core.getDataFolder(), "shaders.txt");
|
||||
if(!core.updateUsingDefaultResource("/shaders.txt", f, "shaders")) {
|
||||
return;
|
||||
}
|
||||
ConfigurationNode shadercfg = new ConfigurationNode(f);
|
||||
shadercfg.load();
|
||||
|
||||
for(HDShader shader : shadercfg.<HDShader>createInstances("shaders", new Class<?>[] { DynmapCore.class }, new Object[] { core })) {
|
||||
if(shader.getName() == null) continue;
|
||||
shaders.put(shader.getName(), shader);
|
||||
}
|
||||
/* Load custom shaders, if file is defined - or create empty one if not */
|
||||
f = new File(core.getDataFolder(), "custom-shaders.txt");
|
||||
core.createDefaultFileFromResource("/custom-shaders.txt", f);
|
||||
if(f.exists()) {
|
||||
ConfigurationNode customshadercfg = new ConfigurationNode(f);
|
||||
customshadercfg.load();
|
||||
for(HDShader shader : customshadercfg.<HDShader>createInstances("shaders", new Class<?>[] { DynmapCore.class }, new Object[] { core })) {
|
||||
if(shader.getName() == null) continue;
|
||||
shaders.put(shader.getName(), shader);
|
||||
}
|
||||
}
|
||||
Log.info("Loaded " + shaders.size() + " shaders.");
|
||||
/* Update ore mappings, if needed */
|
||||
TexturePack.handleHideOres();
|
||||
}
|
||||
|
||||
public void loadHDPerspectives(DynmapCore core) {
|
||||
Log.verboseinfo("Loading perspectives...");
|
||||
File f = new File(core.getDataFolder(), "perspectives.txt");
|
||||
if(!core.updateUsingDefaultResource("/perspectives.txt", f, "perspectives")) {
|
||||
return;
|
||||
}
|
||||
ConfigurationNode perspectivecfg = new ConfigurationNode(f);
|
||||
perspectivecfg.load();
|
||||
for(HDPerspective perspective : perspectivecfg.<HDPerspective>createInstances("perspectives", new Class<?>[] { DynmapCore.class }, new Object[] { core })) {
|
||||
if(perspective.getName() == null) continue;
|
||||
perspectives.put(perspective.getName(), perspective);
|
||||
}
|
||||
/* Load custom perspectives, if file is defined - or create empty one if not */
|
||||
f = new File(core.getDataFolder(), "custom-perspectives.txt");
|
||||
core.createDefaultFileFromResource("/custom-perspectives.txt", f);
|
||||
if(f.exists()) {
|
||||
perspectivecfg = new ConfigurationNode(f);
|
||||
perspectivecfg.load();
|
||||
for(HDPerspective perspective : perspectivecfg.<HDPerspective>createInstances("perspectives", new Class<?>[] { DynmapCore.class }, new Object[] { core })) {
|
||||
if(perspective.getName() == null) continue;
|
||||
perspectives.put(perspective.getName(), perspective);
|
||||
}
|
||||
}
|
||||
Log.info("Loaded " + perspectives.size() + " perspectives.");
|
||||
}
|
||||
|
||||
public void loadHDLightings(DynmapCore core) {
|
||||
Log.verboseinfo("Loading lightings...");
|
||||
File f = new File(core.getDataFolder(), "lightings.txt");
|
||||
if(!core.updateUsingDefaultResource("/lightings.txt", f, "lightings")) {
|
||||
return;
|
||||
}
|
||||
ConfigurationNode lightingcfg = new ConfigurationNode(f);
|
||||
lightingcfg.load();
|
||||
|
||||
for(HDLighting lighting : lightingcfg.<HDLighting>createInstances("lightings", new Class<?>[] { DynmapCore.class }, new Object[] { core })) {
|
||||
if(lighting.getName() == null) continue;
|
||||
lightings.put(lighting.getName(), lighting);
|
||||
}
|
||||
/* Load custom lightings, if file is defined - or create empty one if not */
|
||||
f = new File(core.getDataFolder(), "custom-lightings.txt");
|
||||
core.createDefaultFileFromResource("/custom-lightings.txt", f);
|
||||
if(f.exists()) {
|
||||
lightingcfg = new ConfigurationNode(f);
|
||||
lightingcfg.load();
|
||||
for(HDLighting lighting : lightingcfg.<HDLighting>createInstances("lightings", new Class<?>[] { DynmapCore.class }, new Object[] { core })) {
|
||||
if(lighting.getName() == null) continue;
|
||||
lightings.put(lighting.getName(), lighting);
|
||||
}
|
||||
}
|
||||
Log.info("Loaded " + lightings.size() + " lightings.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize shader states for all shaders for given tile
|
||||
*/
|
||||
public HDShaderState[] getShaderStateForTile(HDMapTile tile, MapChunkCache cache, MapIterator mapiter, String mapname) {
|
||||
DynmapWorld w = MapManager.mapman.worldsLookup.get(tile.getDynmapWorld().getName());
|
||||
if(w == null) return new HDShaderState[0];
|
||||
ArrayList<HDShaderState> shaders = new ArrayList<HDShaderState>();
|
||||
for(MapType map : w.maps) {
|
||||
if(map instanceof HDMap) {
|
||||
HDMap hdmap = (HDMap)map;
|
||||
if(hdmap.getPerspective() == tile.perspective) {
|
||||
/* If limited to one map, and this isn't it, skip */
|
||||
if((mapname != null) && (!hdmap.getName().equals(mapname)))
|
||||
continue;
|
||||
shaders.add(hdmap.getShader().getStateInstance(hdmap, cache, mapiter));
|
||||
}
|
||||
}
|
||||
}
|
||||
return shaders.toArray(new HDShaderState[shaders.size()]);
|
||||
}
|
||||
|
||||
private static final int BIOMEDATAFLAG = 0;
|
||||
private static final int HIGHESTZFLAG = 1;
|
||||
private static final int RAWBIOMEFLAG = 2;
|
||||
private static final int BLOCKTYPEFLAG = 3;
|
||||
|
||||
public boolean isBiomeDataNeeded(HDMapTile t) {
|
||||
return getCachedFlags(t)[BIOMEDATAFLAG];
|
||||
}
|
||||
|
||||
public boolean isHightestBlockYDataNeeded(HDMapTile t) {
|
||||
return getCachedFlags(t)[HIGHESTZFLAG];
|
||||
}
|
||||
|
||||
public boolean isRawBiomeDataNeeded(HDMapTile t) {
|
||||
return getCachedFlags(t)[RAWBIOMEFLAG];
|
||||
}
|
||||
|
||||
public boolean isBlockTypeDataNeeded(HDMapTile t) {
|
||||
return getCachedFlags(t)[BLOCKTYPEFLAG];
|
||||
}
|
||||
|
||||
private HashMap<String, boolean[]> cached_data_flags_by_world_perspective = new HashMap<String, boolean[]>();
|
||||
|
||||
private boolean[] getCachedFlags(HDMapTile t) {
|
||||
String w = t.getDynmapWorld().getName();
|
||||
String k = w + "/" + t.perspective.getName();
|
||||
boolean[] flags = cached_data_flags_by_world_perspective.get(k);
|
||||
if(flags != null)
|
||||
return flags;
|
||||
flags = new boolean[4];
|
||||
cached_data_flags_by_world_perspective.put(k, flags);
|
||||
DynmapWorld dw = MapManager.mapman.worldsLookup.get(w);
|
||||
if(dw == null) return flags;
|
||||
|
||||
for(MapType map : dw.maps) {
|
||||
if(map instanceof HDMap) {
|
||||
HDMap hdmap = (HDMap)map;
|
||||
if(hdmap.getPerspective() == t.perspective) {
|
||||
HDShader sh = hdmap.getShader();
|
||||
HDLighting lt = hdmap.getLighting();
|
||||
flags[BIOMEDATAFLAG] |= sh.isBiomeDataNeeded() | lt.isBiomeDataNeeded();
|
||||
flags[HIGHESTZFLAG] |= sh.isHightestBlockYDataNeeded() | lt.isHightestBlockYDataNeeded();
|
||||
flags[RAWBIOMEFLAG] |= sh.isRawBiomeDataNeeded() | lt.isRawBiomeDataNeeded();
|
||||
flags[BLOCKTYPEFLAG] |= sh.isBlockTypeDataNeeded() | lt.isBlockTypeDataNeeded();
|
||||
}
|
||||
}
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
package org.dynmap.hdmap;
|
||||
|
||||
import org.dynmap.DynmapChunk;
|
||||
import org.dynmap.DynmapWorld;
|
||||
import org.dynmap.MapManager;
|
||||
import org.dynmap.MapType;
|
||||
|
||||
import java.util.List;
|
||||
import org.dynmap.MapTile;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
|
||||
public class HDMapTile extends MapTile {
|
||||
public HDPerspective perspective;
|
||||
public int tx, ty; /* Tile X and Tile Y are in tile coordinates (pixels/tile-size) */
|
||||
|
||||
public HDMapTile(DynmapWorld world, HDPerspective perspective, int tx, int ty) {
|
||||
super(world);
|
||||
this.perspective = perspective;
|
||||
this.tx = tx;
|
||||
this.ty = ty;
|
||||
}
|
||||
|
||||
public HDMapTile(DynmapWorld world, String parm) throws Exception {
|
||||
super(world);
|
||||
|
||||
String[] parms = parm.split(",");
|
||||
if(parms.length < 3) throw new Exception("wrong parameter count");
|
||||
this.tx = Integer.parseInt(parms[0]);
|
||||
this.ty = Integer.parseInt(parms[1]);
|
||||
this.perspective = MapManager.mapman.hdmapman.perspectives.get(parms[2]);
|
||||
if(this.perspective == null) throw new Exception("invalid perspective");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String saveTileData() {
|
||||
return String.format("%d,%d,%s", tx, ty, perspective.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return getFilename("hdmap", MapType.ImageFormat.FORMAT_PNG);
|
||||
}
|
||||
|
||||
public String getFilename(String prefix, MapType.ImageFormat format) {
|
||||
return prefix + "/" + (tx >> 5) + '_' + (ty >> 5) + '/' + tx + "_" + ty + "." + format.getFileExt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDayFilename() {
|
||||
return getDayFilename("hdmap", MapType.ImageFormat.FORMAT_PNG);
|
||||
}
|
||||
|
||||
public String getDayFilename(String prefix, MapType.ImageFormat format) {
|
||||
return prefix + "_day/" + (tx >> 5) + '_' + (ty >> 5) + '/' + tx + "_" + ty + "." + format.getFileExt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return tx ^ ty ^ perspective.getName().hashCode() ^ world.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof HDMapTile) {
|
||||
return equals((HDMapTile) obj);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean equals(HDMapTile o) {
|
||||
return o.tx == tx && o.ty == ty && (perspective == o.perspective) && (o.world == world);
|
||||
}
|
||||
|
||||
public String getKey(String prefix) {
|
||||
return world.getName() + "." + prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return world.getName() + ":" + getFilename();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBiomeDataNeeded() { return MapManager.mapman.hdmapman.isBiomeDataNeeded(this); }
|
||||
|
||||
@Override
|
||||
public boolean isHightestBlockYDataNeeded() { return MapManager.mapman.hdmapman.isHightestBlockYDataNeeded(this); }
|
||||
|
||||
@Override
|
||||
public boolean isRawBiomeDataNeeded() { return MapManager.mapman.hdmapman.isRawBiomeDataNeeded(this); }
|
||||
|
||||
@Override
|
||||
public boolean isBlockTypeDataNeeded() { return MapManager.mapman.hdmapman.isBlockTypeDataNeeded(this); }
|
||||
|
||||
public boolean render(MapChunkCache cache, String mapname) {
|
||||
return perspective.render(cache, this, mapname);
|
||||
}
|
||||
|
||||
public List<DynmapChunk> getRequiredChunks() {
|
||||
return perspective.getRequiredChunks(this);
|
||||
}
|
||||
|
||||
public MapTile[] getAdjecentTiles() {
|
||||
return perspective.getAdjecentTiles(this);
|
||||
}
|
||||
|
||||
public int tileOrdinalX() { return tx; }
|
||||
public int tileOrdinalY() { return ty; }
|
||||
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package org.dynmap.hdmap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.dynmap.DynmapChunk;
|
||||
import org.dynmap.DynmapWorld;
|
||||
import org.dynmap.MapTile;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public interface HDPerspective {
|
||||
/* Get name of perspective */
|
||||
String getName();
|
||||
/* Get tiles invalidated by change at given location */
|
||||
MapTile[] getTiles(DynmapWorld w, int x, int y, int z);
|
||||
/* Get tiles invalidated by change at given volume, defined by 2 opposite corner locations */
|
||||
MapTile[] getTiles(DynmapWorld w, int minx, int miny, int minz, int maxx, int maxy, int maxz);
|
||||
/* Get tiles adjacent to given tile */
|
||||
MapTile[] getAdjecentTiles(MapTile tile);
|
||||
/* Get chunks needed for given tile */
|
||||
List<DynmapChunk> getRequiredChunks(MapTile tile);
|
||||
/* Render given tile */
|
||||
boolean render(MapChunkCache cache, HDMapTile tile, String mapname);
|
||||
|
||||
public boolean isBiomeDataNeeded();
|
||||
public boolean isHightestBlockYDataNeeded();
|
||||
public boolean isRawBiomeDataNeeded();
|
||||
public boolean isBlockTypeDataNeeded();
|
||||
|
||||
double getScale();
|
||||
int getModelScale();
|
||||
|
||||
public void addClientConfiguration(JSONObject mapObject);
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
package org.dynmap.hdmap;
|
||||
|
||||
import org.dynmap.utils.MapIterator;
|
||||
import org.dynmap.utils.MapIterator.BlockStep;
|
||||
import org.dynmap.utils.Vector3D;
|
||||
|
||||
public interface HDPerspectiveState {
|
||||
/**
|
||||
* Get sky light level - only available if shader requested it
|
||||
*/
|
||||
int getSkyLightLevel();
|
||||
/**
|
||||
* Get emitted light level - only available if shader requested it
|
||||
*/
|
||||
int getEmittedLightLevel();
|
||||
/**
|
||||
* Get current block type ID
|
||||
*/
|
||||
int getBlockTypeID();
|
||||
/**
|
||||
* Get current block data
|
||||
*/
|
||||
int getBlockData();
|
||||
/**
|
||||
* Get current block render data
|
||||
*/
|
||||
int getBlockRenderData();
|
||||
/**
|
||||
* Get direction of last block step
|
||||
*/
|
||||
BlockStep getLastBlockStep();
|
||||
/**
|
||||
* Get perspective scale
|
||||
*/
|
||||
double getScale();
|
||||
/**
|
||||
* Get start of current ray, in world coordinates
|
||||
*/
|
||||
Vector3D getRayStart();
|
||||
/**
|
||||
* Get end of current ray, in world coordinates
|
||||
*/
|
||||
Vector3D getRayEnd();
|
||||
/**
|
||||
* Get pixel X coordinate
|
||||
*/
|
||||
int getPixelX();
|
||||
/**
|
||||
* Get pixel Y coordinate
|
||||
*/
|
||||
int getPixelY();
|
||||
/**
|
||||
* Return submodel alpha value (-1 if no submodel rendered)
|
||||
*/
|
||||
int getSubmodelAlpha();
|
||||
/**
|
||||
* Return subblock coordinates of current ray position
|
||||
*/
|
||||
int[] getSubblockCoord();
|
||||
/**
|
||||
* Get map iterator
|
||||
*/
|
||||
MapIterator getMapIterator();
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package org.dynmap.hdmap;
|
||||
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
import org.dynmap.utils.MapIterator;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public interface HDShader {
|
||||
/* Get shader name */
|
||||
String getName();
|
||||
/**
|
||||
* Get renderer state object for use rendering a tile
|
||||
* @param map - map being rendered
|
||||
* @param cache - chunk cache containing data for tile to be rendered
|
||||
* @param mapiter - iterator used when traversing rays in tile
|
||||
* @return state object to use for all rays in tile
|
||||
*/
|
||||
HDShaderState getStateInstance(HDMap map, MapChunkCache cache, MapIterator mapiter);
|
||||
/* Test if Biome Data is needed for this renderer */
|
||||
boolean isBiomeDataNeeded();
|
||||
/* Test if raw biome temperature/rainfall data is needed */
|
||||
boolean isRawBiomeDataNeeded();
|
||||
/* Test if highest block Y data is needed */
|
||||
boolean isHightestBlockYDataNeeded();
|
||||
/* Tet if block type data needed */
|
||||
boolean isBlockTypeDataNeeded();
|
||||
/* Test if sky light level needed */
|
||||
boolean isSkyLightLevelNeeded();
|
||||
/* Test if emitted light level needed */
|
||||
boolean isEmittedLightLevelNeeded();
|
||||
/* Add shader's contributions to JSON for map object */
|
||||
void addClientConfiguration(JSONObject mapObject);
|
||||
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package org.dynmap.hdmap;
|
||||
|
||||
import org.dynmap.Color;
|
||||
|
||||
/**
|
||||
* This interface is used to define the operational state of a renderer during raytracing
|
||||
* All method should be considered performance critical
|
||||
*/
|
||||
public interface HDShaderState {
|
||||
/**
|
||||
* Get our shader
|
||||
*/
|
||||
HDShader getShader();
|
||||
/**
|
||||
* Get our lighting
|
||||
*/
|
||||
HDLighting getLighting();
|
||||
/**
|
||||
* Get our map
|
||||
*/
|
||||
HDMap getMap();
|
||||
/**
|
||||
* Reset renderer state for new ray - passes in pixel coordinate for ray
|
||||
*/
|
||||
void reset(HDPerspectiveState ps);
|
||||
/**
|
||||
* Process next ray step - called for each block on route
|
||||
* @return true if ray is done, false if ray needs to continue
|
||||
*/
|
||||
boolean processBlock(HDPerspectiveState ps);
|
||||
/**
|
||||
* Ray ended - used to report that ray has exited map (called if renderer has not reported complete)
|
||||
*/
|
||||
void rayFinished(HDPerspectiveState ps);
|
||||
/**
|
||||
* Get result color - get resulting color for ray
|
||||
* @param c - object to store color value in
|
||||
* @param index - index of color to request (renderer specific - 0=default, 1=day for night/day renderer
|
||||
*/
|
||||
void getRayColor(Color c, int index);
|
||||
/**
|
||||
* Clean up state object - called after last ray completed
|
||||
*/
|
||||
void cleanup();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,97 +0,0 @@
|
||||
package org.dynmap.hdmap;
|
||||
|
||||
import org.dynmap.Color;
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.Log;
|
||||
|
||||
public class ShadowHDLighting extends DefaultHDLighting {
|
||||
|
||||
protected int shadowscale[]; /* index=skylight level, value = 256 * scaling value */
|
||||
protected int lightscale[]; /* scale skylight level (light = lightscale[skylight] */
|
||||
protected boolean night_and_day; /* If true, render both day (prefix+'-day') and night (prefix) tiles */
|
||||
|
||||
public ShadowHDLighting(DynmapCore core, ConfigurationNode configuration) {
|
||||
super(core, configuration);
|
||||
double shadowweight = configuration.getDouble("shadowstrength", 0.0);
|
||||
if(shadowweight > 0.0) {
|
||||
shadowscale = new int[16];
|
||||
shadowscale[15] = 256;
|
||||
/* Normal brightness weight in MC is a 20% relative dropoff per step */
|
||||
for(int i = 14; i >= 0; i--) {
|
||||
double v = shadowscale[i+1] * (1.0 - (0.2 * shadowweight));
|
||||
shadowscale[i] = (int)v;
|
||||
if(shadowscale[i] > 256) shadowscale[i] = 256;
|
||||
if(shadowscale[i] < 0) shadowscale[i] = 0;
|
||||
}
|
||||
}
|
||||
int v = configuration.getInteger("ambientlight", -1);
|
||||
if((v >= 0) && (v < 15)) {
|
||||
lightscale = new int[16];
|
||||
for(int i = 0; i < 16; i++) {
|
||||
if(i < (15-v))
|
||||
lightscale[i] = 0;
|
||||
else
|
||||
lightscale[i] = i - (15-v);
|
||||
}
|
||||
}
|
||||
night_and_day = configuration.getBoolean("night-and-day", false);
|
||||
if(night_and_day) {
|
||||
if(lightscale == null) {
|
||||
Log.severe("night-and-day in lighting '" + getName() + "' requires ambientlight<15");
|
||||
night_and_day = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply lighting to given pixel colors (1 outcolor if normal, 2 if night/day) */
|
||||
public void applyLighting(HDPerspectiveState ps, HDShaderState ss, Color incolor, Color[] outcolor) {
|
||||
int lightlevel = 15, lightlevel_day = 15;
|
||||
/* If processing for shadows, use sky light level as base lighting */
|
||||
if(shadowscale != null) {
|
||||
lightlevel = lightlevel_day = ps.getSkyLightLevel();
|
||||
}
|
||||
/* If ambient light, adjust base lighting for it */
|
||||
if(lightscale != null)
|
||||
lightlevel = lightscale[lightlevel];
|
||||
/* If we're below max, see if emitted light helps */
|
||||
if((lightlevel < 15) || (lightlevel_day < 15)) {
|
||||
int emitted = ps.getEmittedLightLevel();
|
||||
lightlevel = Math.max(emitted, lightlevel);
|
||||
lightlevel_day = Math.max(emitted, lightlevel_day);
|
||||
}
|
||||
/* Figure out our color, with lighting if needed */
|
||||
outcolor[0].setColor(incolor);
|
||||
if(lightlevel < 15) {
|
||||
shadowColor(outcolor[0], lightlevel);
|
||||
}
|
||||
if(outcolor.length > 1) {
|
||||
if(lightlevel_day == lightlevel) {
|
||||
outcolor[1].setColor(outcolor[0]);
|
||||
}
|
||||
else {
|
||||
outcolor[1].setColor(incolor);
|
||||
if(lightlevel_day < 15) {
|
||||
shadowColor(outcolor[1], lightlevel_day);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final void shadowColor(Color c, int lightlevel) {
|
||||
int scale = shadowscale[lightlevel];
|
||||
if(scale < 256)
|
||||
c.setRGBA((c.getRed() * scale) >> 8, (c.getGreen() * scale) >> 8,
|
||||
(c.getBlue() * scale) >> 8, c.getAlpha());
|
||||
}
|
||||
|
||||
/* Test if night/day is enabled for this renderer */
|
||||
public boolean isNightAndDayEnabled() { return night_and_day; }
|
||||
|
||||
/* Test if sky light level needed */
|
||||
public boolean isSkyLightLevelNeeded() { return (shadowscale != null); }
|
||||
|
||||
/* Test if emitted light level needed */
|
||||
public boolean isEmittedLightLevelNeeded() { return (shadowscale != null) || (lightscale != null); }
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,240 +0,0 @@
|
||||
package org.dynmap.hdmap;
|
||||
|
||||
import static org.dynmap.JSONUtils.s;
|
||||
|
||||
import org.dynmap.Color;
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.Log;
|
||||
import org.dynmap.MapManager;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
import org.dynmap.utils.MapIterator;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class TexturePackHDShader implements HDShader {
|
||||
private String tpname;
|
||||
private String name;
|
||||
private TexturePack tp;
|
||||
private boolean biome_shaded;
|
||||
private boolean swamp_shaded;
|
||||
private boolean waterbiomeshaded;
|
||||
private boolean bettergrass;
|
||||
|
||||
public TexturePackHDShader(DynmapCore core, ConfigurationNode configuration) {
|
||||
tpname = configuration.getString("texturepack", "minecraft");
|
||||
name = configuration.getString("name", tpname);
|
||||
tp = TexturePack.getTexturePack(core, tpname);
|
||||
biome_shaded = configuration.getBoolean("biomeshaded", true);
|
||||
swamp_shaded = configuration.getBoolean("swampshaded", MapManager.mapman.getSwampShading());
|
||||
waterbiomeshaded = configuration.getBoolean("waterbiomeshaded", MapManager.mapman.getWaterBiomeShading());
|
||||
bettergrass = configuration.getBoolean("better-grass", MapManager.mapman.getBetterGrass());
|
||||
if(tp == null) {
|
||||
Log.severe("Error: shader '" + name + "' cannot load texture pack '" + tpname + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBiomeDataNeeded() {
|
||||
return swamp_shaded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRawBiomeDataNeeded() {
|
||||
return biome_shaded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHightestBlockYDataNeeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBlockTypeDataNeeded() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSkyLightLevelNeeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmittedLightLevelNeeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
class ShaderState implements HDShaderState {
|
||||
private Color color[];
|
||||
private Color tmpcolor[];
|
||||
private Color c;
|
||||
protected MapIterator mapiter;
|
||||
protected HDMap map;
|
||||
private TexturePack scaledtp;
|
||||
private HDLighting lighting;
|
||||
private int lastblkid;
|
||||
boolean do_biome_shading;
|
||||
boolean do_swamp_shading;
|
||||
boolean do_water_shading;
|
||||
boolean do_better_grass;
|
||||
|
||||
private ShaderState(MapIterator mapiter, HDMap map, MapChunkCache cache) {
|
||||
this.mapiter = mapiter;
|
||||
this.map = map;
|
||||
this.lighting = map.getLighting();
|
||||
if(lighting.isNightAndDayEnabled()) {
|
||||
color = new Color[] { new Color(), new Color() };
|
||||
tmpcolor = new Color[] { new Color(), new Color() };
|
||||
}
|
||||
else {
|
||||
color = new Color[] { new Color() };
|
||||
tmpcolor = new Color[] { new Color() };
|
||||
}
|
||||
c = new Color();
|
||||
scaledtp = tp.resampleTexturePack(map.getPerspective().getModelScale());
|
||||
/* Biome raw data only works on normal worlds at this point */
|
||||
do_biome_shading = biome_shaded; // && (cache.getWorld().getEnvironment() == Environment.NORMAL);
|
||||
do_swamp_shading = do_biome_shading && swamp_shaded;
|
||||
do_water_shading = do_biome_shading && waterbiomeshaded;
|
||||
do_better_grass = bettergrass;
|
||||
}
|
||||
/**
|
||||
* Get our shader
|
||||
*/
|
||||
public HDShader getShader() {
|
||||
return TexturePackHDShader.this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get our map
|
||||
*/
|
||||
public HDMap getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get our lighting
|
||||
*/
|
||||
public HDLighting getLighting() {
|
||||
return lighting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset renderer state for new ray
|
||||
*/
|
||||
public void reset(HDPerspectiveState ps) {
|
||||
for(int i = 0; i < color.length; i++)
|
||||
color[i].setTransparent();
|
||||
lastblkid = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process next ray step - called for each block on route
|
||||
* @return true if ray is done, false if ray needs to continue
|
||||
*/
|
||||
public boolean processBlock(HDPerspectiveState ps) {
|
||||
int blocktype = ps.getBlockTypeID();
|
||||
int lastblocktype = lastblkid;
|
||||
lastblkid = blocktype;
|
||||
|
||||
if(blocktype == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get color from textures */
|
||||
scaledtp.readColor(ps, mapiter, c, blocktype, lastblocktype, ShaderState.this);
|
||||
|
||||
if (c.getAlpha() > 0) {
|
||||
/* Scale brightness depending upon face */
|
||||
switch(ps.getLastBlockStep()) {
|
||||
case X_MINUS:
|
||||
case X_PLUS:
|
||||
/* 60% brightness */
|
||||
c.blendColor(0xFFA0A0A0);
|
||||
break;
|
||||
case Y_MINUS:
|
||||
case Y_PLUS:
|
||||
/* 85% brightness for even, 90% for even*/
|
||||
if((mapiter.getY() & 0x01) == 0)
|
||||
c.blendColor(0xFFD9D9D9);
|
||||
else
|
||||
c.blendColor(0xFFE6E6E6);
|
||||
break;
|
||||
}
|
||||
/* Handle light level, if needed */
|
||||
lighting.applyLighting(ps, this, c, tmpcolor);
|
||||
/* If we got alpha from subblock model, use it instead if it is lower */
|
||||
/* (disable for now: weighting is wrong, as crosssection is 2D, not 3D based) */
|
||||
// if(subalpha >= 0) {
|
||||
// for(Color clr : tmpcolor) {
|
||||
// int a = clr.getAlpha();
|
||||
// if(subalpha < a)
|
||||
// clr.setAlpha(subalpha);
|
||||
// }
|
||||
// }
|
||||
/* If no previous color contribution, use new color */
|
||||
if(color[0].isTransparent()) {
|
||||
for(int i = 0; i < color.length; i++)
|
||||
color[i].setColor(tmpcolor[i]);
|
||||
return (color[0].getAlpha() == 255);
|
||||
}
|
||||
/* Else, blend and generate new alpha */
|
||||
else {
|
||||
int alpha = color[0].getAlpha();
|
||||
int alpha2 = tmpcolor[0].getAlpha() * (255-alpha) / 255;
|
||||
int talpha = alpha + alpha2;
|
||||
if(talpha > 0)
|
||||
for(int i = 0; i < color.length; i++)
|
||||
color[i].setRGBA((tmpcolor[i].getRed()*alpha2 + color[i].getRed()*alpha) / talpha,
|
||||
(tmpcolor[i].getGreen()*alpha2 + color[i].getGreen()*alpha) / talpha,
|
||||
(tmpcolor[i].getBlue()*alpha2 + color[i].getBlue()*alpha) / talpha, talpha);
|
||||
else
|
||||
for(int i = 0; i < color.length; i++)
|
||||
color[i].setTransparent();
|
||||
|
||||
return (talpha >= 254); /* If only one short, no meaningful contribution left */
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Ray ended - used to report that ray has exited map (called if renderer has not reported complete)
|
||||
*/
|
||||
public void rayFinished(HDPerspectiveState ps) {
|
||||
}
|
||||
/**
|
||||
* Get result color - get resulting color for ray
|
||||
* @param c - object to store color value in
|
||||
* @param index - index of color to request (renderer specific - 0=default, 1=day for night/day renderer
|
||||
*/
|
||||
public void getRayColor(Color c, int index) {
|
||||
c.setColor(color[index]);
|
||||
}
|
||||
/**
|
||||
* Clean up state object - called after last ray completed
|
||||
*/
|
||||
public void cleanup() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get renderer state object for use rendering a tile
|
||||
* @param map - map being rendered
|
||||
* @param cache - chunk cache containing data for tile to be rendered
|
||||
* @param mapiter - iterator used when traversing rays in tile
|
||||
* @return state object to use for all rays in tile
|
||||
*/
|
||||
public HDShaderState getStateInstance(HDMap map, MapChunkCache cache, MapIterator mapiter) {
|
||||
return new ShaderState(mapiter, map, cache);
|
||||
}
|
||||
|
||||
/* Add shader's contributions to JSON for map object */
|
||||
public void addClientConfiguration(JSONObject mapObject) {
|
||||
s(mapObject, "shader", name);
|
||||
}
|
||||
}
|
@ -1,235 +0,0 @@
|
||||
package org.dynmap.hdmap;
|
||||
|
||||
import static org.dynmap.JSONUtils.s;
|
||||
|
||||
import org.dynmap.Color;
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.Log;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
import org.dynmap.utils.MapIterator;
|
||||
import org.dynmap.utils.MapIterator.BlockStep;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class TopoHDShader implements HDShader {
|
||||
private String name;
|
||||
private Color linecolor; /* Color for topo lines */
|
||||
private Color fillcolor[]; /* Color for nontopo surfaces */
|
||||
private Color watercolor;
|
||||
|
||||
private Color readColor(String id, ConfigurationNode cfg) {
|
||||
String lclr = cfg.getString(id, null);
|
||||
if((lclr != null) && (lclr.startsWith("#"))) {
|
||||
try {
|
||||
int c = Integer.parseInt(lclr.substring(1), 16);
|
||||
return new Color((c>>16)&0xFF, (c>>8)&0xFF, c&0xFF);
|
||||
} catch (NumberFormatException nfx) {
|
||||
Log.severe("Invalid color value: " + lclr + " for '" + id + "'");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public TopoHDShader(DynmapCore core, ConfigurationNode configuration) {
|
||||
name = (String) configuration.get("name");
|
||||
|
||||
fillcolor = new Color[128]; /* Color by Y */
|
||||
/* Load defined colors from parameters */
|
||||
for(int i = 0; i < 128; i++) {
|
||||
fillcolor[i] = readColor("color" + i, configuration);
|
||||
}
|
||||
linecolor = readColor("linecolor", configuration);
|
||||
watercolor = readColor("watercolor", configuration);
|
||||
/* Now, interpolate missing colors */
|
||||
if(fillcolor[0] == null) {
|
||||
fillcolor[0] = new Color(0, 0, 0);
|
||||
}
|
||||
if(fillcolor[127] == null) {
|
||||
fillcolor[127] = new Color(255, 255, 255);
|
||||
}
|
||||
int starty = 0;
|
||||
for(int i = 1; i < 128; i++) {
|
||||
if(fillcolor[i] != null) { /* Found color? */
|
||||
int delta = i - starty;
|
||||
Color c0 = fillcolor[starty];
|
||||
Color c1 = fillcolor[i];
|
||||
/* Interpolate missing colors since last one */
|
||||
for(int j = 1; j < delta; j++) {
|
||||
fillcolor[starty + j] = new Color((c0.getRed()*(delta-j) + c1.getRed()*j)/delta, (c0.getGreen()*(delta-j) + c1.getGreen()*j)/delta, (c0.getBlue()*(delta-j) + c1.getBlue()*j)/delta);
|
||||
}
|
||||
starty = i; /* New start color */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBiomeDataNeeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRawBiomeDataNeeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHightestBlockYDataNeeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBlockTypeDataNeeded() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSkyLightLevelNeeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmittedLightLevelNeeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
private class OurShaderState implements HDShaderState {
|
||||
private Color color[];
|
||||
private Color tmpcolor[];
|
||||
private Color c;
|
||||
protected MapIterator mapiter;
|
||||
protected HDMap map;
|
||||
private HDLighting lighting;
|
||||
private int scale;
|
||||
|
||||
private OurShaderState(MapIterator mapiter, HDMap map, MapChunkCache cache) {
|
||||
this.mapiter = mapiter;
|
||||
this.map = map;
|
||||
this.lighting = map.getLighting();
|
||||
if(lighting.isNightAndDayEnabled()) {
|
||||
color = new Color[] { new Color(), new Color() };
|
||||
tmpcolor = new Color[] { new Color(), new Color() };
|
||||
}
|
||||
else {
|
||||
color = new Color[] { new Color() };
|
||||
tmpcolor = new Color[] { new Color() };
|
||||
}
|
||||
scale = (int)map.getPerspective().getScale();
|
||||
c = new Color();
|
||||
}
|
||||
/**
|
||||
* Get our shader
|
||||
*/
|
||||
public HDShader getShader() {
|
||||
return TopoHDShader.this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get our map
|
||||
*/
|
||||
public HDMap getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get our lighting
|
||||
*/
|
||||
public HDLighting getLighting() {
|
||||
return lighting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset renderer state for new ray
|
||||
*/
|
||||
public void reset(HDPerspectiveState ps) {
|
||||
for(int i = 0; i < color.length; i++)
|
||||
color[i].setTransparent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process next ray step - called for each block on route
|
||||
* @return true if ray is done, false if ray needs to continue
|
||||
*/
|
||||
public boolean processBlock(HDPerspectiveState ps) {
|
||||
int blocktype = ps.getBlockTypeID();
|
||||
|
||||
if(blocktype == 0) {
|
||||
return false;
|
||||
}
|
||||
/* See if we're close to an edge */
|
||||
int[] xyz = ps.getSubblockCoord();
|
||||
/* See which face we're on (only do lines on top face) */
|
||||
switch(ps.getLastBlockStep()) {
|
||||
case Y_MINUS:
|
||||
case Y_PLUS:
|
||||
if((linecolor != null) &&
|
||||
(((xyz[0] == 0) && (mapiter.getBlockTypeIDAt(BlockStep.X_MINUS) == 0)) ||
|
||||
((xyz[0] == (scale-1)) && (mapiter.getBlockTypeIDAt(BlockStep.X_PLUS) == 0)) ||
|
||||
((xyz[2] == 0) && (mapiter.getBlockTypeIDAt(BlockStep.Z_MINUS) == 0)) ||
|
||||
((xyz[2] == (scale-1)) && (mapiter.getBlockTypeIDAt(BlockStep.Z_PLUS) == 0)))) {
|
||||
c.setColor(linecolor);
|
||||
}
|
||||
else if((watercolor != null) && ((blocktype == 8) || (blocktype == 9))) {
|
||||
c.setColor(watercolor);
|
||||
}
|
||||
else {
|
||||
c.setColor(fillcolor[mapiter.getY()]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if((linecolor != null) && (xyz[1] == (scale-1)))
|
||||
c.setColor(linecolor);
|
||||
else if((watercolor != null) && ((blocktype == 8) || (blocktype == 9))) {
|
||||
c.setColor(watercolor);
|
||||
}
|
||||
else
|
||||
c.setColor(fillcolor[mapiter.getY()]);
|
||||
break;
|
||||
}
|
||||
/* Handle light level, if needed */
|
||||
lighting.applyLighting(ps, this, c, tmpcolor);
|
||||
|
||||
for(int i = 0; i < color.length; i++)
|
||||
color[i] = tmpcolor[i];
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Ray ended - used to report that ray has exited map (called if renderer has not reported complete)
|
||||
*/
|
||||
public void rayFinished(HDPerspectiveState ps) {
|
||||
}
|
||||
/**
|
||||
* Get result color - get resulting color for ray
|
||||
* @param c - object to store color value in
|
||||
* @param index - index of color to request (renderer specific - 0=default, 1=day for night/day renderer
|
||||
*/
|
||||
public void getRayColor(Color c, int index) {
|
||||
c.setColor(color[index]);
|
||||
}
|
||||
/**
|
||||
* Clean up state object - called after last ray completed
|
||||
*/
|
||||
public void cleanup() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get renderer state object for use rendering a tile
|
||||
* @param map - map being rendered
|
||||
* @param cache - chunk cache containing data for tile to be rendered
|
||||
* @param mapiter - iterator used when traversing rays in tile
|
||||
* @return state object to use for all rays in tile
|
||||
*/
|
||||
public HDShaderState getStateInstance(HDMap map, MapChunkCache cache, MapIterator mapiter) {
|
||||
return new OurShaderState(mapiter, map, cache);
|
||||
}
|
||||
|
||||
/* Add shader's contributions to JSON for map object */
|
||||
public void addClientConfiguration(JSONObject mapObject) {
|
||||
s(mapObject, "shader", name);
|
||||
}
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
package org.dynmap.kzedmap;
|
||||
|
||||
import org.dynmap.Color;
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.DynmapWorld;
|
||||
import org.dynmap.utils.MapIterator;
|
||||
import org.dynmap.utils.MapIterator.BlockStep;
|
||||
|
||||
public class CaveTileRenderer extends DefaultTileRenderer {
|
||||
private boolean iflit;
|
||||
public CaveTileRenderer(DynmapCore core, ConfigurationNode configuration) {
|
||||
super(core, configuration);
|
||||
iflit = configuration.getBoolean("onlyiflit", false);
|
||||
}
|
||||
|
||||
public boolean isNightAndDayEnabled() { return false; }
|
||||
|
||||
@Override
|
||||
protected void scan(DynmapWorld world, int seq, boolean isnether, final Color result, final Color result_day,
|
||||
MapIterator mapiter) {
|
||||
boolean air = true;
|
||||
int emitted = 0;
|
||||
result.setTransparent();
|
||||
for (;;) {
|
||||
if (mapiter.getY() < 0)
|
||||
return;
|
||||
|
||||
int id = mapiter.getBlockTypeID();
|
||||
if(isnether) { /* Make ceiling into air in nether */
|
||||
if(id != 0)
|
||||
id = 0;
|
||||
else
|
||||
isnether = false;
|
||||
}
|
||||
if(iflit && (!air))
|
||||
emitted = mapiter.getBlockEmittedLight();
|
||||
|
||||
switch (seq) {
|
||||
case 0:
|
||||
mapiter.stepPosition(BlockStep.X_MINUS);
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
mapiter.stepPosition(BlockStep.Y_MINUS);
|
||||
break;
|
||||
case 2:
|
||||
mapiter.stepPosition(BlockStep.Z_PLUS);
|
||||
break;
|
||||
}
|
||||
|
||||
seq = (seq + 1) & 3;
|
||||
|
||||
switch (id) {
|
||||
case 17:
|
||||
case 18:
|
||||
case 20:
|
||||
case 64:
|
||||
case 71:
|
||||
case 78:
|
||||
case 79:
|
||||
id = 0;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
if (id != 0) {
|
||||
air = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (id == 0 && !air) {
|
||||
if(iflit && (emitted == 0)) {
|
||||
continue;
|
||||
}
|
||||
int cr, cg, cb;
|
||||
int mult = 256;
|
||||
|
||||
if (mapiter.getY() < 64) {
|
||||
cr = 0;
|
||||
cg = 64 + mapiter.getY() * 3;
|
||||
cb = 255 - mapiter.getY() * 4;
|
||||
} else {
|
||||
cr = (mapiter.getY() - 64) * 4;
|
||||
cg = 255;
|
||||
cb = 0;
|
||||
}
|
||||
|
||||
switch (seq) {
|
||||
case 0:
|
||||
mult = 224;
|
||||
break;
|
||||
case 1:
|
||||
mult = 256;
|
||||
break;
|
||||
case 2:
|
||||
mult = 192;
|
||||
break;
|
||||
case 3:
|
||||
mult = 160;
|
||||
break;
|
||||
}
|
||||
|
||||
cr = cr * mult / 256;
|
||||
cg = cg * mult / 256;
|
||||
cb = cb * mult / 256;
|
||||
|
||||
result.setRGBA(cr, cg, cb, 255);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,596 +0,0 @@
|
||||
package org.dynmap.kzedmap;
|
||||
|
||||
import static org.dynmap.JSONUtils.a;
|
||||
import static org.dynmap.JSONUtils.s;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.dynmap.Client;
|
||||
import org.dynmap.Color;
|
||||
import org.dynmap.ColorScheme;
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.DynmapWorld;
|
||||
import org.dynmap.MapManager;
|
||||
import org.dynmap.DynmapCore.CompassMode;
|
||||
import org.dynmap.MapType.ImageFormat;
|
||||
import org.dynmap.TileHashManager;
|
||||
import org.dynmap.common.BiomeMap;
|
||||
import org.dynmap.debug.Debug;
|
||||
import org.dynmap.utils.DynmapBufferedImage;
|
||||
import org.dynmap.utils.FileLockManager;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
import org.dynmap.utils.MapIterator;
|
||||
import org.dynmap.utils.MapIterator.BlockStep;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class DefaultTileRenderer implements MapTileRenderer {
|
||||
protected static final Color translucent = new Color(0, 0, 0, 0);
|
||||
protected String name;
|
||||
protected String prefix;
|
||||
protected ConfigurationNode configuration;
|
||||
protected int maximumHeight = 127;
|
||||
protected ColorScheme colorScheme;
|
||||
|
||||
protected HashSet<Integer> highlightBlocks = new HashSet<Integer>();
|
||||
protected Color highlightColor = new Color(255, 0, 0);
|
||||
|
||||
protected int shadowscale[]; /* index=skylight level, value = 256 * scaling value */
|
||||
protected int lightscale[]; /* scale skylight level (light = lightscale[skylight] */
|
||||
protected boolean night_and_day; /* If true, render both day (prefix+'-day') and night (prefix) tiles */
|
||||
protected boolean transparency; /* Is transparency support active? */
|
||||
public enum BiomeColorOption {
|
||||
NONE, BIOME, TEMPERATURE, RAINFALL
|
||||
}
|
||||
protected BiomeColorOption biomecolored = BiomeColorOption.NONE; /* Use biome for coloring */
|
||||
|
||||
@Override
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isNightAndDayEnabled() { return night_and_day; }
|
||||
|
||||
public DefaultTileRenderer(DynmapCore core, ConfigurationNode configuration) {
|
||||
this.configuration = configuration;
|
||||
name = configuration.getString("name", null);
|
||||
prefix = configuration.getString("prefix", name);
|
||||
Object o = configuration.get("maximumheight");
|
||||
if (o != null) {
|
||||
maximumHeight = Integer.parseInt(String.valueOf(o));
|
||||
if (maximumHeight > 127)
|
||||
maximumHeight = 127;
|
||||
}
|
||||
o = configuration.get("shadowstrength");
|
||||
if(o != null) {
|
||||
double shadowweight = Double.parseDouble(String.valueOf(o));
|
||||
if(shadowweight > 0.0) {
|
||||
shadowscale = new int[16];
|
||||
shadowscale[15] = 256;
|
||||
/* Normal brightness weight in MC is a 20% relative dropoff per step */
|
||||
for(int i = 14; i >= 0; i--) {
|
||||
double v = shadowscale[i+1] * (1.0 - (0.2 * shadowweight));
|
||||
shadowscale[i] = (int)v;
|
||||
if(shadowscale[i] > 256) shadowscale[i] = 256;
|
||||
if(shadowscale[i] < 0) shadowscale[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
o = configuration.get("ambientlight");
|
||||
if(o != null) {
|
||||
int v = Integer.parseInt(String.valueOf(o));
|
||||
lightscale = new int[16];
|
||||
for(int i = 0; i < 16; i++) {
|
||||
if(i < (15-v))
|
||||
lightscale[i] = 0;
|
||||
else
|
||||
lightscale[i] = i - (15-v);
|
||||
}
|
||||
}
|
||||
colorScheme = ColorScheme.getScheme(core, (String)configuration.get("colorscheme"));
|
||||
night_and_day = configuration.getBoolean("night-and-day", false);
|
||||
transparency = configuration.getBoolean("transparency", true); /* Default on */
|
||||
String biomeopt = configuration.getString("biomecolored", "none");
|
||||
if(biomeopt.equals("biome")) {
|
||||
biomecolored = BiomeColorOption.BIOME;
|
||||
}
|
||||
else if(biomeopt.equals("temperature")) {
|
||||
biomecolored = BiomeColorOption.TEMPERATURE;
|
||||
}
|
||||
else if(biomeopt.equals("rainfall")) {
|
||||
biomecolored = BiomeColorOption.RAINFALL;
|
||||
}
|
||||
else {
|
||||
biomecolored = BiomeColorOption.NONE;
|
||||
}
|
||||
}
|
||||
public boolean isBiomeDataNeeded() { return biomecolored.equals(BiomeColorOption.BIOME); }
|
||||
public boolean isRawBiomeDataNeeded() {
|
||||
return biomecolored.equals(BiomeColorOption.RAINFALL) || biomecolored.equals(BiomeColorOption.TEMPERATURE);
|
||||
}
|
||||
|
||||
public boolean render(MapChunkCache cache, KzedMapTile tile, File outputFile) {
|
||||
DynmapWorld world = tile.getDynmapWorld();
|
||||
boolean isnether = world.isNether();
|
||||
DynmapBufferedImage im = DynmapBufferedImage.allocateBufferedImage(KzedMap.tileWidth, KzedMap.tileHeight);
|
||||
DynmapBufferedImage zim = DynmapBufferedImage.allocateBufferedImage(KzedMap.tileWidth/2, KzedMap.tileHeight/2);
|
||||
|
||||
DynmapBufferedImage im_day = null;
|
||||
DynmapBufferedImage zim_day = null;
|
||||
if(night_and_day) {
|
||||
im_day = DynmapBufferedImage.allocateBufferedImage(KzedMap.tileWidth, KzedMap.tileHeight);
|
||||
zim_day = DynmapBufferedImage.allocateBufferedImage(KzedMap.tileWidth/2, KzedMap.tileHeight/2);
|
||||
}
|
||||
|
||||
int ix = KzedMap.anchorx + tile.px / 2 + tile.py / 2 - ((127-maximumHeight)/2);
|
||||
int iy = maximumHeight;
|
||||
int iz = KzedMap.anchorz + tile.px / 2 - tile.py / 2 + ((127-maximumHeight)/2);
|
||||
|
||||
/* Don't mess with existing height-clipped renders */
|
||||
if(maximumHeight < 127)
|
||||
isnether = false;
|
||||
|
||||
int jx, jz;
|
||||
|
||||
int x, y;
|
||||
|
||||
MapIterator mapiter = cache.getIterator(ix, iy, iz);
|
||||
|
||||
Color c1 = new Color();
|
||||
Color c2 = new Color();
|
||||
int[] argb = im.argb_buf;
|
||||
int[] zargb = zim.argb_buf;
|
||||
Color c1_day = null;
|
||||
Color c2_day = null;
|
||||
int[] argb_day = null;
|
||||
int[] zargb_day = null;
|
||||
if(night_and_day) {
|
||||
c1_day = new Color();
|
||||
c2_day = new Color();
|
||||
argb_day = im_day.argb_buf;
|
||||
zargb_day = zim_day.argb_buf;
|
||||
}
|
||||
int rowoff = 0;
|
||||
/* draw the map */
|
||||
for (y = 0; y < KzedMap.tileHeight;) {
|
||||
jx = ix;
|
||||
jz = iz;
|
||||
|
||||
for (x = KzedMap.tileWidth - 1; x >= 0; x -= 2) {
|
||||
mapiter.initialize(jx, iy, jz);
|
||||
scan(world, 0, isnether, c1, c1_day, mapiter);
|
||||
mapiter.initialize(jx, iy, jz);
|
||||
scan(world, 2, isnether, c2, c2_day, mapiter);
|
||||
|
||||
argb[rowoff+x] = c1.getARGB();
|
||||
argb[rowoff+x-1] = c2.getARGB();
|
||||
|
||||
if(night_and_day) {
|
||||
argb_day[rowoff+x] = c1_day.getARGB();
|
||||
argb_day[rowoff+x-1] = c2_day.getARGB();
|
||||
}
|
||||
|
||||
jx++;
|
||||
jz++;
|
||||
|
||||
}
|
||||
|
||||
y++;
|
||||
rowoff += KzedMap.tileWidth;
|
||||
|
||||
jx = ix;
|
||||
jz = iz - 1;
|
||||
|
||||
for (x = KzedMap.tileWidth - 1; x >= 0; x -= 2) {
|
||||
mapiter.initialize(jx, iy, jz);
|
||||
scan(world, 2, isnether, c1, c1_day, mapiter);
|
||||
jx++;
|
||||
jz++;
|
||||
mapiter.initialize(jx, iy, jz);
|
||||
scan(world, 0, isnether, c2, c2_day, mapiter);
|
||||
|
||||
argb[rowoff+x] = c1.getARGB();
|
||||
argb[rowoff+x-1] = c2.getARGB();
|
||||
|
||||
if(night_and_day) {
|
||||
argb_day[rowoff+x] = c1_day.getARGB();
|
||||
argb_day[rowoff+x-1] = c2_day.getARGB();
|
||||
}
|
||||
}
|
||||
y++;
|
||||
rowoff += KzedMap.tileWidth;
|
||||
|
||||
ix++;
|
||||
iz--;
|
||||
}
|
||||
/* Now, compute zoomed tile - bilinear filter 2x2 -> 1x1 */
|
||||
doScaleWithBilinear(argb, zargb, KzedMap.tileWidth, KzedMap.tileHeight);
|
||||
if(night_and_day) {
|
||||
doScaleWithBilinear(argb_day, zargb_day, KzedMap.tileWidth, KzedMap.tileHeight);
|
||||
}
|
||||
|
||||
/* Hand encoding and writing file off to MapManager */
|
||||
KzedZoomedMapTile zmtile = new KzedZoomedMapTile(tile.getDynmapWorld(), tile);
|
||||
File zoomFile = MapManager.mapman.getTileFile(zmtile);
|
||||
|
||||
return doFileWrites(outputFile, tile, im, im_day, zmtile, zoomFile, zim, zim_day);
|
||||
}
|
||||
|
||||
private void doScaleWithBilinear(int[] argb, int[] zargb, int width, int height) {
|
||||
Color c1 = new Color();
|
||||
/* Now, compute zoomed tile - bilinear filter 2x2 -> 1x1 */
|
||||
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);
|
||||
zargb[(y*width/4) + (x/2)] = c1.getARGB();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean doFileWrites(final File fname, final KzedMapTile mtile,
|
||||
final DynmapBufferedImage img, final DynmapBufferedImage img_day,
|
||||
final KzedZoomedMapTile zmtile, final File zoomFile,
|
||||
final DynmapBufferedImage zimg, final DynmapBufferedImage zimg_day) {
|
||||
boolean didwrite = false;
|
||||
|
||||
/* Get coordinates of zoomed tile */
|
||||
int ox = (mtile.px == zmtile.getTileX())?0:KzedMap.tileWidth/2;
|
||||
int oy = (mtile.py == zmtile.getTileY())?0:KzedMap.tileHeight/2;
|
||||
|
||||
/* Test to see if we're unchanged from older tile */
|
||||
TileHashManager hashman = MapManager.mapman.hashman;
|
||||
long crc = hashman.calculateTileHash(img.argb_buf);
|
||||
boolean updated_fname = false;
|
||||
int tx = mtile.px/KzedMap.tileWidth;
|
||||
int ty = mtile.py/KzedMap.tileHeight;
|
||||
FileLockManager.getWriteLock(fname);
|
||||
try {
|
||||
if((!fname.exists()) || (crc != hashman.getImageHashCode(mtile.getKey(prefix), null, tx, ty))) {
|
||||
Debug.debug("saving image " + fname.getPath());
|
||||
if(!fname.getParentFile().exists())
|
||||
fname.getParentFile().mkdirs();
|
||||
try {
|
||||
FileLockManager.imageIOWrite(img.buf_img, ImageFormat.FORMAT_PNG, fname);
|
||||
} catch (IOException e) {
|
||||
Debug.error("Failed to save image: " + fname.getPath(), e);
|
||||
} catch (java.lang.NullPointerException e) {
|
||||
Debug.error("Failed to save image (NullPointerException): " + fname.getPath(), e);
|
||||
}
|
||||
MapManager.mapman.pushUpdate(mtile.getDynmapWorld(), new Client.Tile(mtile.getFilename()));
|
||||
hashman.updateHashCode(mtile.getKey(prefix), null, tx, ty, crc);
|
||||
updated_fname = true;
|
||||
didwrite = true;
|
||||
}
|
||||
} finally {
|
||||
FileLockManager.releaseWriteLock(fname);
|
||||
DynmapBufferedImage.freeBufferedImage(img);
|
||||
}
|
||||
MapManager.mapman.updateStatistics(mtile, prefix, true, updated_fname, true);
|
||||
|
||||
mtile.file = fname;
|
||||
|
||||
boolean updated_dfname = false;
|
||||
|
||||
File dfname = new File(mtile.getDynmapWorld().worldtilepath, mtile.getDayFilename());
|
||||
if(img_day != null) {
|
||||
crc = hashman.calculateTileHash(img.argb_buf);
|
||||
FileLockManager.getWriteLock(dfname);
|
||||
try {
|
||||
if((!dfname.exists()) || (crc != hashman.getImageHashCode(mtile.getKey(prefix), "day", tx, ty))) {
|
||||
Debug.debug("saving image " + dfname.getPath());
|
||||
if(!dfname.getParentFile().exists())
|
||||
dfname.getParentFile().mkdirs();
|
||||
try {
|
||||
FileLockManager.imageIOWrite(img_day.buf_img, ImageFormat.FORMAT_PNG, dfname);
|
||||
} catch (IOException e) {
|
||||
Debug.error("Failed to save image: " + dfname.getPath(), e);
|
||||
} catch (java.lang.NullPointerException e) {
|
||||
Debug.error("Failed to save image (NullPointerException): " + dfname.getPath(), e);
|
||||
}
|
||||
MapManager.mapman.pushUpdate(mtile.getDynmapWorld(), new Client.Tile(mtile.getDayFilename()));
|
||||
hashman.updateHashCode(mtile.getKey(prefix), "day", tx, ty, crc);
|
||||
updated_dfname = true;
|
||||
didwrite = true;
|
||||
}
|
||||
} finally {
|
||||
FileLockManager.releaseWriteLock(dfname);
|
||||
DynmapBufferedImage.freeBufferedImage(img_day);
|
||||
}
|
||||
MapManager.mapman.updateStatistics(mtile, prefix+"_day", true, updated_dfname, true);
|
||||
}
|
||||
|
||||
// Since we've already got the new tile, and we're on an async thread, just
|
||||
// make the zoomed tile here
|
||||
boolean ztile_updated = false;
|
||||
FileLockManager.getWriteLock(zoomFile);
|
||||
try {
|
||||
if(updated_fname || (!zoomFile.exists())) {
|
||||
saveZoomedTile(zmtile, zoomFile, zimg, ox, oy, null);
|
||||
MapManager.mapman.pushUpdate(zmtile.getDynmapWorld(),
|
||||
new Client.Tile(zmtile.getFilename()));
|
||||
zmtile.getDynmapWorld().enqueueZoomOutUpdate(zoomFile);
|
||||
ztile_updated = true;
|
||||
}
|
||||
} finally {
|
||||
FileLockManager.releaseWriteLock(zoomFile);
|
||||
DynmapBufferedImage.freeBufferedImage(zimg);
|
||||
}
|
||||
MapManager.mapman.updateStatistics(zmtile, null, true, ztile_updated, true);
|
||||
|
||||
if(zimg_day != null) {
|
||||
File zoomFile_day = new File(zmtile.getDynmapWorld().worldtilepath, zmtile.getDayFilename());
|
||||
ztile_updated = false;
|
||||
FileLockManager.getWriteLock(zoomFile_day);
|
||||
try {
|
||||
if(updated_dfname || (!zoomFile_day.exists())) {
|
||||
saveZoomedTile(zmtile, zoomFile_day, zimg_day, ox, oy, "day");
|
||||
MapManager.mapman.pushUpdate(zmtile.getDynmapWorld(),
|
||||
new Client.Tile(zmtile.getDayFilename()));
|
||||
zmtile.getDynmapWorld().enqueueZoomOutUpdate(zoomFile_day);
|
||||
ztile_updated = true;
|
||||
}
|
||||
} finally {
|
||||
FileLockManager.releaseWriteLock(zoomFile_day);
|
||||
DynmapBufferedImage.freeBufferedImage(zimg_day);
|
||||
}
|
||||
MapManager.mapman.updateStatistics(zmtile, "day", true, ztile_updated, true);
|
||||
}
|
||||
return didwrite;
|
||||
}
|
||||
|
||||
private void saveZoomedTile(final KzedZoomedMapTile zmtile, final File zoomFile,
|
||||
final DynmapBufferedImage zimg, int ox, int oy, String subkey) {
|
||||
BufferedImage zIm = null;
|
||||
DynmapBufferedImage kzIm = null;
|
||||
try {
|
||||
zIm = ImageIO.read(zoomFile);
|
||||
} catch (IOException e) {
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
}
|
||||
|
||||
boolean zIm_allocated = false;
|
||||
if (zIm == null) {
|
||||
/* create new one */
|
||||
kzIm = DynmapBufferedImage.allocateBufferedImage(KzedMap.tileWidth, KzedMap.tileHeight);
|
||||
zIm = kzIm.buf_img;
|
||||
zIm_allocated = true;
|
||||
Debug.debug("New zoom-out tile created " + zmtile.getFilename());
|
||||
} else {
|
||||
Debug.debug("Loaded zoom-out tile from " + zmtile.getFilename());
|
||||
}
|
||||
|
||||
/* blit scaled rendered tile onto zoom-out tile */
|
||||
zIm.setRGB(ox, oy, KzedMap.tileWidth/2, KzedMap.tileHeight/2, zimg.argb_buf, 0, KzedMap.tileWidth/2);
|
||||
|
||||
/* save zoom-out tile */
|
||||
if(!zoomFile.getParentFile().exists())
|
||||
zoomFile.getParentFile().mkdirs();
|
||||
|
||||
try {
|
||||
FileLockManager.imageIOWrite(zIm, ImageFormat.FORMAT_PNG, zoomFile);
|
||||
Debug.debug("Saved zoom-out tile at " + zoomFile.getName());
|
||||
} catch (IOException e) {
|
||||
Debug.error("Failed to save zoom-out tile: " + zoomFile.getName(), e);
|
||||
} catch (java.lang.NullPointerException e) {
|
||||
Debug.error("Failed to save zoom-out tile (NullPointerException): " + zoomFile.getName(), e);
|
||||
}
|
||||
|
||||
if(zIm_allocated)
|
||||
DynmapBufferedImage.freeBufferedImage(kzIm);
|
||||
else
|
||||
zIm.flush();
|
||||
|
||||
}
|
||||
protected void scan(DynmapWorld world, int seq, boolean isnether, final Color result, final Color result_day,
|
||||
MapIterator mapiter) {
|
||||
int lightlevel = 15;
|
||||
int lightlevel_day = 15;
|
||||
BiomeMap bio = null;
|
||||
double rain = 0.0;
|
||||
double temp = 0.0;
|
||||
result.setTransparent();
|
||||
if(result_day != null)
|
||||
result_day.setTransparent();
|
||||
for (;;) {
|
||||
if (mapiter.getY() < 0) {
|
||||
return;
|
||||
}
|
||||
int id = mapiter.getBlockTypeID();
|
||||
int data = 0;
|
||||
if(isnether) { /* Make bedrock ceiling into air in nether */
|
||||
if(id != 0) {
|
||||
/* Remember first color we see, in case we wind up solid */
|
||||
if(result.isTransparent())
|
||||
if(colorScheme.colors[id] != null)
|
||||
result.setColor(colorScheme.colors[id][seq]);
|
||||
id = 0;
|
||||
}
|
||||
else
|
||||
isnether = false;
|
||||
}
|
||||
if(id != 0) { /* No update needed for air */
|
||||
switch(biomecolored) {
|
||||
case NONE:
|
||||
if(colorScheme.datacolors[id] != null) { /* If data colored */
|
||||
data = mapiter.getBlockData();
|
||||
}
|
||||
break;
|
||||
case BIOME:
|
||||
bio = mapiter.getBiome();
|
||||
break;
|
||||
case RAINFALL:
|
||||
rain = mapiter.getRawBiomeRainfall();
|
||||
break;
|
||||
case TEMPERATURE:
|
||||
temp = mapiter.getRawBiomeTemperature();
|
||||
break;
|
||||
}
|
||||
if((shadowscale != null) && (mapiter.getY() < 127)) {
|
||||
/* Find light level of previous chunk */
|
||||
BlockStep last = mapiter.unstepPosition();
|
||||
lightlevel = lightlevel_day = mapiter.getBlockSkyLight();
|
||||
if(lightscale != null)
|
||||
lightlevel = lightscale[lightlevel];
|
||||
if((lightlevel < 15) || (lightlevel_day < 15)) {
|
||||
int emitted = mapiter.getBlockEmittedLight();
|
||||
lightlevel = Math.max(emitted, lightlevel);
|
||||
lightlevel_day = Math.max(emitted, lightlevel_day);
|
||||
}
|
||||
mapiter.stepPosition(last);
|
||||
}
|
||||
}
|
||||
|
||||
switch (seq) {
|
||||
case 0:
|
||||
mapiter.stepPosition(BlockStep.X_MINUS);
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
mapiter.stepPosition(BlockStep.Y_MINUS);
|
||||
break;
|
||||
case 2:
|
||||
mapiter.stepPosition(BlockStep.Z_PLUS);
|
||||
break;
|
||||
}
|
||||
|
||||
seq = (seq + 1) & 3;
|
||||
|
||||
if (id != 0) {
|
||||
if (highlightBlocks.contains(id)) {
|
||||
result.setColor(highlightColor);
|
||||
return;
|
||||
}
|
||||
Color[] colors = null;
|
||||
switch(biomecolored) {
|
||||
case NONE:
|
||||
if(data != 0)
|
||||
colors = colorScheme.datacolors[id][data];
|
||||
else
|
||||
colors = colorScheme.colors[id];
|
||||
break;
|
||||
case BIOME:
|
||||
if(bio != null)
|
||||
colors = colorScheme.biomecolors[bio.ordinal()];
|
||||
break;
|
||||
case RAINFALL:
|
||||
colors = colorScheme.getRainColor(rain);
|
||||
break;
|
||||
case TEMPERATURE:
|
||||
colors = colorScheme.getTempColor(temp);
|
||||
break;
|
||||
}
|
||||
if (colors != null) {
|
||||
Color c = colors[seq];
|
||||
if (c.getAlpha() > 0) {
|
||||
/* we found something that isn't transparent, or not doing transparency */
|
||||
if ((!transparency) || (c.getAlpha() == 255)) {
|
||||
/* it's opaque - the ray ends here */
|
||||
result.setARGB(c.getARGB() | 0xFF000000);
|
||||
if(lightlevel < 15) { /* Not full light? */
|
||||
shadowColor(result, lightlevel);
|
||||
}
|
||||
if(result_day != null) {
|
||||
if(lightlevel_day == lightlevel) /* Same light = same result */
|
||||
result_day.setColor(result);
|
||||
else {
|
||||
result_day.setColor(c);
|
||||
if(lightlevel_day < 15)
|
||||
shadowColor(result_day, lightlevel_day);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* this block is transparent, so recurse */
|
||||
scan(world, seq, isnether, result, result_day, mapiter);
|
||||
|
||||
int cr = c.getRed();
|
||||
int cg = c.getGreen();
|
||||
int cb = c.getBlue();
|
||||
int ca = c.getAlpha();
|
||||
if(lightlevel < 15) {
|
||||
int scale = shadowscale[lightlevel];
|
||||
cr = (cr * scale) >> 8;
|
||||
cg = (cg * scale) >> 8;
|
||||
cb = (cb * scale) >> 8;
|
||||
}
|
||||
cr *= ca;
|
||||
cg *= ca;
|
||||
cb *= ca;
|
||||
int na = 255 - ca;
|
||||
result.setRGBA((result.getRed() * na + cr) >> 8, (result.getGreen() * na + cg) >> 8, (result.getBlue() * na + cb) >> 8, 255);
|
||||
/* Handle day also */
|
||||
if(result_day != null) {
|
||||
cr = c.getRed();
|
||||
cg = c.getGreen();
|
||||
cb = c.getBlue();
|
||||
if(lightlevel_day < 15) {
|
||||
int scale = shadowscale[lightlevel_day];
|
||||
cr = (cr * scale) >> 8;
|
||||
cg = (cg * scale) >> 8;
|
||||
cb = (cb * scale) >> 8;
|
||||
}
|
||||
cr *= ca;
|
||||
cg *= ca;
|
||||
cb *= ca;
|
||||
result_day.setRGBA((result_day.getRed() * na + cr) >> 8, (result_day.getGreen() * na + cg) >> 8, (result_day.getBlue() * na + cb) >> 8,
|
||||
255);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private final void shadowColor(Color c, int lightlevel) {
|
||||
int scale = shadowscale[lightlevel];
|
||||
if(scale < 256)
|
||||
c.setRGBA((c.getRed() * scale) >> 8, (c.getGreen() * scale) >> 8,
|
||||
(c.getBlue() * scale) >> 8, c.getAlpha());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildClientConfiguration(JSONObject worldObject, DynmapWorld world, KzedMap map) {
|
||||
ConfigurationNode c = configuration;
|
||||
JSONObject o = new JSONObject();
|
||||
s(o, "type", "KzedMapType");
|
||||
s(o, "name", c.getString("name"));
|
||||
s(o, "title", c.getString("title"));
|
||||
s(o, "icon", c.getString("icon"));
|
||||
s(o, "prefix", c.getString("prefix"));
|
||||
s(o, "background", c.getString("background"));
|
||||
s(o, "nightandday", c.getBoolean("night-and-day", false));
|
||||
s(o, "backgroundday", c.getString("backgroundday"));
|
||||
s(o, "backgroundnight", c.getString("backgroundnight"));
|
||||
s(o, "bigmap", map.isBigWorldMap(world));
|
||||
s(o, "mapzoomin", c.getInteger("mapzoomin", 2));
|
||||
s(o, "mapzoomout", world.getExtraZoomOutLevels()+1);
|
||||
if(MapManager.mapman.getCompassMode() != CompassMode.PRE19)
|
||||
s(o, "compassview", "NE"); /* Always from northeast */
|
||||
else
|
||||
s(o, "compassview", "SE"); /* Always from southeast */
|
||||
s(o, "image-format", ImageFormat.FORMAT_PNG.getFileExt());
|
||||
a(worldObject, "maps", o);
|
||||
}
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
package org.dynmap.kzedmap;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.dynmap.Color;
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.DynmapWorld;
|
||||
import org.dynmap.utils.MapIterator;
|
||||
import org.dynmap.utils.MapIterator.BlockStep;
|
||||
|
||||
public class HighlightTileRenderer extends DefaultTileRenderer {
|
||||
protected HashSet<Integer> highlightBlocks = new HashSet<Integer>();
|
||||
|
||||
public HighlightTileRenderer(DynmapCore core, ConfigurationNode configuration) {
|
||||
super(core, configuration);
|
||||
List<Integer> highlight = configuration.<Integer>getList("highlight");
|
||||
for(Integer i : highlight) {
|
||||
highlightBlocks.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void scan(DynmapWorld world,int seq, boolean isnether, final Color result, final Color result_day,
|
||||
MapIterator mapiter) {
|
||||
result.setTransparent();
|
||||
for (;;) {
|
||||
if (mapiter.getY() < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
int id = mapiter.getBlockTypeID();
|
||||
if(isnether) { /* Make bedrock ceiling into air in nether */
|
||||
if(id != 0) {
|
||||
/* Remember first color we see, in case we wind up solid */
|
||||
if(result.isTransparent())
|
||||
if(colorScheme.colors[id] != null)
|
||||
result.setColor(colorScheme.colors[id][seq]);
|
||||
id = 0;
|
||||
}
|
||||
else
|
||||
isnether = false;
|
||||
}
|
||||
int data = 0;
|
||||
if(colorScheme.datacolors[id] != null) { /* If data colored */
|
||||
data = mapiter.getBlockData();
|
||||
}
|
||||
|
||||
switch (seq) {
|
||||
case 0:
|
||||
mapiter.stepPosition(BlockStep.X_MINUS);
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
mapiter.stepPosition(BlockStep.Y_MINUS);
|
||||
break;
|
||||
case 2:
|
||||
mapiter.stepPosition(BlockStep.Z_PLUS);
|
||||
break;
|
||||
}
|
||||
|
||||
seq = (seq + 1) & 3;
|
||||
|
||||
if (id != 0) {
|
||||
Color[] colors;
|
||||
if(data != 0)
|
||||
colors = colorScheme.datacolors[id][data];
|
||||
else
|
||||
colors = colorScheme.colors[id];
|
||||
if (colors != null) {
|
||||
Color c = colors[seq];
|
||||
|
||||
if (highlightBlocks.contains(id)) {
|
||||
result.setColor(c);
|
||||
return;
|
||||
}
|
||||
|
||||
if (c.getAlpha() > 0) {
|
||||
|
||||
/* we found something that isn't transparent! */
|
||||
/*
|
||||
* if (c.getAlpha() == 255) { return c; }
|
||||
*/
|
||||
/* this block is transparent, so recurse */
|
||||
|
||||
// No need to blend if result is opaque.
|
||||
if (result.getAlpha() < 255) {
|
||||
int cr = result.getRed();
|
||||
int cg = result.getGreen();
|
||||
int cb = result.getBlue();
|
||||
int ca = result.getAlpha();
|
||||
cr *= ca;
|
||||
cg *= ca;
|
||||
cb *= ca;
|
||||
int na = 255 - ca;
|
||||
|
||||
result.setRGBA((c.getRed() * na + cr) >> 8, (c.getGreen() * na + cg) >> 8, (c.getBlue() * na + cb) >> 8,
|
||||
Math.min(255, c.getAlpha()+ca) // Not really correct, but gets the job done without recursion while still looking ok.
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,336 +0,0 @@
|
||||
package org.dynmap.kzedmap;
|
||||
|
||||
import org.dynmap.DynmapWorld;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.DynmapChunk;
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.Log;
|
||||
import org.dynmap.MapTile;
|
||||
import org.dynmap.MapType;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class KzedMap extends MapType {
|
||||
protected static final Logger log = Logger.getLogger("Minecraft");
|
||||
protected static final String LOG_PREFIX = "[dynmap] ";
|
||||
|
||||
/* dimensions of a map tile */
|
||||
public static final int tileWidth = 128;
|
||||
public static final int tileHeight = 128;
|
||||
|
||||
/*
|
||||
* (logical!) dimensions of a zoomed out map tile must be twice the size of
|
||||
* the normal tile
|
||||
*/
|
||||
public static final int zTileWidth = 256;
|
||||
public static final int zTileHeight = 256;
|
||||
|
||||
/* map x, y, z for projection origin */
|
||||
public static final int anchorx = 0;
|
||||
public static final int anchory = 127;
|
||||
public static final int anchorz = 0;
|
||||
|
||||
MapTileRenderer[] renderers;
|
||||
private boolean isbigmap;
|
||||
|
||||
public KzedMap(DynmapCore core, ConfigurationNode configuration) {
|
||||
Log.verboseinfo("Loading renderers for map '" + getClass().toString() + "'...");
|
||||
List<MapTileRenderer> renderers = configuration.<MapTileRenderer>createInstances("renderers", new Class<?>[] { DynmapCore.class }, new Object[] { core } );
|
||||
this.renderers = new MapTileRenderer[renderers.size()];
|
||||
renderers.toArray(this.renderers);
|
||||
Log.verboseinfo("Loaded " + renderers.size() + " renderers for map '" + getClass().toString() + "'.");
|
||||
isbigmap = configuration.getBoolean("isbigmap", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapTile[] getTiles(DynmapWorld world, int x, int y, int z) {
|
||||
int dx = x - anchorx;
|
||||
int dy = y - anchory;
|
||||
int dz = z - anchorz;
|
||||
int px = dx + dz;
|
||||
int py = dx - dz - dy;
|
||||
|
||||
int tx = tilex(px);
|
||||
int ty = tiley(py);
|
||||
|
||||
ArrayList<MapTile> tiles = new ArrayList<MapTile>();
|
||||
|
||||
addTile(tiles, world, tx, ty);
|
||||
|
||||
boolean ledge = tilex(px - 4) != tx;
|
||||
boolean tedge = tiley(py - 4) != ty;
|
||||
boolean redge = tilex(px + 4) != tx;
|
||||
boolean bedge = tiley(py + 4) != ty;
|
||||
|
||||
if (ledge)
|
||||
addTile(tiles, world, tx - tileWidth, ty);
|
||||
if (redge)
|
||||
addTile(tiles, world, tx + tileWidth, ty);
|
||||
if (tedge)
|
||||
addTile(tiles, world, tx, ty - tileHeight);
|
||||
if (bedge)
|
||||
addTile(tiles, world, tx, ty + tileHeight);
|
||||
|
||||
if (ledge && tedge)
|
||||
addTile(tiles, world, tx - tileWidth, ty - tileHeight);
|
||||
if (ledge && bedge)
|
||||
addTile(tiles, world, tx - tileWidth, ty + tileHeight);
|
||||
if (redge && tedge)
|
||||
addTile(tiles, world, tx + tileWidth, ty - tileHeight);
|
||||
if (redge && bedge)
|
||||
addTile(tiles, world, tx + tileWidth, ty + tileHeight);
|
||||
|
||||
MapTile[] result = new MapTile[tiles.size()];
|
||||
tiles.toArray(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapTile[] getTiles(DynmapWorld world, int minx, int miny, int minz, int maxx, int maxy, int maxz) {
|
||||
ArrayList<MapTile> tiles = new ArrayList<MapTile>();
|
||||
/* Transform both to tile coordinates */
|
||||
int dx = minx - anchorx;
|
||||
int dy = miny - anchory;
|
||||
int dz = minz - anchorz;
|
||||
int px0 = dx + dz;
|
||||
int py0 = dx - dz - dy;
|
||||
dx = maxx - anchorx;
|
||||
dy = maxy - anchory;
|
||||
dz = maxz - anchorz;
|
||||
int px1 = dx + dz;
|
||||
int py1 = dx - dz - dy;
|
||||
/* Compute ranges */
|
||||
int mintx = (px1<px0)?px0:px1;
|
||||
int maxtx = (px1<px0)?px1+1:px0+1;
|
||||
int minty = (py1<py0)?py0:py1;
|
||||
int maxty = (py1<py0)?py1+1:py0+1;
|
||||
|
||||
/* Now, add the tiles for the ranges - not perfect, but it works (some extra tiles on corners possible) */
|
||||
for(int i = mintx >> 7; i <= maxtx >> 7; i++) {
|
||||
for(int j = minty >> 7; j < maxty >> 7; j++) {
|
||||
addTile(tiles, world, i << 7, j << 7);
|
||||
}
|
||||
}
|
||||
return tiles.toArray(new MapTile[tiles.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapTile[] getAdjecentTiles(MapTile tile) {
|
||||
if (tile instanceof KzedMapTile) {
|
||||
KzedMapTile t = (KzedMapTile) tile;
|
||||
DynmapWorld world = tile.getDynmapWorld();
|
||||
MapTileRenderer renderer = t.renderer;
|
||||
return new MapTile[] {
|
||||
new KzedMapTile(world, this, renderer, t.px - tileWidth, t.py + tileHeight),
|
||||
new KzedMapTile(world, this, renderer, t.px + tileWidth, t.py - tileHeight),
|
||||
new KzedMapTile(world, this, renderer, t.px - tileWidth, t.py - tileHeight),
|
||||
new KzedMapTile(world, this, renderer, t.px + tileWidth, t.py + tileHeight),
|
||||
new KzedMapTile(world, this, renderer, t.px - tileWidth, t.py),
|
||||
new KzedMapTile(world, this, renderer, t.px + tileWidth, t.py),
|
||||
new KzedMapTile(world, this, renderer, t.px, t.py - tileHeight),
|
||||
new KzedMapTile(world, this, renderer, t.px, t.py + tileHeight) };
|
||||
}
|
||||
return new MapTile[0];
|
||||
}
|
||||
|
||||
public void addTile(ArrayList<MapTile> tiles, DynmapWorld world, int px, int py) {
|
||||
for (int i = 0; i < renderers.length; i++) {
|
||||
tiles.add(new KzedMapTile(world, this, renderers[i], px, py));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if point x,z is inside rectangle with corner at r0x,r0z and with
|
||||
* size vectors s1x,s1z and s2x,s2z
|
||||
*
|
||||
*/
|
||||
private boolean testPointInRectangle(int x, int z, int r0x, int r0z, int s1x, int s1z,
|
||||
int s2x, int s2z) {
|
||||
int xr = x - r0x;
|
||||
int zr = z - r0z; /* Get position relative to rectangle corner */
|
||||
int dots1 = xr*s1x + zr*s1z;
|
||||
int dots2 = xr*s2x + zr*s2z;
|
||||
/* If dot product of relative point and each side is between zero and dot product
|
||||
* of each side and itself, we're inside
|
||||
*/
|
||||
if((dots1 >= 0) && (dots1 <= (s1x*s1x+s1z*s1z)) &&
|
||||
(dots2 >= 0) && (dots2 <= (s2x*s2x+s2z*s2z))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public List<DynmapChunk> getRequiredChunks(MapTile tile) {
|
||||
if (tile instanceof KzedMapTile) {
|
||||
KzedMapTile t = (KzedMapTile) tile;
|
||||
|
||||
int ix = KzedMap.anchorx + t.px / 2 + t.py / 2;
|
||||
//int iy = 127;
|
||||
int iz = KzedMap.anchorz + t.px / 2 - t.py / 2;
|
||||
|
||||
int x1 = ix - KzedMap.tileHeight / 2;
|
||||
int x2 = ix + KzedMap.tileWidth / 2 + KzedMap.tileHeight / 2;
|
||||
|
||||
int z1 = iz - KzedMap.tileHeight / 2;
|
||||
int z2 = iz + KzedMap.tileWidth / 2 + KzedMap.tileHeight / 2;
|
||||
|
||||
int x, z;
|
||||
|
||||
/* Actual pattern of chunks needed is create by the slanted
|
||||
* square prism corresponding to the render path of the tile.
|
||||
* Top of prism (corresponding to y=127) is diamond shape from
|
||||
* ix, iz to ix+64,iz+64 to ix+128,iz to ix+64,iz-64
|
||||
* Bottom is same shape, offset by -64 on x, +64 on z (net
|
||||
* render path to y=0), correspond to ix-64, iz+64 to
|
||||
* ix,iz+128 to ix+64,iz+64 to ix,iz. Projection of
|
||||
* the prism on to the x,z plane (which is all that matters for
|
||||
* chunks) yields a diagonal rectangular area from ix-64(x1),iz+64
|
||||
* to ix,iz+128(z2) to ix+128(x2),iz to ix+64,iz-64(z1).
|
||||
* Chunks outside this are not needed - we scan a simple rectangle
|
||||
* (chunk grid aligned) and skip adding the ones that are outside.
|
||||
* This results in 42% less chunks being loaded.
|
||||
*/
|
||||
ArrayList<DynmapChunk> chunks = new ArrayList<DynmapChunk>();
|
||||
|
||||
for (x = x1; x < x2; x += 16) {
|
||||
for (z = z1; z < z2; z += 16) {
|
||||
/* If any of the chunk corners are inside the rectangle, we need it */
|
||||
if((!testPointInRectangle(x, z, x1, iz + KzedMap.tileWidth/2,
|
||||
KzedMap.tileWidth/2, KzedMap.tileHeight/2,
|
||||
KzedMap.tileWidth, -KzedMap.tileHeight)) &&
|
||||
(!testPointInRectangle(x+15, z, x1, iz + KzedMap.tileWidth/2,
|
||||
KzedMap.tileWidth/2, KzedMap.tileHeight/2,
|
||||
KzedMap.tileWidth, -KzedMap.tileHeight)) &&
|
||||
(!testPointInRectangle(x+15, z+15, x1, iz + KzedMap.tileWidth/2,
|
||||
KzedMap.tileWidth/2, KzedMap.tileHeight/2,
|
||||
KzedMap.tileWidth, -KzedMap.tileHeight)) &&
|
||||
(!testPointInRectangle(x, z+15, x1, iz + KzedMap.tileWidth/2,
|
||||
KzedMap.tileWidth/2, KzedMap.tileHeight/2,
|
||||
KzedMap.tileWidth, -KzedMap.tileHeight)))
|
||||
continue;
|
||||
DynmapChunk chunk = new DynmapChunk(x / 16, z / 16);
|
||||
chunks.add(chunk);
|
||||
}
|
||||
}
|
||||
return chunks;
|
||||
} else {
|
||||
return new ArrayList<DynmapChunk>();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean render(MapChunkCache cache, MapTile tile, File outputFile) {
|
||||
if (tile instanceof KzedMapTile) {
|
||||
return ((KzedMapTile) tile).renderer.render(cache, (KzedMapTile) tile, outputFile);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* tile X for position x */
|
||||
static int tilex(int x) {
|
||||
if (x < 0)
|
||||
return x - (tileWidth + (x % tileWidth));
|
||||
else
|
||||
return x - (x % tileWidth);
|
||||
}
|
||||
|
||||
/* tile Y for position y */
|
||||
static int tiley(int y) {
|
||||
if (y < 0)
|
||||
return y - (tileHeight + (y % tileHeight));
|
||||
else
|
||||
return y - (y % tileHeight);
|
||||
}
|
||||
|
||||
/* zoomed-out tile X for tile position x */
|
||||
static int ztilex(int x) {
|
||||
if (x < 0)
|
||||
return x + x % zTileWidth;
|
||||
else
|
||||
return x - (x % zTileWidth);
|
||||
}
|
||||
|
||||
/* zoomed-out tile Y for tile position y */
|
||||
static int ztiley(int y) {
|
||||
if (y < 0)
|
||||
return y + y % zTileHeight;
|
||||
// return y - (zTileHeight + (y % zTileHeight));
|
||||
else
|
||||
return y - (y % zTileHeight);
|
||||
}
|
||||
|
||||
|
||||
public boolean isBiomeDataNeeded() {
|
||||
for(MapTileRenderer r : renderers) {
|
||||
if(r.isBiomeDataNeeded())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isRawBiomeDataNeeded() {
|
||||
for(MapTileRenderer r : renderers) {
|
||||
if(r.isRawBiomeDataNeeded())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<ZoomInfo> baseZoomFileInfo() {
|
||||
ArrayList<ZoomInfo> s = new ArrayList<ZoomInfo>();
|
||||
for(MapTileRenderer r : renderers) {
|
||||
s.add(new ZoomInfo("z" + r.getPrefix(), 0));
|
||||
if(r.isNightAndDayEnabled())
|
||||
s.add(new ZoomInfo("z" + r.getPrefix() + "_day", 0));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
public int baseZoomFileStepSize() { return zTileWidth; }
|
||||
|
||||
public MapStep zoomFileMapStep() { return MapStep.X_MINUS_Y_PLUS; }
|
||||
|
||||
private static final int[] stepseq = { 0, 2, 1, 3 };
|
||||
|
||||
public int[] zoomFileStepSequence() { return stepseq; }
|
||||
/* How many bits of coordinate are shifted off to make big world directory name */
|
||||
public int getBigWorldShift() { return 12; }
|
||||
|
||||
/* Returns true if big world file structure is in effect for this map */
|
||||
@Override
|
||||
public boolean isBigWorldMap(DynmapWorld w) {
|
||||
return w.bigworld || isbigmap;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "KzedMap";
|
||||
}
|
||||
|
||||
/* Get maps rendered concurrently with this map in this world */
|
||||
public List<MapType> getMapsSharingRender(DynmapWorld w) {
|
||||
return Collections.singletonList((MapType)this);
|
||||
}
|
||||
|
||||
/* Get names of maps rendered concurrently with this map type in this world */
|
||||
public List<String> getMapNamesSharingRender(DynmapWorld w) {
|
||||
ArrayList<String> lst = new ArrayList<String>();
|
||||
for(MapTileRenderer rend : renderers) {
|
||||
if(rend.isNightAndDayEnabled())
|
||||
lst.add(rend.getName() + "(night/day)");
|
||||
else
|
||||
lst.add(rend.getName());
|
||||
}
|
||||
return lst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildClientConfiguration(JSONObject worldObject, DynmapWorld world) {
|
||||
for(MapTileRenderer renderer : renderers) {
|
||||
renderer.buildClientConfiguration(worldObject, world, this);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,133 +0,0 @@
|
||||
package org.dynmap.kzedmap;
|
||||
|
||||
import org.dynmap.DynmapChunk;
|
||||
import org.dynmap.DynmapWorld;
|
||||
import org.dynmap.MapManager;
|
||||
import org.dynmap.MapType;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import org.dynmap.MapTile;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
|
||||
public class KzedMapTile extends MapTile {
|
||||
public KzedMap map;
|
||||
public MapTileRenderer renderer;
|
||||
public int px, py;
|
||||
private String fname;
|
||||
private String fname_day;
|
||||
|
||||
// Hack.
|
||||
public File file = null;
|
||||
|
||||
public KzedMapTile(DynmapWorld world, KzedMap map, MapTileRenderer renderer, int px, int py) {
|
||||
super(world);
|
||||
this.map = map;
|
||||
this.renderer = renderer;
|
||||
this.px = px;
|
||||
this.py = py;
|
||||
}
|
||||
|
||||
public KzedMapTile(DynmapWorld world, String parm) throws Exception {
|
||||
super(world);
|
||||
|
||||
String[] parms = parm.split(",");
|
||||
if(parms.length < 4) throw new Exception("wrong parameter count");
|
||||
this.px = Integer.parseInt(parms[0]);
|
||||
this.py = Integer.parseInt(parms[1]);
|
||||
|
||||
for(MapType t : world.maps) {
|
||||
if(t.getName().equals(parms[2]) && (t instanceof KzedMap)) {
|
||||
this.map = (KzedMap)t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(this.map == null) throw new Exception("invalid map");
|
||||
for(MapTileRenderer r : map.renderers) {
|
||||
if(r.getName().equals(parms[3])) {
|
||||
this.renderer = r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(this.renderer == null) throw new Exception("invalid renderer");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String saveTileData() {
|
||||
return String.format("%d,%d,%s,%s", px, py, map.getName(), renderer.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilename() {
|
||||
if(fname == null) {
|
||||
if(map.isBigWorldMap(world))
|
||||
fname = renderer.getPrefix() + "/" + (px >> 12) + '_' + (py >> 12) + '/' + px + "_" + py + ".png";
|
||||
else
|
||||
fname = renderer.getPrefix() + "_" + px + "_" + py + ".png";
|
||||
}
|
||||
return fname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDayFilename() {
|
||||
if(fname_day == null) {
|
||||
if(map.isBigWorldMap(world))
|
||||
fname_day = renderer.getPrefix() + "_day/" + (px >> 12) + '_' + (py >> 12) + '/' + px + "_" + py + ".png";
|
||||
else
|
||||
fname_day = renderer.getPrefix() + "_day_" + px + "_" + py + ".png";
|
||||
}
|
||||
return fname_day;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return px ^ py ^ map.getName().hashCode() ^ world.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof KzedMapTile) {
|
||||
return equals((KzedMapTile) obj);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean equals(KzedMapTile o) {
|
||||
return o.px == px && o.py == py && (o.map == map) && (o.world == world);
|
||||
}
|
||||
|
||||
public String getKey(String prefix) {
|
||||
return world.getName() + "." + prefix;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return world.getName() + ":" + getFilename();
|
||||
}
|
||||
|
||||
public boolean render(MapChunkCache cache, String mapname) {
|
||||
boolean rslt = false;
|
||||
for(MapTileRenderer r : map.renderers) {
|
||||
if((mapname == null) || (r.getName().equals(mapname))) {
|
||||
KzedMapTile t = new KzedMapTile(world, map, r, px, py);
|
||||
rslt |= map.render(cache, t, MapManager.mapman.getTileFile(t));
|
||||
}
|
||||
}
|
||||
return rslt;
|
||||
}
|
||||
|
||||
public List<DynmapChunk> getRequiredChunks() {
|
||||
return map.getRequiredChunks(this);
|
||||
}
|
||||
|
||||
public MapTile[] getAdjecentTiles() {
|
||||
return map.getAdjecentTiles(this);
|
||||
}
|
||||
|
||||
public boolean isBiomeDataNeeded() { return map.isBiomeDataNeeded(); }
|
||||
public boolean isHightestBlockYDataNeeded() { return false; }
|
||||
public boolean isRawBiomeDataNeeded() { return map.isRawBiomeDataNeeded(); }
|
||||
public boolean isBlockTypeDataNeeded() { return true; }
|
||||
public int tileOrdinalX() { return px >> 7; }
|
||||
public int tileOrdinalY() { return py >> 7; }
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
package org.dynmap.kzedmap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.dynmap.DynmapChunk;
|
||||
import org.dynmap.DynmapWorld;
|
||||
import org.dynmap.MapTile;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
|
||||
public class KzedZoomedMapTile extends MapTile {
|
||||
private String fname;
|
||||
private String fname_day;
|
||||
|
||||
@Override
|
||||
public String getFilename() {
|
||||
if(fname == null) {
|
||||
if(world.bigworld)
|
||||
fname = "z" + originalTile.renderer.getPrefix() + "/" + (getTileX()>>12) + '_' +
|
||||
(getTileY() >> 12) + '/' + getTileX() + "_" + getTileY() + ".png";
|
||||
else
|
||||
fname = "z" + originalTile.renderer.getPrefix() + "_" + getTileX() + "_" + getTileY() + ".png";
|
||||
}
|
||||
return fname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDayFilename() {
|
||||
if(fname_day == null) {
|
||||
if(world.bigworld)
|
||||
fname_day = "z" + originalTile.renderer.getPrefix() + "_day/" + (getTileX()>>12) + '_' +
|
||||
(getTileY() >> 12) + '/' + getTileX() + "_" + getTileY() + ".png";
|
||||
else
|
||||
fname_day = "z" + originalTile.renderer.getPrefix() + "_day_" + getTileX() + "_" + getTileY() + ".png";
|
||||
}
|
||||
return fname_day;
|
||||
}
|
||||
|
||||
public KzedMapTile originalTile;
|
||||
|
||||
public KzedZoomedMapTile(DynmapWorld world, KzedMapTile original) {
|
||||
super(world);
|
||||
this.originalTile = original;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String saveTileData() {
|
||||
return originalTile.saveTileData();
|
||||
}
|
||||
|
||||
public int getTileX() {
|
||||
return ztilex(originalTile.px + KzedMap.tileWidth);
|
||||
}
|
||||
|
||||
public int getTileY() {
|
||||
return ztiley(originalTile.py);
|
||||
}
|
||||
|
||||
private static int ztilex(int x) {
|
||||
if (x < 0)
|
||||
return x + (x % (KzedMap.tileWidth * 2));
|
||||
else
|
||||
return x - (x % (KzedMap.tileWidth * 2));
|
||||
}
|
||||
|
||||
/* zoomed-out tile Y for tile position y */
|
||||
private static int ztiley(int y) {
|
||||
if (y < 0)
|
||||
return y + (y % (KzedMap.tileHeight * 2));
|
||||
else
|
||||
return y - (y % (KzedMap.tileHeight * 2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getFilename().hashCode() ^ world.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof KzedZoomedMapTile) {
|
||||
return ((KzedZoomedMapTile) obj).originalTile.equals(originalTile);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public String getKey(String prefix) {
|
||||
return world.getName() + ".z" + prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean render(MapChunkCache cache, String mapname) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DynmapChunk> getRequiredChunks() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapTile[] getAdjecentTiles() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isBiomeDataNeeded() { return originalTile.isBiomeDataNeeded(); }
|
||||
public boolean isHightestBlockYDataNeeded() { return false; }
|
||||
public boolean isRawBiomeDataNeeded() { return originalTile.isRawBiomeDataNeeded(); }
|
||||
public boolean isBlockTypeDataNeeded() { return true; }
|
||||
public int tileOrdinalX() { return originalTile.px >> 8; }
|
||||
public int tileOrdinalY() { return originalTile.py >> 8; }
|
||||
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
package org.dynmap.kzedmap;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.dynmap.DynmapWorld;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public interface MapTileRenderer {
|
||||
String getPrefix();
|
||||
String getName();
|
||||
|
||||
boolean render(MapChunkCache cache, KzedMapTile tile, File outputFile);
|
||||
|
||||
void buildClientConfiguration(JSONObject worldObject, DynmapWorld w, KzedMap map);
|
||||
|
||||
boolean isBiomeDataNeeded();
|
||||
boolean isRawBiomeDataNeeded();
|
||||
boolean isNightAndDayEnabled();
|
||||
}
|
@ -1,332 +0,0 @@
|
||||
package org.dynmap.markers.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.markers.AreaMarker;
|
||||
import org.dynmap.markers.MarkerSet;
|
||||
import org.dynmap.markers.impl.MarkerAPIImpl.MarkerUpdate;
|
||||
|
||||
class AreaMarkerImpl implements AreaMarker {
|
||||
private String markerid;
|
||||
private String label;
|
||||
private boolean markup;
|
||||
private String desc;
|
||||
private MarkerSetImpl markerset;
|
||||
private String world;
|
||||
private boolean ispersistent;
|
||||
private ArrayList<Coord> corners;
|
||||
private int lineweight = 3;
|
||||
private double lineopacity = 0.8;
|
||||
private int linecolor = 0xFF0000;
|
||||
private double fillopacity = 0.35;
|
||||
private int fillcolor = 0xFF0000;
|
||||
private double ytop = 64.0;
|
||||
private double ybottom = 64.0;
|
||||
|
||||
private static class Coord {
|
||||
double x, z;
|
||||
Coord(double x, double z) {
|
||||
this.x = x; this.z = z;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create area marker
|
||||
* @param id - marker ID
|
||||
* @param lbl - label
|
||||
* @param markup - if true, label is HTML markup
|
||||
* @param world - world id
|
||||
* @param x - x coord list
|
||||
* @param z - z coord list
|
||||
* @param persistent - true if persistent
|
||||
* @param set - marker set
|
||||
*/
|
||||
AreaMarkerImpl(String id, String lbl, boolean markup, String world, double x[], double z[], boolean persistent, MarkerSetImpl set) {
|
||||
markerid = id;
|
||||
if(lbl != null)
|
||||
label = lbl;
|
||||
else
|
||||
label = id;
|
||||
this.markup = markup;
|
||||
this.corners = new ArrayList<Coord>();
|
||||
for(int i = 0; i < x.length; i++) {
|
||||
this.corners.add(new Coord(x[i], z[i]));
|
||||
}
|
||||
this.world = world;
|
||||
this.desc = null;
|
||||
ispersistent = persistent;
|
||||
markerset = set;
|
||||
}
|
||||
/**
|
||||
* Make bare area marker - used for persistence load
|
||||
* @param id - marker ID
|
||||
* @param set - marker set
|
||||
*/
|
||||
AreaMarkerImpl(String id, MarkerSetImpl set) {
|
||||
markerid = id;
|
||||
markerset = set;
|
||||
label = id;
|
||||
markup = false;
|
||||
desc = null;
|
||||
corners = new ArrayList<Coord>();
|
||||
world = "world";
|
||||
}
|
||||
/**
|
||||
* Load marker from configuration node
|
||||
* @param node - configuration node
|
||||
*/
|
||||
boolean loadPersistentData(ConfigurationNode node) {
|
||||
label = node.getString("label", markerid);
|
||||
markup = node.getBoolean("markup", false);
|
||||
ytop = node.getDouble("ytop", 64.0);
|
||||
ybottom = node.getDouble("ybottom", 64.0);
|
||||
List<Double> xx = node.getList("x");
|
||||
List<Double> zz = node.getList("z");
|
||||
corners.clear();
|
||||
if((xx != null) && (zz != null)) {
|
||||
for(int i = 0; (i < xx.size()) && (i < zz.size()); i++)
|
||||
corners.add(new Coord(xx.get(i), zz.get(i)));
|
||||
}
|
||||
world = node.getString("world", "world");
|
||||
desc = node.getString("desc", null);
|
||||
lineweight = node.getInteger("strokeWeight", 3);
|
||||
lineopacity = node.getDouble("strokeOpacity", 0.8);
|
||||
linecolor = node.getInteger("strokeColor", 0xFF0000);
|
||||
fillopacity = node.getDouble("fillOpacity", 0.35);
|
||||
fillcolor = node.getInteger("fillColor", 0xFF0000);
|
||||
ispersistent = true; /* Loaded from config, so must be */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
corners.clear();
|
||||
markerset = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMarkerID() {
|
||||
return markerid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkerSet getMarkerSet() {
|
||||
return markerset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteMarker() {
|
||||
markerset.removeAreaMarker(this); /* Remove from our marker set (notified by set) */
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistentMarker() {
|
||||
return ispersistent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLabel(String lbl) {
|
||||
setLabel(lbl, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLabel(String lbl, boolean markup) {
|
||||
label = lbl;
|
||||
this.markup = markup;
|
||||
MarkerAPIImpl.areaMarkerUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configuration node to be saved
|
||||
* @return node
|
||||
*/
|
||||
Map<String, Object> getPersistentData() {
|
||||
if(!ispersistent) /* Nothing if not persistent */
|
||||
return null;
|
||||
HashMap<String, Object> node = new HashMap<String, Object>();
|
||||
node.put("label", label);
|
||||
node.put("markup", markup);
|
||||
List<Double> xx = new ArrayList<Double>();
|
||||
List<Double> zz = new ArrayList<Double>();
|
||||
for(int i = 0; i < corners.size(); i++) {
|
||||
xx.add(corners.get(i).x);
|
||||
zz.add(corners.get(i).z);
|
||||
}
|
||||
node.put("x", xx);
|
||||
node.put("ytop", Double.valueOf(ytop));
|
||||
node.put("ybottom", Double.valueOf(ybottom));
|
||||
node.put("z", zz);
|
||||
node.put("world", world);
|
||||
if(desc != null)
|
||||
node.put("desc", desc);
|
||||
node.put("stokeWeight", lineweight);
|
||||
node.put("strokeOpacity", lineopacity);
|
||||
node.put("strokeColor", linecolor);
|
||||
node.put("fillOpacity", fillopacity);
|
||||
node.put("fillColor", fillcolor);
|
||||
|
||||
return node;
|
||||
}
|
||||
@Override
|
||||
public String getWorld() {
|
||||
return world;
|
||||
}
|
||||
@Override
|
||||
public boolean isLabelMarkup() {
|
||||
return markup;
|
||||
}
|
||||
@Override
|
||||
public void setDescription(String desc) {
|
||||
if((this.desc == null) || (this.desc.equals(desc) == false)) {
|
||||
this.desc = desc;
|
||||
MarkerAPIImpl.areaMarkerUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get marker description
|
||||
* @return descrption
|
||||
*/
|
||||
public String getDescription() {
|
||||
return this.desc;
|
||||
}
|
||||
@Override
|
||||
public double getTopY() {
|
||||
return ytop;
|
||||
}
|
||||
@Override
|
||||
public double getBottomY() {
|
||||
return ybottom;
|
||||
}
|
||||
@Override
|
||||
public void setRangeY(double ytop, double ybottom) {
|
||||
if((this.ytop != ytop) || (this.ybottom != ybottom)) {
|
||||
this.ytop = ytop;
|
||||
this.ybottom = ybottom;
|
||||
MarkerAPIImpl.areaMarkerUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public int getCornerCount() {
|
||||
return corners.size();
|
||||
}
|
||||
@Override
|
||||
public double getCornerX(int n) {
|
||||
Coord c = corners.get(n);
|
||||
if(c != null)
|
||||
return c.x;
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public double getCornerZ(int n) {
|
||||
Coord c = corners.get(n);
|
||||
if(c != null)
|
||||
return c.z;
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public void setCornerLocation(int n, double x, double z) {
|
||||
Coord c;
|
||||
if(n >= corners.size()) {
|
||||
corners.add(new Coord(x, z));
|
||||
}
|
||||
else {
|
||||
c = corners.get(n);
|
||||
if((c.x == x) && (c.z == z))
|
||||
return;
|
||||
c.x = x;
|
||||
c.z = z;
|
||||
}
|
||||
MarkerAPIImpl.areaMarkerUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
@Override
|
||||
public void deleteCorner(int n) {
|
||||
if(n < corners.size()) {
|
||||
corners.remove(n);
|
||||
MarkerAPIImpl.areaMarkerUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void setCornerLocations(double[] x, double[] z) {
|
||||
/* Check if equals */
|
||||
if(x.length == corners.size()) {
|
||||
boolean match = true;
|
||||
for(int i = 0; i < x.length; i++) {
|
||||
Coord c = corners.get(i);
|
||||
if((c.x != x[i]) || (c.z != z[i])) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(match)
|
||||
return;
|
||||
}
|
||||
corners.clear();
|
||||
for(int i = 0; (i < x.length) && (i < z.length); i++) {
|
||||
corners.add(new Coord(x[i], z[i]));
|
||||
}
|
||||
MarkerAPIImpl.areaMarkerUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
@Override
|
||||
public void setLineStyle(int weight, double opacity, int color) {
|
||||
if((weight != lineweight) || (opacity != lineopacity) || (color != linecolor)) {
|
||||
lineweight = weight;
|
||||
lineopacity = opacity;
|
||||
linecolor = color;
|
||||
MarkerAPIImpl.areaMarkerUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public int getLineWeight() {
|
||||
return lineweight;
|
||||
}
|
||||
@Override
|
||||
public double getLineOpacity() {
|
||||
return lineopacity;
|
||||
}
|
||||
@Override
|
||||
public int getLineColor() {
|
||||
return linecolor;
|
||||
}
|
||||
@Override
|
||||
public void setFillStyle(double opacity, int color) {
|
||||
if((opacity != fillopacity) || (color != fillcolor)) {
|
||||
fillopacity = opacity;
|
||||
fillcolor = color;
|
||||
MarkerAPIImpl.areaMarkerUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public double getFillOpacity() {
|
||||
return fillopacity;
|
||||
}
|
||||
@Override
|
||||
public int getFillColor() {
|
||||
return fillcolor;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,101 +0,0 @@
|
||||
package org.dynmap.markers.impl;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.markers.MarkerIcon;
|
||||
|
||||
class MarkerIconImpl implements MarkerIcon {
|
||||
private String iconid;
|
||||
private String label;
|
||||
private boolean is_builtin;
|
||||
private MarkerSize size = MarkerSize.MARKER_16x16;
|
||||
|
||||
MarkerIconImpl(String id) {
|
||||
iconid = id;
|
||||
label = id;
|
||||
is_builtin = false;
|
||||
}
|
||||
|
||||
MarkerIconImpl(String id, String lbl, boolean is_builtin) {
|
||||
iconid = id;
|
||||
if(lbl != null)
|
||||
label = lbl;
|
||||
else
|
||||
label = id;
|
||||
this.is_builtin = is_builtin;
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMarkerIconID() {
|
||||
return iconid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMarkerIconLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMarkerIconLabel(String lbl) {
|
||||
if(lbl == null) lbl = iconid;
|
||||
if(label.equals(lbl) == false) {
|
||||
label = lbl;
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMarkerIconImage(InputStream in) {
|
||||
if(MarkerAPIImpl.api.loadMarkerIconStream(this.iconid, in))
|
||||
MarkerAPIImpl.api.publishMarkerIcon(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteIcon() {
|
||||
MarkerAPIImpl.removeIcon(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltIn() {
|
||||
return is_builtin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configuration node to be saved
|
||||
* @return node
|
||||
*/
|
||||
Map<String, Object> getPersistentData() {
|
||||
if(is_builtin)
|
||||
return null;
|
||||
|
||||
HashMap<String, Object> node = new HashMap<String, Object>();
|
||||
node.put("label", label);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
boolean loadPersistentData(ConfigurationNode node) {
|
||||
if(is_builtin)
|
||||
return false;
|
||||
|
||||
label = node.getString("label", iconid);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkerSize getMarkerIconSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
void setMarkerIconSize(MarkerSize sz) {
|
||||
size = sz;
|
||||
}
|
||||
}
|
@ -1,217 +0,0 @@
|
||||
package org.dynmap.markers.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.markers.Marker;
|
||||
import org.dynmap.markers.MarkerIcon;
|
||||
import org.dynmap.markers.MarkerSet;
|
||||
import org.dynmap.markers.impl.MarkerAPIImpl.MarkerUpdate;
|
||||
|
||||
class MarkerImpl implements Marker {
|
||||
private String markerid;
|
||||
private String label;
|
||||
private boolean markup;
|
||||
private String desc;
|
||||
private MarkerSetImpl markerset;
|
||||
private double x, y, z;
|
||||
private String world;
|
||||
private MarkerIconImpl icon;
|
||||
private boolean ispersistent;
|
||||
|
||||
/**
|
||||
* Create marker
|
||||
* @param id - marker ID
|
||||
* @param lbl - label
|
||||
* @param markup - if true, label is HTML markup
|
||||
* @param world - world id
|
||||
* @param x - x coord
|
||||
* @param y - y coord
|
||||
* @param z - z coord
|
||||
* @param icon - marker icon
|
||||
* @param persistent - true if persistent
|
||||
*/
|
||||
MarkerImpl(String id, String lbl, boolean markup, String world, double x, double y, double z, MarkerIconImpl icon, boolean persistent, MarkerSetImpl set) {
|
||||
markerid = id;
|
||||
if(lbl != null)
|
||||
label = lbl;
|
||||
else
|
||||
label = id;
|
||||
this.markup = markup;
|
||||
this.x = x; this.y = y; this.z = z;
|
||||
this.world = world;
|
||||
this.icon = icon;
|
||||
this.desc = null;
|
||||
ispersistent = persistent;
|
||||
markerset = set;
|
||||
}
|
||||
/**
|
||||
* Make bare marker - used for persistence load
|
||||
* @param id - marker ID
|
||||
* @param set - marker set
|
||||
*/
|
||||
MarkerImpl(String id, MarkerSetImpl set) {
|
||||
markerid = id;
|
||||
markerset = set;
|
||||
label = id;
|
||||
markup = false;
|
||||
desc = null;
|
||||
x = z = 0; y = 64; world = "world";
|
||||
icon = MarkerAPIImpl.getMarkerIconImpl(MarkerIcon.DEFAULT);
|
||||
}
|
||||
/**
|
||||
* Load marker from configuration node
|
||||
* @param node - configuration node
|
||||
*/
|
||||
boolean loadPersistentData(ConfigurationNode node) {
|
||||
label = node.getString("label", markerid);
|
||||
markup = node.getBoolean("markup", false);
|
||||
x = node.getDouble("x", 0);
|
||||
y = node.getDouble("y", 64);
|
||||
z = node.getDouble("z", 0);
|
||||
world = node.getString("world", "world");
|
||||
desc = node.getString("desc", null);
|
||||
icon = MarkerAPIImpl.getMarkerIconImpl(node.getString("icon", MarkerIcon.DEFAULT));
|
||||
ispersistent = true; /* Loaded from config, so must be */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
icon = null;
|
||||
markerset = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMarkerID() {
|
||||
return markerid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkerSet getMarkerSet() {
|
||||
return markerset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteMarker() {
|
||||
markerset.removeMarker(this); /* Remove from our marker set (notified by set) */
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkerIcon getMarkerIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setMarkerIcon(MarkerIcon icon) {
|
||||
if(!(icon instanceof MarkerIconImpl)) {
|
||||
return false;
|
||||
}
|
||||
/* Check if icons restricted for this set */
|
||||
Set<MarkerIcon> icns = markerset.getAllowedMarkerIcons();
|
||||
if((icns != null) && (icns.contains(icon) == false)) {
|
||||
return false;
|
||||
}
|
||||
this.icon = (MarkerIconImpl)icon;
|
||||
MarkerAPIImpl.markerUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistentMarker() {
|
||||
return ispersistent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLabel(String lbl) {
|
||||
setLabel(lbl, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLabel(String lbl, boolean markup) {
|
||||
label = lbl;
|
||||
this.markup = markup;
|
||||
MarkerAPIImpl.markerUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configuration node to be saved
|
||||
* @return node
|
||||
*/
|
||||
Map<String, Object> getPersistentData() {
|
||||
if(!ispersistent) /* Nothing if not persistent */
|
||||
return null;
|
||||
HashMap<String, Object> node = new HashMap<String, Object>();
|
||||
node.put("label", label);
|
||||
node.put("markup", markup);
|
||||
node.put("x", Double.valueOf(x));
|
||||
node.put("y", Double.valueOf(y));
|
||||
node.put("z", Double.valueOf(z));
|
||||
node.put("world", world);
|
||||
node.put("icon", icon.getMarkerIconID());
|
||||
if(desc != null)
|
||||
node.put("desc", desc);
|
||||
|
||||
return node;
|
||||
}
|
||||
@Override
|
||||
public String getWorld() {
|
||||
return world;
|
||||
}
|
||||
@Override
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
@Override
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
@Override
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
@Override
|
||||
public void setLocation(String worldid, double x, double y, double z) {
|
||||
this.world = worldid;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
MarkerAPIImpl.markerUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
@Override
|
||||
public boolean isLabelMarkup() {
|
||||
return markup;
|
||||
}
|
||||
@Override
|
||||
public void setDescription(String desc) {
|
||||
if((this.desc == null) || (this.desc.equals(desc) == false)) {
|
||||
this.desc = desc;
|
||||
MarkerAPIImpl.markerUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get marker description
|
||||
* @return descrption
|
||||
*/
|
||||
public String getDescription() {
|
||||
return this.desc;
|
||||
}
|
||||
|
||||
}
|
@ -1,389 +0,0 @@
|
||||
package org.dynmap.markers.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.Log;
|
||||
import org.dynmap.markers.AreaMarker;
|
||||
import org.dynmap.markers.Marker;
|
||||
import org.dynmap.markers.MarkerIcon;
|
||||
import org.dynmap.markers.MarkerSet;
|
||||
import org.dynmap.markers.impl.MarkerAPIImpl.MarkerUpdate;
|
||||
|
||||
class MarkerSetImpl implements MarkerSet {
|
||||
private HashMap<String, MarkerImpl> markers = new HashMap<String, MarkerImpl>();
|
||||
private HashMap<String, AreaMarkerImpl> areamarkers = new HashMap<String, AreaMarkerImpl>();
|
||||
private String setid;
|
||||
private String label;
|
||||
private HashMap<String, MarkerIconImpl> allowedicons = null;
|
||||
private boolean hide_by_def;
|
||||
private boolean ispersistent;
|
||||
private int prio = 0;
|
||||
private int minzoom = 0;
|
||||
|
||||
MarkerSetImpl(String id) {
|
||||
setid = id;
|
||||
label = id;
|
||||
}
|
||||
|
||||
MarkerSetImpl(String id, String lbl, Set<MarkerIcon> iconlimit, boolean persistent) {
|
||||
setid = id;
|
||||
if(lbl != null)
|
||||
label = lbl;
|
||||
else
|
||||
label = id;
|
||||
if(iconlimit != null) {
|
||||
allowedicons = new HashMap<String, MarkerIconImpl>();
|
||||
for(MarkerIcon ico : iconlimit) {
|
||||
if(ico instanceof MarkerIconImpl) {
|
||||
allowedicons.put(ico.getMarkerIconID(), (MarkerIconImpl)ico);
|
||||
}
|
||||
}
|
||||
}
|
||||
ispersistent = persistent;
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
for(MarkerImpl m : markers.values())
|
||||
m.cleanup();
|
||||
for(AreaMarkerImpl m : areamarkers.values())
|
||||
m.cleanup();
|
||||
markers.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Marker> getMarkers() {
|
||||
return new HashSet<Marker>(markers.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<AreaMarker> getAreaMarkers() {
|
||||
return new HashSet<AreaMarker>(areamarkers.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Marker createMarker(String id, String label, String world, double x, double y, double z, MarkerIcon icon, boolean is_persistent) {
|
||||
return createMarker(id, label, false, world, x, y, z, icon, is_persistent);
|
||||
}
|
||||
@Override
|
||||
public Marker createMarker(String id, String label, boolean markup, String world, double x, double y, double z, MarkerIcon icon, boolean is_persistent) {
|
||||
if(id == null) { /* If not defined, generate unique one */
|
||||
int i = 0;
|
||||
do {
|
||||
i++;
|
||||
id = "marker_" + i;
|
||||
} while(markers.containsKey(id));
|
||||
}
|
||||
if(markers.containsKey(id)) return null; /* Duplicate ID? */
|
||||
if(!(icon instanceof MarkerIconImpl)) return null;
|
||||
/* If limited icons, and this isn't valid one, quit */
|
||||
if((allowedicons != null) && (allowedicons.containsKey(icon.getMarkerIconID()) == false)) return null;
|
||||
/* Create marker */
|
||||
is_persistent = is_persistent && this.ispersistent;
|
||||
MarkerImpl marker = new MarkerImpl(id, label, markup, world, x, y, z, (MarkerIconImpl)icon, is_persistent, this);
|
||||
markers.put(id, marker); /* Add to set */
|
||||
if(is_persistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
|
||||
MarkerAPIImpl.markerUpdated(marker, MarkerUpdate.CREATED); /* Signal create */
|
||||
|
||||
return marker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Marker findMarker(String id) {
|
||||
return markers.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Marker findMarkerByLabel(String lbl) {
|
||||
Marker match = null;
|
||||
int matchlen = Integer.MAX_VALUE;
|
||||
for(Marker m : markers.values()) {
|
||||
if(m.getLabel().contains(lbl)) {
|
||||
if(matchlen > m.getLabel().length()) {
|
||||
match = m;
|
||||
matchlen = m.getLabel().length();
|
||||
}
|
||||
}
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMarkerSetID() {
|
||||
return setid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMarkerSetLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMarkerSetLabel(String lbl) {
|
||||
label = lbl;
|
||||
MarkerAPIImpl.markerSetUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMarkerSetPersistent() {
|
||||
return ispersistent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MarkerIcon> getAllowedMarkerIcons() {
|
||||
if(allowedicons != null)
|
||||
return new HashSet<MarkerIcon>(allowedicons.values());
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAllowedMarkerIcon(MarkerIcon icon) {
|
||||
if(!(icon instanceof MarkerIconImpl)) return;
|
||||
if(allowedicons == null) return;
|
||||
allowedicons.put(icon.getMarkerIconID(), (MarkerIconImpl)icon);
|
||||
MarkerAPIImpl.markerSetUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllowedMarkerIcon(MarkerIcon icon) {
|
||||
if(!(icon instanceof MarkerIconImpl)) return;
|
||||
if(allowedicons == null) return;
|
||||
allowedicons.remove(icon.getMarkerIconID());
|
||||
MarkerAPIImpl.markerSetUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllowedMarkerIcon(MarkerIcon icon) {
|
||||
if(allowedicons == null) return true;
|
||||
return allowedicons.containsKey(icon.getMarkerIconID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MarkerIcon> getMarkerIconsInUse() {
|
||||
HashSet<String> ids = new HashSet<String>();
|
||||
HashSet<MarkerIcon> icons = new HashSet<MarkerIcon>();
|
||||
for(Marker m : markers.values()) {
|
||||
MarkerIcon mi = m.getMarkerIcon();
|
||||
if(!ids.contains(mi.getMarkerIconID())) {
|
||||
ids.add(mi.getMarkerIconID());
|
||||
icons.add(mi);
|
||||
}
|
||||
}
|
||||
return icons;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteMarkerSet() {
|
||||
MarkerAPIImpl.removeMarkerSet(this); /* Remove from top level sets (notification from there) */
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
cleanup();
|
||||
}
|
||||
/**
|
||||
* Remove marker from set
|
||||
*
|
||||
* @param marker
|
||||
*/
|
||||
void removeMarker(MarkerImpl marker) {
|
||||
markers.remove(marker.getMarkerID()); /* Remove from set */
|
||||
if(ispersistent && marker.isPersistentMarker()) { /* If persistent */
|
||||
MarkerAPIImpl.saveMarkers(); /* Drive save */
|
||||
}
|
||||
MarkerAPIImpl.markerUpdated(marker, MarkerUpdate.DELETED);
|
||||
}
|
||||
/**
|
||||
* Remove marker from set
|
||||
*
|
||||
* @param marker
|
||||
*/
|
||||
void removeAreaMarker(AreaMarkerImpl marker) {
|
||||
areamarkers.remove(marker.getMarkerID()); /* Remove from set */
|
||||
if(ispersistent && marker.isPersistentMarker()) { /* If persistent */
|
||||
MarkerAPIImpl.saveMarkers(); /* Drive save */
|
||||
}
|
||||
MarkerAPIImpl.areaMarkerUpdated(marker, MarkerUpdate.DELETED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configuration node to be saved
|
||||
* @return node
|
||||
*/
|
||||
Map<String, Object> getPersistentData() {
|
||||
if(!ispersistent) /* Nothing if not persistent */
|
||||
return null;
|
||||
HashMap<String, Object> node = new HashMap<String, Object>();
|
||||
for(String id : markers.keySet()) {
|
||||
MarkerImpl m = markers.get(id);
|
||||
if(m.isPersistentMarker()) {
|
||||
node.put(id, m.getPersistentData());
|
||||
}
|
||||
}
|
||||
HashMap<String, Object> anode = new HashMap<String, Object>();
|
||||
for(String id : areamarkers.keySet()) {
|
||||
AreaMarkerImpl m = areamarkers.get(id);
|
||||
if(m.isPersistentMarker()) {
|
||||
anode.put(id, m.getPersistentData());
|
||||
}
|
||||
}
|
||||
/* Make top level node */
|
||||
HashMap<String, Object> setnode = new HashMap<String, Object>();
|
||||
setnode.put("label", label);
|
||||
if(allowedicons != null) {
|
||||
ArrayList<String> allowed = new ArrayList<String>(allowedicons.keySet());
|
||||
setnode.put("allowedicons", allowed);
|
||||
}
|
||||
setnode.put("markers", node);
|
||||
setnode.put("areas", anode);
|
||||
setnode.put("hide", hide_by_def);
|
||||
setnode.put("layerprio", prio);
|
||||
setnode.put("minzoom", minzoom);
|
||||
return setnode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load marker from configuration node
|
||||
* @param node - configuration node
|
||||
*/
|
||||
boolean loadPersistentData(ConfigurationNode node) {
|
||||
label = node.getString("label", setid); /* Get label */
|
||||
ConfigurationNode markernode = node.getNode("markers");
|
||||
if(markernode != null) {
|
||||
for(String id : markernode.keySet()) {
|
||||
MarkerImpl marker = new MarkerImpl(id, this); /* Make and load marker */
|
||||
if(marker.loadPersistentData(markernode.getNode(id))) {
|
||||
markers.put(id, marker);
|
||||
}
|
||||
else {
|
||||
Log.info("Error loading marker '" + id + "' for set '" + setid + "'");
|
||||
marker.cleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
ConfigurationNode areamarkernode = node.getNode("areas");
|
||||
if(areamarkernode != null) {
|
||||
for(String id : areamarkernode.keySet()) {
|
||||
AreaMarkerImpl marker = new AreaMarkerImpl(id, this); /* Make and load marker */
|
||||
if(marker.loadPersistentData(areamarkernode.getNode(id))) {
|
||||
areamarkers.put(id, marker);
|
||||
}
|
||||
else {
|
||||
Log.info("Error loading area marker '" + id + "' for set '" + setid + "'");
|
||||
marker.cleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
List<String> allowed = node.getList("allowedicons");
|
||||
if(allowed != null) {
|
||||
for(String id : allowed) {
|
||||
MarkerIconImpl icon = MarkerAPIImpl.getMarkerIconImpl(id);
|
||||
if(icon != null)
|
||||
allowedicons.put(id, icon);
|
||||
else
|
||||
Log.info("Error loading allowed icon '" + id + "' for set '" + setid + "'");
|
||||
}
|
||||
}
|
||||
hide_by_def = node.getBoolean("hide", false);
|
||||
prio = node.getInteger("layerprio", 0);
|
||||
minzoom = node.getInteger("minzoom", 0);
|
||||
ispersistent = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public void setHideByDefault(boolean hide) {
|
||||
if(hide_by_def != hide) {
|
||||
hide_by_def = hide;
|
||||
MarkerAPIImpl.markerSetUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean getHideByDefault() {
|
||||
return hide_by_def;
|
||||
}
|
||||
@Override
|
||||
public void setLayerPriority(int prio) {
|
||||
if(this.prio != prio) {
|
||||
this.prio = prio;
|
||||
MarkerAPIImpl.markerSetUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public int getLayerPriority() {
|
||||
return this.prio;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AreaMarker createAreaMarker(String id, String lbl, boolean markup, String world, double[] x, double[] z, boolean persistent) {
|
||||
if(id == null) { /* If not defined, generate unique one */
|
||||
int i = 0;
|
||||
do {
|
||||
i++;
|
||||
id = "area_" + i;
|
||||
} while(areamarkers.containsKey(id));
|
||||
}
|
||||
if(areamarkers.containsKey(id)) return null; /* Duplicate ID? */
|
||||
/* Create marker */
|
||||
persistent = persistent && this.ispersistent;
|
||||
AreaMarkerImpl marker = new AreaMarkerImpl(id, lbl, markup, world, x, z, persistent, this);
|
||||
areamarkers.put(id, marker); /* Add to set */
|
||||
if(persistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
|
||||
MarkerAPIImpl.areaMarkerUpdated(marker, MarkerUpdate.CREATED); /* Signal create */
|
||||
|
||||
return marker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AreaMarker findAreaMarker(String id) {
|
||||
return areamarkers.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AreaMarker findAreaMarkerByLabel(String lbl) {
|
||||
AreaMarker match = null;
|
||||
int matchlen = Integer.MAX_VALUE;
|
||||
for(AreaMarker m : areamarkers.values()) {
|
||||
if(m.getLabel().contains(lbl)) {
|
||||
if(matchlen > m.getLabel().length()) {
|
||||
match = m;
|
||||
matchlen = m.getLabel().length();
|
||||
}
|
||||
}
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMinZoom(int minzoom) {
|
||||
if(this.minzoom != minzoom) {
|
||||
this.minzoom = minzoom;
|
||||
MarkerAPIImpl.markerSetUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public int getMinZoom() {
|
||||
return this.minzoom;
|
||||
}
|
||||
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
package org.dynmap.markers.impl;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.common.DynmapChatColor;
|
||||
import org.dynmap.common.DynmapListenerManager;
|
||||
import org.dynmap.common.DynmapListenerManager.EventType;
|
||||
import org.dynmap.common.DynmapPlayer;
|
||||
import org.dynmap.markers.Marker;
|
||||
import org.dynmap.markers.MarkerIcon;
|
||||
import org.dynmap.markers.MarkerSet;
|
||||
|
||||
public class MarkerSignManager {
|
||||
|
||||
private static MarkerSignManager mgr = null;
|
||||
private static DynmapCore plugin = null;
|
||||
|
||||
private static final int SIGNPOST_ID = 63;
|
||||
private static final int WALLSIGN_ID = 68;
|
||||
|
||||
private static class SignListener implements DynmapListenerManager.BlockEventListener, DynmapListenerManager.SignChangeEventListener {
|
||||
@Override
|
||||
public void signChangeEvent(int blkid, String wname, int x, int y, int z, String[] lines, DynmapPlayer p) {
|
||||
if(mgr == null)
|
||||
return;
|
||||
if(!lines[0].equalsIgnoreCase("[dynmap]")) { /* If not dynmap sign, quit */
|
||||
return;
|
||||
}
|
||||
/* If allowed to do marker signs */
|
||||
if((p == null) || ((plugin != null) && (plugin.checkPlayerPermission(p, "marker.sign")))) {
|
||||
String id = getSignMarkerID(wname, x, y, z); /* Get marker ID */
|
||||
String set = MarkerSet.DEFAULT;
|
||||
String icon = MarkerIcon.SIGN;
|
||||
String label = "";
|
||||
lines[0] = ""; /* Blank out [dynmap] */
|
||||
for(int i = 1; i < 4; i++) { /* Check other lines for icon: or set: */
|
||||
String v = plugin.getServer().stripChatColor(lines[i]);
|
||||
if(v.startsWith("icon:")) { /* icon: */
|
||||
icon = v.substring(5);
|
||||
lines[i] = "";
|
||||
}
|
||||
else if(v.startsWith("set:")) { /* set: */
|
||||
set = v.substring(4);
|
||||
lines[i] = "";
|
||||
}
|
||||
else if(v.length() > 0) {
|
||||
if(label.length() > 0) {
|
||||
label = label + "<br/>";
|
||||
}
|
||||
label = label + escapeMarkup(v);
|
||||
}
|
||||
}
|
||||
/* Get the set and see if the marker is already defined */
|
||||
MarkerSet ms = MarkerAPIImpl.api.getMarkerSet(set);
|
||||
if(ms == null) {
|
||||
if(p != null) p.sendMessage("Bad marker set - [dynmap] sign invalid");
|
||||
lines[0] = DynmapChatColor.RED + "<Bad Marker Set>";
|
||||
return;
|
||||
}
|
||||
MarkerIcon mi = MarkerAPIImpl.api.getMarkerIcon(icon); /* Get icon */
|
||||
if(mi == null) {
|
||||
if(p != null) p.sendMessage("Bad marker icon - [dynmap] sign invalid");
|
||||
lines[0] = DynmapChatColor.RED + "<Bad Marker Icon>";
|
||||
return;
|
||||
}
|
||||
Marker marker = ms.findMarker(id);
|
||||
/* If exists, update it */
|
||||
if(marker != null) {
|
||||
marker.setLabel(label, true);
|
||||
marker.setMarkerIcon(mi);
|
||||
}
|
||||
else { /* Make new marker */
|
||||
marker = ms.createMarker(id, label, true, wname, (double)x + 0.5, (double)y + 0.5, (double)z + 0.5,
|
||||
mi, true);
|
||||
if(marker == null) {
|
||||
if(p != null) p.sendMessage("Bad marker - [dynmap] sign invalid");
|
||||
lines[0] = DynmapChatColor.RED + "<Bad Marker>";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void blockEvent(int blkid, String wname, int x, int y, int z) {
|
||||
if(mgr == null)
|
||||
return;
|
||||
if((blkid == WALLSIGN_ID) || (blkid == SIGNPOST_ID)) { /* If sign */
|
||||
String id = getSignMarkerID(wname, x, y, z); /* Marker sign? */
|
||||
Set<MarkerSet> sets = MarkerAPIImpl.api.getMarkerSets();
|
||||
for(MarkerSet ms : sets) {
|
||||
Marker marker = ms.findMarker(id); /* See if in this set */
|
||||
if(marker != null) {
|
||||
marker.deleteMarker();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private static SignListener sl = null; /* Do once - /dynmap reload doesn't reset listeners */
|
||||
|
||||
private static String escapeMarkup(String v) {
|
||||
v = v.replace("&", "&");
|
||||
v = v.replace("\"", ""e;");
|
||||
v = v.replace("<", "<");
|
||||
v = v.replace(">", ">");
|
||||
return v;
|
||||
}
|
||||
|
||||
public static MarkerSignManager initializeSignManager(DynmapCore plugin) {
|
||||
mgr = new MarkerSignManager();
|
||||
if(sl == null) {
|
||||
sl = new SignListener();
|
||||
plugin.listenerManager.addListener(EventType.BLOCK_BREAK, sl);
|
||||
plugin.listenerManager.addListener(EventType.SIGN_CHANGE, sl);
|
||||
}
|
||||
MarkerSignManager.plugin = plugin;
|
||||
return mgr;
|
||||
}
|
||||
public static void terminateSignManager(DynmapCore plugin) {
|
||||
mgr = null;
|
||||
}
|
||||
|
||||
private static String getSignMarkerID(String wname, int x, int y, int z) {
|
||||
return "_sign_" + wname + "_" + x + "_" + y + "_" + z;
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package org.dynmap.regions;
|
||||
|
||||
import org.dynmap.Component;
|
||||
import org.dynmap.ConfigurationNode;
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.Log;
|
||||
|
||||
public class RegionsComponent extends Component {
|
||||
private static String deprecated_ids[] = { "Residence", "Factions", "Towny", "WorldGuard" };
|
||||
private static String deprecated_new_plugins[] = { "dynmap-residence", "Dynmap-Factions", "Dynmap-Towny", "Dynmap-WorldGuard" };
|
||||
|
||||
public RegionsComponent(final DynmapCore plugin, final ConfigurationNode configuration) {
|
||||
super(plugin, configuration);
|
||||
|
||||
String regiontype = configuration.getString("name", "WorldGuard");
|
||||
/* Check if a deprecated component */
|
||||
for(int i = 0; i < deprecated_ids.length; i++) {
|
||||
if(regiontype.equals(deprecated_ids[i])) { /* If match */
|
||||
Log.info("Region component for '" + regiontype + "' has been RETIRED - migrate to '" + deprecated_new_plugins[i] + "' plugin");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package org.dynmap.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.DynmapWorld;
|
||||
import org.dynmap.Event;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class ClientConfigurationServlet extends HttpServlet {
|
||||
private static final long serialVersionUID = 9106801553080522469L;
|
||||
private DynmapCore plugin;
|
||||
private byte[] cachedConfiguration = null;
|
||||
private int cached_config_hashcode = 0;
|
||||
|
||||
public ClientConfigurationServlet(DynmapCore plugin) {
|
||||
this.plugin = plugin;
|
||||
plugin.events.addListener("worldactivated", new Event.Listener<DynmapWorld>() {
|
||||
@Override
|
||||
public void triggered(DynmapWorld t) {
|
||||
cachedConfiguration = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
|
||||
byte[] outputBytes = cachedConfiguration;
|
||||
if ((outputBytes == null) || (cached_config_hashcode != plugin.getConfigHashcode())) {
|
||||
JSONObject json = new JSONObject();
|
||||
plugin.events.<JSONObject>trigger("buildclientconfiguration", json);
|
||||
|
||||
String s = json.toJSONString();
|
||||
|
||||
outputBytes = s.getBytes("UTF-8");
|
||||
}
|
||||
if (outputBytes != null) {
|
||||
cachedConfiguration = outputBytes;
|
||||
cached_config_hashcode = plugin.getConfigHashcode();
|
||||
}
|
||||
String dateStr = new Date().toString();
|
||||
res.addHeader("Date", dateStr);
|
||||
res.setContentType("text/plain; charset=utf-8");
|
||||
res.addHeader("Expires", "Thu, 01 Dec 1994 16:00:00 GMT");
|
||||
res.addHeader("Last-modified", dateStr);
|
||||
res.setContentLength(outputBytes.length);
|
||||
res.getOutputStream().write(outputBytes);
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
package org.dynmap.servlet;
|
||||
|
||||
import static org.dynmap.JSONUtils.s;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.dynmap.ClientUpdateEvent;
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.DynmapWorld;
|
||||
import org.dynmap.web.HttpField;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class ClientUpdateServlet extends HttpServlet {
|
||||
private DynmapCore plugin;
|
||||
|
||||
public ClientUpdateServlet(DynmapCore plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
Pattern updatePathPattern = Pattern.compile("/([^/]+)/([0-9]*)");
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String path = req.getPathInfo();
|
||||
Matcher match = updatePathPattern.matcher(path);
|
||||
|
||||
if (!match.matches()) {
|
||||
resp.sendError(404, "World not found");
|
||||
return;
|
||||
}
|
||||
|
||||
String worldName = match.group(1);
|
||||
String timeKey = match.group(2);
|
||||
|
||||
DynmapWorld dynmapWorld = null;
|
||||
if(plugin.mapManager != null) {
|
||||
dynmapWorld = plugin.mapManager.getWorld(worldName);
|
||||
}
|
||||
if (dynmapWorld == null || !dynmapWorld.isLoaded()) {
|
||||
resp.sendError(404, "World not found");
|
||||
return;
|
||||
}
|
||||
long current = System.currentTimeMillis();
|
||||
long since = 0;
|
||||
|
||||
try {
|
||||
since = Long.parseLong(timeKey);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
|
||||
JSONObject u = new JSONObject();
|
||||
s(u, "timestamp", current);
|
||||
plugin.events.trigger("buildclientupdate", new ClientUpdateEvent(since, dynmapWorld, u));
|
||||
|
||||
byte[] bytes = u.toJSONString().getBytes("UTF-8");
|
||||
|
||||
String dateStr = new Date().toString();
|
||||
resp.addHeader(HttpField.Date, dateStr);
|
||||
resp.addHeader(HttpField.ContentType, "text/plain; charset=utf-8");
|
||||
resp.addHeader(HttpField.Expires, "Thu, 01 Dec 1994 16:00:00 GMT");
|
||||
resp.addHeader(HttpField.LastModified, dateStr);
|
||||
resp.addHeader(HttpField.ContentLength, Integer.toString(bytes.length));
|
||||
|
||||
resp.getOutputStream().write(bytes);
|
||||
}
|
||||
}
|
@ -1,579 +0,0 @@
|
||||
/*
|
||||
* net/balusc/webapp/FileServlet.java
|
||||
*
|
||||
* Copyright (C) 2009 BalusC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the
|
||||
* GNU Lesser General Public License as published by the Free Software Foundation, either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.dynmap.servlet;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.net.URLDecoder;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* A file servlet supporting resume of downloads and client-side caching and GZIP of text content.
|
||||
* This servlet can also be used for images, client-side caching would become more efficient.
|
||||
* This servlet can also be used for text files, GZIP would decrease network bandwidth.
|
||||
*
|
||||
* @author BalusC
|
||||
* @link http://balusc.blogspot.com/2009/02/fileservlet-supporting-resume-and.html
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class FileServlet extends HttpServlet {
|
||||
|
||||
// Constants ----------------------------------------------------------------------------------
|
||||
|
||||
private static final int DEFAULT_BUFFER_SIZE = 10240; // ..bytes = 10KB.
|
||||
private static final String MULTIPART_BOUNDARY = "MULTIPART_BYTERANGES";
|
||||
|
||||
// Properties ---------------------------------------------------------------------------------
|
||||
|
||||
private String basePath = null;
|
||||
private boolean allow_symlinks = true;
|
||||
private String[] indexFiles = new String[] {
|
||||
"index.html"
|
||||
};
|
||||
|
||||
// Actions ------------------------------------------------------------------------------------
|
||||
|
||||
public FileServlet() {
|
||||
}
|
||||
|
||||
public FileServlet(String basePath, boolean allow_symlinks) {
|
||||
this.basePath = new File(basePath).getAbsolutePath();
|
||||
this.allow_symlinks = allow_symlinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the servlet.
|
||||
* @see HttpServlet#init().
|
||||
*/
|
||||
public void init() throws ServletException {
|
||||
if (basePath == null) {
|
||||
setBasePath(new File(getServletContext().getRealPath(getInitParameter("basePath"))).getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
public void setBasePath(String basePath) {
|
||||
// Validate base path.
|
||||
if (basePath == null) {
|
||||
throw new InvalidParameterException("'basePath' is required.");
|
||||
} else {
|
||||
File path = new File(basePath);
|
||||
if (!path.exists()) {
|
||||
throw new InvalidParameterException("'basePath' value '"
|
||||
+ basePath + "' does actually not exist in file system.");
|
||||
} else if (!path.isDirectory()) {
|
||||
throw new InvalidParameterException("'basePath' value '"
|
||||
+ basePath + "' is actually not a directory in file system.");
|
||||
} else if (!path.canRead()) {
|
||||
throw new InvalidParameterException("'basePath' value '"
|
||||
+ basePath + "' is actually not readable in file system.");
|
||||
}
|
||||
}
|
||||
this.basePath = basePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process HEAD request. This returns the same headers as GET request, but without content.
|
||||
* @see HttpServlet#doHead(HttpServletRequest, HttpServletResponse).
|
||||
*/
|
||||
protected void doHead(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
// Process request without content.
|
||||
processRequest(request, response, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process GET request.
|
||||
* @see HttpServlet#doGet(HttpServletRequest, HttpServletResponse).
|
||||
*/
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
// Process request with content.
|
||||
processRequest(request, response, true);
|
||||
}
|
||||
|
||||
private static String getNormalizedPath(String p) {
|
||||
p = p.replace('\\', '/');
|
||||
String[] tok = p.split("/");
|
||||
int i, j;
|
||||
for(i = 0, j = 0; i < tok.length; i++) {
|
||||
if((tok[i] == null) || (tok[i].length() == 0) || (tok[i].equals("."))) {
|
||||
tok[i] = null;
|
||||
}
|
||||
else if(tok[i].equals("..")) {
|
||||
if(j > 0) { j--; tok[j] = null; }
|
||||
tok[i] = null;
|
||||
}
|
||||
else {
|
||||
tok[j] = tok[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
String path = "";
|
||||
for(i = 0; i < j; i++) {
|
||||
if(tok[i] != null)
|
||||
path = path + "/" + tok[i];
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the actual request.
|
||||
* @param request The request to be processed.
|
||||
* @param response The response to be created.
|
||||
* @param content Whether the request body should be written (GET) or not (HEAD).
|
||||
* @throws IOException If something fails at I/O level.
|
||||
*/
|
||||
private void processRequest
|
||||
(HttpServletRequest request, HttpServletResponse response, boolean content)
|
||||
throws IOException
|
||||
{
|
||||
// Validate the requested file ------------------------------------------------------------
|
||||
|
||||
// Get requested file by path info.
|
||||
String requestedFile = request.getPathInfo();
|
||||
|
||||
if (requestedFile != null)
|
||||
requestedFile = getNormalizedPath(requestedFile);
|
||||
|
||||
// Check if file is actually supplied to the request URL.
|
||||
if (requestedFile == null) {
|
||||
// Do your thing if the file is not supplied to the request URL.
|
||||
// Throw an exception, or send 404, or show default/warning page, or just ignore it.
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
// URL-decode the file name (might contain spaces and on) and prepare file object.
|
||||
File file = new File(basePath, URLDecoder.decode(requestedFile, "UTF-8"));
|
||||
|
||||
String fpath = null;
|
||||
if(allow_symlinks)
|
||||
fpath = file.getAbsolutePath();
|
||||
else
|
||||
fpath = file.getCanonicalPath();
|
||||
|
||||
if (!fpath.startsWith(basePath)) {
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
if (file.isDirectory()) {
|
||||
File directory = file;
|
||||
for (int i = 0; i < indexFiles.length; i++) {
|
||||
file = new File(directory, indexFiles[i]);
|
||||
if (file.isFile())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if file actually exists in filesystem.
|
||||
if (!file.exists()) {
|
||||
// Do your thing if the file appears to be non-existing.
|
||||
// Throw an exception, or send 404, or show default/warning page, or just ignore it.
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare some variables. The ETag is an unique identifier of the file.
|
||||
String fileName = file.getName();
|
||||
long length = file.length();
|
||||
long lastModified = file.lastModified();
|
||||
String eTag = fileName + "_" + length + "_" + lastModified;
|
||||
|
||||
|
||||
// Validate request headers for caching ---------------------------------------------------
|
||||
|
||||
// If-None-Match header should contain "*" or ETag. If so, then return 304.
|
||||
String ifNoneMatch = request.getHeader("If-None-Match");
|
||||
if (ifNoneMatch != null && matches(ifNoneMatch, eTag)) {
|
||||
response.setHeader("ETag", eTag); // Required in 304.
|
||||
response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
return;
|
||||
}
|
||||
|
||||
// If-Modified-Since header should be greater than LastModified. If so, then return 304.
|
||||
// This header is ignored if any If-None-Match header is specified.
|
||||
long ifModifiedSince = request.getDateHeader("If-Modified-Since");
|
||||
if (ifNoneMatch == null && ifModifiedSince != -1 && ifModifiedSince + 1000 > lastModified) {
|
||||
response.setHeader("ETag", eTag); // Required in 304.
|
||||
response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Validate request headers for resume ----------------------------------------------------
|
||||
|
||||
// If-Match header should contain "*" or ETag. If not, then return 412.
|
||||
String ifMatch = request.getHeader("If-Match");
|
||||
if (ifMatch != null && !matches(ifMatch, eTag)) {
|
||||
response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
// If-Unmodified-Since header should be greater than LastModified. If not, then return 412.
|
||||
long ifUnmodifiedSince = request.getDateHeader("If-Unmodified-Since");
|
||||
if (ifUnmodifiedSince != -1 && ifUnmodifiedSince + 1000 <= lastModified) {
|
||||
response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Validate and process range -------------------------------------------------------------
|
||||
|
||||
// Prepare some variables. The full Range represents the complete file.
|
||||
Range full = new Range(0, length - 1, length);
|
||||
List<Range> ranges = new ArrayList<Range>();
|
||||
|
||||
// Validate and process Range and If-Range headers.
|
||||
String range = request.getHeader("Range");
|
||||
if (range != null) {
|
||||
|
||||
// Range header should match format "bytes=n-n,n-n,n-n...". If not, then return 416.
|
||||
if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) {
|
||||
response.setHeader("Content-Range", "bytes */" + length); // Required in 416.
|
||||
response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
// If-Range header should either match ETag or be greater then LastModified. If not,
|
||||
// then return full file.
|
||||
String ifRange = request.getHeader("If-Range");
|
||||
if (ifRange != null && !ifRange.equals(eTag)) {
|
||||
try {
|
||||
long ifRangeTime = request.getDateHeader("If-Range"); // Throws IAE if invalid.
|
||||
if (ifRangeTime != -1 && ifRangeTime + 1000 < lastModified) {
|
||||
ranges.add(full);
|
||||
}
|
||||
} catch (IllegalArgumentException ignore) {
|
||||
ranges.add(full);
|
||||
}
|
||||
}
|
||||
|
||||
// If any valid If-Range header, then process each part of byte range.
|
||||
if (ranges.isEmpty()) {
|
||||
String[] rangesParts = range.substring(6).split(",");
|
||||
|
||||
if (rangesParts.length > 1) {
|
||||
response.setHeader("Content-Range", "bytes */" + length); // Required in 416.
|
||||
response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||
return;
|
||||
}
|
||||
for (String part : rangesParts) {
|
||||
// Assuming a file with length of 100, the following examples returns bytes at:
|
||||
// 50-80 (50 to 80), 40- (40 to length=100), -20 (length-20=80 to length=100).
|
||||
long start = sublong(part, 0, part.indexOf("-"));
|
||||
long end = sublong(part, part.indexOf("-") + 1, part.length());
|
||||
|
||||
if (start == -1) {
|
||||
start = length - end;
|
||||
end = length - 1;
|
||||
} else if (end == -1 || end > length - 1) {
|
||||
end = length - 1;
|
||||
}
|
||||
|
||||
// Check if Range is syntactically valid. If not, then return 416.
|
||||
if (start > end) {
|
||||
response.setHeader("Content-Range", "bytes */" + length); // Required in 416.
|
||||
response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add range.
|
||||
ranges.add(new Range(start, end, length));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Prepare and initialize response --------------------------------------------------------
|
||||
|
||||
// Get content type by file name and set default GZIP support and content disposition.
|
||||
boolean acceptsGzip = false;
|
||||
String disposition = "inline";
|
||||
|
||||
String contentType = getContentType(fileName);
|
||||
|
||||
// If content type is text, then determine whether GZIP content encoding is supported by
|
||||
// the browser and expand content type with the one and right character encoding.
|
||||
if (contentType.startsWith("text")) {
|
||||
String acceptEncoding = request.getHeader("Accept-Encoding");
|
||||
acceptsGzip = acceptEncoding != null && accepts(acceptEncoding, "gzip");
|
||||
contentType += ";charset=UTF-8";
|
||||
}
|
||||
// Else, expect for images, determine content disposition. If content type is supported by
|
||||
// the browser, then set to inline, else attachment which will pop a 'save as' dialogue.
|
||||
else if (!contentType.startsWith("image")) {
|
||||
String accept = request.getHeader("Accept");
|
||||
disposition = accept != null && accepts(accept, contentType) ? "inline" : "attachment";
|
||||
}
|
||||
|
||||
// Initialize response.
|
||||
response.reset();
|
||||
response.setBufferSize(DEFAULT_BUFFER_SIZE);
|
||||
response.setHeader("Content-Disposition", disposition + ";filename=\"" + fileName + "\"");
|
||||
response.setHeader("Accept-Ranges", "bytes");
|
||||
response.setHeader("ETag", eTag);
|
||||
response.setDateHeader("Last-Modified", lastModified);
|
||||
|
||||
|
||||
// Send requested file (part(s)) to client ------------------------------------------------
|
||||
|
||||
// Prepare streams.
|
||||
RandomAccessFile input = null;
|
||||
OutputStream output = null;
|
||||
|
||||
try {
|
||||
// Open streams.
|
||||
input = new RandomAccessFile(file, "r");
|
||||
output = response.getOutputStream();
|
||||
|
||||
if (ranges.isEmpty() || ranges.get(0) == full) {
|
||||
|
||||
// Return full file.
|
||||
Range r = full;
|
||||
response.setContentType(contentType);
|
||||
response.setHeader("Content-Range", "bytes " + r.start + "-" + r.end + "/" + r.total);
|
||||
|
||||
if (content) {
|
||||
if (acceptsGzip) {
|
||||
// The browser accepts GZIP, so GZIP the content.
|
||||
response.setHeader("Content-Encoding", "gzip");
|
||||
output = new GZIPOutputStream(output, DEFAULT_BUFFER_SIZE);
|
||||
} else {
|
||||
// Content length is not directly predictable in case of GZIP.
|
||||
// So only add it if there is no means of GZIP, else browser will hang.
|
||||
response.setHeader("Content-Length", String.valueOf(r.length));
|
||||
}
|
||||
|
||||
// Copy full range.
|
||||
copy(input, output, r.start, r.length);
|
||||
}
|
||||
|
||||
} else if (ranges.size() == 1) {
|
||||
|
||||
// Return single part of file.
|
||||
Range r = ranges.get(0);
|
||||
response.setContentType(contentType);
|
||||
response.setHeader("Content-Range", "bytes " + r.start + "-" + r.end + "/" + r.total);
|
||||
response.setHeader("Content-Length", String.valueOf(r.length));
|
||||
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); // 206.
|
||||
|
||||
if (content) {
|
||||
// Copy single part range.
|
||||
copy(input, output, r.start, r.length);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Return multiple parts of file.
|
||||
response.setContentType("multipart/byteranges; boundary=" + MULTIPART_BOUNDARY);
|
||||
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); // 206.
|
||||
|
||||
if (content) {
|
||||
// Cast back to ServletOutputStream to get the easy println methods.
|
||||
ServletOutputStream sos = (ServletOutputStream) output;
|
||||
|
||||
// Copy multi part range.
|
||||
for (Range r : ranges) {
|
||||
// Add multipart boundary and header fields for every range.
|
||||
sos.println();
|
||||
sos.println("--" + MULTIPART_BOUNDARY);
|
||||
sos.println("Content-Type: " + contentType);
|
||||
sos.println("Content-Range: bytes " + r.start + "-" + r.end + "/" + r.total);
|
||||
|
||||
// Copy single part range of multi part range.
|
||||
copy(input, output, r.start, r.length);
|
||||
}
|
||||
|
||||
// End with multipart boundary.
|
||||
sos.println();
|
||||
sos.println("--" + MULTIPART_BOUNDARY + "--");
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// Gently close streams.
|
||||
close(output);
|
||||
close(input);
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers (can be refactored to public utility class) ----------------------------------------
|
||||
|
||||
|
||||
final static Map<String, String> mimeTypes = new HashMap<String, String>() {{
|
||||
this.put(".html", "text/html");
|
||||
this.put(".htm", "text/html");
|
||||
this.put(".js", "text/javascript");
|
||||
this.put(".png", "image/png");
|
||||
this.put(".jpg", "image/jpeg");
|
||||
this.put(".css", "text/css");
|
||||
this.put(".txt", "text/plain");
|
||||
}};
|
||||
public String getContentType(String fileName) {
|
||||
// Don't use getServetContext!
|
||||
/*String contentType = getServletContext().getMimeType(fileName);
|
||||
*/
|
||||
String contentType = null;
|
||||
int i = fileName.lastIndexOf('.');
|
||||
if (i >= 0) {
|
||||
String extension = fileName.substring(i);
|
||||
contentType = mimeTypes.get(extension);
|
||||
}
|
||||
|
||||
if (contentType == null) {
|
||||
contentType = "application/octet-stream";
|
||||
}
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given accept header accepts the given value.
|
||||
* @param acceptHeader The accept header.
|
||||
* @param toAccept The value to be accepted.
|
||||
* @return True if the given accept header accepts the given value.
|
||||
*/
|
||||
private static boolean accepts(String acceptHeader, String toAccept) {
|
||||
String[] acceptValues = acceptHeader.split("\\s*(,|;)\\s*");
|
||||
Arrays.sort(acceptValues);
|
||||
return Arrays.binarySearch(acceptValues, toAccept) > -1
|
||||
|| Arrays.binarySearch(acceptValues, toAccept.replaceAll("/.*$", "/*")) > -1
|
||||
|| Arrays.binarySearch(acceptValues, "*/*") > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given match header matches the given value.
|
||||
* @param matchHeader The match header.
|
||||
* @param toMatch The value to be matched.
|
||||
* @return True if the given match header matches the given value.
|
||||
*/
|
||||
private static boolean matches(String matchHeader, String toMatch) {
|
||||
String[] matchValues = matchHeader.split("\\s*,\\s*");
|
||||
Arrays.sort(matchValues);
|
||||
return Arrays.binarySearch(matchValues, toMatch) > -1
|
||||
|| Arrays.binarySearch(matchValues, "*") > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a substring of the given string value from the given begin index to the given end
|
||||
* index as a long. If the substring is empty, then -1 will be returned
|
||||
* @param value The string value to return a substring as long for.
|
||||
* @param beginIndex The begin index of the substring to be returned as long.
|
||||
* @param endIndex The end index of the substring to be returned as long.
|
||||
* @return A substring of the given string value as long or -1 if substring is empty.
|
||||
*/
|
||||
private static long sublong(String value, int beginIndex, int endIndex) {
|
||||
String substring = value.substring(beginIndex, endIndex);
|
||||
return (substring.length() > 0) ? Long.parseLong(substring) : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the given byte range of the given input to the given output.
|
||||
* @param input The input to copy the given range to the given output for.
|
||||
* @param output The output to copy the given range from the given input for.
|
||||
* @param start Start of the byte range.
|
||||
* @param length Length of the byte range.
|
||||
* @throws IOException If something fails at I/O level.
|
||||
*/
|
||||
private static void copy(RandomAccessFile input, OutputStream output, long start, long length)
|
||||
throws IOException
|
||||
{
|
||||
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
|
||||
int read;
|
||||
|
||||
if (input.length() == length) {
|
||||
// Write full range.
|
||||
while ((read = input.read(buffer)) > 0) {
|
||||
output.write(buffer, 0, read);
|
||||
}
|
||||
} else {
|
||||
// Write partial range.
|
||||
input.seek(start);
|
||||
long toRead = length;
|
||||
|
||||
while ((read = input.read(buffer)) > 0) {
|
||||
if ((toRead -= read) > 0) {
|
||||
output.write(buffer, 0, read);
|
||||
} else {
|
||||
output.write(buffer, 0, (int) toRead + read);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the given resource.
|
||||
* @param resource The resource to be closed.
|
||||
*/
|
||||
private static void close(Closeable resource) {
|
||||
if (resource != null) {
|
||||
try {
|
||||
resource.close();
|
||||
} catch (IOException ignore) {
|
||||
// Ignore IOException. If you want to handle this anyway, it might be useful to know
|
||||
// that this will generally only be thrown when the client aborted the request.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inner classes ------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* This class represents a byte range.
|
||||
*/
|
||||
protected class Range {
|
||||
long start;
|
||||
long end;
|
||||
long length;
|
||||
long total;
|
||||
|
||||
/**
|
||||
* Construct a byte range.
|
||||
* @param start Start of the byte range.
|
||||
* @param end End of the byte range.
|
||||
* @param total Total length of the byte source.
|
||||
*/
|
||||
public Range(long start, long end, long total) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.length = end - start + 1;
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,17 +0,0 @@
|
||||
package org.dynmap.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.json.simple.JSONStreamAware;
|
||||
|
||||
public class JSONServlet {
|
||||
public static void respond(HttpServletResponse response, JSONStreamAware json) throws IOException {
|
||||
response.setContentType("application/json");
|
||||
PrintWriter writer = response.getWriter();
|
||||
json.writeJSONString(writer);
|
||||
writer.close();
|
||||
}
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
package org.dynmap.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class MainServlet extends HttpServlet {
|
||||
public static class Header {
|
||||
public String name;
|
||||
public String value;
|
||||
public Header(String name, String value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Registration {
|
||||
public String pattern;
|
||||
public HttpServlet servlet;
|
||||
|
||||
public Registration(String pattern, HttpServlet servlet) {
|
||||
this.pattern = pattern;
|
||||
this.servlet = servlet;
|
||||
}
|
||||
}
|
||||
|
||||
List<Registration> registrations = new LinkedList<Registration>();
|
||||
public List<Header> customHeaders = new LinkedList<Header>();
|
||||
|
||||
public void addServlet(String pattern, HttpServlet servlet) {
|
||||
registrations.add(new Registration(pattern, servlet));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
HashMap<String, Object> properties = new HashMap<String, Object>();
|
||||
String path = req.getPathInfo();
|
||||
|
||||
for(Header header : customHeaders) {
|
||||
resp.setHeader(header.name, header.value);
|
||||
}
|
||||
|
||||
Registration bestMatch = null;
|
||||
String bestMatchPart = null;
|
||||
HashMap<String, Object> bestProperties = null;
|
||||
|
||||
for (Registration r : registrations) {
|
||||
String matchingPart = match(r.pattern, path, properties);
|
||||
if (matchingPart != null) {
|
||||
if (bestMatchPart == null || bestMatchPart.length() < matchingPart.length()) {
|
||||
bestMatch = r;
|
||||
bestMatchPart = matchingPart;
|
||||
bestProperties = properties;
|
||||
properties = new HashMap<String, Object>();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestMatch == null) {
|
||||
resp.sendError(404);
|
||||
} else {
|
||||
String leftOverPath = path.substring(bestMatchPart.length());
|
||||
HttpServletRequest newreq = new RequestWrapper(req, leftOverPath);
|
||||
for(String key : bestProperties.keySet()) {
|
||||
newreq.setAttribute(key, bestProperties.get(key));
|
||||
}
|
||||
bestMatch.servlet.service(newreq, resp);
|
||||
}
|
||||
}
|
||||
|
||||
public String match(String pattern, String path, Map<String, Object> properties) {
|
||||
int patternStart = 0;
|
||||
int pathStart = 0;
|
||||
while (patternStart < pattern.length()) {
|
||||
if (pattern.charAt(patternStart) == '{') {
|
||||
// Found a variable.
|
||||
int endOfVariable = pattern.indexOf('}', patternStart+1);
|
||||
String variableName = pattern.substring(patternStart+1, endOfVariable);
|
||||
|
||||
int endOfSection = indexOfAny(path, new char[] { '/', '?' }, pathStart);
|
||||
if (endOfSection < 0) {
|
||||
endOfSection = path.length();
|
||||
}
|
||||
String variableValue = path.substring(pathStart, endOfSection);
|
||||
|
||||
// Store variable.
|
||||
properties.put(variableName, variableValue);
|
||||
|
||||
patternStart = endOfVariable+1;
|
||||
pathStart = endOfSection;
|
||||
} else {
|
||||
int endOfLiteral = pattern.indexOf('{', patternStart);
|
||||
if (endOfLiteral < 0) {
|
||||
endOfLiteral = pattern.length();
|
||||
}
|
||||
String literal = pattern.substring(patternStart, endOfLiteral);
|
||||
int endOfPathLiteral = pathStart + literal.length();
|
||||
if (endOfPathLiteral > path.length()) {
|
||||
return null;
|
||||
}
|
||||
String matchingLiteral = path.substring(pathStart, endOfPathLiteral);
|
||||
if (!literal.equals(matchingLiteral)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
patternStart = endOfLiteral;
|
||||
pathStart = endOfPathLiteral;
|
||||
}
|
||||
}
|
||||
// Return the part of the url that matches the pattern. (if the pattern does not contain any variables, this will be equal to the pattern)
|
||||
return path.substring(0, pathStart);
|
||||
}
|
||||
|
||||
private int indexOfAny(String s, char[] cs, int startIndex) {
|
||||
for(int i = startIndex; i < s.length(); i++) {
|
||||
char c = s.charAt(i);
|
||||
for(int j = 0; j < cs.length; j++) {
|
||||
if (c == cs[j]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
class RequestWrapper extends HttpServletRequestWrapper {
|
||||
String pathInfo;
|
||||
public RequestWrapper(HttpServletRequest request, String pathInfo) {
|
||||
super(request);
|
||||
this.pathInfo = pathInfo;
|
||||
}
|
||||
@Override
|
||||
public String getPathInfo() {
|
||||
return pathInfo;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,148 +0,0 @@
|
||||
package org.dynmap.servlet;
|
||||
|
||||
import org.dynmap.DynmapCore;
|
||||
import org.dynmap.Event;
|
||||
import org.dynmap.Log;
|
||||
import org.dynmap.web.HttpStatus;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class SendMessageServlet extends HttpServlet {
|
||||
protected static final Logger log = Logger.getLogger("Minecraft");
|
||||
|
||||
private static final JSONParser parser = new JSONParser();
|
||||
public Event<Message> onMessageReceived = new Event<Message>();
|
||||
private Charset cs_utf8 = Charset.forName("UTF-8");
|
||||
public int maximumMessageInterval = 1000;
|
||||
public boolean hideip = false;
|
||||
public boolean trustclientname = false;
|
||||
|
||||
public String spamMessage = "\"You may only chat once every %interval% seconds.\"";
|
||||
private HashMap<String, WebUser> disallowedUsers = new HashMap<String, WebUser>();
|
||||
private LinkedList<WebUser> disallowedUserQueue = new LinkedList<WebUser>();
|
||||
private Object disallowedUsersLock = new Object();
|
||||
private HashMap<String,String> useralias = new HashMap<String,String>();
|
||||
private int aliasindex = 1;
|
||||
public boolean use_player_login_ip = false;
|
||||
public boolean require_player_login_ip = false;
|
||||
public boolean check_user_ban = false;
|
||||
public DynmapCore core;
|
||||
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
InputStreamReader reader = new InputStreamReader(request.getInputStream(), cs_utf8);
|
||||
|
||||
JSONObject o = null;
|
||||
try {
|
||||
o = (JSONObject)parser.parse(reader);
|
||||
} catch (ParseException e) {
|
||||
response.sendError(HttpStatus.BadRequest.getCode());
|
||||
return;
|
||||
}
|
||||
|
||||
final Message message = new Message();
|
||||
|
||||
message.name = "";
|
||||
if(trustclientname) {
|
||||
message.name = String.valueOf(o.get("name"));
|
||||
}
|
||||
boolean isip = true;
|
||||
if((message.name == null) || message.name.equals("")) {
|
||||
/* If proxied client address, get original */
|
||||
if(request.getHeader("X-Forwarded-For") != null)
|
||||
message.name = request.getHeader("X-Forwarded-For");
|
||||
/* If from loopback, we're probably getting from proxy - need to trust client */
|
||||
else if(request.getRemoteAddr() == "127.0.0.1")
|
||||
message.name = String.valueOf(o.get("name"));
|
||||
else
|
||||
message.name = request.getRemoteAddr();
|
||||
}
|
||||
if (use_player_login_ip) {
|
||||
List<String> ids = core.getIDsForIP(message.name);
|
||||
if (ids != null) {
|
||||
String id = ids.get(0);
|
||||
if (check_user_ban) {
|
||||
if (core.getServer().isPlayerBanned(id)) {
|
||||
Log.info("Ignore message from '" + message.name + "' - banned player (" + id + ")");
|
||||
response.sendError(HttpStatus.Forbidden.getCode());
|
||||
return;
|
||||
}
|
||||
}
|
||||
message.name = ids.get(0);
|
||||
isip = false;
|
||||
} else if (require_player_login_ip) {
|
||||
Log.info("Ignore message from '" + message.name + "' - no matching player login recorded");
|
||||
response.sendError(HttpStatus.Forbidden.getCode());
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (hideip && isip) { /* If hiding IP, find or assign alias */
|
||||
synchronized (disallowedUsersLock) {
|
||||
String n = useralias.get(message.name);
|
||||
if (n == null) { /* Make ID */
|
||||
n = String.format("web-%03d", aliasindex);
|
||||
aliasindex++;
|
||||
useralias.put(message.name, n);
|
||||
}
|
||||
message.name = n;
|
||||
}
|
||||
}
|
||||
message.message = String.valueOf(o.get("message"));
|
||||
|
||||
final long now = System.currentTimeMillis();
|
||||
|
||||
synchronized (disallowedUsersLock) {
|
||||
// Allow users that user that are now allowed to send messages.
|
||||
while (!disallowedUserQueue.isEmpty()) {
|
||||
WebUser wu = disallowedUserQueue.getFirst();
|
||||
if (now >= wu.nextMessageTime) {
|
||||
disallowedUserQueue.remove();
|
||||
disallowedUsers.remove(wu.name);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WebUser user = disallowedUsers.get(message.name);
|
||||
if (user == null) {
|
||||
user = new WebUser() {
|
||||
{
|
||||
name = message.name;
|
||||
nextMessageTime = now + maximumMessageInterval;
|
||||
}
|
||||
};
|
||||
disallowedUsers.put(user.name, user);
|
||||
disallowedUserQueue.add(user);
|
||||
} else {
|
||||
response.sendError(HttpStatus.Forbidden.getCode());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
onMessageReceived.trigger(message);
|
||||
}
|
||||
|
||||
public static class Message {
|
||||
public String name;
|
||||
public String message;
|
||||
}
|
||||
public static class WebUser {
|
||||
public long nextMessageTime;
|
||||
public String name;
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
package org.dynmap.utils;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class DynmapBufferedImage {
|
||||
public BufferedImage buf_img;
|
||||
public int[] argb_buf;
|
||||
public int width;
|
||||
public int height;
|
||||
|
||||
/* BufferedImage cache - we use the same things a lot... */
|
||||
private static Object lock = new Object();
|
||||
private static HashMap<Long, LinkedList<DynmapBufferedImage>> imgcache =
|
||||
new HashMap<Long, LinkedList<DynmapBufferedImage>>(); /* Indexed by resolution - X<<32+Y */
|
||||
private static final int CACHE_LIMIT = 10;
|
||||
|
||||
/**
|
||||
* Allocate buffered image from pool, if possible
|
||||
* @param x - x dimension
|
||||
* @param y - y dimension
|
||||
*/
|
||||
public static DynmapBufferedImage allocateBufferedImage(int x, int y) {
|
||||
DynmapBufferedImage img = null;
|
||||
synchronized(lock) {
|
||||
long k = (x<<16) + y;
|
||||
LinkedList<DynmapBufferedImage> ll = imgcache.get(k);
|
||||
if(ll != null) {
|
||||
img = ll.poll();
|
||||
}
|
||||
}
|
||||
if(img != null) { /* Got it - reset it for use */
|
||||
Arrays.fill(img.argb_buf, 0);
|
||||
}
|
||||
else {
|
||||
img = new DynmapBufferedImage();
|
||||
img.width = x;
|
||||
img.height = y;
|
||||
img.argb_buf = new int[x*y];
|
||||
}
|
||||
img.buf_img = createBufferedImage(img.argb_buf, img.width, img.height);
|
||||
return img;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return buffered image to pool
|
||||
*/
|
||||
public static void freeBufferedImage(DynmapBufferedImage img) {
|
||||
img.buf_img.flush();
|
||||
img.buf_img = null; /* Toss bufferedimage - seems to hold on to other memory */
|
||||
synchronized(lock) {
|
||||
long k = (img.width<<16) + img.height;
|
||||
LinkedList<DynmapBufferedImage> ll = imgcache.get(k);
|
||||
if(ll == null) {
|
||||
ll = new LinkedList<DynmapBufferedImage>();
|
||||
imgcache.put(k, ll);
|
||||
}
|
||||
if(ll.size() < CACHE_LIMIT) {
|
||||
ll.add(img);
|
||||
img = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ARGB band masks */
|
||||
private static final int [] band_masks = {0xFF0000, 0xFF00, 0xff, 0xff000000};
|
||||
|
||||
/**
|
||||
* Build BufferedImage from provided ARGB array and dimensions
|
||||
*/
|
||||
public static BufferedImage createBufferedImage(int[] argb_buf, int w, int h) {
|
||||
/* Create integer-base data buffer */
|
||||
DataBuffer db = new DataBufferInt (argb_buf, w*h);
|
||||
/* Create writable raster */
|
||||
WritableRaster raster = Raster.createPackedRaster(db, w, h, w, band_masks, null);
|
||||
/* RGB color model */
|
||||
ColorModel color_model = ColorModel.getRGBdefault ();
|
||||
/* Return buffered image */
|
||||
return new BufferedImage (color_model, raster, false, null);
|
||||
}
|
||||
}
|
@ -1,227 +0,0 @@
|
||||
package org.dynmap.utils;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DirectColorModel;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.IIOImage;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageWriteParam;
|
||||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
|
||||
import org.dynmap.Log;
|
||||
import org.dynmap.MapType.ImageFormat;
|
||||
import org.dynmap.debug.Debug;
|
||||
/**
|
||||
* Implements soft-locks for prevent concurrency issues with file updates
|
||||
*/
|
||||
public class FileLockManager {
|
||||
private static Object lock = new Object();
|
||||
private static HashMap<String, Integer> filelocks = new HashMap<String, Integer>();
|
||||
private static final Integer WRITELOCK = new Integer(-1);
|
||||
/**
|
||||
* Get write lock on file - exclusive lock, no other writers or readers
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public static boolean getWriteLock(File f) {
|
||||
String fn = f.getPath();
|
||||
synchronized(lock) {
|
||||
boolean got_lock = false;
|
||||
while(!got_lock) {
|
||||
Integer lockcnt = filelocks.get(fn); /* Get lock count */
|
||||
if(lockcnt != null) { /* If any locks, can't get write lock */
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (InterruptedException ix) {
|
||||
Log.severe("getWriteLock(" + fn + ") interrupted");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
filelocks.put(fn, WRITELOCK);
|
||||
got_lock = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Log.info("getWriteLock(" + f + ")");
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Release write lock
|
||||
*/
|
||||
public static void releaseWriteLock(File f) {
|
||||
String fn = f.getPath();
|
||||
synchronized(lock) {
|
||||
Integer lockcnt = filelocks.get(fn); /* Get lock count */
|
||||
if(lockcnt == null)
|
||||
Log.severe("releaseWriteLock(" + fn + ") on unlocked file");
|
||||
else if(lockcnt.equals(WRITELOCK)) {
|
||||
filelocks.remove(fn); /* Remove lock */
|
||||
lock.notifyAll(); /* Wake up folks waiting for locks */
|
||||
}
|
||||
else
|
||||
Log.severe("releaseWriteLock(" + fn + ") on read-locked file");
|
||||
}
|
||||
//Log.info("releaseWriteLock(" + f + ")");
|
||||
}
|
||||
/**
|
||||
* Get read lock on file - multiple readers allowed, blocks writers
|
||||
*/
|
||||
public static boolean getReadLock(File f) {
|
||||
return getReadLock(f, -1);
|
||||
}
|
||||
/**
|
||||
* Get read lock on file - multiple readers allowed, blocks writers - with timeout (msec)
|
||||
*/
|
||||
public static boolean getReadLock(File f, long timeout) {
|
||||
String fn = f.getPath();
|
||||
synchronized(lock) {
|
||||
boolean got_lock = false;
|
||||
long starttime = 0;
|
||||
if(timeout > 0)
|
||||
starttime = System.currentTimeMillis();
|
||||
while(!got_lock) {
|
||||
Integer lockcnt = filelocks.get(fn); /* Get lock count */
|
||||
if(lockcnt == null) {
|
||||
filelocks.put(fn, Integer.valueOf(1)); /* First lock */
|
||||
got_lock = true;
|
||||
}
|
||||
else if(!lockcnt.equals(WRITELOCK)) { /* Other read locks */
|
||||
filelocks.put(fn, Integer.valueOf(lockcnt+1));
|
||||
got_lock = true;
|
||||
}
|
||||
else { /* Write lock in place */
|
||||
try {
|
||||
if(timeout < 0) {
|
||||
lock.wait();
|
||||
}
|
||||
else {
|
||||
long now = System.currentTimeMillis();
|
||||
long elapsed = now-starttime;
|
||||
if(elapsed > timeout) /* Give up on timeout */
|
||||
return false;
|
||||
lock.wait(timeout-elapsed);
|
||||
}
|
||||
} catch (InterruptedException ix) {
|
||||
Log.severe("getReadLock(" + fn + ") interrupted");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//Log.info("getReadLock(" + f + ")");
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Release read lock
|
||||
*/
|
||||
public static void releaseReadLock(File f) {
|
||||
String fn = f.getPath();
|
||||
synchronized(lock) {
|
||||
Integer lockcnt = filelocks.get(fn); /* Get lock count */
|
||||
if(lockcnt == null)
|
||||
Log.severe("releaseReadLock(" + fn + ") on unlocked file");
|
||||
else if(lockcnt.equals(WRITELOCK))
|
||||
Log.severe("releaseReadLock(" + fn + ") on write-locked file");
|
||||
else if(lockcnt > 1) {
|
||||
filelocks.put(fn, Integer.valueOf(lockcnt-1));
|
||||
}
|
||||
else {
|
||||
filelocks.remove(fn); /* Remove lock */
|
||||
lock.notifyAll(); /* Wake up folks waiting for locks */
|
||||
}
|
||||
}
|
||||
//Log.info("releaseReadLock(" + f + ")");
|
||||
}
|
||||
private static final int MAX_WRITE_RETRIES = 6;
|
||||
|
||||
private static LinkedList<ByteArrayOutputStream> baoslist = new LinkedList<ByteArrayOutputStream>();
|
||||
private static Object baos_lock = new Object();
|
||||
/**
|
||||
* Wrapper for IOImage.write - implements retries for busy files
|
||||
*/
|
||||
public static void imageIOWrite(BufferedImage img, ImageFormat fmt, File fname) throws IOException {
|
||||
int retrycnt = 0;
|
||||
boolean done = false;
|
||||
byte[] rslt;
|
||||
ByteArrayOutputStream baos;
|
||||
synchronized(baos_lock) {
|
||||
if(baoslist.isEmpty()) {
|
||||
baos = new ByteArrayOutputStream();
|
||||
}
|
||||
else {
|
||||
baos = baoslist.removeFirst();
|
||||
baos.reset();
|
||||
}
|
||||
}
|
||||
ImageIO.setUseCache(false); /* Don't use file cache - too small to be worth it */
|
||||
if(fmt.getFileExt().equals("jpg")) {
|
||||
WritableRaster raster = img.getRaster();
|
||||
WritableRaster newRaster = raster.createWritableChild(0, 0, img.getWidth(),
|
||||
img.getHeight(), 0, 0, new int[] {0, 1, 2});
|
||||
DirectColorModel cm = (DirectColorModel)img.getColorModel();
|
||||
DirectColorModel newCM = new DirectColorModel(cm.getPixelSize(),
|
||||
cm.getRedMask(), cm.getGreenMask(), cm.getBlueMask());
|
||||
// now create the new buffer that is used ot write the image:
|
||||
BufferedImage rgbBuffer = new BufferedImage(newCM, newRaster, false, null);
|
||||
|
||||
// Find a jpeg writer
|
||||
ImageWriter writer = null;
|
||||
Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName("jpg");
|
||||
if (iter.hasNext()) {
|
||||
writer = iter.next();
|
||||
}
|
||||
if(writer == null) {
|
||||
Log.severe("No JPEG ENCODER - Java VM does not support JPEG encoding");
|
||||
return;
|
||||
}
|
||||
ImageWriteParam iwp = writer.getDefaultWriteParam();
|
||||
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
||||
iwp.setCompressionQuality(fmt.getQuality());
|
||||
|
||||
ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
|
||||
writer.setOutput(ios);
|
||||
|
||||
writer.write(null, new IIOImage(rgbBuffer, null, null), iwp);
|
||||
writer.dispose();
|
||||
|
||||
rgbBuffer.flush();
|
||||
}
|
||||
else {
|
||||
ImageIO.write(img, fmt.getFileExt(), baos); /* Write to byte array stream - prevent bogus I/O errors */
|
||||
}
|
||||
rslt = baos.toByteArray();
|
||||
synchronized(baos_lock) {
|
||||
baoslist.addFirst(baos);
|
||||
}
|
||||
while(!done) {
|
||||
RandomAccessFile f = null;
|
||||
try {
|
||||
f = new RandomAccessFile(fname, "rw");
|
||||
f.write(rslt);
|
||||
done = true;
|
||||
} catch (IOException fnfx) {
|
||||
if(retrycnt < MAX_WRITE_RETRIES) {
|
||||
Debug.debug("Image file " + fname.getPath() + " - unable to write - retry #" + retrycnt);
|
||||
try { Thread.sleep(50 << retrycnt); } catch (InterruptedException ix) { throw fnfx; }
|
||||
retrycnt++;
|
||||
}
|
||||
else {
|
||||
Log.info("Image file " + fname.getPath() + " - unable to write - failed");
|
||||
throw fnfx;
|
||||
}
|
||||
} finally {
|
||||
if(f != null) {
|
||||
try { f.close(); } catch (IOException iox) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package org.dynmap.utils;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class LRULinkedHashMap<T, K> extends LinkedHashMap<T, K> {
|
||||
private int limit;
|
||||
public LRULinkedHashMap(int lim) {
|
||||
super(16, (float)0.75, true);
|
||||
limit = lim;
|
||||
}
|
||||
protected boolean removeEldestEntry(Map.Entry<T, K> last) {
|
||||
return(size() >= limit);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user