diff --git a/src/main/resources/colors.txt b/colorschemes/default.txt similarity index 97% rename from src/main/resources/colors.txt rename to colorschemes/default.txt index bc39be7d..dce3a714 100644 --- a/src/main/resources/colors.txt +++ b/colorschemes/default.txt @@ -1,175 +1,175 @@ -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 -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 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 -17 102 81 51 255 81 64 40 255 51 40 25 255 40 32 20 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 -Aqua Green Cloth -26 43 192 117 255 38 168 101 255 34 150 90 255 29 130 78 255 -Cyan Cloth -27 43 192 192 255 36 185 185 255 29 130 130 255 22 99 99 255 -Blue Cloth -28 0 0 255 255 0 0 204 255 0 0 127 255 0 0 102 255 -Purple Cloth -29 101 101 188 255 95 95 175 255 86 86 160 255 78 78 145 255 -Indigo Cloth -30 113 41 186 255 99 38 165 255 85 32 142 255 72 27 119 255 -Violet Cloth -31 156 65 198 255 132 55 168 255 112 47 142 255 84 35 107 255 -Magenta Cloth -32 187 42 187 255 160 36 160 255 135 31 135 255 112 25 112 255 -Pink Cloth -33 192 43 117 255 168 38 103 255 142 32 87 255 127 29 78 255 -Black Cloth -34 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 -Wool -35 222 222 222 255 177 177 177 255 111 111 111 255 88 88 88 255 -Gray Cloth -36 125 125 125 255 114 114 114 255 104 104 104 255 86 86 86 255 -Yellow Flower -37 255 255 0 255 204 204 0 255 127 127 0 255 102 102 0 255 -Red Rose -38 255 0 0 255 204 0 0 255 127 0 0 255 102 0 0 255 -Brown Mushroom -39 204 153 120 32 145 109 85 32 114 86 67 32 73 64 58 32 -Red Mushroom -40 255 43 43 32 196 29 38 32 186 105 109 32 124 64 64 32 -Gold Block -41 232 245 46 255 185 196 36 255 116 122 23 255 92 98 18 255 -Iron Block -42 191 191 191 255 152 152 152 255 95 95 95 255 76 76 76 255 -Double Stone Slab -43 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255 -Stone Slab -44 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255 -Brick -45 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255 -TNT -46 160 83 65 255 128 66 52 255 80 41 32 255 64 33 26 255 -Bookshelf -54 125 91 38 192 100 72 30 192 62 45 19 192 50 36 15 192 -Moss Stone -48 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255 -Obsidian -49 26 11 43 255 20 8 34 255 13 5 21 255 10 4 17 255 -Torch -50 159 127 80 255 98 88 20 0 245 220 50 255 196 176 40 0 -Fire -51 255 170 30 200 204 136 24 200 127 85 15 200 102 68 12 200 -Monster Spawner -52 0 150 110 196 0 150 130 196 0 150 110 196 0 150 130 196 -Wooden Stair -53 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255 -Chest -54 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255 - -Diamond Ore -56 129 140 143 255 103 112 114 255 64 70 71 255 51 56 57 255 -Diamond Block -57 45 166 152 255 36 132 121 255 22 83 76 255 18 66 60 255 -Workbench -58 114 88 56 255 91 70 44 255 57 44 28 255 45 35 22 255 -Crops -59 146 192 0 255 116 153 0 255 73 96 0 255 58 76 0 255 -Farmland -60 95 58 30 255 76 46 24 255 47 29 15 255 38 23 12 255 -Furnace -61 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255 -Burning Furnace -62 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255 -Sign Post -63 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255 -Wooden Door -64 136 109 67 255 108 87 53 255 68 54 33 255 54 43 26 255 -Ladder -65 181 140 64 32 144 112 51 32 90 70 32 32 72 56 25 32 -Minecart Tracks -66 150 134 102 180 120 107 81 180 75 67 51 180 60 53 40 180 -Cobblestone Stairs -67 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255 - -Iron Door -71 191 191 191 255 152 152 152 255 95 95 95 255 76 76 76 255 - -Redstone Ore -73 131 107 107 255 104 85 85 255 65 53 53 255 52 42 42 255 -Glowing Redstone Ore -74 131 107 107 255 104 85 85 255 65 53 53 255 52 42 42 255 -Redstone Torch off -75 159 127 80 255 72 56 25 0 181 140 64 255 144 112 51 0 -Redstone Torch on -76 159 127 80 255 102 0 0 0 255 0 0 255 204 0 0 0 -Snow -78 255 255 255 255 204 204 204 255 127 127 127 255 102 102 102 255 -Ice -79 83 113 163 51 66 90 130 51 41 56 81 51 33 45 65 51 -Snow Block -80 250 250 250 255 200 200 200 255 125 125 125 255 100 100 100 255 -Cactus -81 25 120 25 255 20 96 20 255 12 60 12 255 10 48 10 255 -Clay -82 151 157 169 255 120 125 135 255 75 78 84 255 60 62 67 255 -Sugar Cane -83 193 234 150 255 154 187 120 255 96 117 75 255 77 93 60 255 -Jukebox -84 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255 -Fence -85 127 98 49 96 95 72 33 96 48 34 9 96 32 21 21 96 -Pumpkin -86 255 115 0 200 204 92 0 200 126 57 0 200 102 46 0 200 -Netherrack -87 166 89 89 255 141 80 62 255 135 15 15 255 96 6 6 255 -Soulsand -88 133 109 94 255 121 97 82 255 90 70 57 255 79 59 46 255 -Glowstone -89 249 212 156 255 255 188 94 255 192 143 70 255 122 91 44 255 -Portal -90 140 0 196 128 120 0 196 128 140 0 196 128 120 0 196 128 -Jack-o-lantern -91 255 115 0 255 204 92 0 255 126 57 0 255 102 46 0 255 -Cake Block -92 234 234 234 255 210 210 210 255 203 203 203 255 190 190 190 255 +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 +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 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 +17 102 81 51 255 81 64 40 255 51 40 25 255 40 32 20 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 +Aqua Green Cloth +26 43 192 117 255 38 168 101 255 34 150 90 255 29 130 78 255 +Cyan Cloth +27 43 192 192 255 36 185 185 255 29 130 130 255 22 99 99 255 +Blue Cloth +28 0 0 255 255 0 0 204 255 0 0 127 255 0 0 102 255 +Purple Cloth +29 101 101 188 255 95 95 175 255 86 86 160 255 78 78 145 255 +Indigo Cloth +30 113 41 186 255 99 38 165 255 85 32 142 255 72 27 119 255 +Violet Cloth +31 156 65 198 255 132 55 168 255 112 47 142 255 84 35 107 255 +Magenta Cloth +32 187 42 187 255 160 36 160 255 135 31 135 255 112 25 112 255 +Pink Cloth +33 192 43 117 255 168 38 103 255 142 32 87 255 127 29 78 255 +Black Cloth +34 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 +Wool +35 222 222 222 255 177 177 177 255 111 111 111 255 88 88 88 255 +Gray Cloth +36 125 125 125 255 114 114 114 255 104 104 104 255 86 86 86 255 +Yellow Flower +37 255 255 0 255 204 204 0 255 127 127 0 255 102 102 0 255 +Red Rose +38 255 0 0 255 204 0 0 255 127 0 0 255 102 0 0 255 +Brown Mushroom +39 204 153 120 32 145 109 85 32 114 86 67 32 73 64 58 32 +Red Mushroom +40 255 43 43 32 196 29 38 32 186 105 109 32 124 64 64 32 +Gold Block +41 232 245 46 255 185 196 36 255 116 122 23 255 92 98 18 255 +Iron Block +42 191 191 191 255 152 152 152 255 95 95 95 255 76 76 76 255 +Double Stone Slab +43 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255 +Stone Slab +44 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255 +Brick +45 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255 +TNT +46 160 83 65 255 128 66 52 255 80 41 32 255 64 33 26 255 +Bookshelf +54 125 91 38 192 100 72 30 192 62 45 19 192 50 36 15 192 +Moss Stone +48 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255 +Obsidian +49 26 11 43 255 20 8 34 255 13 5 21 255 10 4 17 255 +Torch +50 159 127 80 255 98 88 20 0 245 220 50 255 196 176 40 0 +Fire +51 255 170 30 200 204 136 24 200 127 85 15 200 102 68 12 200 +Monster Spawner +52 0 150 110 196 0 150 130 196 0 150 110 196 0 150 130 196 +Wooden Stair +53 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255 +Chest +54 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255 + +Diamond Ore +56 129 140 143 255 103 112 114 255 64 70 71 255 51 56 57 255 +Diamond Block +57 45 166 152 255 36 132 121 255 22 83 76 255 18 66 60 255 +Workbench +58 114 88 56 255 91 70 44 255 57 44 28 255 45 35 22 255 +Crops +59 146 192 0 255 116 153 0 255 73 96 0 255 58 76 0 255 +Farmland +60 95 58 30 255 76 46 24 255 47 29 15 255 38 23 12 255 +Furnace +61 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255 +Burning Furnace +62 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255 +Sign Post +63 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255 +Wooden Door +64 136 109 67 255 108 87 53 255 68 54 33 255 54 43 26 255 +Ladder +65 181 140 64 32 144 112 51 32 90 70 32 32 72 56 25 32 +Minecart Tracks +66 150 134 102 180 120 107 81 180 75 67 51 180 60 53 40 180 +Cobblestone Stairs +67 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255 + +Iron Door +71 191 191 191 255 152 152 152 255 95 95 95 255 76 76 76 255 + +Redstone Ore +73 131 107 107 255 104 85 85 255 65 53 53 255 52 42 42 255 +Glowing Redstone Ore +74 131 107 107 255 104 85 85 255 65 53 53 255 52 42 42 255 +Redstone Torch off +75 159 127 80 255 72 56 25 0 181 140 64 255 144 112 51 0 +Redstone Torch on +76 159 127 80 255 102 0 0 0 255 0 0 255 204 0 0 0 +Snow +78 255 255 255 255 204 204 204 255 127 127 127 255 102 102 102 255 +Ice +79 83 113 163 51 66 90 130 51 41 56 81 51 33 45 65 51 +Snow Block +80 250 250 250 255 200 200 200 255 125 125 125 255 100 100 100 255 +Cactus +81 25 120 25 255 20 96 20 255 12 60 12 255 10 48 10 255 +Clay +82 151 157 169 255 120 125 135 255 75 78 84 255 60 62 67 255 +Sugar Cane +83 193 234 150 255 154 187 120 255 96 117 75 255 77 93 60 255 +Jukebox +84 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255 +Fence +85 127 98 49 96 95 72 33 96 48 34 9 96 32 21 21 96 +Pumpkin +86 255 115 0 200 204 92 0 200 126 57 0 200 102 46 0 200 +Netherrack +87 166 89 89 255 141 80 62 255 135 15 15 255 96 6 6 255 +Soulsand +88 133 109 94 255 121 97 82 255 90 70 57 255 79 59 46 255 +Glowstone +89 249 212 156 255 255 188 94 255 192 143 70 255 122 91 44 255 +Portal +90 140 0 196 128 120 0 196 128 140 0 196 128 120 0 196 128 +Jack-o-lantern +91 255 115 0 255 204 92 0 255 126 57 0 255 102 46 0 255 +Cake Block +92 234 234 234 255 210 210 210 255 203 203 203 255 190 190 190 255 diff --git a/colorschemes/ovocean.txt b/colorschemes/ovocean.txt new file mode 100644 index 00000000..794d8038 --- /dev/null +++ b/colorschemes/ovocean.txt @@ -0,0 +1,175 @@ +Stone +1 119 104 84 255 104 95 80 255 96 87 72 255 77 68 53 255 +Grass +2 75 156 43 255 56 117 32 255 35 104 10 255 32 82 0 255 +Dirt +3 134 96 67 255 107 76 53 255 67 48 33 255 68 49 33 255 +Cobblestone +4 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255 +Wooden Plank +5 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255 +Sappling +6 120 120 120 0 96 96 96 0 60 60 60 0 48 48 48 0 +Bedrock +7 84 84 84 255 67 67 67 255 42 42 42 255 33 33 33 255 +Water +8 21 88 125 80 7 70 117 80 6 68 115 80 5 53 90 80 +Stationary Water +9 21 88 125 80 7 70 117 80 6 68 115 80 5 53 90 80 +Lava +10 255 90 0 255 204 72 0 255 127 45 0 255 102 36 0 255 +Stationary Lava +11 255 90 0 255 204 72 0 255 127 45 0 255 102 36 0 255 +Sand +12 214 182 111 255 203 171 100 255 186 154 83 255 173 141 70 255 +Gravel +13 136 126 126 255 108 100 100 255 68 63 63 255 54 50 50 255 +Gold Ore +14 143 140 125 255 114 112 100 255 71 70 62 255 57 56 50 255 +Iron Ore +15 136 130 127 255 108 104 101 255 68 65 63 255 54 52 50 255 +Coal Ore +16 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255 +Wood +17 102 81 51 255 81 64 40 255 51 40 25 255 40 32 20 255 +Leaves +18 23 68 6 100 12 56 0 100 6 52 0 100 0 42 0 100 +Sponge +19 193 193 65 255 174 174 47 255 97 97 5 255 76 76 20 255 +Glass +20 255 255 255 64 204 204 204 64 127 127 127 64 102 102 102 64 +Lapis Lazuli Ore +21 23 68 196 255 18 56 158 255 14 43 122 255 14 43 78 255 +Lapis Lazuli Block +22 23 68 196 255 18 56 158 255 14 43 122 255 14 43 78 255 +Dispenser +23 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255 +Sandstone +24 214 182 111 255 203 171 100 255 186 154 83 255 173 141 70 255 +Note Block +25 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255 +Aqua Green Cloth +26 43 192 117 255 38 168 101 255 34 150 90 255 29 130 78 255 +Cyan Cloth +27 43 192 192 255 36 185 185 255 29 130 130 255 22 99 99 255 +Blue Cloth +28 0 0 255 255 0 0 204 255 0 0 127 255 0 0 102 255 +Purple Cloth +29 101 101 188 255 95 95 175 255 86 86 160 255 78 78 145 255 +Indigo Cloth +30 113 41 186 255 99 38 165 255 85 32 142 255 72 27 119 255 +Violet Cloth +31 156 65 198 255 132 55 168 255 112 47 142 255 84 35 107 255 +Magenta Cloth +32 187 42 187 255 160 36 160 255 135 31 135 255 112 25 112 255 +Pink Cloth +33 192 43 117 255 168 38 103 255 142 32 87 255 127 29 78 255 +Black Cloth +34 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 +Wool +35 222 222 222 255 177 177 177 255 111 111 111 255 88 88 88 255 +Gray Cloth +36 125 125 125 255 114 114 114 255 104 104 104 255 86 86 86 255 +Yellow Flower +37 255 255 0 255 204 204 0 255 127 127 0 255 102 102 0 255 +Red Rose +38 255 0 0 255 204 0 0 255 127 0 0 255 102 0 0 255 +Brown Mushroom +39 204 153 120 32 145 109 85 32 114 86 67 32 73 64 58 32 +Red Mushroom +40 255 43 43 32 196 29 38 32 186 105 109 32 124 64 64 32 +Gold Block +41 232 245 46 255 185 196 36 255 116 122 23 255 92 98 18 255 +Iron Block +42 191 191 191 255 152 152 152 255 95 95 95 255 76 76 76 255 +Double Stone Slab +43 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255 +Stone Slab +44 200 200 200 255 160 160 160 255 100 100 100 255 80 80 80 255 +Brick +45 170 86 62 255 136 68 49 255 85 43 31 255 68 34 24 255 +TNT +46 160 83 65 255 128 66 52 255 80 41 32 255 64 33 26 255 +Bookshelf +54 125 91 38 192 100 72 30 192 62 45 19 192 50 36 15 192 +Moss Stone +48 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255 +Obsidian +49 26 11 43 255 20 8 34 255 13 5 21 255 10 4 17 255 +Torch +50 159 127 80 255 98 88 20 0 245 220 50 255 196 176 40 0 +Fire +51 255 170 30 200 204 136 24 200 127 85 15 200 102 68 12 200 +Monster Spawner +52 0 150 110 196 0 150 130 196 0 150 110 196 0 150 130 196 +Wooden Stair +53 157 128 79 255 125 102 63 255 78 64 39 255 62 51 31 255 +Chest +54 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255 + +Diamond Ore +56 129 140 143 255 103 112 114 255 64 70 71 255 51 56 57 255 +Diamond Block +57 45 166 152 255 36 132 121 255 22 83 76 255 18 66 60 255 +Workbench +58 114 88 56 255 91 70 44 255 57 44 28 255 45 35 22 255 +Crops +59 146 192 0 255 116 153 0 255 73 96 0 255 58 76 0 255 +Farmland +60 95 58 30 255 76 46 24 255 47 29 15 255 38 23 12 255 +Furnace +61 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255 +Burning Furnace +62 96 96 96 255 76 76 76 255 48 48 48 255 38 38 38 255 +Sign Post +63 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255 +Wooden Door +64 136 109 67 255 108 87 53 255 68 54 33 255 54 43 26 255 +Ladder +65 181 140 64 32 144 112 51 32 90 70 32 32 72 56 25 32 +Minecart Tracks +66 150 134 102 180 120 107 81 180 75 67 51 180 60 53 40 180 +Cobblestone Stairs +67 115 115 115 255 92 92 92 255 57 57 57 255 46 46 46 255 + +Iron Door +71 191 191 191 255 152 152 152 255 95 95 95 255 76 76 76 255 + +Redstone Ore +73 131 107 107 255 104 85 85 255 65 53 53 255 52 42 42 255 +Glowing Redstone Ore +74 131 107 107 255 104 85 85 255 65 53 53 255 52 42 42 255 +Redstone Torch off +75 159 127 80 255 72 56 25 0 181 140 64 255 144 112 51 0 +Redstone Torch on +76 159 127 80 255 102 0 0 0 255 0 0 255 204 0 0 0 +Snow +78 255 255 255 255 204 204 204 255 127 127 127 255 102 102 102 255 +Ice +79 83 113 163 51 66 90 130 51 41 56 81 51 33 45 65 51 +Snow Block +80 250 250 250 255 200 200 200 255 125 125 125 255 100 100 100 255 +Cactus +81 25 120 25 255 20 96 20 255 12 60 12 255 10 48 10 255 +Clay +82 151 157 169 255 120 125 135 255 75 78 84 255 60 62 67 255 +Sugar Cane +83 193 234 150 255 154 187 120 255 96 117 75 255 77 93 60 255 +Jukebox +84 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255 +Fence +85 127 98 49 96 95 72 33 96 48 34 9 96 32 21 21 96 +Pumpkin +86 255 115 0 200 204 92 0 200 126 57 0 200 102 46 0 200 +Netherrack +87 166 89 89 255 141 80 62 255 135 15 15 255 96 6 6 255 +Soulsand +88 133 109 94 255 121 97 82 255 90 70 57 255 79 59 46 255 +Glowstone +89 249 212 156 255 255 188 94 255 192 143 70 255 122 91 44 255 +Portal +90 140 0 196 128 120 0 196 128 140 0 196 128 120 0 196 128 +Jack-o-lantern +91 255 115 0 255 204 92 0 255 126 57 0 255 102 46 0 255 +Cake Block +92 234 234 234 255 210 210 210 255 203 203 203 255 190 190 190 255 diff --git a/configuration.txt b/configuration.txt index 7c741dd5..10d54410 100755 --- a/configuration.txt +++ b/configuration.txt @@ -3,6 +3,14 @@ # How often a tile gets rendered (in seconds). renderinterval: 1 +render-triggers: +# - playermove +# - playerjoin + - blockplaced + - blockbreak +# - chunkgenerated +# - chunkloaded + # The path where the tile-files are placed. tilespath: web/tiles @@ -28,21 +36,29 @@ jsonfile-interval: 1 worlds: - name: world maps: + - class: org.dynmap.flat.FlatMap + prefix: flat + colorscheme: default - class: org.dynmap.kzedmap.KzedMap renderers: - class: org.dynmap.kzedmap.DefaultTileRenderer prefix: t maximumheight: 127 + colorscheme: default - class: org.dynmap.kzedmap.CaveTileRenderer prefix: ct maximumheight: 127 - name: nether maps: + - class: org.dynmap.flat.FlatMap + prefix: flat + colorscheme: default - class: org.dynmap.kzedmap.KzedMap renderers: - class: org.dynmap.kzedmap.DefaultTileRenderer prefix: nt maximumheight: 64 + colorscheme: default web: # Handles the clientside updates differently only enable if using jsonfile @@ -61,15 +77,15 @@ web: joinmessage: "%playername% joined" quitmessage: "%playername% quit" - # The clock that is shown alongside the map. - clock: timeofday - #clock: digital - defaultworld: world worlds: - title: World name: world maps: + - type: FlatMapType + title: Flat + name: flat + prefix: flat - type: KzedMapType title: Surface name: surface @@ -81,19 +97,23 @@ web: - title: Nether name: nether maps: + - type: FlatMapType + title: Flat + name: flat + prefix: flat - type: KzedMapType title: Surface name: nether prefix: nt # Example: - #- title: Other World # Under what name the world is displayed. + #- title: Other World # With what name the world is displayed. # name: world_other # The actual name of the world (equal to your directory-name). # maps: # - type: KzedMapType # The type (or perspective) of the map. At the moment, there are no others than KzedMapType. # title: Surface # The name of the map that will be displayed. # name: surface # The actual name of the map (should be unique for this world). # prefix: t # The prefix of the tile-files that are generated. - # icon: block_other.png # Sets the icon of the map. (optional) + # icon: images/block_other.png # Sets a custom icon for the map. (optional) # - type: KzedMapType # title: Cave # name: cave @@ -102,4 +122,3 @@ web: # Enables debugging. #debuggers: # - class: org.dynmap.debug.LogDebugger -# - class: org.dynmap.debug.BukkitPlayerDebugger diff --git a/pom.xml b/pom.xml index 3ad7428c..69c589d5 100644 --- a/pom.xml +++ b/pom.xml @@ -1,8 +1,8 @@ 4.0.0 - org.bukkit + org.dynmap dynmap - 0.0.1-SNAPSHOT + 0.13 DynamicMap http://www.bukkit.org @@ -20,7 +20,7 @@ maven-assembly-plugin - assembly.xml + src/main/assembly/package.xml diff --git a/assembly.xml b/src/main/assembly/package.xml similarity index 83% rename from assembly.xml rename to src/main/assembly/package.xml index c7d25f5a..d27afbf9 100644 --- a/assembly.xml +++ b/src/main/assembly/package.xml @@ -1,5 +1,5 @@ - build + bin false tar.bz2 @@ -13,13 +13,17 @@ README* LICENSE* NOTICE* - LICENSE* + CHANGELOG* ${project.basedir}/web /dynmap/web + + ${project.basedir}/colorschemes + /dynmap/colorschemes + ${project.basedir} /dynmap/ diff --git a/src/main/java/org/dynmap/ColorScheme.java b/src/main/java/org/dynmap/ColorScheme.java new file mode 100644 index 00000000..49ba68da --- /dev/null +++ b/src/main/java/org/dynmap/ColorScheme.java @@ -0,0 +1,85 @@ +package org.dynmap; + +import java.awt.Color; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Scanner; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.dynmap.debug.Debug; + +public class ColorScheme { + protected static final Logger log = Logger.getLogger("Minecraft"); + private static final HashMap cache = new HashMap(); + + public String name; + public java.util.Map colors; + + public ColorScheme(String name, java.util.Map colors) { + this.name = name; + this.colors = colors; + } + + private static File getColorSchemeDirectory() { + return new File(DynmapPlugin.dataDirectory, "colorschemes"); + } + + public static ColorScheme getScheme(String name) { + if (name == null) + name = "default"; + ColorScheme scheme = cache.get(name); + if (scheme == null) { + scheme = loadScheme(name); + cache.put(name, scheme); + } + return scheme; + } + + public static ColorScheme loadScheme(String name) { + File colorSchemeFile = new File(getColorSchemeDirectory(), name + ".txt"); + java.util.Map colors = new HashMap(); + InputStream stream; + try { + Debug.debug("Loading colors from '" + colorSchemeFile + "'..."); + stream = new FileInputStream(colorSchemeFile); + + Scanner scanner = new Scanner(stream); + int nc = 0; + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (line.startsWith("#") || line.equals("")) { + continue; + } + + String[] split = line.split("\t"); + if (split.length < 17) { + continue; + } + + Integer id = new Integer(split[0]); + + Color[] c = new Color[4]; + + /* store colors by raycast sequence number */ + c[0] = new Color(Integer.parseInt(split[1]), Integer.parseInt(split[2]), Integer.parseInt(split[3]), Integer.parseInt(split[4])); + c[3] = new Color(Integer.parseInt(split[5]), Integer.parseInt(split[6]), Integer.parseInt(split[7]), Integer.parseInt(split[8])); + c[1] = new Color(Integer.parseInt(split[9]), Integer.parseInt(split[10]), Integer.parseInt(split[11]), Integer.parseInt(split[12])); + c[2] = new Color(Integer.parseInt(split[13]), Integer.parseInt(split[14]), Integer.parseInt(split[15]), Integer.parseInt(split[16])); + + colors.put(id, c); + nc += 1; + } + scanner.close(); + } catch (RuntimeException e) { + log.log(Level.SEVERE, "Could not load colors '" + name + "' ('" + colorSchemeFile + "').", e); + return null; + } catch (FileNotFoundException e) { + log.log(Level.SEVERE, "Could not load colors '" + name + "' ('" + colorSchemeFile + "'): File not found.", e); + } + return new ColorScheme(name, colors); + } +} diff --git a/src/main/java/org/dynmap/DynmapBlockListener.java b/src/main/java/org/dynmap/DynmapBlockListener.java deleted file mode 100644 index 41a8b61c..00000000 --- a/src/main/java/org/dynmap/DynmapBlockListener.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.dynmap; - -import org.bukkit.block.Block; -import org.bukkit.block.BlockDamageLevel; -import org.bukkit.event.block.BlockDamageEvent; -import org.bukkit.event.block.BlockListener; -import org.bukkit.event.block.BlockPlaceEvent; - -public class DynmapBlockListener extends BlockListener { - private MapManager mgr; - - public DynmapBlockListener(MapManager mgr) { - this.mgr = mgr; - } - - @Override - public void onBlockPlace(BlockPlaceEvent event) { - Block blockPlaced = event.getBlockPlaced(); - mgr.touch(blockPlaced.getLocation()); - } - - public void onBlockDamage(BlockDamageEvent event) { - if (event.getDamageLevel() == BlockDamageLevel.BROKEN) { - Block blockBroken = event.getBlock(); - mgr.touch(blockBroken.getLocation()); - } - } -} diff --git a/src/main/java/org/dynmap/DynmapPlugin.java b/src/main/java/org/dynmap/DynmapPlugin.java index bcbb4441..8ac9f555 100644 --- a/src/main/java/org/dynmap/DynmapPlugin.java +++ b/src/main/java/org/dynmap/DynmapPlugin.java @@ -1,40 +1,50 @@ package org.dynmap; import java.io.File; -import java.io.FileOutputStream; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.Constructor; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.logging.Logger; import java.util.Timer; +import java.util.logging.Level; +import java.util.logging.Logger; import org.bukkit.Location; import org.bukkit.World; +import org.bukkit.block.BlockDamageLevel; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.Event.Priority; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockDamageEvent; import org.bukkit.event.block.BlockListener; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerEvent; import org.bukkit.event.player.PlayerListener; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.event.world.WorldEvent; import org.bukkit.event.world.WorldListener; +import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.util.config.Configuration; import org.dynmap.Event.Listener; import org.dynmap.debug.Debug; import org.dynmap.debug.Debugger; import org.dynmap.web.HttpServer; +import org.dynmap.web.Json; import org.dynmap.web.handlers.ClientConfigurationHandler; import org.dynmap.web.handlers.ClientUpdateHandler; import org.dynmap.web.handlers.FilesystemHandler; import org.dynmap.web.handlers.SendMessageHandler; import org.dynmap.web.handlers.SendMessageHandler.Message; -import org.dynmap.web.Json; public class DynmapPlugin extends JavaPlugin { @@ -44,9 +54,11 @@ public class DynmapPlugin extends JavaPlugin { public MapManager mapManager = null; public PlayerList playerList; public Configuration configuration; + public HashSet enabledTriggers = new HashSet(); public Timer timer; + public static File dataDirectory; public static File tilesDirectory; public World getWorld() { @@ -62,13 +74,17 @@ public class DynmapPlugin extends JavaPlugin { } public void onEnable() { + dataDirectory = this.getDataFolder(); + configuration = new Configuration(new File(this.getDataFolder(), "configuration.txt")); configuration.load(); loadDebuggers(); - + tilesDirectory = getFile(configuration.getString("tilespath", "web/tiles")); - tilesDirectory.mkdirs(); + if (!tilesDirectory.isDirectory() && !tilesDirectory.mkdirs()) { + log.warning("Could not create directory for tiles ('" + tilesDirectory + "')."); + } playerList = new PlayerList(getServer(), getFile("hiddenplayers.txt")); playerList.load(); @@ -76,7 +92,9 @@ public class DynmapPlugin extends JavaPlugin { mapManager = new MapManager(this, configuration); mapManager.startRendering(); - loadWebserver(); + if (!configuration.getBoolean("disable-webserver", false)) { + loadWebserver(); + } if (configuration.getBoolean("jsonfile", false)) { jsonConfig(); @@ -85,6 +103,11 @@ public class DynmapPlugin extends JavaPlugin { timer.scheduleAtFixedRate(new JsonTimerTask(this, configuration), jsonInterval, jsonInterval); } + enabledTriggers.clear(); + for (Object trigger : configuration.getList("render-triggers")) { + enabledTriggers.add((String) trigger); + } + registerEvents(); } @@ -141,25 +164,81 @@ public class DynmapPlugin extends JavaPlugin { Debug.clearDebuggers(); } + public boolean isTrigger(String s) { + return enabledTriggers.contains(s); + } + public void registerEvents() { - BlockListener blockListener = new DynmapBlockListener(mapManager); - getServer().getPluginManager().registerEvent(Event.Type.BLOCK_PLACED, blockListener, Priority.Monitor, this); - getServer().getPluginManager().registerEvent(Event.Type.BLOCK_DAMAGED, blockListener, Priority.Monitor, this); + final PluginManager pm = getServer().getPluginManager(); + final MapManager mm = mapManager; + + // To trigger rendering. + { + BlockListener renderTrigger = new BlockListener() { + @Override + public void onBlockPlace(BlockPlaceEvent event) { + mm.touch(event.getBlockPlaced().getLocation()); + } + @Override + public void onBlockBreak(BlockBreakEvent event) { + mm.touch(event.getBlock().getLocation()); + } + }; + if (isTrigger("blockplaced")) pm.registerEvent(Event.Type.BLOCK_PLACED, renderTrigger, Priority.Monitor, this); + if (isTrigger("blockbreak")) pm.registerEvent(Event.Type.BLOCK_BREAK, renderTrigger, Priority.Monitor, this); + } + { + PlayerListener renderTrigger = new PlayerListener() { + @Override + public void onPlayerJoin(PlayerEvent event) { + mm.touch(event.getPlayer().getLocation()); + } + @Override + public void onPlayerMove(PlayerMoveEvent event) { + mm.touch(event.getPlayer().getLocation()); + } + }; + if (isTrigger("playerjoin")) pm.registerEvent(Event.Type.PLAYER_JOIN, renderTrigger, Priority.Monitor, this); + if (isTrigger("playermove")) pm.registerEvent(Event.Type.PLAYER_MOVE, renderTrigger, Priority.Monitor, this); + } + { + WorldListener renderTrigger = new WorldListener() { + @Override + public void onChunkLoaded(ChunkLoadEvent event) { + int x = event.getChunk().getX() * 16 + 8; + int z = event.getChunk().getZ() * 16 + 8; + mm.touch(new Location(event.getWorld(), x, 127, z)); + } + + /*@Override + public void onChunkGenerated(ChunkLoadEvent event) { + int x = event.getChunk().getX() * 16 + 8; + int z = event.getChunk().getZ() * 16 + 8; + mm.touch(new Location(event.getWorld(), x, 127, z)); + }*/ + }; + if (isTrigger("chunkloaded")) pm.registerEvent(Event.Type.CHUNK_LOADED, renderTrigger, Priority.Monitor, this); + //if (isTrigger("chunkgenerated")) pm.registerEvent(Event.Type.CHUNK_GENERATED, renderTrigger, Priority.Monitor, this); + } + + // To link configuration to real loaded worlds. WorldListener worldListener = new WorldListener() { @Override public void onWorldLoaded(WorldEvent event) { - mapManager.activateWorld(event.getWorld()); + mm.activateWorld(event.getWorld()); } }; - getServer().getPluginManager().registerEvent(Event.Type.WORLD_LOADED, worldListener, Priority.Monitor, this); + pm.registerEvent(Event.Type.WORLD_LOADED, worldListener, Priority.Monitor, this); + // To handle webchat. PlayerListener playerListener = new DynmapPlayerListener(this); //getServer().getPluginManager().registerEvent(Event.Type.PLAYER_COMMAND, playerListener, Priority.Normal, this); - getServer().getPluginManager().registerEvent(Event.Type.PLAYER_CHAT, playerListener, Priority.Normal, this); - getServer().getPluginManager().registerEvent(Event.Type.PLAYER_LOGIN, playerListener, Priority.Normal, this); - getServer().getPluginManager().registerEvent(Event.Type.PLAYER_JOIN, playerListener, Priority.Normal, this); - getServer().getPluginManager().registerEvent(Event.Type.PLAYER_QUIT, playerListener, Priority.Normal, this); + pm.registerEvent(Event.Type.PLAYER_CHAT, playerListener, Priority.Monitor, this); + pm.registerEvent(Event.Type.PLAYER_LOGIN, playerListener, Priority.Monitor, this); + pm.registerEvent(Event.Type.PLAYER_JOIN, playerListener, Priority.Monitor, this); + pm.registerEvent(Event.Type.PLAYER_QUIT, playerListener, Priority.Monitor, this); + } private static File combinePaths(File parent, String path) { @@ -269,9 +348,9 @@ public class DynmapPlugin extends JavaPlugin { fos.write(Json.stringifyJson(clientConfig).getBytes()); fos.close(); } catch (FileNotFoundException ex) { - System.out.println("FileNotFoundException : " + ex); + log.log(Level.SEVERE, "Exception while writing JSON-configuration-file.", ex); } catch (IOException ioe) { - System.out.println("IOException : " + ioe); + log.log(Level.SEVERE, "Exception while writing JSON-configuration-file.", ioe); } } } diff --git a/src/main/java/org/dynmap/JsonTimerTask.java b/src/main/java/org/dynmap/JsonTimerTask.java index 4fece6ef..d7f95e76 100644 --- a/src/main/java/org/dynmap/JsonTimerTask.java +++ b/src/main/java/org/dynmap/JsonTimerTask.java @@ -5,6 +5,8 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.TimerTask; +import java.util.logging.Level; +import java.util.logging.Logger; import org.bukkit.Location; import org.bukkit.Server; @@ -14,6 +16,8 @@ import org.bukkit.util.config.Configuration; import org.dynmap.web.Json; class JsonTimerTask extends TimerTask { + protected static final Logger log = Logger.getLogger("Minecraft"); + private final DynmapPlugin plugin; private Server server; private MapManager mapManager; @@ -57,10 +61,10 @@ class JsonTimerTask extends TimerTask { fos.write(Json.stringifyJson(update).getBytes()); fos.close(); } catch (FileNotFoundException ex) { - System.out.println("FileNotFoundException : " + ex); + log.log(Level.SEVERE, "Exception while writing JSON-file.", ex); } catch (IOException ioe) { - System.out.println("IOException : " + ioe); + log.log(Level.SEVERE, "Exception while writing JSON-file.", ioe); } } } -} \ No newline at end of file +} diff --git a/src/main/java/org/dynmap/MapManager.java b/src/main/java/org/dynmap/MapManager.java index 4d4f4eb1..936546e4 100644 --- a/src/main/java/org/dynmap/MapManager.java +++ b/src/main/java/org/dynmap/MapManager.java @@ -23,7 +23,7 @@ public class MapManager { public Map worlds = new HashMap(); public Map inactiveworlds = new HashMap(); - + /* lock for our data structures */ public static final Object lock = new Object(); @@ -107,7 +107,6 @@ public class MapManager { } } found.remove(tile); - System.gc(); } // Unload remaining chunks to clean-up. @@ -202,7 +201,9 @@ public class MapManager { worldTileDirectory = new File(DynmapPlugin.tilesDirectory, tile.getWorld().getName()); worldTileDirectories.put(world, worldTileDirectory); } - worldTileDirectory.mkdirs(); + if (!worldTileDirectory.isDirectory() && !worldTileDirectory.mkdirs()) { + log.warning("Could not create directory for tiles ('" + worldTileDirectory + "')."); + } return new File(worldTileDirectory, tile.getFilename()); } diff --git a/src/main/java/org/dynmap/MapTile.java b/src/main/java/org/dynmap/MapTile.java index 25bb2c77..9484a352 100644 --- a/src/main/java/org/dynmap/MapTile.java +++ b/src/main/java/org/dynmap/MapTile.java @@ -25,4 +25,13 @@ public abstract class MapTile { public int hashCode() { return getFilename().hashCode() ^ getWorld().hashCode(); } + + @Override + public boolean equals(Object obj) { + if (obj instanceof MapTile) { + MapTile t = (MapTile)obj; + return getFilename().equals(t.getFilename()) && getWorld().equals(t.getWorld()); + } + return super.equals(obj); + } } diff --git a/src/main/java/org/dynmap/UpdateQueue.java b/src/main/java/org/dynmap/UpdateQueue.java index 24a35eb5..368c987d 100644 --- a/src/main/java/org/dynmap/UpdateQueue.java +++ b/src/main/java/org/dynmap/UpdateQueue.java @@ -58,7 +58,7 @@ public class UpdateQueue { return updates; } - public class Update { + public static class Update { public long time; public Object obj; diff --git a/src/main/java/org/dynmap/debug/BukkitPlayerDebugger.java b/src/main/java/org/dynmap/debug/BukkitPlayerDebugger.java deleted file mode 100644 index 49336a24..00000000 --- a/src/main/java/org/dynmap/debug/BukkitPlayerDebugger.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.dynmap.debug; - -import java.util.HashSet; -import java.util.Map; - -import org.bukkit.ChatColor; -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.Event.Priority; -import org.bukkit.event.player.PlayerChatEvent; -import org.bukkit.event.player.PlayerEvent; -import org.bukkit.event.player.PlayerListener; -import org.bukkit.plugin.java.JavaPlugin; - -public class BukkitPlayerDebugger implements Debugger { - private JavaPlugin plugin; - private HashSet debugees = new HashSet(); - private String debugCommand; - private String undebugCommand; - private String prepend; - - public BukkitPlayerDebugger(JavaPlugin plugin, Map configuration) { - this.plugin = plugin; - - String name = "dynmap"; - debugCommand = "/debug_" + name; - undebugCommand = "/undebug_" + name; - prepend = name + ": "; - } - - public synchronized void enable() { - plugin.getServer().getPluginManager().registerEvent(Event.Type.PLAYER_COMMAND, new CommandListener(), Priority.Normal, plugin); - plugin.getServer().getPluginManager().registerEvent(Event.Type.PLAYER_QUIT, new CommandListener(), Priority.Normal, plugin); - } - - public synchronized void disable() { - clearDebugees(); - } - - public synchronized void addDebugee(Player p) { - debugees.add(p); - } - - public synchronized void removeDebugee(Player p) { - debugees.remove(p); - } - - public synchronized void clearDebugees() { - debugees.clear(); - } - - public synchronized void sendToDebuggees(String message) { - for (Player p : debugees) { - p.sendMessage(prepend + message); - } - } - - public synchronized void debug(String message) { - sendToDebuggees(message); - } - - public synchronized void error(String message) { - sendToDebuggees(prepend + ChatColor.RED + message); - } - - public synchronized void error(String message, Throwable thrown) { - sendToDebuggees(prepend + ChatColor.RED + message); - sendToDebuggees(thrown.toString()); - } - - protected class CommandListener extends PlayerListener { - @Override - public void onPlayerCommand(PlayerChatEvent event) { - String[] split = event.getMessage().split(" "); - Player player = event.getPlayer(); - if (split[0].equalsIgnoreCase(debugCommand)) { - addDebugee(player); - event.setCancelled(true); - } else if (split[0].equalsIgnoreCase(undebugCommand)) { - removeDebugee(player); - event.setCancelled(true); - } - } - - @Override - public void onPlayerQuit(PlayerEvent event) { - removeDebugee(event.getPlayer()); - } - } -} diff --git a/src/main/java/org/dynmap/flat/FlatMap.java b/src/main/java/org/dynmap/flat/FlatMap.java new file mode 100644 index 00000000..a0adc02a --- /dev/null +++ b/src/main/java/org/dynmap/flat/FlatMap.java @@ -0,0 +1,123 @@ +package org.dynmap.flat; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.awt.image.WritableRaster; +import java.io.File; +import java.io.IOException; +import java.util.Map; + +import javax.imageio.ImageIO; + +import org.bukkit.Location; +import org.bukkit.World; +import org.dynmap.ColorScheme; +import org.dynmap.DynmapChunk; +import org.dynmap.MapTile; +import org.dynmap.MapType; +import org.dynmap.debug.Debug; + +public class FlatMap extends MapType { + private String prefix; + private ColorScheme colorScheme; + + public FlatMap(Map configuration) { + prefix = (String)configuration.get("prefix"); + colorScheme = ColorScheme.getScheme((String)configuration.get("colorscheme")); + } + + @Override + public MapTile[] getTiles(Location l) { + return new MapTile[] { new FlatMapTile(l.getWorld(), this, (int) Math.floor(l.getBlockX() / 128.0), (int) Math.floor(l.getBlockZ() / 128.0), 128) }; + } + + @Override + public MapTile[] getAdjecentTiles(MapTile tile) { + FlatMapTile t = (FlatMapTile) tile; + World w = t.getWorld(); + int x = t.x; + int y = t.y; + int s = t.size; + return new MapTile[] { + new FlatMapTile(w, this, x, y - 1, s), + new FlatMapTile(w, this, x + 1, y, s), + new FlatMapTile(w, this, x, y + 1, s), + new FlatMapTile(w, this, x - 1, y, s) }; + } + + @Override + public DynmapChunk[] getRequiredChunks(MapTile tile) { + FlatMapTile t = (FlatMapTile) tile; + int chunksPerTile = t.size / 16; + int sx = t.x * chunksPerTile; + int sz = t.y * chunksPerTile; + + DynmapChunk[] result = new DynmapChunk[chunksPerTile * chunksPerTile]; + int index = 0; + for (int x = 0; x < chunksPerTile; x++) + for (int z = 0; z < chunksPerTile; z++) { + result[index] = new DynmapChunk(sx + x, sz + z); + index++; + } + return result; + } + + @Override + public boolean render(MapTile tile, File outputFile) { + FlatMapTile t = (FlatMapTile) tile; + World w = t.getWorld(); + + boolean rendered = false; + BufferedImage im = new BufferedImage(t.size, t.size, BufferedImage.TYPE_INT_RGB); + WritableRaster r = im.getRaster(); + + for (int x = 0; x < t.size; x++) + for (int y = 0; y < t.size; y++) { + int mx = x + t.x * t.size; + int mz = y + t.y * t.size; + int my = w.getHighestBlockYAt(mx, mz) - 1; + int blockType = w.getBlockTypeIdAt(mx, my, mz); + Color[] colors = colorScheme.colors.get(blockType); + if (colors == null) + continue; + Color c = colors[0]; + if (c == null) + continue; + r.setPixel(x, y, new int[] { + c.getRed(), + c.getGreen(), + c.getBlue() }); + rendered = true; + } + + try { + ImageIO.write(im, "png", outputFile); + } catch (IOException e) { + Debug.error("Failed to save image: " + outputFile.getPath(), e); + } catch (java.lang.NullPointerException e) { + Debug.error("Failed to save image (NullPointerException): " + outputFile.getPath(), e); + } + im.flush(); + return rendered; + } + + public static class FlatMapTile extends MapTile { + FlatMap map; + public int x; + public int y; + public int size; + + public FlatMapTile(World world, FlatMap map, int x, int y, int size) { + super(world, map); + this.map = map; + this.x = x; + this.y = y; + this.size = size; + } + + @Override + public String getFilename() { + return map.prefix + "_" + size + "_" + x + "_" + y + ".png"; + } + } +} diff --git a/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java b/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java index 147282c6..f24dbbce 100644 --- a/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java +++ b/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java @@ -10,12 +10,14 @@ import java.util.Map; import javax.imageio.ImageIO; import org.bukkit.World; +import org.dynmap.ColorScheme; import org.dynmap.debug.Debug; public class DefaultTileRenderer implements MapTileRenderer { protected static Color translucent = new Color(0, 0, 0, 0); private String name; protected int maximumHeight = 127; + private ColorScheme colorScheme; @Override public String getName() { @@ -30,6 +32,7 @@ public class DefaultTileRenderer implements MapTileRenderer { if (maximumHeight > 127) maximumHeight = 127; } + colorScheme = ColorScheme.getScheme((String)configuration.get("colorscheme")); } public boolean render(KzedMapTile tile, File outputFile) { @@ -39,9 +42,9 @@ public class DefaultTileRenderer implements MapTileRenderer { WritableRaster r = im.getRaster(); boolean isempty = true; - int ix = KzedMap.anchorx + tile.px / 2 + tile.py / 2; + int ix = KzedMap.anchorx + tile.px / 2 + tile.py / 2 - ((127-maximumHeight)/2); int iy = maximumHeight; - int iz = KzedMap.anchorz + tile.px / 2 - tile.py / 2; + int iz = KzedMap.anchorz + tile.px / 2 - tile.py / 2 + ((127-maximumHeight)/2); int jx, jz; @@ -132,7 +135,7 @@ public class DefaultTileRenderer implements MapTileRenderer { seq = (seq + 1) & 3; if (id != 0) { - Color[] colors = KzedMap.colors.get(id); + Color[] colors = colorScheme.colors.get(id); if (colors != null) { Color c = colors[seq]; if (c.getAlpha() > 0) { diff --git a/src/main/java/org/dynmap/kzedmap/KzedMap.java b/src/main/java/org/dynmap/kzedmap/KzedMap.java index 860a1e07..a32e589f 100644 --- a/src/main/java/org/dynmap/kzedmap/KzedMap.java +++ b/src/main/java/org/dynmap/kzedmap/KzedMap.java @@ -1,15 +1,10 @@ package org.dynmap.kzedmap; -import java.awt.Color; import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; import java.lang.reflect.Constructor; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Scanner; import java.util.logging.Logger; import org.bukkit.Location; @@ -38,15 +33,10 @@ public class KzedMap extends MapType { public static final int anchory = 127; public static final int anchorz = 0; - public static java.util.Map colors; MapTileRenderer[] renderers; ZoomedTileRenderer zoomrenderer; public KzedMap(Map configuration) { - if (colors == null) { - colors = loadColorSet("colors.txt"); - } - renderers = loadRenderers(configuration); zoomrenderer = new ZoomedTileRenderer(configuration); } @@ -223,54 +213,4 @@ public class KzedMap extends MapType { else return y - (y % zTileHeight); } - - public java.util.Map loadColorSet(String colorsetpath) { - java.util.Map colors = new HashMap(); - - InputStream stream; - - try { - /* load colorset */ - File cfile = new File(colorsetpath); - if (cfile.isFile()) { - Debug.debug("Loading colors from '" + colorsetpath + "'..."); - stream = new FileInputStream(cfile); - } else { - Debug.debug("Loading colors from jar..."); - stream = KzedMap.class.getResourceAsStream("/colors.txt"); - } - - Scanner scanner = new Scanner(stream); - int nc = 0; - while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - if (line.startsWith("#") || line.equals("")) { - continue; - } - - String[] split = line.split("\t"); - if (split.length < 17) { - continue; - } - - Integer id = new Integer(split[0]); - - Color[] c = new Color[4]; - - /* store colors by raycast sequence number */ - c[0] = new Color(Integer.parseInt(split[1]), Integer.parseInt(split[2]), Integer.parseInt(split[3]), Integer.parseInt(split[4])); - c[3] = new Color(Integer.parseInt(split[5]), Integer.parseInt(split[6]), Integer.parseInt(split[7]), Integer.parseInt(split[8])); - c[1] = new Color(Integer.parseInt(split[9]), Integer.parseInt(split[10]), Integer.parseInt(split[11]), Integer.parseInt(split[12])); - c[2] = new Color(Integer.parseInt(split[13]), Integer.parseInt(split[14]), Integer.parseInt(split[15]), Integer.parseInt(split[16])); - - colors.put(id, c); - nc += 1; - } - scanner.close(); - } catch (Exception e) { - Debug.error("Could not load colors", e); - return null; - } - return colors; - } } diff --git a/src/main/java/org/dynmap/web/HttpErrorHandler.java b/src/main/java/org/dynmap/web/HttpErrorHandler.java deleted file mode 100644 index f2476390..00000000 --- a/src/main/java/org/dynmap/web/HttpErrorHandler.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.dynmap.web; - -import java.io.IOException; - -public class HttpErrorHandler { - public static void handle(HttpResponse response, int statusCode, String statusMessage) throws IOException { - response.statusCode = statusCode; - response.statusMessage = statusMessage; - response.fields.put("Content-Length", "0"); - response.getBody(); - } - - public static void handleNotFound(HttpResponse response) throws IOException { - handle(response, 404, "Not found"); - } - - public static void handleMethodNotAllowed(HttpResponse response) throws IOException { - handle(response, 405, "Method not allowed"); - } -} diff --git a/src/main/java/org/dynmap/web/HttpField.java b/src/main/java/org/dynmap/web/HttpField.java index 06535189..8a1a5f2e 100644 --- a/src/main/java/org/dynmap/web/HttpField.java +++ b/src/main/java/org/dynmap/web/HttpField.java @@ -1,6 +1,52 @@ package org.dynmap.web; public class HttpField { - public static final String contentLength = "Content-Length"; - public static final String contentType = "Content-Type"; + // Reference: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html + public static final String Accept = "Accept"; + public static final String AcceptCharset = "Accept-Charset"; + public static final String AcceptEncoding = "Accept-Encoding"; + public static final String AcceptLanguage = "Accept-Language"; + public static final String AcceptRanges = "Accept-Ranges"; + public static final String Age = "Age"; + public static final String Allow = "Allow"; + public static final String Authorization = "Authorization"; + public static final String CacheControl = "Cache-Control"; + public static final String Connection = "Connection"; + public static final String ContentEncoding = "Content-Encoding"; + public static final String ContentLanguage = "Content-Language"; + public static final String ContentLength = "Content-Length"; + public static final String ContentLocation = "Content-Location"; + public static final String ContentRange = "Content-Range"; + public static final String ContentType = "Content-Type"; + public static final String Date = "Date"; + public static final String ETag = "ETag"; + public static final String Expect = "Expect"; + public static final String Expires = "Expires"; + public static final String From = "From"; + public static final String Host = "Host"; + public static final String IfMatch = "If-Match"; + public static final String IfModifiedSince = "If-Modified-Since"; + public static final String IfNoneMatch = "If-None-Match"; + public static final String IfRange = "If-Range"; + public static final String IfUnmodifiedSince = "If-Unmodified-Since"; + public static final String LastModified = "Last-Modified"; + public static final String Location = "Location"; + public static final String MaxForwards = "Max-Forwards"; + public static final String Pragma = "Pragma"; + public static final String ProxyAuthenticate = "Proxy-Authenticate"; + public static final String ProxyAuthorization = "Proxy-Authorization"; + public static final String Range = "Range"; + public static final String Referer = "Referer"; + public static final String RetryAfter = "Retry-After"; + public static final String Server = "Server"; + public static final String TE = "TE"; + public static final String Trailer = "Trailer"; + public static final String TransferEncoding = "Transfer-Encoding"; + public static final String Upgrade = "Upgrade"; + public static final String UserAgent = "User-Agent"; + public static final String Vary = "Vary"; + public static final String Via = "Via"; + public static final String Warning = "Warning"; + public static final String WwwAuthenticate = "WWW-Authenticate"; + } diff --git a/src/main/java/org/dynmap/web/HttpMethods.java b/src/main/java/org/dynmap/web/HttpMethod.java similarity index 86% rename from src/main/java/org/dynmap/web/HttpMethods.java rename to src/main/java/org/dynmap/web/HttpMethod.java index 8c116519..bb6d28b7 100644 --- a/src/main/java/org/dynmap/web/HttpMethods.java +++ b/src/main/java/org/dynmap/web/HttpMethod.java @@ -1,6 +1,6 @@ package org.dynmap.web; -public class HttpMethods { +public final class HttpMethod { public static final String Get = "GET"; public static final String Post = "POST"; public static final String Put = "PUT"; diff --git a/src/main/java/org/dynmap/web/HttpResponse.java b/src/main/java/org/dynmap/web/HttpResponse.java index 0a6813b5..102f249e 100644 --- a/src/main/java/org/dynmap/web/HttpResponse.java +++ b/src/main/java/org/dynmap/web/HttpResponse.java @@ -8,8 +8,7 @@ import java.util.Map; public class HttpResponse { private HttpServerConnection connection; public String version = "1.1"; - public int statusCode = 200; - public String statusMessage = "OK"; + public HttpStatus status = null; public Map fields = new HashMap(); private OutputStream body; diff --git a/src/main/java/org/dynmap/web/HttpServerConnection.java b/src/main/java/org/dynmap/web/HttpServerConnection.java index 830ed5ae..c1c96d12 100644 --- a/src/main/java/org/dynmap/web/HttpServerConnection.java +++ b/src/main/java/org/dynmap/web/HttpServerConnection.java @@ -95,9 +95,9 @@ public class HttpServerConnection extends Thread { out.append("HTTP/"); out.append(response.version); out.append(" "); - out.append(String.valueOf(response.statusCode)); + out.append(String.valueOf(response.status.getCode())); out.append(" "); - out.append(response.statusMessage); + out.append(response.status.getText()); out.append("\r\n"); for (Entry field : response.fields.entrySet()) { out.append(field.getKey()); @@ -115,6 +115,8 @@ public class HttpServerConnection extends Thread { public void run() { try { + if (socket == null) + return; socket.setSoTimeout(5000); InputStream in = socket.getInputStream(); BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream(), 40960); @@ -131,7 +133,7 @@ public class HttpServerConnection extends Thread { long bound = -1; BoundInputStream boundBody = null; { - String contentLengthStr = request.fields.get(HttpField.contentLength); + String contentLengthStr = request.fields.get(HttpField.ContentLength); if (contentLengthStr != null) { try { bound = Long.parseLong(contentLengthStr); @@ -178,8 +180,10 @@ public class HttpServerConnection extends Thread { return; } - if (bound > 0) { - boundBody.skip(bound); + if (bound > 0 && boundBody.skip(bound) < bound) { + Debug.debug("Incoming stream was only read partially by handler '" + handler + "'."); + //socket.close(); + //return; } String connection = response.fields.get("Connection"); diff --git a/src/main/java/org/dynmap/web/HttpStatus.java b/src/main/java/org/dynmap/web/HttpStatus.java new file mode 100644 index 00000000..e4aaa3d6 --- /dev/null +++ b/src/main/java/org/dynmap/web/HttpStatus.java @@ -0,0 +1,61 @@ +package org.dynmap.web; + +public final class HttpStatus { + private int code; + private String text; + + public int getCode() { + return code; + } + + public String getText() { + return text; + } + + public HttpStatus(int code, String text) { + this.code = code; + this.text = text; + } + + // Reference: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html + public static final HttpStatus Continue = new HttpStatus(100, "Continue"); + public static final HttpStatus SwitchingProtocols = new HttpStatus(101, "Switching Protocols"); + public static final HttpStatus OK = new HttpStatus(200, "OK"); + public static final HttpStatus Created = new HttpStatus(201, "Created"); + public static final HttpStatus Accepted = new HttpStatus(202, "Accepted"); + public static final HttpStatus NonAuthoritativeInformation = new HttpStatus(203, "Non-Authoritative Information"); + public static final HttpStatus NoContent = new HttpStatus(204, "No Content"); + public static final HttpStatus ResetContent = new HttpStatus(205, "Reset Content"); + public static final HttpStatus PartialContent = new HttpStatus(206, "Partial Content"); + public static final HttpStatus MultipleChoices = new HttpStatus(300, "Multiple Choices"); + public static final HttpStatus MovedPermanently = new HttpStatus(301, "Moved Permanently"); + public static final HttpStatus Found = new HttpStatus(302, "Found"); + public static final HttpStatus SeeOther = new HttpStatus(303, "See Other"); + public static final HttpStatus NotModified = new HttpStatus(304, "Not Modified"); + public static final HttpStatus UseProxy = new HttpStatus(305, "Use Proxy"); + public static final HttpStatus TemporaryRedirect = new HttpStatus(307, "Temporary Redirect"); + public static final HttpStatus BadRequest = new HttpStatus(400, "Bad Request"); + public static final HttpStatus Unauthorized = new HttpStatus(401, "Unauthorized"); + public static final HttpStatus PaymentRequired = new HttpStatus(402, "Payment Required"); + public static final HttpStatus Forbidden = new HttpStatus(403, "Forbidden"); + public static final HttpStatus NotFound = new HttpStatus(404, "Not Found"); + public static final HttpStatus MethodNotAllowed = new HttpStatus(405, "Method Not Allowed"); + public static final HttpStatus NotAcceptable = new HttpStatus(406, "Not Acceptable"); + public static final HttpStatus ProxyAuthenticationRequired = new HttpStatus(407, "Proxy Authentication Required"); + public static final HttpStatus RequestTimeout = new HttpStatus(408, "Request Timeout"); + public static final HttpStatus Conflict = new HttpStatus(409, "Conflict"); + public static final HttpStatus Gone = new HttpStatus(410, "Gone"); + public static final HttpStatus LengthRequired = new HttpStatus(411, "Length Required"); + public static final HttpStatus PreconditionFailed = new HttpStatus(412, "Precondition Failed"); + public static final HttpStatus RequestEntityTooLarge = new HttpStatus(413, "Request Entity Too Large"); + public static final HttpStatus RequestURITooLong = new HttpStatus(414, "Request-URI Too Long"); + public static final HttpStatus UnsupportedMediaType = new HttpStatus(415, "Unsupported Media Type"); + public static final HttpStatus RequestedRangeNotSatisfiable = new HttpStatus(416, "Requested Range Not Satisfiable"); + public static final HttpStatus ExpectationFailed = new HttpStatus(417, "Expectation Failed"); + public static final HttpStatus InternalServerError = new HttpStatus(500, "Internal Server Error"); + public static final HttpStatus NotImplemented = new HttpStatus(501, "Not Implemented"); + public static final HttpStatus BadGateway = new HttpStatus(502, "Bad Gateway"); + public static final HttpStatus ServiceUnavailable = new HttpStatus(503, "Service Unavailable"); + public static final HttpStatus GatewayTimeout = new HttpStatus(504, "Gateway Timeout"); + public static final HttpStatus HttpVersionNotSupported = new HttpStatus(505, "HTTP Version Not Supported"); +} diff --git a/src/main/java/org/dynmap/web/Json.java b/src/main/java/org/dynmap/web/Json.java index 67aa8924..b1b95f38 100644 --- a/src/main/java/org/dynmap/web/Json.java +++ b/src/main/java/org/dynmap/web/Json.java @@ -3,61 +3,62 @@ package org.dynmap.web; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.security.KeyStore.Entry; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; public class Json { public static String stringifyJson(Object o) { + StringBuilder sb = new StringBuilder(); + appendJson(o, sb); + return sb.toString(); + } + + public static void appendJson(Object o, StringBuilder s) { if (o == null) { - return "null"; + s.append("null"); } else if (o instanceof Boolean) { - return ((Boolean) o) ? "true" : "false"; + s.append(((Boolean) o) ? "true" : "false"); } else if (o instanceof String) { - return "\"" + ((String)o).replace("\"", "\\\"") + "\""; + s.append("\"" + ((String)o).replace("\"", "\\\"") + "\""); } else if (o instanceof Integer || o instanceof Long || o instanceof Float || o instanceof Double) { - return o.toString(); + s.append(o.toString()); } else if (o instanceof LinkedHashMap) { LinkedHashMap m = (LinkedHashMap) o; - StringBuilder sb = new StringBuilder(); - sb.append("{"); + s.append("{"); boolean first = true; - for (Object key : m.keySet()) { + for (Map.Entry entry : m.entrySet()) { if (first) first = false; else - sb.append(","); + s.append(","); - sb.append(stringifyJson(key)); - sb.append(": "); - sb.append(stringifyJson(m.get(key))); + appendJson(entry.getKey(), s); + s.append(": "); + appendJson(entry.getValue(), s); } - sb.append("}"); - return sb.toString(); + s.append("}"); } else if (o instanceof List) { List l = (List) o; - StringBuilder sb = new StringBuilder(); - sb.append("["); + s.append("["); int count = 0; for (int i = 0; i < l.size(); i++) { - if (count++ > 0) sb.append(","); - sb.append(stringifyJson(l.get(i))); + if (count++ > 0) s.append(","); + appendJson(l.get(i), s); } - sb.append("]"); - return sb.toString(); + s.append("]"); } else if (o.getClass().isArray()) { int length = Array.getLength(o); - StringBuilder sb = new StringBuilder(); - sb.append("["); + s.append("["); int count = 0; for (int i = 0; i < length; i++) { - if (count++ > 0) sb.append(","); - sb.append(stringifyJson(Array.get(o, i))); + if (count++ > 0) s.append(","); + appendJson(Array.get(o, i), s); } - sb.append("]"); - return sb.toString(); + s.append("]"); } else if (o instanceof Object) /* TODO: Always true, maybe interface? */ { - StringBuilder sb = new StringBuilder(); - sb.append("{"); + s.append("{"); boolean first = true; Class c = o.getClass(); @@ -77,15 +78,14 @@ public class Json { if (first) first = false; else - sb.append(","); - sb.append(stringifyJson(fieldName)); - sb.append(": "); - sb.append(stringifyJson(fieldValue)); + s.append(","); + appendJson(fieldName, s); + s.append(": "); + appendJson(fieldValue, s); } - sb.append("}"); - return sb.toString(); + s.append("}"); } else { - return "undefined"; + s.append("undefined"); } } } diff --git a/src/main/java/org/dynmap/web/handlers/ClientConfigurationHandler.java b/src/main/java/org/dynmap/web/handlers/ClientConfigurationHandler.java index 02cfdfa3..3117d0e2 100644 --- a/src/main/java/org/dynmap/web/handlers/ClientConfigurationHandler.java +++ b/src/main/java/org/dynmap/web/handlers/ClientConfigurationHandler.java @@ -7,27 +7,33 @@ import java.util.Map; import org.dynmap.web.HttpHandler; import org.dynmap.web.HttpRequest; import org.dynmap.web.HttpResponse; +import org.dynmap.web.HttpStatus; import org.dynmap.web.Json; public class ClientConfigurationHandler implements HttpHandler { private Map configuration; + private byte[] cachedConfiguration = null; public ClientConfigurationHandler(Map configuration) { this.configuration = configuration; } @Override public void handle(String path, HttpRequest request, HttpResponse response) throws Exception { - String s = Json.stringifyJson(configuration); - - byte[] bytes = s.getBytes(); + if (cachedConfiguration == null) { + String s = Json.stringifyJson(configuration); + + cachedConfiguration = s.getBytes(); + } String dateStr = new Date().toString(); response.fields.put("Date", dateStr); response.fields.put("Content-Type", "text/plain"); response.fields.put("Expires", "Thu, 01 Dec 1994 16:00:00 GMT"); response.fields.put("Last-modified", dateStr); - response.fields.put("Content-Length", Integer.toString(bytes.length)); + response.fields.put("Content-Length", Integer.toString(cachedConfiguration.length)); + response.status = HttpStatus.OK; + BufferedOutputStream out = new BufferedOutputStream(response.getBody()); - out.write(s.getBytes()); + out.write(cachedConfiguration); out.flush(); } } diff --git a/src/main/java/org/dynmap/web/handlers/ClientUpdateHandler.java b/src/main/java/org/dynmap/web/handlers/ClientUpdateHandler.java index 58d33786..24d41d5a 100644 --- a/src/main/java/org/dynmap/web/handlers/ClientUpdateHandler.java +++ b/src/main/java/org/dynmap/web/handlers/ClientUpdateHandler.java @@ -12,9 +12,11 @@ import org.bukkit.entity.Player; import org.dynmap.Client; import org.dynmap.MapManager; import org.dynmap.PlayerList; +import org.dynmap.web.HttpField; import org.dynmap.web.HttpHandler; import org.dynmap.web.HttpRequest; import org.dynmap.web.HttpResponse; +import org.dynmap.web.HttpStatus; import org.dynmap.web.Json; public class ClientUpdateHandler implements HttpHandler { @@ -28,21 +30,26 @@ public class ClientUpdateHandler implements HttpHandler { this.server = server; } - Pattern updatePathPattern = Pattern.compile("world/([a-zA-Z0-9_]+)/([0-9]*)"); + Pattern updatePathPattern = Pattern.compile("world/([a-zA-Z0-9_\\-\\.]+)/([0-9]*)"); + private static final HttpStatus WorldNotFound = new HttpStatus(HttpStatus.NotFound.getCode(), "World Not Found"); @Override public void handle(String path, HttpRequest request, HttpResponse response) throws Exception { Matcher match = updatePathPattern.matcher(path); - if (!match.matches()) + if (!match.matches()) { + response.status = HttpStatus.Forbidden; return; + } String worldName = match.group(1); String timeKey = match.group(2); World world = server.getWorld(worldName); - if (world == null) + if (world == null) { + response.status = WorldNotFound; return; + } long current = System.currentTimeMillis(); long since = 0; @@ -73,11 +80,13 @@ public class ClientUpdateHandler implements HttpHandler { byte[] bytes = Json.stringifyJson(update).getBytes(); String dateStr = new Date().toString(); - response.fields.put("Date", dateStr); - response.fields.put("Content-Type", "text/plain"); - response.fields.put("Expires", "Thu, 01 Dec 1994 16:00:00 GMT"); - response.fields.put("Last-modified", dateStr); - response.fields.put("Content-Length", Integer.toString(bytes.length)); + response.fields.put(HttpField.Date, dateStr); + response.fields.put(HttpField.ContentType, "text/plain"); + response.fields.put(HttpField.Expires, "Thu, 01 Dec 1994 16:00:00 GMT"); + response.fields.put(HttpField.LastModified, dateStr); + response.fields.put(HttpField.ContentLength, Integer.toString(bytes.length)); + response.status = HttpStatus.OK; + BufferedOutputStream out = new BufferedOutputStream(response.getBody()); out.write(bytes); out.flush(); diff --git a/src/main/java/org/dynmap/web/handlers/FileHandler.java b/src/main/java/org/dynmap/web/handlers/FileHandler.java index 89c2dc9c..240c9979 100644 --- a/src/main/java/org/dynmap/web/handlers/FileHandler.java +++ b/src/main/java/org/dynmap/web/handlers/FileHandler.java @@ -7,9 +7,11 @@ import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; +import org.dynmap.web.HttpField; import org.dynmap.web.HttpHandler; import org.dynmap.web.HttpRequest; import org.dynmap.web.HttpResponse; +import org.dynmap.web.HttpStatus; public abstract class FileHandler implements HttpHandler { protected static final Logger log = Logger.getLogger("Minecraft"); @@ -64,17 +66,15 @@ public abstract class FileHandler implements HttpHandler { path = formatPath(path); fileInput = getFileInput(path, request, response); if (fileInput == null) { - response.statusCode = 404; - response.statusMessage = "Not found"; - response.fields.put("Content-Length", "0"); - response.getBody(); + response.status = HttpStatus.NotFound; return; } String extension = getExtension(path); String mimeType = getMimeTypeFromExtension(extension); - response.fields.put("Content-Type", mimeType); + response.fields.put(HttpField.ContentType, mimeType); + response.status = HttpStatus.OK; OutputStream out = response.getBody(); try { int readBytes; diff --git a/src/main/java/org/dynmap/web/handlers/FilesystemHandler.java b/src/main/java/org/dynmap/web/handlers/FilesystemHandler.java index 96d8858b..9ad5a3dc 100644 --- a/src/main/java/org/dynmap/web/handlers/FilesystemHandler.java +++ b/src/main/java/org/dynmap/web/handlers/FilesystemHandler.java @@ -5,6 +5,7 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; +import org.dynmap.web.HttpField; import org.dynmap.web.HttpRequest; import org.dynmap.web.HttpResponse; @@ -26,7 +27,7 @@ public class FilesystemHandler extends FileHandler { } catch (FileNotFoundException e) { return null; } - response.fields.put("Content-Length", Long.toString(file.length())); + response.fields.put(HttpField.ContentLength, Long.toString(file.length())); return result; } return null; diff --git a/src/main/java/org/dynmap/web/handlers/SendMessageHandler.java b/src/main/java/org/dynmap/web/handlers/SendMessageHandler.java index e410b7da..27e77562 100644 --- a/src/main/java/org/dynmap/web/handlers/SendMessageHandler.java +++ b/src/main/java/org/dynmap/web/handlers/SendMessageHandler.java @@ -4,12 +4,12 @@ import java.io.InputStreamReader; import java.util.logging.Logger; import org.dynmap.Event; -import org.dynmap.web.HttpErrorHandler; import org.dynmap.web.HttpField; import org.dynmap.web.HttpHandler; -import org.dynmap.web.HttpMethods; +import org.dynmap.web.HttpMethod; import org.dynmap.web.HttpRequest; import org.dynmap.web.HttpResponse; +import org.dynmap.web.HttpStatus; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; @@ -20,8 +20,9 @@ public class SendMessageHandler implements HttpHandler { public Event onMessageReceived = new Event(); @Override public void handle(String path, HttpRequest request, HttpResponse response) throws Exception { - if (!request.method.equals(HttpMethods.Post)) { - HttpErrorHandler.handleMethodNotAllowed(response); + if (!request.method.equals(HttpMethod.Post)) { + response.status = HttpStatus.MethodNotAllowed; + response.fields.put(HttpField.Accept, HttpMethod.Post); return; } @@ -34,10 +35,11 @@ public class SendMessageHandler implements HttpHandler { onMessageReceived.trigger(message); - response.fields.put(HttpField.contentLength, "0"); + response.fields.put(HttpField.ContentLength, "0"); + response.status = HttpStatus.OK; response.getBody(); } - public class Message { + public static class Message { public String name; public String message; } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 0707bb08..f88b518d 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: dynmap main: org.dynmap.DynmapPlugin -version: 0.1 +version: 0.13 commands: dynmap: description: Controls Dynmap. diff --git a/web/chat_style.css b/web/chat_style.css index 089bd6c8..312d1f77 100644 --- a/web/chat_style.css +++ b/web/chat_style.css @@ -29,7 +29,7 @@ color: white; border: 0px; background: rgba(0, 0, 0, 0.6); - background: url(chat_cursor.png) rgba(0,0,0,0.6); background-repeat: no-repeat; background-position:left; + background: url(images/chat_cursor.png) rgba(0,0,0,0.6); background-repeat: no-repeat; background-position:left; outline: none; } .messagelist { diff --git a/web/dynmap_style.css b/web/dynmap_style.css index 78344522..0f9c88ff 100644 --- a/web/dynmap_style.css +++ b/web/dynmap_style.css @@ -182,8 +182,8 @@ body { text-align: center; - background: url(sidebar_hint.png) rgb(0,0,0); - background: url(sidebar_hint.png) rgba(0,0,0,0.6); + background: url(images/sidebar_hint.png) rgb(0,0,0); + background: url(images/sidebar_hint.png) rgba(0,0,0,0.6); background-repeat: no-repeat; background-position:center; @@ -223,19 +223,19 @@ body { width: 16px; height: 16px; - background-image: url(window_close.png); + background-image: url(images/window_close.png); } .dynmap .sidebar .panel > .pin:hover { - background-image: url(window_pinned_hover.png); + background-image: url(images/window_pinned_hover.png); } .dynmap .sidebar.pinned .panel > .pin:hover { - background-image: url(window_close_hover.png); + background-image: url(images/window_close_hover.png); } .dynmap .sidebar.pinned .panel > .pin { - background-image: url(window_pinned.png); + background-image: url(images/window_pinned.png); } @@ -260,12 +260,12 @@ body { } .clock.night { - /* background-image: url(clock_night.png); */ + /* background-image: url(images/clock_night.png); */ color: #dff; } .clock.day { - /* background-image: url(clock_day.png); */ + /* background-image: url(images/clock_day.png); */ color: #fd3; } @@ -299,11 +299,11 @@ body { } .timeofday.sun { - background-image: url(sun.png); + background-image: url(images/sun.png); } .timeofday.moon { - background-image: url(moon.png); + background-image: url(images/moon.png); } /******************* @@ -418,11 +418,11 @@ body { } .dynmap .playerlist .player:hover .playericon { - background: url(player_follow_off.png) no-repeat; + background: url(images/player_follow_off.png) no-repeat; } .dynmap .playerlist .player.following .playericon { - background: url(player_follow_on.gif) no-repeat; + background: url(images/player_follow_on.gif) no-repeat; } .dynmap .playerlist .player.following .playericon > *, @@ -465,7 +465,7 @@ body { width: 83px; background-repeat: no-repeat; - background-image: url(compass.png); + background-image: url(images/compass.png); } /******************* @@ -499,7 +499,7 @@ body { border: 0px; background: rgba(0, 0, 0, 0.6); - background: url(chat_cursor.png) rgba(0,0,0,0.6); + background: url(images/chat_cursor.png) rgba(0,0,0,0.6); background-repeat: no-repeat; background-position: 1px center; diff --git a/web/flatmap.js b/web/flatmap.js new file mode 100644 index 00000000..1ceaa154 --- /dev/null +++ b/web/flatmap.js @@ -0,0 +1,43 @@ +function FlatProjection() {} +FlatProjection.prototype = { + fromLatLngToPoint: function(latLng) { + return new google.maps.Point(latLng.lat()*128.0, latLng.lng()*128.0); + }, + fromPointToLatLng: function(point) { + return new google.maps.LatLng(point.x/128.0, point.y/128.0); + }, + fromWorldToLatLng: function(x, y, z) { + return new google.maps.LatLng(x / 128.0, z / 128.0); + } +}; + +function FlatMapType(configuration) { + $.extend(this, configuration); } +FlatMapType.prototype = $.extend(new DynMapType(), { + constructor: FlatMapType, + projection: new FlatProjection(), + tileSize: new google.maps.Size(128.0, 128.0), + minZoom: 0, + maxZoom: 0, + prefix: null, + getTile: function(coord, zoom, doc) { + var tileName; + var tile = $('') + .attr('src', this.dynmap.getTileUrl(tileName = this.prefix + '_128_' + coord.x + '_' + coord.y + '.png')) + .error(function() { tile.hide(); }) + .bind('load', function() { tile.show(); }) + .css({ + width: '128px', + height: '128px', + borderStyle: 'none' + }) + .hide(); + this.dynmap.registerTile(this, tileName, tile); + //this.dynmap.unregisterTile(this, tileName); + return tile.get(0); + }, + updateTileSize: function(zoom) { + } +}); + +maptypes.FlatMapType = function(configuration) { return new FlatMapType(configuration); }; \ No newline at end of file diff --git a/web/block_cave.png b/web/images/block_cave.png similarity index 100% rename from web/block_cave.png rename to web/images/block_cave.png diff --git a/web/block_nether.png b/web/images/block_nether.png similarity index 100% rename from web/block_nether.png rename to web/images/block_nether.png diff --git a/web/block_other.png b/web/images/block_other.png similarity index 100% rename from web/block_other.png rename to web/images/block_other.png diff --git a/web/block_surface.png b/web/images/block_surface.png similarity index 100% rename from web/block_surface.png rename to web/images/block_surface.png diff --git a/web/book.png b/web/images/book.png similarity index 100% rename from web/book.png rename to web/images/book.png diff --git a/web/cave_off.png b/web/images/cave_off.png similarity index 100% rename from web/cave_off.png rename to web/images/cave_off.png diff --git a/web/cave_on.png b/web/images/cave_on.png similarity index 100% rename from web/cave_on.png rename to web/images/cave_on.png diff --git a/web/chat_bubble.png b/web/images/chat_bubble.png similarity index 100% rename from web/chat_bubble.png rename to web/images/chat_bubble.png diff --git a/web/chat_cursor.png b/web/images/chat_cursor.png similarity index 100% rename from web/chat_cursor.png rename to web/images/chat_cursor.png diff --git a/web/clock_day.png b/web/images/clock_day.png similarity index 100% rename from web/clock_day.png rename to web/images/clock_day.png diff --git a/web/clock_night.png b/web/images/clock_night.png similarity index 100% rename from web/clock_night.png rename to web/images/clock_night.png diff --git a/web/compass.png b/web/images/compass.png similarity index 100% rename from web/compass.png rename to web/images/compass.png diff --git a/web/compass_alt.png b/web/images/compass_alt.png similarity index 100% rename from web/compass_alt.png rename to web/images/compass_alt.png diff --git a/web/dynmap.ico b/web/images/dynmap.ico similarity index 100% rename from web/dynmap.ico rename to web/images/dynmap.ico diff --git a/web/follow_off.png b/web/images/follow_off.png similarity index 100% rename from web/follow_off.png rename to web/images/follow_off.png diff --git a/web/follow_on.png b/web/images/follow_on.png similarity index 100% rename from web/follow_on.png rename to web/images/follow_on.png diff --git a/web/home.png b/web/images/home.png similarity index 100% rename from web/home.png rename to web/images/home.png diff --git a/web/list_off.png b/web/images/list_off.png similarity index 100% rename from web/list_off.png rename to web/images/list_off.png diff --git a/web/list_on.png b/web/images/list_on.png similarity index 100% rename from web/list_on.png rename to web/images/list_on.png diff --git a/web/moon.png b/web/images/moon.png similarity index 100% rename from web/moon.png rename to web/images/moon.png diff --git a/web/player.png b/web/images/player.png similarity index 100% rename from web/player.png rename to web/images/player.png diff --git a/web/player_death.png b/web/images/player_death.png similarity index 100% rename from web/player_death.png rename to web/images/player_death.png diff --git a/web/player_face.png b/web/images/player_face.png similarity index 100% rename from web/player_face.png rename to web/images/player_face.png diff --git a/web/player_follow_off.png b/web/images/player_follow_off.png similarity index 100% rename from web/player_follow_off.png rename to web/images/player_follow_off.png diff --git a/web/player_follow_on.gif b/web/images/player_follow_on.gif similarity index 100% rename from web/player_follow_on.gif rename to web/images/player_follow_on.gif diff --git a/web/player_follow_on.png b/web/images/player_follow_on.png similarity index 100% rename from web/player_follow_on.png rename to web/images/player_follow_on.png diff --git a/web/player_travel.png b/web/images/player_travel.png similarity index 100% rename from web/player_travel.png rename to web/images/player_travel.png diff --git a/web/server.png b/web/images/server.png similarity index 100% rename from web/server.png rename to web/images/server.png diff --git a/web/sidebar_hint.png b/web/images/sidebar_hint.png similarity index 100% rename from web/sidebar_hint.png rename to web/images/sidebar_hint.png diff --git a/web/sign.png b/web/images/sign.png similarity index 100% rename from web/sign.png rename to web/images/sign.png diff --git a/web/sign_home.png b/web/images/sign_home.png similarity index 100% rename from web/sign_home.png rename to web/images/sign_home.png diff --git a/web/sign_sign.png b/web/images/sign_sign.png similarity index 100% rename from web/sign_sign.png rename to web/images/sign_sign.png diff --git a/web/sign_sign_alt.png b/web/images/sign_sign_alt.png similarity index 100% rename from web/sign_sign_alt.png rename to web/images/sign_sign_alt.png diff --git a/web/sign_warp.png b/web/images/sign_warp.png similarity index 100% rename from web/sign_warp.png rename to web/images/sign_warp.png diff --git a/web/spawn.png b/web/images/spawn.png similarity index 100% rename from web/spawn.png rename to web/images/spawn.png diff --git a/web/sun.png b/web/images/sun.png similarity index 100% rename from web/sun.png rename to web/images/sun.png diff --git a/web/warp.png b/web/images/warp.png similarity index 100% rename from web/warp.png rename to web/images/warp.png diff --git a/web/window_close.png b/web/images/window_close.png similarity index 100% rename from web/window_close.png rename to web/images/window_close.png diff --git a/web/window_close_hover.png b/web/images/window_close_hover.png similarity index 100% rename from web/window_close_hover.png rename to web/images/window_close_hover.png diff --git a/web/window_open.png b/web/images/window_open.png similarity index 100% rename from web/window_open.png rename to web/images/window_open.png diff --git a/web/window_pinned.png b/web/images/window_pinned.png similarity index 100% rename from web/window_pinned.png rename to web/images/window_pinned.png diff --git a/web/window_pinned_hover.png b/web/images/window_pinned_hover.png similarity index 100% rename from web/window_pinned_hover.png rename to web/images/window_pinned_hover.png diff --git a/web/window_unpinned.png b/web/images/window_unpinned.png similarity index 100% rename from web/window_unpinned.png rename to web/images/window_unpinned.png diff --git a/web/zoom_in.png b/web/images/zoom_in.png similarity index 100% rename from web/zoom_in.png rename to web/images/zoom_in.png diff --git a/web/zoom_out.png b/web/images/zoom_out.png similarity index 100% rename from web/zoom_out.png rename to web/images/zoom_out.png diff --git a/web/index.html b/web/index.html index 9ad0328d..6f57c402 100644 --- a/web/index.html +++ b/web/index.html @@ -8,7 +8,7 @@ - + @@ -20,6 +20,7 @@ + diff --git a/web/kzedmaps.js b/web/kzedmaps.js index 3814ad5b..262e7ba9 100644 --- a/web/kzedmaps.js +++ b/web/kzedmaps.js @@ -39,29 +39,21 @@ KzedMapType.prototype = $.extend(new DynMapType(), { var tileSize = 128; var tileName; var imgSize; - var offset = {x: 0, y: 0}; var debugred; var debugblue; if (zoom == 0) { // Most zoomed out tiles. - tileSize = 128; imgSize = tileSize; tileName = 'z' + this.prefix + '_' + (-coord.x * tileSize*2) + '_' + (coord.y * tileSize*2) + '.png'; } else { // Other zoom levels. tileSize = 128; - - // Helper functions. - /*var floor = Math.floor; - var div = function(x,y){return floor(x/y);} - var mod = function(x,y){return ((x%y)+y)%y;};*/ imgSize = Math.pow(2, 6+zoom); - var mapcoord = {x: coord.x*tileSize, y: coord.y*tileSize}; - tileName = this.prefix + '_' + (-mapcoord.x) + '_' + mapcoord.y + '.png'; + tileName = this.prefix + '_' + (-coord.x*tileSize) + '_' + (coord.y*tileSize) + '.png'; } var img; var tile = $('
') @@ -87,9 +79,7 @@ KzedMapType.prototype = $.extend(new DynMapType(), { .css({ width: imgSize + 'px', height: imgSize + 'px', - borderStyle: 'none', - /*marginLeft: offset.x + 'px', - marginTop: offset.y + 'px'*/ + borderStyle: 'none' }) .hide() .appendTo(tile); diff --git a/web/map.js b/web/map.js index 53d48bf0..326bf977 100644 --- a/web/map.js +++ b/web/map.js @@ -44,6 +44,8 @@ function DynMap(options) { $.getJSON(me.options.updateUrl + 'configuration', function(configuration) { me.configure(configuration); me.initialize(); + }, function(status, statusMessage) { + alert('Could not retrieve configuration: ' + statusMessage); }); } DynMap.prototype = { @@ -156,7 +158,7 @@ DynMap.prototype = { .append($('') .attr({ title: map.title, href: '#' }) .addClass('maptype') - .css({ backgroundImage: 'url(' + (map.icon || 'block_' + map.name + '.png') + ')' }) + .css({ backgroundImage: 'url(' + (map.icon || 'images/block_' + map.name + '.png') + ')' }) .text(map.title) ) .click(function() { @@ -208,7 +210,7 @@ DynMap.prototype = { value: '' }) .keydown(function(event) { - if (event.keyCode === '13') { + if (event.keyCode == '13') { event.preventDefault(); sendChat(chatinput.val()); chatinput.val(''); @@ -232,6 +234,7 @@ DynMap.prototype = { var alertbox = me.alertbox = $('
') .addClass('alertbox') + .hide() .appendTo(container); me.selectMap(me.defaultworld.defaultmap); @@ -333,9 +336,9 @@ DynMap.prototype = { //divs.filter(function(i){return parseInt(divs[i].attr('rel')) > timestamp+me.options.messagettl;}).remove(); }); setTimeout(function() { me.update(); }, me.options.updaterate); - }, function(request, statusText, ex) { + }, function(status, statusText, request) { me.alertbox - .text('Could not update map') + .text('Could not update map: ' + (statusText || 'Could not connect to server')) .show(); setTimeout(function() { me.update(); }, me.options.updaterate); } @@ -488,7 +491,7 @@ DynMap.prototype = { .addClass('Marker') .addClass('playerMarker') .append(playerImage = $('') - .attr({ src: 'player.png' })) + .attr({ src: 'images/player.png' })) .append($('') .addClass('playerName') .text(player.name)); @@ -509,7 +512,7 @@ DynMap.prototype = { .addClass('player') .append(playerIconContainer = $('') .addClass('playerIcon') - .append($('').attr({ src: 'player_face.png' })) + .append($('').attr({ src: 'images/player_face.png' })) .attr({ title: 'Follow ' + player.name }) .click(function() { var follow = player !== me.followingPlayer; @@ -523,7 +526,10 @@ DynMap.prototype = { }) .text(player.name) ) - .click(function(e) { me.panTo(player.location); }) + .click(function(e) { + me.followPlayer(null); + me.panTo(player.location); + }) .appendTo(me.playerlist); if (me.options.showplayerfacesinmenu) { getMinecraftHead(player.name, 16, function(head) { diff --git a/web/minecraft.js b/web/minecraft.js index 31900eac..d7eb7cd4 100644 --- a/web/minecraft.js +++ b/web/minecraft.js @@ -34,7 +34,7 @@ function createMinecraftHead(player,completed,failed) { skinImage.src = 'http://www.minecraft.net/img/char.png'; } }; - skinImage.src = 'http://www.minecraft.net/skin/' + player + '.png'; + skinImage.src = 'http://s3.amazonaws.com/MinecraftSkins/' + player + '.png'; } function resizeImage(img,size) { @@ -93,4 +93,4 @@ function getMinecraftTime(servertime) { day: day, night: !day }; -} \ No newline at end of file +} diff --git a/web/override_example.css b/web/override_example.css index a353b45d..56f69c5a 100644 --- a/web/override_example.css +++ b/web/override_example.css @@ -1,17 +1,19 @@ /******************* * This is the over-ride CSS file. * - * if you know any CSS you can easily add any custom rules to change how - * Dynmap looks for your particular install. + * if you know any CSS you can easily add custom rules to change how DynMap + * looks and behaves under your DynMap installation. * - * Simply uncomment the override.css in the index.html and rename this file - * to override.css to use these custom rules. + * 1. Uncomment the override.css in the index.html. + * 2. Rename this file or create a new override.css. + * 3. Add your own rules (or steal these) to personalize how DynMap looks. * - * By adding these rules here you can easily save your changes between updates. + * By adding your own rules here, you can then save your changes + * between DynMap updates and they won't get over-written. */ -/* IE : Use the alternate compass image */ +/* Use the alternate compass image */ .compass { top: 20px; @@ -20,5 +22,18 @@ height: 50px; width: 50px; - background-image: url(compass_alt.png); + background-image: url(images/compass_alt.png); } + +/* These next two keep the DynMap sidebar open... */ + +.dynmap .sidebar { + margin-right: 0px; +} + +/* ...and hide the hitbar along with the sidebar controls */ + +.dynmap .sidebar .hitbar, +.dynmap .sidebar .panel > .pin { + display: none; +} \ No newline at end of file