mirror of https://github.com/webbukkit/dynmap.git
Compare commits
485 Commits
Author | SHA1 | Date |
---|---|---|
|
425ca0fdb6 | |
|
435472085d | |
|
d78a4fd11b | |
|
d00ff62426 | |
|
313933fa5c | |
|
a0effe21f6 | |
|
3365883b60 | |
|
60aac56d40 | |
|
788addccde | |
|
4d7d66f199 | |
|
f38e638d22 | |
|
d90fd79c47 | |
|
eff2f7c512 | |
|
f672be63cb | |
|
8277caa397 | |
|
b434f09035 | |
|
e21198d279 | |
|
1d6346b580 | |
|
e086930133 | |
|
27526e64e5 | |
|
21369ec485 | |
|
120889b500 | |
|
669c75322a | |
|
29f4aaf419 | |
|
13f0f7241a | |
|
8cfc8f35b9 | |
|
41da0aaf63 | |
|
d80fb25213 | |
|
ea24554033 | |
|
b9144e3609 | |
|
9878719337 | |
|
6746631758 | |
|
23cd60ba0a | |
|
328954b256 | |
|
574a400ada | |
|
84ee4cdf0c | |
|
dea6a55acd | |
|
87993219bb | |
|
7cdd90768e | |
|
b0e56d3e5a | |
|
20700c21b8 | |
|
85885ced0e | |
|
06fbcb8d3d | |
|
b181607e5a | |
|
bb1438b3c4 | |
|
1ba6dd4683 | |
|
d16fdc8275 | |
|
914fc5a10c | |
|
a669d75de0 | |
|
bc0117ac5a | |
|
298b31cdc8 | |
|
5244e74d47 | |
|
0d15ee5a46 | |
|
ca80758605 | |
|
96554717f1 | |
|
c807861859 | |
|
65cca049ac | |
|
0ba3c8008f | |
|
030a0e1d24 | |
|
79f354b111 | |
|
92b9016c65 | |
|
e6a18f1029 | |
|
ff87b9dd3e | |
|
2d723afba1 | |
|
f5d2244450 | |
|
e429a53d27 | |
|
169bb81ca7 | |
|
91c4b23a0e | |
|
e2a5fc80d3 | |
|
736dd5a290 | |
|
7905f76d51 | |
|
b97d5045b6 | |
|
85012ae478 | |
|
d1408b7bfd | |
|
c093a95bc0 | |
|
7ed6728e34 | |
|
eed1a2b444 | |
|
b8b1e8bd4e | |
|
ae164f2993 | |
|
ebb9dc00d0 | |
|
31d1b400f0 | |
|
105e3887a0 | |
|
0120c135c4 | |
|
b8166a9122 | |
|
247e81bc61 | |
|
fe49d37fa9 | |
|
20592cd805 | |
|
b310a57b64 | |
|
6b3e18c351 | |
|
105d4f1b62 | |
|
2503dbfdbb | |
|
87d8c73941 | |
|
cee25bc518 | |
|
3715b114e9 | |
|
881b83b7f1 | |
|
7f6dc1d52c | |
|
38ccb50d6a | |
|
fa36d3fa38 | |
|
983fda35b4 | |
|
4e7dcb2cfb | |
|
e0c02b1fc0 | |
|
b2f04ce112 | |
|
57093caa5f | |
|
551b3adda7 | |
|
f249ce60b5 | |
|
2f742734d0 | |
|
dd81ea2d87 | |
|
126d8e5d05 | |
|
6863243d49 | |
|
43a86b820c | |
|
130953bc12 | |
|
2d835eaeec | |
|
5aeca48e2b | |
|
427bd6d0ef | |
|
05b751a60e | |
|
1450a57aba | |
|
0ee1b6001a | |
|
1d94af6a11 | |
|
8f10ece108 | |
|
2456c36649 | |
|
7bcce9c7e0 | |
|
3f2d9dd5df | |
|
7218e56e5b | |
|
4e61fa6b22 | |
|
d1b95c9ae0 | |
|
1ccffb7693 | |
|
5bcfe052a5 | |
|
8b1b26c570 | |
|
022a031829 | |
|
9c0a1e45fc | |
|
3b970c7119 | |
|
436dfa22a0 | |
|
bcd4ed617a | |
|
ab900740b7 | |
|
76649c6250 | |
|
89d06d158d | |
|
2c32cbc0d5 | |
|
cc9f6f0bc4 | |
|
8dd9e6eb5a | |
|
ea21f4c4df | |
|
485aec3c1c | |
|
0f0d4f2ce9 | |
|
83d9247f78 | |
|
bfd43d678c | |
|
9a02868534 | |
|
f25d17d3ce | |
|
4a0225bf83 | |
|
7af46a04a6 | |
|
2fd5db2835 | |
|
caef8f433e | |
|
a52ea70b27 | |
|
b4c4b21a04 | |
|
3bb74d41c2 | |
|
ff5f829f16 | |
|
eee5565f86 | |
|
d85be30e43 | |
|
098081f2f3 | |
|
bb0e9dada7 | |
|
fd2e4ba8c8 | |
|
c508711f1c | |
|
52829462e9 | |
|
1a261c6422 | |
|
bf8a8d9b45 | |
|
cc88883dc1 | |
|
7b82a9182e | |
|
4efc418691 | |
|
f773175a7b | |
|
dbfcfe03d4 | |
|
322c370bbc | |
|
6fd70b65fe | |
|
202625ac23 | |
|
8f62d8e57e | |
|
d681f05eeb | |
|
ae9e144774 | |
|
af930cd9d4 | |
|
a6548ec0b7 | |
|
5ddcf1794e | |
|
9f9d12a580 | |
|
fe100abb51 | |
|
edf6e256e1 | |
|
814068cf53 | |
|
287d900047 | |
|
bc7ecb4f23 | |
|
0122561150 | |
|
e168e87bba | |
|
fe4ff57279 | |
|
8af0ad8b8c | |
|
9e58477f3d | |
|
7dee2150b6 | |
|
7a5440f32e | |
|
c1fcfd15b6 | |
|
743c6ee946 | |
|
68a379cdd2 | |
|
5795ebeac6 | |
|
0f6c2520ff | |
|
2ed13761c4 | |
|
eca305c519 | |
|
d048aad743 | |
|
e0cbd1fe8e | |
|
e15f3f8460 | |
|
26fa3a24c5 | |
|
7d1a273e6d | |
|
9f16074a75 | |
|
9a8ef557af | |
|
7f71e7ef9b | |
|
a5e7ae1013 | |
|
e3911b0d3b | |
|
adc9e273ca | |
|
4fdb04725d | |
|
d434b33cfb | |
|
1f352e0b11 | |
|
ed9fb8614d | |
|
9060c8f32b | |
|
a6ead1bc3d | |
|
6245a18381 | |
|
0043a1e4fb | |
|
ec3c0e998b | |
|
c643430225 | |
|
64407e3ce1 | |
|
0f8174796c | |
|
53b3b7c08b | |
|
ce54de0cd7 | |
|
0ebbc2bbe5 | |
|
a40592021f | |
|
053df84196 | |
|
97a82a3d1b | |
|
f34929c6cf | |
|
5f29846645 | |
|
8a8e2ecfcf | |
|
1f1a342777 | |
|
59f44f7425 | |
|
39adaeca56 | |
|
8ce85322dd | |
|
a70530edc8 | |
|
61bfe66430 | |
|
66fe5d4a8b | |
|
5aaff7cea9 | |
|
686d61c463 | |
|
d25040e1cf | |
|
adfe0471e3 | |
|
e32b8d0f77 | |
|
5d867239b2 | |
|
aa4d50503e | |
|
f96b4d2900 | |
|
2a10499325 | |
|
a6b56dc36e | |
|
0445814ef5 | |
|
4cd915e1ab | |
|
171b7c9e54 | |
|
7ddecaa566 | |
|
a2c1941585 | |
|
b9e57e4e33 | |
|
058599be77 | |
|
36924b4942 | |
|
0eb2dffac2 | |
|
e2da0efd8e | |
|
36ea4c3938 | |
|
d0e9b66d4a | |
|
f89777a0dd | |
|
0ab9c9e47b | |
|
3b0814e853 | |
|
46bd040981 | |
|
8909fea4b1 | |
|
b5ac020a56 | |
|
7570cf5994 | |
|
85f09b9c2f | |
|
fe97e28401 | |
|
43c1159fae | |
|
b331cfaf27 | |
|
dc66d12916 | |
|
082878aade | |
|
bf8d5eb6cf | |
|
7dabbab8c9 | |
|
e943a26a5b | |
|
1de1c7ce69 | |
|
682ed12c69 | |
|
dc0296f845 | |
|
9cd7a3489a | |
|
4ec0d5af37 | |
|
47f5779e6f | |
|
937ab7cee7 | |
|
a71348c3c8 | |
|
9648457727 | |
|
e0619ec650 | |
|
8e27d5defd | |
|
d88ebb0d20 | |
|
e13a515baf | |
|
8beba92f8e | |
|
c80f7adb23 | |
|
ab54919956 | |
|
e68f628131 | |
|
00a0d3ed37 | |
|
fc678a056f | |
|
2d6bcbbca2 | |
|
c248ce3275 | |
|
8f70d5fc3c | |
|
4d34510c8b | |
|
075b27a2c4 | |
|
425c870895 | |
|
8e02c21a36 | |
|
ca5d2f4990 | |
|
b933f6b21c | |
|
17e60cff40 | |
|
8d8a4d088e | |
|
dd789b3a41 | |
|
a8af8037cb | |
|
d93a014c99 | |
|
3b1cbdca09 | |
|
c25945ea13 | |
|
9f865fa5bd | |
|
53f048ac86 | |
|
5818919607 | |
|
69cd5777fc | |
|
a119844669 | |
|
5009159fb4 | |
|
63ab35a9a5 | |
|
e7e8f1c245 | |
|
57b48ba56f | |
|
9b7c7aa496 | |
|
9f20e7a174 | |
|
4f1ec1131c | |
|
a39e00ac0f | |
|
9c9c93493e | |
|
f8a81ce0ac | |
|
0592bc9f04 | |
|
85d558d932 | |
|
61a377a3ac | |
|
374309e004 | |
|
6306ae59ea | |
|
79ed487311 | |
|
536b96a5f9 | |
|
078275d16d | |
|
24ecd0f72c | |
|
f02a73bb0d | |
|
556051dc9a | |
|
f80bb89d96 | |
|
4e41f1778b | |
|
61b03bcdbb | |
|
0ba89fefc4 | |
|
16b30ee40f | |
|
bf4f31c380 | |
|
505d78a8e0 | |
|
a2951b798d | |
|
8763ad91e4 | |
|
b2a072c45c | |
|
5791632d35 | |
|
b3169a6442 | |
|
fa6b729b6e | |
|
9c80489ec6 | |
|
d4b097ea50 | |
|
d0a791b634 | |
|
c3214a81bb | |
|
da05fc4675 | |
|
790f1f4966 | |
|
75789b29a6 | |
|
4a97550b63 | |
|
c5d113b77a | |
|
de510108a2 | |
|
7268db3ed2 | |
|
241bc53cb9 | |
|
5a3a216689 | |
|
b0f0a4deb5 | |
|
c8801dbb8c | |
|
971a492964 | |
|
d93b836ad0 | |
|
7feb9e6735 | |
|
861d1f8606 | |
|
93c9ab0b5b | |
|
ab76953294 | |
|
53b65ab7e4 | |
|
aec1f0cdb6 | |
|
042f387ecf | |
|
8aa757b049 | |
|
8626d0a1cc | |
|
f52d2e6c1a | |
|
015309f8ba | |
|
ec6fd59999 | |
|
04fba09583 | |
|
a765f728f1 | |
|
d4d60882fc | |
|
7dd55de52e | |
|
98f2057dd0 | |
|
4c2e22e273 | |
|
c3d36dfbf2 | |
|
a86c8a29e1 | |
|
92af9b5814 | |
|
d635473d50 | |
|
19ee08716b | |
|
1016c7833b | |
|
fb37658588 | |
|
8fee16cd4e | |
|
0d7bfc718e | |
|
0f482489f7 | |
|
cb167d9c04 | |
|
e47d6521f4 | |
|
ed27140fb5 | |
|
58a2b16217 | |
|
cf528d22cc | |
|
9d1b84c9d2 | |
|
3cbd198a2a | |
|
60147e8d16 | |
|
a9b4ace851 | |
|
037d1803a7 | |
|
97e5627e0d | |
|
f075bf236c | |
|
ad226141fe | |
|
6a95c9231a | |
|
b6d0c816a4 | |
|
9066fa0135 | |
|
50e6317fa9 | |
|
f27fbc9f3e | |
|
1f8bd81894 | |
|
10289f85b7 | |
|
d9c5b78dbc | |
|
ef045da32f | |
|
ea97296684 | |
|
45bc02cf3a | |
|
be43f53d81 | |
|
50dce9b854 | |
|
ec8d44ea7c | |
|
8eb69514f2 | |
|
474c5ecca9 | |
|
a81249539b | |
|
ee78384cdc | |
|
fb0cceca58 | |
|
3a39688dc8 | |
|
342e67e205 | |
|
15b1328c0e | |
|
04147aadb1 | |
|
dacd51aabb | |
|
53c4ebf233 | |
|
19038b3f8b | |
|
b43efb1bb6 | |
|
d0e627607b | |
|
9126cbf649 | |
|
685b4f9e68 | |
|
de79f8e8bc | |
|
dc129548aa | |
|
619167c2df | |
|
41b5c6f353 | |
|
069c518a7c | |
|
6e2959a63a | |
|
95c41d91be | |
|
b88aa42853 | |
|
d941aec6eb | |
|
de344869b7 | |
|
93c84ef15e | |
|
ff2e1b3b50 | |
|
7121233462 | |
|
8fbc3e3534 | |
|
611832fa22 | |
|
a2f8f9defa | |
|
b3de1dafe3 | |
|
f441cf4ecd | |
|
79f27e9565 | |
|
cf5f4a0d9e | |
|
23b33a7828 | |
|
9d89e56586 | |
|
d6b1383825 | |
|
c83af6dfdc | |
|
cfcd8fbf3e | |
|
e16b642e0c | |
|
1093da7657 | |
|
0c34d5a5b5 | |
|
6ce6b4a07f | |
|
b8d08a8ce2 | |
|
88cea7c6e6 | |
|
e70f2845e8 | |
|
bdfa148bfb | |
|
fec2d1af03 | |
|
6b208dd038 | |
|
716635c20e | |
|
e1af7ad952 | |
|
129c666a1a | |
|
8e7b57bd89 | |
|
26a987c98d | |
|
8efdbed0b4 | |
|
327833832d | |
|
014760d142 | |
|
b1a320d4bb | |
|
4b8fa4a81d | |
|
66082093de | |
|
3c76c3f875 | |
|
592ad5028e | |
|
1e5cea1829 |
|
@ -36,6 +36,9 @@ ko
|
||||||
patreon
|
patreon
|
||||||
README
|
README
|
||||||
Gradle
|
Gradle
|
||||||
|
gradlew
|
||||||
|
gradle
|
||||||
|
oldgradle
|
||||||
Curseforge
|
Curseforge
|
||||||
SpigotMC
|
SpigotMC
|
||||||
PaperMC
|
PaperMC
|
||||||
|
@ -55,3 +58,5 @@ JDK
|
||||||
ForgeGradle
|
ForgeGradle
|
||||||
Kosma
|
Kosma
|
||||||
Kosma's
|
Kosma's
|
||||||
|
DEV
|
||||||
|
Modrinth
|
||||||
|
|
|
@ -11,4 +11,4 @@ jobs:
|
||||||
- name: actions/checkout
|
- name: actions/checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
- name: rojopolis/spellcheck - actually doing something
|
- name: rojopolis/spellcheck - actually doing something
|
||||||
uses: rojopolis/spellcheck-github-actions@0.20.0
|
uses: rojopolis/spellcheck-github-actions@0.29.0
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
{
|
{
|
||||||
"java.configuration.updateBuildConfiguration": "automatic"
|
"java.configuration.updateBuildConfiguration": "automatic",
|
||||||
|
"java.compile.nullAnalysis.mode": "automatic"
|
||||||
}
|
}
|
|
@ -1,14 +1,31 @@
|
||||||
description = "DynmapCore"
|
description = "DynmapCore"
|
||||||
|
|
||||||
|
apply plugin: 'eclipse'
|
||||||
|
|
||||||
|
eclipse {
|
||||||
|
project {
|
||||||
|
name = "Dynmap(DynmapCore)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(path: ':DynmapCoreAPI', configuration: 'shadow')
|
implementation project(':DynmapCoreAPI')
|
||||||
implementation 'javax.servlet:javax.servlet-api:3.1'
|
implementation 'javax.servlet:javax.servlet-api:3.1'
|
||||||
implementation 'org.eclipse.jetty:jetty-server:9.4.26.v20200117'
|
implementation'org.eclipse.jetty:jetty-server:9.4.26.v20200117'
|
||||||
implementation 'org.eclipse.jetty:jetty-servlet:9.4.26.v20200117'
|
implementation 'org.eclipse.jetty:jetty-servlet:9.4.26.v20200117'
|
||||||
implementation 'com.googlecode.json-simple:json-simple:1.1.1'
|
implementation 'com.googlecode.json-simple:json-simple:1.1.1'
|
||||||
implementation 'org.yaml:snakeyaml:1.23' // DON'T UPDATE - NEWER ONE TRIPS ON WINDOWS ENCODED FILES
|
implementation 'org.yaml:snakeyaml:1.23' // DON'T UPDATE - NEWER ONE TRIPS ON WINDOWS ENCODED FILES
|
||||||
implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20180219.1'
|
implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20180219.1'
|
||||||
implementation 'org.postgresql:postgresql:42.2.18'
|
implementation 'org.postgresql:postgresql:42.2.18'
|
||||||
|
implementation 'io.github.linktosriram.s3lite:core:0.0.2-SNAPSHOT'
|
||||||
|
implementation 'io.github.linktosriram.s3lite:api:0.0.2-SNAPSHOT'
|
||||||
|
implementation 'io.github.linktosriram.s3lite:http-client-url-connection:0.0.2-SNAPSHOT'
|
||||||
|
implementation 'io.github.linktosriram.s3lite:http-client-spi:0.0.2-SNAPSHOT'
|
||||||
|
implementation 'io.github.linktosriram.s3lite:util:0.0.2-SNAPSHOT'
|
||||||
|
implementation 'jakarta.xml.bind:jakarta.xml.bind-api:3.0.1'
|
||||||
|
implementation 'com.sun.xml.bind:jaxb-impl:3.0.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
|
@ -31,7 +48,7 @@ processResources {
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
classifier = 'unshaded'
|
archiveClassifier = 'unshaded'
|
||||||
}
|
}
|
||||||
|
|
||||||
shadowJar {
|
shadowJar {
|
||||||
|
@ -43,6 +60,13 @@ shadowJar {
|
||||||
include(dependency('org.eclipse.jetty::'))
|
include(dependency('org.eclipse.jetty::'))
|
||||||
include(dependency('org.eclipse.jetty.orbit:javax.servlet:'))
|
include(dependency('org.eclipse.jetty.orbit:javax.servlet:'))
|
||||||
include(dependency('org.postgresql:postgresql:'))
|
include(dependency('org.postgresql:postgresql:'))
|
||||||
|
include(dependency('io.github.linktosriram.s3lite:core:'))
|
||||||
|
include(dependency('io.github.linktosriram.s3lite:api:'))
|
||||||
|
include(dependency('io.github.linktosriram.s3lite:http-client-url-connection:'))
|
||||||
|
include(dependency('io.github.linktosriram.s3lite:http-client-spi:'))
|
||||||
|
include(dependency('io.github.linktosriram.s3lite:util:'))
|
||||||
|
include(dependency('jakarta.xml.bind::'))
|
||||||
|
include(dependency('com.sun.xml.bind::'))
|
||||||
include(dependency(':DynmapCoreAPI'))
|
include(dependency(':DynmapCoreAPI'))
|
||||||
exclude("META-INF/maven/**")
|
exclude("META-INF/maven/**")
|
||||||
exclude("META-INF/services/**")
|
exclude("META-INF/services/**")
|
||||||
|
@ -53,8 +77,10 @@ shadowJar {
|
||||||
relocate('org.owasp.html', 'org.dynmap.org.owasp.html')
|
relocate('org.owasp.html', 'org.dynmap.org.owasp.html')
|
||||||
relocate('javax.servlet', 'org.dynmap.javax.servlet' )
|
relocate('javax.servlet', 'org.dynmap.javax.servlet' )
|
||||||
relocate('org.postgresql', 'org.dynmap.org.postgresql')
|
relocate('org.postgresql', 'org.dynmap.org.postgresql')
|
||||||
destinationDir = file '../target'
|
relocate('io.github.linktosriram.s3lite', 'org.dynmap.s3lite')
|
||||||
classifier = ''
|
|
||||||
|
destinationDirectory = file '../target'
|
||||||
|
archiveClassifier = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
artifacts {
|
artifacts {
|
||||||
|
|
|
@ -4,8 +4,6 @@ import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import javax.sound.sampled.AudioFormat.Encoding;
|
|
||||||
|
|
||||||
import org.json.simple.JSONAware;
|
import org.json.simple.JSONAware;
|
||||||
import org.json.simple.JSONStreamAware;
|
import org.json.simple.JSONStreamAware;
|
||||||
import org.owasp.html.HtmlPolicyBuilder;
|
import org.owasp.html.HtmlPolicyBuilder;
|
||||||
|
@ -286,11 +284,14 @@ public class Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PolicyFactory sanitizer = null;
|
private static PolicyFactory sanitizer = null;
|
||||||
|
private static PolicyFactory OLDTAGS = new HtmlPolicyBuilder().allowElements("center", "basefont", "hr").toFactory();
|
||||||
public static String sanitizeHTML(String html) {
|
public static String sanitizeHTML(String html) {
|
||||||
|
// Don't sanitize if null or no html markup
|
||||||
|
if ((html == null) || (html.indexOf('<') < 0)) return html;
|
||||||
PolicyFactory s = sanitizer;
|
PolicyFactory s = sanitizer;
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
// Generous but safe html formatting allowances
|
// Generous but safe html formatting allowances
|
||||||
s = Sanitizers.FORMATTING.and(Sanitizers.BLOCKS).and(Sanitizers.IMAGES).and(Sanitizers.LINKS).and(Sanitizers.STYLES);
|
s = Sanitizers.FORMATTING.and(Sanitizers.BLOCKS).and(Sanitizers.IMAGES).and(Sanitizers.LINKS).and(Sanitizers.STYLES).and(Sanitizers.TABLES).and(OLDTAGS);
|
||||||
sanitizer = s;
|
sanitizer = s;
|
||||||
}
|
}
|
||||||
return s.sanitize(html);
|
return s.sanitize(html);
|
||||||
|
|
|
@ -12,6 +12,7 @@ public class ClientUpdateComponent extends Component {
|
||||||
private int hideifshadow;
|
private int hideifshadow;
|
||||||
private int hideifunder;
|
private int hideifunder;
|
||||||
private boolean hideifsneaking;
|
private boolean hideifsneaking;
|
||||||
|
private boolean hideifspectator;
|
||||||
private boolean hideifinvisiblepotion;
|
private boolean hideifinvisiblepotion;
|
||||||
private boolean is_protected;
|
private boolean is_protected;
|
||||||
public static boolean usePlayerColors;
|
public static boolean usePlayerColors;
|
||||||
|
@ -24,6 +25,7 @@ public class ClientUpdateComponent extends Component {
|
||||||
hideifshadow = configuration.getInteger("hideifshadow", 15);
|
hideifshadow = configuration.getInteger("hideifshadow", 15);
|
||||||
hideifunder = configuration.getInteger("hideifundercover", 15);
|
hideifunder = configuration.getInteger("hideifundercover", 15);
|
||||||
hideifsneaking = configuration.getBoolean("hideifsneaking", false);
|
hideifsneaking = configuration.getBoolean("hideifsneaking", false);
|
||||||
|
hideifspectator = configuration.getBoolean("hideifspectator", false);
|
||||||
hideifinvisiblepotion = configuration.getBoolean("hide-if-invisiblity-potion", true);
|
hideifinvisiblepotion = configuration.getBoolean("hide-if-invisiblity-potion", true);
|
||||||
is_protected = configuration.getBoolean("protected-player-info", false);
|
is_protected = configuration.getBoolean("protected-player-info", false);
|
||||||
usePlayerColors = configuration.getBoolean("use-name-colors", false);
|
usePlayerColors = configuration.getBoolean("use-name-colors", false);
|
||||||
|
@ -100,6 +102,9 @@ public class ClientUpdateComponent extends Component {
|
||||||
if((!hide) && hideifsneaking && p.isSneaking()) {
|
if((!hide) && hideifsneaking && p.isSneaking()) {
|
||||||
hide = true;
|
hide = true;
|
||||||
}
|
}
|
||||||
|
if((!hide) && hideifspectator && p.isSpectator()) {
|
||||||
|
hide = true;
|
||||||
|
}
|
||||||
if((!hide) && is_protected && (!see_all)) {
|
if((!hide) && is_protected && (!see_all)) {
|
||||||
if(e.user != null) {
|
if(e.user != null) {
|
||||||
hide = !core.testIfPlayerVisibleToPlayer(e.user, p.getName());
|
hide = !core.testIfPlayerVisibleToPlayer(e.user, p.getName());
|
||||||
|
|
|
@ -105,7 +105,6 @@ public class ColorScheme {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Integer id = null;
|
Integer id = null;
|
||||||
Integer dat = null;
|
|
||||||
boolean isbiome = false;
|
boolean isbiome = false;
|
||||||
boolean istemp = false;
|
boolean istemp = false;
|
||||||
boolean israin = false;
|
boolean israin = false;
|
||||||
|
@ -129,7 +128,7 @@ public class ColorScheme {
|
||||||
id = -1;
|
id = -1;
|
||||||
BiomeMap[] bm = BiomeMap.values();
|
BiomeMap[] bm = BiomeMap.values();
|
||||||
for (int i = 0; i < bm.length; i++) {
|
for (int i = 0; i < bm.length; i++) {
|
||||||
if (bm[i].toString().equalsIgnoreCase(bio)) {
|
if (bm[i].getId().equalsIgnoreCase(bio)) {
|
||||||
id = i;
|
id = i;
|
||||||
break;
|
break;
|
||||||
} else if (bio.equalsIgnoreCase("BIOME_" + i)) {
|
} else if (bio.equalsIgnoreCase("BIOME_" + i)) {
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
package org.dynmap;
|
package org.dynmap;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.Reader;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -82,13 +86,13 @@ public class ConfigurationNode implements Map<String, Object> {
|
||||||
initparse();
|
initparse();
|
||||||
// If no file to read, just return false
|
// If no file to read, just return false
|
||||||
if (!f.canRead()) { return false; }
|
if (!f.canRead()) { return false; }
|
||||||
FileInputStream fis = null;
|
Reader fr = null;
|
||||||
try {
|
try {
|
||||||
fis = new FileInputStream(f);
|
fr = new UnicodeReader(new BufferedInputStream(new FileInputStream(f)));
|
||||||
Object o = yaml.load(new UnicodeReader(fis));
|
Object o = yaml.load(fr);
|
||||||
if((o != null) && (o instanceof Map))
|
if((o != null) && (o instanceof Map))
|
||||||
entries = (Map<String, Object>)o;
|
entries = (Map<String, Object>)o;
|
||||||
fis.close();
|
fr.close();
|
||||||
}
|
}
|
||||||
catch (YAMLException e) {
|
catch (YAMLException e) {
|
||||||
Log.severe("Error parsing " + f.getPath() + ". Use http://yamllint.com to debug the YAML syntax." );
|
Log.severe("Error parsing " + f.getPath() + ". Use http://yamllint.com to debug the YAML syntax." );
|
||||||
|
@ -97,8 +101,8 @@ public class ConfigurationNode implements Map<String, Object> {
|
||||||
Log.severe("Error reading " + f.getPath());
|
Log.severe("Error reading " + f.getPath());
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
if(fis != null) {
|
if(fr != null) {
|
||||||
try { fis.close(); } catch (IOException x) {}
|
try { fr.close(); } catch (IOException x) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (entries != null);
|
return (entries != null);
|
||||||
|
@ -111,7 +115,7 @@ public class ConfigurationNode implements Map<String, Object> {
|
||||||
public boolean save(File file) {
|
public boolean save(File file) {
|
||||||
initparse();
|
initparse();
|
||||||
|
|
||||||
FileOutputStream stream = null;
|
OutputStream stream = null;
|
||||||
|
|
||||||
File parent = file.getParentFile();
|
File parent = file.getParentFile();
|
||||||
|
|
||||||
|
@ -120,7 +124,7 @@ public class ConfigurationNode implements Map<String, Object> {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
stream = new FileOutputStream(file);
|
stream = new BufferedOutputStream(new FileOutputStream(file));
|
||||||
OutputStreamWriter writer = new OutputStreamWriter(stream, "UTF-8");
|
OutputStreamWriter writer = new OutputStreamWriter(stream, "UTF-8");
|
||||||
yaml.dump(entries, writer);
|
yaml.dump(entries, writer);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -54,12 +54,15 @@ import org.dynmap.modsupport.ModSupportImpl;
|
||||||
import org.dynmap.renderer.DynmapBlockState;
|
import org.dynmap.renderer.DynmapBlockState;
|
||||||
import org.dynmap.servlet.*;
|
import org.dynmap.servlet.*;
|
||||||
import org.dynmap.storage.MapStorage;
|
import org.dynmap.storage.MapStorage;
|
||||||
|
import org.dynmap.storage.aws_s3.AWSS3MapStorage;
|
||||||
import org.dynmap.storage.filetree.FileTreeMapStorage;
|
import org.dynmap.storage.filetree.FileTreeMapStorage;
|
||||||
import org.dynmap.storage.mysql.MySQLMapStorage;
|
import org.dynmap.storage.mysql.MySQLMapStorage;
|
||||||
|
import org.dynmap.storage.mssql.MicrosoftSQLMapStorage;
|
||||||
import org.dynmap.storage.mariadb.MariaDBMapStorage;
|
import org.dynmap.storage.mariadb.MariaDBMapStorage;
|
||||||
import org.dynmap.storage.sqllte.SQLiteMapStorage;
|
import org.dynmap.storage.sqllte.SQLiteMapStorage;
|
||||||
import org.dynmap.storage.postgresql.PostgreSQLMapStorage;
|
import org.dynmap.storage.postgresql.PostgreSQLMapStorage;
|
||||||
import org.dynmap.utils.BlockStep;
|
import org.dynmap.utils.BlockStep;
|
||||||
|
import org.dynmap.utils.BufferOutputStream;
|
||||||
import org.dynmap.utils.ImageIOManager;
|
import org.dynmap.utils.ImageIOManager;
|
||||||
import org.dynmap.web.BanIPFilter;
|
import org.dynmap.web.BanIPFilter;
|
||||||
import org.dynmap.web.CustomHeaderFilter;
|
import org.dynmap.web.CustomHeaderFilter;
|
||||||
|
@ -75,7 +78,6 @@ import org.eclipse.jetty.server.handler.HandlerList;
|
||||||
import org.eclipse.jetty.server.session.DefaultSessionIdManager;
|
import org.eclipse.jetty.server.session.DefaultSessionIdManager;
|
||||||
import org.eclipse.jetty.server.session.SessionHandler;
|
import org.eclipse.jetty.server.session.SessionHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
import org.eclipse.jetty.util.resource.FileResource;
|
|
||||||
import org.eclipse.jetty.util.thread.ExecutorThreadPool;
|
import org.eclipse.jetty.util.thread.ExecutorThreadPool;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
|
@ -132,6 +134,8 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
private int config_hashcode; /* Used to signal need to reload web configuration (world changes, config update, etc) */
|
private int config_hashcode; /* Used to signal need to reload web configuration (world changes, config update, etc) */
|
||||||
private int fullrenderplayerlimit; /* Number of online players that will cause fullrender processing to pause */
|
private int fullrenderplayerlimit; /* Number of online players that will cause fullrender processing to pause */
|
||||||
private int updateplayerlimit; /* Number of online players that will cause update processing to pause */
|
private int updateplayerlimit; /* Number of online players that will cause update processing to pause */
|
||||||
|
private String publicURL; // If set, public HRL for accessing dynmap (declared by administrator)
|
||||||
|
private String noPermissionMsg;
|
||||||
private boolean didfullpause;
|
private boolean didfullpause;
|
||||||
private boolean didupdatepause;
|
private boolean didupdatepause;
|
||||||
private Map<String, LinkedList<String>> ids_by_ip = new HashMap<String, LinkedList<String>>();
|
private Map<String, LinkedList<String>> ids_by_ip = new HashMap<String, LinkedList<String>>();
|
||||||
|
@ -160,14 +164,22 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
private File dataDirectory;
|
private File dataDirectory;
|
||||||
private File tilesDirectory;
|
private File tilesDirectory;
|
||||||
private File exportDirectory;
|
private File exportDirectory;
|
||||||
|
private File importDirectory;
|
||||||
private String plugin_ver;
|
private String plugin_ver;
|
||||||
private MapStorage defaultStorage;
|
private MapStorage defaultStorage;
|
||||||
|
|
||||||
|
// Read web path
|
||||||
|
private String webpath;
|
||||||
|
// And whether to disable web file update
|
||||||
|
private boolean updatewebpathfiles = true;
|
||||||
|
|
||||||
private String[] deftriggers = { };
|
private String[] deftriggers = { };
|
||||||
|
|
||||||
private Boolean webserverCompConfigWarn = false;
|
private Boolean webserverCompConfigWarn = false;
|
||||||
private final String CompConfigWiki = "https://github.com/webbukkit/dynmap/wiki/Component-Configuration";
|
private final String CompConfigWiki = "https://github.com/webbukkit/dynmap/wiki/Component-Configuration";
|
||||||
|
|
||||||
|
private final String[] defaultTemplates = {"vlowres", "lowres", "medres", "hires", "low_boost_hi",
|
||||||
|
"hi_boost_vhi", "hi_boost_xhi"};
|
||||||
/* Constructor for core */
|
/* Constructor for core */
|
||||||
public DynmapCore() {
|
public DynmapCore() {
|
||||||
}
|
}
|
||||||
|
@ -213,6 +225,9 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
public final File getExportFolder() {
|
public final File getExportFolder() {
|
||||||
return exportDirectory;
|
return exportDirectory;
|
||||||
}
|
}
|
||||||
|
public final File getImportFolder() {
|
||||||
|
return importDirectory;
|
||||||
|
}
|
||||||
public void setMinecraftVersion(String mcver) {
|
public void setMinecraftVersion(String mcver) {
|
||||||
this.platformVersion = mcver;
|
this.platformVersion = mcver;
|
||||||
}
|
}
|
||||||
|
@ -399,6 +414,11 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
configuration = new ConfigurationNode(f);
|
configuration = new ConfigurationNode(f);
|
||||||
configuration.load();
|
configuration.load();
|
||||||
|
|
||||||
|
// Read web path
|
||||||
|
webpath = configuration.getString("webpath", "web");
|
||||||
|
// And whether to disable web file update
|
||||||
|
updatewebpathfiles = configuration.getBoolean("update-webpath-files", true);
|
||||||
|
|
||||||
// Check if we are disabling the internal web server (implies external)
|
// Check if we are disabling the internal web server (implies external)
|
||||||
isInternalWebServerDisabled = configuration.getBoolean("disable-webserver", false);
|
isInternalWebServerDisabled = configuration.getBoolean("disable-webserver", false);
|
||||||
|
|
||||||
|
@ -412,6 +432,11 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
if (!exportDirectory.isDirectory() && !exportDirectory.mkdirs()) {
|
if (!exportDirectory.isDirectory() && !exportDirectory.mkdirs()) {
|
||||||
Log.warning("Could not create directory for exports ('" + exportDirectory + "').");
|
Log.warning("Could not create directory for exports ('" + exportDirectory + "').");
|
||||||
}
|
}
|
||||||
|
// Prime the imports directory
|
||||||
|
importDirectory = getFile(configuration.getString("importpath", "import"));
|
||||||
|
if (!importDirectory.isDirectory() && !importDirectory.mkdirs()) {
|
||||||
|
Log.warning("Could not create directory for imports ('" + importDirectory + "').");
|
||||||
|
}
|
||||||
// Create default storage handler
|
// Create default storage handler
|
||||||
String storetype = configuration.getString("storage/type", "filetree");
|
String storetype = configuration.getString("storage/type", "filetree");
|
||||||
if (storetype.equals("filetree")) {
|
if (storetype.equals("filetree")) {
|
||||||
|
@ -429,6 +454,12 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
else if (storetype.equals("postgres") || storetype.equals("postgresql")) {
|
else if (storetype.equals("postgres") || storetype.equals("postgresql")) {
|
||||||
defaultStorage = new PostgreSQLMapStorage();
|
defaultStorage = new PostgreSQLMapStorage();
|
||||||
}
|
}
|
||||||
|
else if (storetype.equals("aws_s3")) {
|
||||||
|
defaultStorage = new AWSS3MapStorage();
|
||||||
|
}
|
||||||
|
else if (storetype.equals("microsoftsql")) {
|
||||||
|
defaultStorage = new MicrosoftSQLMapStorage();
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
Log.severe("Invalid storage type for map data: " + storetype);
|
Log.severe("Invalid storage type for map data: " + storetype);
|
||||||
return false;
|
return false;
|
||||||
|
@ -476,7 +507,10 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
authmgr = new WebAuthManager(this);
|
authmgr = new WebAuthManager(this);
|
||||||
defaultStorage.setLoginEnabled(this);
|
defaultStorage.setLoginEnabled(this);
|
||||||
}
|
}
|
||||||
|
// If storage serves web files, extract and publsh them
|
||||||
|
if (defaultStorage.needsStaticWebFiles()) {
|
||||||
|
updateStaticWebToStorage();
|
||||||
|
}
|
||||||
/* Load control for leaf transparency (spout lighting bug workaround) */
|
/* Load control for leaf transparency (spout lighting bug workaround) */
|
||||||
transparentLeaves = configuration.getBoolean("transparent-leaves", true);
|
transparentLeaves = configuration.getBoolean("transparent-leaves", true);
|
||||||
|
|
||||||
|
@ -548,6 +582,11 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
if (migrate_chunks)
|
if (migrate_chunks)
|
||||||
Log.info("EXPERIMENTAL: chunk migration enabled");
|
Log.info("EXPERIMENTAL: chunk migration enabled");
|
||||||
|
|
||||||
|
publicURL = configuration.getString("publicURL", "");
|
||||||
|
|
||||||
|
/* Send this message if the player does not have permission to use the command */
|
||||||
|
noPermissionMsg = configuration.getString("noPermissionMsg", "You don't have permission to use this command!");
|
||||||
|
|
||||||
/* Load preupdate/postupdate commands */
|
/* Load preupdate/postupdate commands */
|
||||||
ImageIOManager.preUpdateCommand = configuration.getString("custom-commands/image-updates/preupdatecommand", "");
|
ImageIOManager.preUpdateCommand = configuration.getString("custom-commands/image-updates/preupdatecommand", "");
|
||||||
ImageIOManager.postUpdateCommand = configuration.getString("custom-commands/image-updates/postupdatecommand", "");
|
ImageIOManager.postUpdateCommand = configuration.getString("custom-commands/image-updates/postupdatecommand", "");
|
||||||
|
@ -673,7 +712,7 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
/* Print version info */
|
/* Print version info */
|
||||||
Log.info("version " + plugin_ver + " is enabled - core version " + version );
|
Log.info("version " + plugin_ver + " is enabled - core version " + version );
|
||||||
Log.info("For support, visit our Discord at https://discord.gg/s3rd5qn");
|
Log.info("For support, visit our Discord at https://discord.gg/s3rd5qn");
|
||||||
Log.info("For news, visit https://reddit.com/r/Dynmap or follow https://twitter.com/Dynmap");
|
Log.info("For news, visit https://reddit.com/r/Dynmap or follow https://universeodon.com/@dynmap");
|
||||||
Log.info("To report or track bugs, visit https://github.com/webbukkit/dynmap/issues");
|
Log.info("To report or track bugs, visit https://github.com/webbukkit/dynmap/issues");
|
||||||
Log.info("If you'd like to donate, please visit https://www.patreon.com/dynmap or https://ko-fi.com/michaelprimm");
|
Log.info("If you'd like to donate, please visit https://www.patreon.com/dynmap or https://ko-fi.com/michaelprimm");
|
||||||
|
|
||||||
|
@ -903,12 +942,13 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
return config_hashcode;
|
return config_hashcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileResource createFileResource(String path) {
|
@SuppressWarnings("deprecation")
|
||||||
|
private org.eclipse.jetty.util.resource.FileResource createFileResource(String path) {
|
||||||
try {
|
try {
|
||||||
File f = new File(path);
|
File f = new File(path);
|
||||||
URI uri = f.toURI();
|
URI uri = f.toURI();
|
||||||
URL url = uri.toURL();
|
URL url = uri.toURL();
|
||||||
return new FileResource(url);
|
return new org.eclipse.jetty.util.resource.FileResource(url);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.info("Could not create file resource");
|
Log.info("Could not create file resource");
|
||||||
return null;
|
return null;
|
||||||
|
@ -1084,7 +1124,9 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
mapManager.stopRendering();
|
mapManager.stopRendering();
|
||||||
mapManager = null;
|
mapManager = null;
|
||||||
}
|
}
|
||||||
|
if (defaultStorage != null) {
|
||||||
|
defaultStorage.shutdownStorage();
|
||||||
|
}
|
||||||
playerfacemgr = null;
|
playerfacemgr = null;
|
||||||
/* Clean up registered listeners */
|
/* Clean up registered listeners */
|
||||||
listenerManager.cleanup();
|
listenerManager.cleanup();
|
||||||
|
@ -1200,6 +1242,7 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
"del-id-for-ip",
|
"del-id-for-ip",
|
||||||
"webregister",
|
"webregister",
|
||||||
"dumpmemory",
|
"dumpmemory",
|
||||||
|
"url",
|
||||||
"help"}));
|
"help"}));
|
||||||
|
|
||||||
private static class CommandInfo {
|
private static class CommandInfo {
|
||||||
|
@ -1267,6 +1310,7 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
new CommandInfo("dynmap", "webregister", "<player>", "Start registration process for creating web login account for player <player>"),
|
new CommandInfo("dynmap", "webregister", "<player>", "Start registration process for creating web login account for player <player>"),
|
||||||
new CommandInfo("dynmap", "version", "Return version information"),
|
new CommandInfo("dynmap", "version", "Return version information"),
|
||||||
new CommandInfo("dynmap", "dumpmemory", "Return mempry use information"),
|
new CommandInfo("dynmap", "dumpmemory", "Return mempry use information"),
|
||||||
|
new CommandInfo("dynmap", "url", "Return confgured URL for Dynmap web"),
|
||||||
new CommandInfo("dmarker", "", "Manipulate map markers."),
|
new CommandInfo("dmarker", "", "Manipulate map markers."),
|
||||||
new CommandInfo("dmarker", "add", "<label>", "Add new marker with label <label> at current location (use double-quotes if spaces needed)."),
|
new CommandInfo("dmarker", "add", "<label>", "Add new marker with label <label> at current location (use double-quotes if spaces needed)."),
|
||||||
new CommandInfo("dmarker", "add", "id:<id> <label>", "Add new marker with ID <id> at current location (use double-quotes if spaces needed)."),
|
new CommandInfo("dmarker", "add", "id:<id> <label>", "Add new marker with ID <id> at current location (use double-quotes if spaces needed)."),
|
||||||
|
@ -1324,7 +1368,7 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
new CommandInfo("dmap", "mapadd", "<world>:<map> <attrib>:<value> <attrib>:<value>", "Create map for world <world> with name <map> using provided attributes."),
|
new CommandInfo("dmap", "mapadd", "<world>:<map> <attrib>:<value> <attrib>:<value>", "Create map for world <world> with name <map> using provided attributes."),
|
||||||
new CommandInfo("dmap", "mapset", "<world>:<map> <attrib>:<value> <attrib>:<value>", "Update map <map> of world <world> with new attribute values."),
|
new CommandInfo("dmap", "mapset", "<world>:<map> <attrib>:<value> <attrib>:<value>", "Update map <map> of world <world> with new attribute values."),
|
||||||
new CommandInfo("dmap", "worldreset", "<world>", "Reset world <world> to default template for world type"),
|
new CommandInfo("dmap", "worldreset", "<world>", "Reset world <world> to default template for world type"),
|
||||||
new CommandInfo("dmap", "worldreset", "<world> <templatename>", "Reset world <world> to temaplte <templatename>."),
|
new CommandInfo("dmap", "worldreset", "<world> <templatename>", "Reset world <world> to template <templatename>."),
|
||||||
new CommandInfo("dmap", "worldgetlimits", "<world>", "List visibity and hidden limits for world"),
|
new CommandInfo("dmap", "worldgetlimits", "<world>", "List visibity and hidden limits for world"),
|
||||||
new CommandInfo("dmap", "worldaddlimit", "<world> corner1:<x>/<z> corner2:<x>/<z>", "Add rectangular visibilty limit"),
|
new CommandInfo("dmap", "worldaddlimit", "<world> corner1:<x>/<z> corner2:<x>/<z>", "Add rectangular visibilty limit"),
|
||||||
new CommandInfo("dmap", "worldaddlimit", "<world> type:round center:<x>/<z> radius:<radius>", "Add round visibilty limit"),
|
new CommandInfo("dmap", "worldaddlimit", "<world> type:round center:<x>/<z> radius:<radius>", "Add round visibilty limit"),
|
||||||
|
@ -1574,7 +1618,7 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
printCommandHelp(sender, cmd, "");
|
printCommandHelp(sender, cmd, "");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.equals("render") && checkPlayerPermission(sender,"render")) {
|
if (c.equals("render") && checkPlayerPermission(sender,"render")) {
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
DynmapLocation loc = player.getLocation();
|
DynmapLocation loc = player.getLocation();
|
||||||
|
@ -1897,12 +1941,20 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
else if(c.equals("help")) {
|
else if(c.equals("help")) {
|
||||||
printCommandHelp(sender, cmd, (args.length > 1)?args[1]:"");
|
printCommandHelp(sender, cmd, (args.length > 1)?args[1]:"");
|
||||||
}
|
}
|
||||||
else if(c.equals("dumpmemory")) {
|
else if(c.equals("dumpmemory") && checkPlayerPermission(sender, "dumpmemory")) {
|
||||||
TexturePack.tallyMemory(sender);
|
TexturePack.tallyMemory(sender);
|
||||||
}
|
}
|
||||||
else if(c.equals("version")) {
|
else if(c.equals("version")) {
|
||||||
sender.sendMessage("Dynmap version: core=" + this.getDynmapCoreVersion() + ", plugin=" + this.getDynmapPluginVersion());
|
sender.sendMessage("Dynmap version: core=" + this.getDynmapCoreVersion() + ", plugin=" + this.getDynmapPluginVersion());
|
||||||
}
|
}
|
||||||
|
else if (c.equals("url")) {
|
||||||
|
if (publicURL.length() > 0) {
|
||||||
|
sender.sendMessage("Dynmap URL for this server is: " + publicURL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sender.sendMessage("URL of Dynmap not configured");
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
printCommandHelp(sender, cmd, (args.length > 0)?args[0]:"");
|
printCommandHelp(sender, cmd, (args.length > 0)?args[0]:"");
|
||||||
|
@ -1960,11 +2012,11 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
if(args.length == 2) { // /dynmap radiusrender *<world>* <x> <z> <radius> <map>
|
if(args.length == 2) { // /dynmap radiusrender *<world>* <x> <z> <radius> <map>
|
||||||
return getWorldSuggestions(args[1]);
|
return getWorldSuggestions(args[1]);
|
||||||
} if(args.length == 3 && player != null) { // /dynmap radiusrender <radius> *<mapname>*
|
} if(args.length == 3 && player != null) { // /dynmap radiusrender <radius> *<mapname>*
|
||||||
Scanner sc = new Scanner(args[1]);
|
try (Scanner sc = new Scanner(args[1])) {
|
||||||
|
if(sc.hasNextInt(10)) { //Only show map suggestions if a number was entered before
|
||||||
if(sc.hasNextInt(10)) { //Only show map suggestions if a number was entered before
|
return getMapSuggestions(player.getLocation().world, args[2], false);
|
||||||
return getMapSuggestions(player.getLocation().world, args[2], false);
|
}
|
||||||
}
|
}
|
||||||
} else if(args.length == 6) { // /dynmap radiusrender <world> <x> <z> <radius> *<map>*
|
} else if(args.length == 6) { // /dynmap radiusrender <world> <x> <z> <radius> *<map>*
|
||||||
return getMapSuggestions(args[1], args[5], false);
|
return getMapSuggestions(args[1], args[5], false);
|
||||||
}
|
}
|
||||||
|
@ -2062,7 +2114,7 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
if (!(sender instanceof DynmapPlayer) || sender.isOp()) {
|
if (!(sender instanceof DynmapPlayer) || sender.isOp()) {
|
||||||
return true;
|
return true;
|
||||||
} else if (!sender.hasPrivilege(permission.toLowerCase())) {
|
} else if (!sender.hasPrivilege(permission.toLowerCase())) {
|
||||||
sender.sendMessage("You don't have permission to use this command!");
|
sender.sendMessage(noPermissionMsg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -2126,6 +2178,9 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
ConfigurationNode getDefaultTemplateConfigurationNode(DynmapWorld world) {
|
ConfigurationNode getDefaultTemplateConfigurationNode(DynmapWorld world) {
|
||||||
String environmentName = world.getEnvironment();
|
String environmentName = world.getEnvironment();
|
||||||
if(deftemplatesuffix.length() > 0) {
|
if(deftemplatesuffix.length() > 0) {
|
||||||
|
if(!Arrays.asList(defaultTemplates).contains(deftemplatesuffix)) {
|
||||||
|
Log.warning("Not using a default defined template, worlds might not be accessible.");
|
||||||
|
}
|
||||||
environmentName += "-" + deftemplatesuffix;
|
environmentName += "-" + deftemplatesuffix;
|
||||||
}
|
}
|
||||||
Log.verboseinfo("Using environment as template: " + environmentName);
|
Log.verboseinfo("Using environment as template: " + environmentName);
|
||||||
|
@ -2152,7 +2207,7 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
|
|
||||||
|
|
||||||
public String getWebPath() {
|
public String getWebPath() {
|
||||||
return configuration.getString("webpath", "web");
|
return webpath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setIgnoreChunkLoads(boolean ignore) {
|
public static void setIgnoreChunkLoads(boolean ignore) {
|
||||||
|
@ -2634,7 +2689,6 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
int off = 0;
|
int off = 0;
|
||||||
int firsthit = -1;
|
int firsthit = -1;
|
||||||
boolean done = false;
|
boolean done = false;
|
||||||
String orig = msg;
|
|
||||||
while (!done) {
|
while (!done) {
|
||||||
int idx = msg.indexOf("${", off); // Look for next ${
|
int idx = msg.indexOf("${", off); // Look for next ${
|
||||||
if (idx >= 0) { // Hit
|
if (idx >= 0) { // Hit
|
||||||
|
@ -2780,7 +2834,7 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
return platformVersion;
|
return platformVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean deleteDirectory(File dir) {
|
public static boolean deleteDirectory(File dir) {
|
||||||
File[] files = dir.listFiles();
|
File[] files = dir.listFiles();
|
||||||
if (files != null) {
|
if (files != null) {
|
||||||
for (File f : files) {
|
for (File f : files) {
|
||||||
|
@ -2795,13 +2849,73 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
}
|
}
|
||||||
return dir.delete();
|
return dir.delete();
|
||||||
}
|
}
|
||||||
|
private void updateStaticWebToStorage() {
|
||||||
|
if(jarfile == null) return;
|
||||||
|
// If doing update and web path update is disabled, send warning
|
||||||
|
if (!this.updatewebpathfiles) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Log.info("Publishing web files to storage");
|
||||||
|
/* Open JAR as ZIP */
|
||||||
|
ZipFile zf = null;
|
||||||
|
InputStream ins = null;
|
||||||
|
byte[] buf = new byte[2048];
|
||||||
|
String n = null;
|
||||||
|
try {
|
||||||
|
zf = new ZipFile(jarfile);
|
||||||
|
Enumeration<? extends ZipEntry> e = zf.entries();
|
||||||
|
while (e.hasMoreElements()) {
|
||||||
|
ZipEntry ze = e.nextElement();
|
||||||
|
n = ze.getName();
|
||||||
|
if (!n.startsWith("extracted/web/")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
n = n.substring("extracted/web/".length());
|
||||||
|
// If file is going to web path, redirect it to the configured web
|
||||||
|
if (ze.isDirectory()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
ins = zf.getInputStream(ze);
|
||||||
|
BufferOutputStream buffer = new BufferOutputStream();
|
||||||
|
int len;
|
||||||
|
while ((len = ins.read(buf)) >= 0) {
|
||||||
|
buffer.write(buf, 0, len);
|
||||||
|
}
|
||||||
|
defaultStorage.setStaticWebFile(n, buffer);
|
||||||
|
} catch(IOException io) {
|
||||||
|
Log.severe("Error updating file in storage - " + n, io);
|
||||||
|
} finally {
|
||||||
|
if (ins != null) {
|
||||||
|
ins.close();
|
||||||
|
ins = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException iox) {
|
||||||
|
Log.severe("Error extracting file - " + n);
|
||||||
|
} finally {
|
||||||
|
if (ins != null) {
|
||||||
|
try { ins.close(); } catch (IOException iox) {}
|
||||||
|
ins = null;
|
||||||
|
}
|
||||||
|
if (zf != null) {
|
||||||
|
try { zf.close(); } catch (IOException iox) {}
|
||||||
|
zf = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateExtractedFiles() {
|
private void updateExtractedFiles() {
|
||||||
if(jarfile == null) return;
|
if(jarfile == null) return;
|
||||||
File df = this.getDataFolder();
|
File df = this.getDataFolder();
|
||||||
if(df.exists() == false) df.mkdirs();
|
if(df.exists() == false) df.mkdirs();
|
||||||
File ver = new File(df, "version.txt");
|
File ver = new File(df, "version.txt");
|
||||||
|
File wpath = this.getFile(this.getWebPath());
|
||||||
|
File webver = new File(wpath, "version.txt");
|
||||||
String prevver = "1.6";
|
String prevver = "1.6";
|
||||||
if(ver.exists()) {
|
String prevwebver = "1.6";
|
||||||
|
if (ver.exists()) {
|
||||||
Reader ir = null;
|
Reader ir = null;
|
||||||
try {
|
try {
|
||||||
ir = new FileReader(ver);
|
ir = new FileReader(ver);
|
||||||
|
@ -2817,17 +2931,34 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // First time, delete old external texture pack
|
if (webver.exists()) {
|
||||||
deleteDirectory(new File(df, "texturepacks/standard"));
|
Reader ir = null;
|
||||||
|
try {
|
||||||
|
ir = new FileReader(webver);
|
||||||
|
prevwebver = "";
|
||||||
|
int c;
|
||||||
|
while((c = ir.read()) >= 0) {
|
||||||
|
prevwebver += (char)c;
|
||||||
|
}
|
||||||
|
} catch (IOException iox) {
|
||||||
|
} finally {
|
||||||
|
if(ir != null) {
|
||||||
|
try { ir.close(); } catch (IOException iox) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
String curver = this.getDynmapCoreVersion();
|
String curver = this.getDynmapCoreVersion();
|
||||||
/* If matched, we're good */
|
/* If matched, we're good */
|
||||||
if (prevver.equals(curver) && (!curver.endsWith(("-Dev")))) {
|
if (prevver.equals(curver) && prevwebver.equals(curver) && (!curver.endsWith(("-Dev")))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// If doing update and web path update is disabled, send warning
|
||||||
|
if (!this.updatewebpathfiles) {
|
||||||
|
Log.warning("Update of web interface is disabled, and update is available - UI may not function without updates");
|
||||||
|
}
|
||||||
/* Get deleted file list */
|
/* Get deleted file list */
|
||||||
InputStream in = getClass().getResourceAsStream("/deleted.txt");
|
InputStream in = getClass().getResourceAsStream("/deleted.txt");
|
||||||
if(in != null) {
|
if (in != null) {
|
||||||
try {
|
try {
|
||||||
BufferedReader br = new BufferedReader(new InputStreamReader(in));
|
BufferedReader br = new BufferedReader(new InputStreamReader(in));
|
||||||
String line;
|
String line;
|
||||||
|
@ -2843,7 +2974,6 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
try { in.close(); } catch (IOException x) {}
|
try { in.close(); } catch (IOException x) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open JAR as ZIP */
|
/* Open JAR as ZIP */
|
||||||
ZipFile zf = null;
|
ZipFile zf = null;
|
||||||
FileOutputStream fos = null;
|
FileOutputStream fos = null;
|
||||||
|
@ -2857,24 +2987,45 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
while (e.hasMoreElements()) {
|
while (e.hasMoreElements()) {
|
||||||
ZipEntry ze = e.nextElement();
|
ZipEntry ze = e.nextElement();
|
||||||
n = ze.getName();
|
n = ze.getName();
|
||||||
if(!n.startsWith("extracted/")) continue;
|
if (!n.startsWith("extracted/")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
n = n.substring("extracted/".length());
|
n = n.substring("extracted/".length());
|
||||||
f = new File(df, n);
|
// If file is going to web path, redirect it to the configured web
|
||||||
|
if (n.startsWith("web/")) {
|
||||||
|
// Don't update unless we are allowed to
|
||||||
|
if (!updatewebpathfiles) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
f = new File(wpath, n.substring("web/".length()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
f = new File(df, n);
|
||||||
|
}
|
||||||
if(ze.isDirectory()) {
|
if(ze.isDirectory()) {
|
||||||
f.mkdirs();
|
f.mkdirs();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
f.getParentFile().mkdirs();
|
try {
|
||||||
fos = new FileOutputStream(f);
|
f.getParentFile().mkdirs();
|
||||||
ins = zf.getInputStream(ze);
|
fos = new FileOutputStream(f);
|
||||||
int len;
|
ins = zf.getInputStream(ze);
|
||||||
while ((len = ins.read(buf)) >= 0) {
|
int len;
|
||||||
fos.write(buf, 0, len);
|
while ((len = ins.read(buf)) >= 0) {
|
||||||
}
|
fos.write(buf, 0, len);
|
||||||
ins.close();
|
}
|
||||||
ins = null;
|
} catch(IOException io) {
|
||||||
fos.close();
|
Log.severe("Error updating file - " + f.getPath(), io);
|
||||||
fos = null;
|
} finally {
|
||||||
|
if (ins != null) {
|
||||||
|
ins.close();
|
||||||
|
ins = null;
|
||||||
|
}
|
||||||
|
if (fos != null) {
|
||||||
|
fos.close();
|
||||||
|
fos = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException iox) {
|
} catch (IOException iox) {
|
||||||
|
@ -2894,7 +3045,7 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally, write new version cookie */
|
/* Finally, write new version cookie to both data folder and web folder*/
|
||||||
Writer out = null;
|
Writer out = null;
|
||||||
try {
|
try {
|
||||||
out = new FileWriter(ver);
|
out = new FileWriter(ver);
|
||||||
|
@ -2905,7 +3056,21 @@ public class DynmapCore implements DynmapCommonAPI {
|
||||||
try { out.close(); } catch (IOException iox) {}
|
try { out.close(); } catch (IOException iox) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.info("Extracted files upgraded");
|
if (this.updatewebpathfiles) {
|
||||||
|
try {
|
||||||
|
out = new FileWriter(webver);
|
||||||
|
out.write(this.getDynmapCoreVersion());
|
||||||
|
} catch (IOException iox) {
|
||||||
|
} finally {
|
||||||
|
if(out != null) {
|
||||||
|
try { out.close(); } catch (IOException iox) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.info("Extracted files upgraded");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log.info("Extracted files upgraded (excluding webpath files)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Server thread tick : nominally, once per 20 Hz tick
|
// Server thread tick : nominally, once per 20 Hz tick
|
||||||
public void serverTick(double tps) {
|
public void serverTick(double tps) {
|
||||||
|
|
|
@ -90,7 +90,9 @@ public class DynmapMapCommands {
|
||||||
mapSetArgs.put("mapzoomin", emptySupplier);
|
mapSetArgs.put("mapzoomin", emptySupplier);
|
||||||
mapSetArgs.put("mapzoomout", emptySupplier);
|
mapSetArgs.put("mapzoomout", emptySupplier);
|
||||||
mapSetArgs.put("boostzoom", emptySupplier);
|
mapSetArgs.put("boostzoom", emptySupplier);
|
||||||
|
mapSetArgs.put("tilescale", emptySupplier);
|
||||||
mapSetArgs.put("tileupdatedelay", emptySupplier);
|
mapSetArgs.put("tileupdatedelay", emptySupplier);
|
||||||
|
mapSetArgs.put("readonly", booleanSupplier);
|
||||||
|
|
||||||
tabCompletions = new HashMap<>();
|
tabCompletions = new HashMap<>();
|
||||||
tabCompletions.put("worldaddlimit", worldAddLimitArgs);
|
tabCompletions.put("worldaddlimit", worldAddLimitArgs);
|
||||||
|
@ -695,7 +697,7 @@ public class DynmapMapCommands {
|
||||||
sb.append(", lighting=").append(hdmt.getLighting().getName()).append(", mapzoomin=").append(hdmt.getMapZoomIn()).append(", mapzoomout=").append(hdmt.getMapZoomOutLevels());
|
sb.append(", lighting=").append(hdmt.getLighting().getName()).append(", mapzoomin=").append(hdmt.getMapZoomIn()).append(", mapzoomout=").append(hdmt.getMapZoomOutLevels());
|
||||||
sb.append(", img-format=").append(hdmt.getImageFormatSetting()).append(", icon=").append(hdmt.getIcon());
|
sb.append(", img-format=").append(hdmt.getImageFormatSetting()).append(", icon=").append(hdmt.getIcon());
|
||||||
sb.append(", append-to-world=").append(hdmt.getAppendToWorld()).append(", boostzoom=").append(hdmt.getBoostZoom());
|
sb.append(", append-to-world=").append(hdmt.getAppendToWorld()).append(", boostzoom=").append(hdmt.getBoostZoom());
|
||||||
sb.append(", protected=").append(hdmt.isProtected());
|
sb.append(", protected=").append(hdmt.isProtected()).append(", tilescale=").append(hdmt.getTileScale()).append(", readonly=").append(hdmt.isReadOnly());
|
||||||
if(hdmt.tileupdatedelay > 0) {
|
if(hdmt.tileupdatedelay > 0) {
|
||||||
sb.append(", tileupdatedelay=").append(hdmt.tileupdatedelay);
|
sb.append(", tileupdatedelay=").append(hdmt.tileupdatedelay);
|
||||||
}
|
}
|
||||||
|
@ -913,6 +915,18 @@ public class DynmapMapCommands {
|
||||||
}
|
}
|
||||||
did_update |= mt.setBoostZoom(mzi);
|
did_update |= mt.setBoostZoom(mzi);
|
||||||
}
|
}
|
||||||
|
else if(tok[0].equalsIgnoreCase("tilescale")) {
|
||||||
|
int mzi = -1;
|
||||||
|
try {
|
||||||
|
mzi = Integer.valueOf(tok[1]);
|
||||||
|
} catch (NumberFormatException nfx) {
|
||||||
|
}
|
||||||
|
if((mzi < 0) || (mzi > 4)) {
|
||||||
|
sender.sendMessage("Invalid tilescale value: " + tok[1]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
did_update |= mt.setTileScale(mzi);
|
||||||
|
}
|
||||||
else if(tok[0].equalsIgnoreCase("tileupdatedelay")) {
|
else if(tok[0].equalsIgnoreCase("tileupdatedelay")) {
|
||||||
int tud = -1;
|
int tud = -1;
|
||||||
try {
|
try {
|
||||||
|
@ -983,6 +997,9 @@ public class DynmapMapCommands {
|
||||||
else if(tok[0].equalsIgnoreCase("protected")) {
|
else if(tok[0].equalsIgnoreCase("protected")) {
|
||||||
did_update |= mt.setProtected(Boolean.parseBoolean(tok[1]));
|
did_update |= mt.setProtected(Boolean.parseBoolean(tok[1]));
|
||||||
}
|
}
|
||||||
|
else if(tok[0].equalsIgnoreCase("readonly")) {
|
||||||
|
did_update |= mt.setReadOnly(Boolean.parseBoolean(tok[1]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(did_update) {
|
if(did_update) {
|
||||||
if(core.updateWorldConfig(w)) {
|
if(core.updateWorldConfig(w)) {
|
||||||
|
|
|
@ -136,7 +136,7 @@ public abstract class DynmapWorld {
|
||||||
long mostRecentTimestamp = 0;
|
long mostRecentTimestamp = 0;
|
||||||
int step = 1 << tile.zoom;
|
int step = 1 << tile.zoom;
|
||||||
MapStorageTile ztile = tile.getZoomOutTile();
|
MapStorageTile ztile = tile.getZoomOutTile();
|
||||||
int width = 128, height = 128;
|
int width = mts.tileSize, height = mts.tileSize;
|
||||||
BufferedImage zIm = null;
|
BufferedImage zIm = null;
|
||||||
DynmapBufferedImage kzIm = null;
|
DynmapBufferedImage kzIm = null;
|
||||||
boolean blank = true;
|
boolean blank = true;
|
||||||
|
@ -178,7 +178,7 @@ public abstract class DynmapWorld {
|
||||||
if ((iwidth == width) && (iheight == height)) {
|
if ((iwidth == width) && (iheight == height)) {
|
||||||
im.getRGB(0, 0, width, height, argb, 0, width); /* Read data */
|
im.getRGB(0, 0, width, height, argb, 0, width); /* Read data */
|
||||||
im.flush();
|
im.flush();
|
||||||
/* Do binlinear scale to 64x64 */
|
/* Do binlinear scale to width/2 x height/2 */
|
||||||
int off = 0;
|
int off = 0;
|
||||||
for(int y = 0; y < height; y += 2) {
|
for(int y = 0; y < height; y += 2) {
|
||||||
off = y*width;
|
off = y*width;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.dynmap.servlet.ClientUpdateServlet;
|
import org.dynmap.servlet.ClientUpdateServlet;
|
||||||
import org.dynmap.servlet.SendMessageServlet;
|
import org.dynmap.servlet.SendMessageServlet;
|
||||||
|
import org.dynmap.utils.IpAddressMatcher;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
import static org.dynmap.JSONUtils.*;
|
import static org.dynmap.JSONUtils.*;
|
||||||
|
|
||||||
|
@ -65,12 +66,12 @@ public class InternalClientUpdateComponent extends ClientUpdateComponent {
|
||||||
this.core = dcore;
|
this.core = dcore;
|
||||||
if(trustedproxy != null) {
|
if(trustedproxy != null) {
|
||||||
for(String s : trustedproxy) {
|
for(String s : trustedproxy) {
|
||||||
this.proxyaddress.add(s.trim());
|
this.proxyaddress.add(new IpAddressMatcher(s.trim()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.proxyaddress.add("127.0.0.1");
|
this.proxyaddress.add(new IpAddressMatcher("127.0.0.1"));
|
||||||
this.proxyaddress.add("0:0:0:0:0:0:0:1");
|
this.proxyaddress.add(new IpAddressMatcher("0:0:0:0:0:0:0:1"));
|
||||||
}
|
}
|
||||||
onMessageReceived.addListener(new Event.Listener<Message> () {
|
onMessageReceived.addListener(new Event.Listener<Message> () {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.json.simple.parser.ParseException;
|
||||||
import static org.dynmap.JSONUtils.*;
|
import static org.dynmap.JSONUtils.*;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||||
protected long jsonInterval;
|
protected long jsonInterval;
|
||||||
|
@ -272,21 +273,28 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||||
byte[] outputBytes = sb.toString().getBytes(cs_utf8);
|
byte[] outputBytes = sb.toString().getBytes(cs_utf8);
|
||||||
MapManager.scheduleDelayedJob(new Runnable() {
|
MapManager.scheduleDelayedJob(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
File f = new File(baseStandaloneDir, "config.js");
|
if (core.getDefaultMapStorage().needsStaticWebFiles()) {
|
||||||
FileOutputStream fos = null;
|
BufferOutputStream os = new BufferOutputStream();
|
||||||
try {
|
os.write(outputBytes);
|
||||||
fos = new FileOutputStream(f);
|
core.getDefaultMapStorage().setStaticWebFile("standalone/config.js", os);
|
||||||
fos.write(outputBytes);
|
}
|
||||||
} catch (IOException iox) {
|
else {
|
||||||
Log.severe("Exception while writing " + f.getPath(), iox);
|
File f = new File(baseStandaloneDir, "config.js");
|
||||||
} finally {
|
FileOutputStream fos = null;
|
||||||
if(fos != null) {
|
try {
|
||||||
try {
|
fos = new FileOutputStream(f);
|
||||||
fos.close();
|
fos.write(outputBytes);
|
||||||
} catch (IOException x) {}
|
} catch (IOException iox) {
|
||||||
fos = null;
|
Log.severe("Exception while writing " + f.getPath(), iox);
|
||||||
}
|
} finally {
|
||||||
}
|
if(fos != null) {
|
||||||
|
try {
|
||||||
|
fos.close();
|
||||||
|
} catch (IOException x) {}
|
||||||
|
fos = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
@ -331,9 +339,12 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||||
else {
|
else {
|
||||||
outputFile = "dynmap_" + dynmapWorld.getName() + ".json";
|
outputFile = "dynmap_" + dynmapWorld.getName() + ".json";
|
||||||
}
|
}
|
||||||
byte[] content = Json.stringifyJson(update).getBytes(cs_utf8);
|
|
||||||
|
|
||||||
enqueueFileWrite(outputFile, content, dowrap);
|
CompletableFuture.runAsync(() -> {
|
||||||
|
byte[] content = Json.stringifyJson(update).getBytes(cs_utf8);
|
||||||
|
|
||||||
|
enqueueFileWrite(outputFile, content, dowrap);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,8 +488,10 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||||
jsonMsgs = (JSONArray) parser.parse(inputFileReader);
|
jsonMsgs = (JSONArray) parser.parse(inputFileReader);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Log.severe("Exception while reading JSON-file.", ex);
|
Log.severe("Exception while reading JSON-file.", ex);
|
||||||
|
storage.setStandaloneFile("dynmap_webchat.json", null); // Delete it
|
||||||
} catch (ParseException ex) {
|
} catch (ParseException ex) {
|
||||||
Log.severe("Exception while parsing JSON-file.", ex);
|
Log.severe("Exception while parsing JSON-file.", ex);
|
||||||
|
storage.setStandaloneFile("dynmap_webchat.json", null); // Delete it
|
||||||
} finally {
|
} finally {
|
||||||
if(inputFileReader != null) {
|
if(inputFileReader != null) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -60,6 +60,7 @@ public class MapManager {
|
||||||
private int progressinterval = 100;
|
private int progressinterval = 100;
|
||||||
private int tileupdatedelay = 30;
|
private int tileupdatedelay = 30;
|
||||||
private int savependingperiod = 15 * 60; // every 15 minutes, by default
|
private int savependingperiod = 15 * 60; // every 15 minutes, by default
|
||||||
|
private int defaulttilescale = 0;
|
||||||
private boolean saverestorepending = true;
|
private boolean saverestorepending = true;
|
||||||
private boolean pauseupdaterenders = false;
|
private boolean pauseupdaterenders = false;
|
||||||
private boolean hideores = false;
|
private boolean hideores = false;
|
||||||
|
@ -190,6 +191,10 @@ public class MapManager {
|
||||||
return tileupdatedelay;
|
return tileupdatedelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getDefaultTileScale() {
|
||||||
|
return defaulttilescale;
|
||||||
|
}
|
||||||
|
|
||||||
private static class OurThreadFactory implements ThreadFactory {
|
private static class OurThreadFactory implements ThreadFactory {
|
||||||
@Override
|
@Override
|
||||||
public Thread newThread(Runnable r) {
|
public Thread newThread(Runnable r) {
|
||||||
|
@ -228,8 +233,10 @@ public class MapManager {
|
||||||
try {
|
try {
|
||||||
r.run();
|
r.run();
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
Log.severe("Exception during render job: " + r);
|
if (!(x instanceof InterruptedException)) { // Avoid shutdown noise
|
||||||
x.printStackTrace();
|
Log.severe("Exception during render job: " + r);
|
||||||
|
x.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -244,8 +251,10 @@ public class MapManager {
|
||||||
try {
|
try {
|
||||||
command.run();
|
command.run();
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
Log.severe("Exception during render job: " + command);
|
if (!(x instanceof InterruptedException)) { // Avoid shutdown noise
|
||||||
x.printStackTrace();
|
Log.severe("Exception during render job: " + command);
|
||||||
|
x.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, delay, unit);
|
}, delay, unit);
|
||||||
|
@ -284,6 +293,7 @@ public class MapManager {
|
||||||
boolean pausedforworld = false;
|
boolean pausedforworld = false;
|
||||||
boolean updaterender = false;
|
boolean updaterender = false;
|
||||||
boolean resume = false;
|
boolean resume = false;
|
||||||
|
boolean resumeInitDone = false;
|
||||||
boolean quiet = false;
|
boolean quiet = false;
|
||||||
String mapname;
|
String mapname;
|
||||||
AtomicLong total_render_ns = new AtomicLong(0L);
|
AtomicLong total_render_ns = new AtomicLong(0L);
|
||||||
|
@ -302,32 +312,6 @@ public class MapManager {
|
||||||
rendertype = RENDERTYPE_FULLRENDER;
|
rendertype = RENDERTYPE_FULLRENDER;
|
||||||
}
|
}
|
||||||
this.resume = resume;
|
this.resume = resume;
|
||||||
|
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
|
||||||
|
|
||||||
if (resume) { // if resume render
|
|
||||||
final MapStorage ms = world.getMapStorage();
|
|
||||||
ms.enumMapBaseTiles(world, map, new MapStorageBaseTileEnumCB() {
|
|
||||||
@Override
|
|
||||||
public void tileFound(MapStorageTile tile, MapType.ImageEncoding enc) {
|
|
||||||
String tileId = String.format("%s_%s_%d_%d", tile.world.getName(), tile.map.getName(), tile.x, tile.y);
|
|
||||||
//sender.sendMessage("Tile found: " + tileId);
|
|
||||||
storedTileIds.add(tileId);
|
|
||||||
}
|
|
||||||
}, new MapStorageTileSearchEndCB() {
|
|
||||||
@Override
|
|
||||||
public void searchEnded() {
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
latch.await(10, TimeUnit.SECONDS);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
sender.sendMessage(e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Full world, all maps render, with optional render radius */
|
/* Full world, all maps render, with optional render radius */
|
||||||
|
@ -519,6 +503,27 @@ public class MapManager {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// If doing resume, load existing tile IDs here (constructor was stupid, and caused timeouts for non-trivial maps - need to check PRs better....
|
||||||
|
if (resume && (!resumeInitDone)) { // if resume render AND init not completed
|
||||||
|
sendMessage(String.format("Scanning map to find existing tiles for resume..."));
|
||||||
|
final MapStorage ms = world.getMapStorage();
|
||||||
|
ms.enumMapBaseTiles(world, map, new MapStorageBaseTileEnumCB() {
|
||||||
|
@Override
|
||||||
|
public void tileFound(MapStorageTile tile, MapType.ImageEncoding enc) {
|
||||||
|
String tileId = String.format("%s_%s_%d_%d", tile.world.getName(), tile.map.getName(), tile.x, tile.y);
|
||||||
|
//sender.sendMessage("Tile found: " + tileId);
|
||||||
|
storedTileIds.add(tileId);
|
||||||
|
}
|
||||||
|
}, new MapStorageTileSearchEndCB() {
|
||||||
|
@Override
|
||||||
|
public void searchEnded() {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sendMessage(String.format("Scan complete - starting render"));
|
||||||
|
resumeInitDone = true; // Only due on first run
|
||||||
|
}
|
||||||
|
|
||||||
if(tile0 == null) { /* Not single tile render */
|
if(tile0 == null) { /* Not single tile render */
|
||||||
if (saverestorepending && world.isLoaded() && (savependingperiod > 0) && ((lastPendingSaveTS + (1000 *savependingperiod)) < System.currentTimeMillis())) {
|
if (saverestorepending && world.isLoaded() && (savependingperiod > 0) && ((lastPendingSaveTS + (1000 *savependingperiod)) < System.currentTimeMillis())) {
|
||||||
savePending(this.world, true); // Save the pending data for the given world
|
savePending(this.world, true); // Save the pending data for the given world
|
||||||
|
@ -624,10 +629,12 @@ public class MapManager {
|
||||||
renderedmaps.addAll(map.getMapsSharingRender(world));
|
renderedmaps.addAll(map.getMapsSharingRender(world));
|
||||||
|
|
||||||
/* Now, prime the render queue */
|
/* Now, prime the render queue */
|
||||||
for (MapTile mt : map.getTiles(world, (int)loc.x, (int)loc.y, (int)loc.z)) {
|
if (map.isReadOnly() == false) {
|
||||||
if (!found.getFlag(mt.tileOrdinalX(), mt.tileOrdinalY())) {
|
for (MapTile mt : map.getTiles(world, (int)loc.x, (int)loc.y, (int)loc.z)) {
|
||||||
found.setFlag(mt.tileOrdinalX(), mt.tileOrdinalY(), true);
|
if (!found.getFlag(mt.tileOrdinalX(), mt.tileOrdinalY())) {
|
||||||
renderQueue.add(mt);
|
found.setFlag(mt.tileOrdinalX(), mt.tileOrdinalY(), true);
|
||||||
|
renderQueue.add(mt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!updaterender) { /* Only add other seed points for fullrender */
|
if(!updaterender) { /* Only add other seed points for fullrender */
|
||||||
|
@ -687,6 +694,7 @@ public class MapManager {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
rslt.add(future);
|
rslt.add(future);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Now, do our render (first one) */
|
/* Now, do our render (first one) */
|
||||||
|
@ -922,6 +930,8 @@ public class MapManager {
|
||||||
f.get();
|
f.get();
|
||||||
} catch (CancellationException cx) {
|
} catch (CancellationException cx) {
|
||||||
return;
|
return;
|
||||||
|
} catch (InterruptedException cx) {
|
||||||
|
return;
|
||||||
} catch (ExecutionException ex) {
|
} catch (ExecutionException ex) {
|
||||||
Log.severe("Error while checking world times: ", ex.getCause());
|
Log.severe("Error while checking world times: ", ex.getCause());
|
||||||
} catch (Exception ix) {
|
} catch (Exception ix) {
|
||||||
|
@ -1064,6 +1074,10 @@ public class MapManager {
|
||||||
tiles.clear();
|
tiles.clear();
|
||||||
for(DynmapWorld w : worlds) {
|
for(DynmapWorld w : worlds) {
|
||||||
for(MapTypeState mts : w.mapstate) {
|
for(MapTypeState mts : w.mapstate) {
|
||||||
|
if (mts.type.isReadOnly()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(mts.getNextInvalidTileCoord(coord)) {
|
if(mts.getNextInvalidTileCoord(coord)) {
|
||||||
mts.type.addMapTiles(tiles, w, coord.x, coord.y);
|
mts.type.addMapTiles(tiles, w, coord.x, coord.y);
|
||||||
mts.validateTile(coord.x, coord.y);
|
mts.validateTile(coord.x, coord.y);
|
||||||
|
@ -1141,7 +1155,9 @@ public class MapManager {
|
||||||
if(progressinterval < 100) progressinterval = 100;
|
if(progressinterval < 100) progressinterval = 100;
|
||||||
saverestorepending = configuration.getBoolean("saverestorepending", true);
|
saverestorepending = configuration.getBoolean("saverestorepending", true);
|
||||||
tileupdatedelay = configuration.getInteger("tileupdatedelay", 30);
|
tileupdatedelay = configuration.getInteger("tileupdatedelay", 30);
|
||||||
|
defaulttilescale = configuration.getInteger("defaulttilescale", 0);
|
||||||
|
if (defaulttilescale < 0) defaulttilescale = 0;
|
||||||
|
if (defaulttilescale > 4) defaulttilescale = 4;
|
||||||
tpslimit_updaterenders = configuration.getDouble("update-min-tps", 18.0);
|
tpslimit_updaterenders = configuration.getDouble("update-min-tps", 18.0);
|
||||||
if (tpslimit_updaterenders > 19.5) tpslimit_updaterenders = 19.5;
|
if (tpslimit_updaterenders > 19.5) tpslimit_updaterenders = 19.5;
|
||||||
tpslimit_fullrenders = configuration.getDouble("fullrender-min-tps", 18.0);
|
tpslimit_fullrenders = configuration.getDouble("fullrender-min-tps", 18.0);
|
||||||
|
@ -1893,6 +1909,10 @@ public class MapManager {
|
||||||
}
|
}
|
||||||
if(world == null) continue;
|
if(world == null) continue;
|
||||||
for (MapTypeState mts : world.mapstate) {
|
for (MapTypeState mts : world.mapstate) {
|
||||||
|
if (mts.type.isReadOnly()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
List<TileFlags.TileCoord> tiles = mts.type.getTileCoords(world, evt.x, evt.y, evt.z);
|
List<TileFlags.TileCoord> tiles = mts.type.getTileCoords(world, evt.x, evt.y, evt.z);
|
||||||
invalidates += mts.invalidateTiles(tiles);
|
invalidates += mts.invalidateTiles(tiles);
|
||||||
}
|
}
|
||||||
|
@ -1925,6 +1945,10 @@ public class MapManager {
|
||||||
if(world == null) continue;
|
if(world == null) continue;
|
||||||
int invalidates = 0;
|
int invalidates = 0;
|
||||||
for (MapTypeState mts : world.mapstate) {
|
for (MapTypeState mts : world.mapstate) {
|
||||||
|
if (mts.type.isReadOnly()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
List<TileFlags.TileCoord> tiles = mts.type.getTileCoords(world, evt.xmin, evt.ymin, evt.zmin, evt.xmax, evt.ymax, evt.zmax);
|
List<TileFlags.TileCoord> tiles = mts.type.getTileCoords(world, evt.xmin, evt.ymin, evt.zmin, evt.xmax, evt.ymax, evt.zmax);
|
||||||
invalidates += mts.invalidateTiles(tiles);
|
invalidates += mts.invalidateTiles(tiles);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ public abstract class MapTile {
|
||||||
public abstract boolean render(MapChunkCache cache, String mapname);
|
public abstract boolean render(MapChunkCache cache, String mapname);
|
||||||
public abstract List<DynmapChunk> getRequiredChunks();
|
public abstract List<DynmapChunk> getRequiredChunks();
|
||||||
public abstract MapTile[] getAdjecentTiles();
|
public abstract MapTile[] getAdjecentTiles();
|
||||||
|
public abstract int getTileSize();
|
||||||
|
|
||||||
public DynmapWorld getDynmapWorld() {
|
public DynmapWorld getDynmapWorld() {
|
||||||
return world;
|
return world;
|
||||||
|
|
|
@ -10,6 +10,10 @@ import org.json.simple.JSONObject;
|
||||||
|
|
||||||
public abstract class MapType {
|
public abstract class MapType {
|
||||||
private boolean is_protected;
|
private boolean is_protected;
|
||||||
|
/**
|
||||||
|
* Is the map type read-only? (i.e. should not be updated by renderer)
|
||||||
|
*/
|
||||||
|
private boolean is_readonly;
|
||||||
protected int tileupdatedelay;
|
protected int tileupdatedelay;
|
||||||
|
|
||||||
public enum ImageVariant {
|
public enum ImageVariant {
|
||||||
|
@ -30,13 +34,15 @@ public abstract class MapType {
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ImageEncoding {
|
public enum ImageEncoding {
|
||||||
PNG("png", "image/png"), JPG("jpg", "image/jpeg"), WEBP("webp", "image/webp");
|
PNG("png", "image/png", true), JPG("jpg", "image/jpeg", false), WEBP("webp", "image/webp", true);
|
||||||
public final String ext;
|
public final String ext;
|
||||||
public final String mimetype;
|
public final String mimetype;
|
||||||
|
public final boolean hasAlpha;
|
||||||
|
|
||||||
ImageEncoding(String ext, String mime) {
|
ImageEncoding(String ext, String mime, boolean has_alpha) {
|
||||||
this.ext = ext;
|
this.ext = ext;
|
||||||
this.mimetype = mime;
|
this.mimetype = mime;
|
||||||
|
this.hasAlpha = has_alpha;
|
||||||
}
|
}
|
||||||
public String getFileExt() { return ext; }
|
public String getFileExt() { return ext; }
|
||||||
public String getContentType() { return mimetype; }
|
public String getContentType() { return mimetype; }
|
||||||
|
@ -47,6 +53,15 @@ public abstract class MapType {
|
||||||
return v[ix];
|
return v[ix];
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
public static ImageEncoding fromContentType(String ct) {
|
||||||
|
ImageEncoding[] v = values();
|
||||||
|
for (int i = 0; i < v.length; i++) {
|
||||||
|
if (v[i].mimetype.equalsIgnoreCase(ct)) {
|
||||||
|
return v[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
public static ImageEncoding fromExt(String x) {
|
public static ImageEncoding fromExt(String x) {
|
||||||
ImageEncoding[] v = values();
|
ImageEncoding[] v = values();
|
||||||
for (int i = 0; i < v.length; i++) {
|
for (int i = 0; i < v.length; i++) {
|
||||||
|
@ -115,6 +130,8 @@ public abstract class MapType {
|
||||||
|
|
||||||
public abstract List<DynmapChunk> getRequiredChunks(MapTile tile);
|
public abstract List<DynmapChunk> getRequiredChunks(MapTile tile);
|
||||||
|
|
||||||
|
public abstract int getTileSize();
|
||||||
|
|
||||||
public void buildClientConfiguration(JSONObject worldObject, DynmapWorld w) {
|
public void buildClientConfiguration(JSONObject worldObject, DynmapWorld w) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +211,26 @@ public abstract class MapType {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Is the map type read-only? (i.e. should not be updated by renderer)
|
||||||
|
* @return true if read-only
|
||||||
|
*/
|
||||||
|
public boolean isReadOnly() {
|
||||||
|
return is_readonly;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set read-only state of map type
|
||||||
|
* @param r - true if read-only
|
||||||
|
* @return true if state changed
|
||||||
|
*/
|
||||||
|
public boolean setReadOnly(boolean r) {
|
||||||
|
if(is_readonly != r) {
|
||||||
|
is_readonly = r;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
public abstract String getPrefix();
|
public abstract String getPrefix();
|
||||||
|
|
||||||
public int getTileUpdateDelay(DynmapWorld w) {
|
public int getTileUpdateDelay(DynmapWorld w) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ public class MapTypeState {
|
||||||
private TileFlags.Iterator zoomOutInvIter = null;
|
private TileFlags.Iterator zoomOutInvIter = null;
|
||||||
private int zoomOutInvIterLevel = -1;
|
private int zoomOutInvIterLevel = -1;
|
||||||
private final int zoomOutLevels;
|
private final int zoomOutLevels;
|
||||||
|
public final int tileSize;
|
||||||
|
|
||||||
public MapTypeState(DynmapWorld world, MapType mt) {
|
public MapTypeState(DynmapWorld world, MapType mt) {
|
||||||
type = mt;
|
type = mt;
|
||||||
|
@ -32,6 +33,7 @@ public class MapTypeState {
|
||||||
zoomOutInv.add(null);
|
zoomOutInv.add(null);
|
||||||
zoomOutInvAccum.add(null);
|
zoomOutInvAccum.add(null);
|
||||||
}
|
}
|
||||||
|
tileSize = mt.getTileSize();
|
||||||
}
|
}
|
||||||
public void setInvalidatePeriod(long inv_per_in_secs) {
|
public void setInvalidatePeriod(long inv_per_in_secs) {
|
||||||
invTSPeriod = inv_per_in_secs * NANOS_PER_SECOND;
|
invTSPeriod = inv_per_in_secs * NANOS_PER_SECOND;
|
||||||
|
|
|
@ -31,6 +31,7 @@ public class MarkersComponent extends ClientComponent {
|
||||||
private MarkerSet spawnbedset;
|
private MarkerSet spawnbedset;
|
||||||
private MarkerIcon spawnbedicon;
|
private MarkerIcon spawnbedicon;
|
||||||
private String spawnbedformat;
|
private String spawnbedformat;
|
||||||
|
private boolean removebedonplayerleave;
|
||||||
private long maxofflineage;
|
private long maxofflineage;
|
||||||
private boolean showSpawn;
|
private boolean showSpawn;
|
||||||
private boolean showBorder;
|
private boolean showBorder;
|
||||||
|
@ -180,7 +181,7 @@ public class MarkersComponent extends ClientComponent {
|
||||||
|
|
||||||
spawnbedicon = api.getMarkerIcon(configuration.getString("spawnbedicon", "bed"));
|
spawnbedicon = api.getMarkerIcon(configuration.getString("spawnbedicon", "bed"));
|
||||||
spawnbedformat = configuration.getString("spawnbedformat", "%name%'s bed");
|
spawnbedformat = configuration.getString("spawnbedformat", "%name%'s bed");
|
||||||
|
removebedonplayerleave = configuration.getBoolean("spawnbedremoveonplayerleave", true);
|
||||||
/* Add listener for players coming and going */
|
/* Add listener for players coming and going */
|
||||||
core.listenerManager.addListener(EventType.PLAYER_JOIN, new PlayerEventListener() {
|
core.listenerManager.addListener(EventType.PLAYER_JOIN, new PlayerEventListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -188,15 +189,17 @@ public class MarkersComponent extends ClientComponent {
|
||||||
updatePlayer(p);
|
updatePlayer(p);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
core.listenerManager.addListener(EventType.PLAYER_QUIT, new PlayerEventListener() {
|
if (removebedonplayerleave) {
|
||||||
@Override
|
core.listenerManager.addListener(EventType.PLAYER_QUIT, new PlayerEventListener() {
|
||||||
public void playerEvent(DynmapPlayer p) {
|
@Override
|
||||||
Marker m = spawnbedset.findMarker(p.getName()+"_bed");
|
public void playerEvent(DynmapPlayer p) {
|
||||||
if(m != null) {
|
Marker m = spawnbedset.findMarker(p.getName() + "_bed");
|
||||||
m.deleteMarker();
|
if (m != null) {
|
||||||
|
m.deleteMarker();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
core.listenerManager.addListener(EventType.PLAYER_BED_LEAVE, new PlayerEventListener() {
|
core.listenerManager.addListener(EventType.PLAYER_BED_LEAVE, new PlayerEventListener() {
|
||||||
@Override
|
@Override
|
||||||
public void playerEvent(final DynmapPlayer p) {
|
public void playerEvent(final DynmapPlayer p) {
|
||||||
|
|
|
@ -174,7 +174,6 @@ public class PlayerFaces {
|
||||||
// Copy face and overlay to icon
|
// Copy face and overlay to icon
|
||||||
copyLayersToTarget(img, 8*scale, 8*scale, 40*scale, 8*scale, 8*scale, 8*scale, faceOriginal, 0, 8*scale);
|
copyLayersToTarget(img, 8*scale, 8*scale, 40*scale, 8*scale, 8*scale, 8*scale, faceOriginal, 0, 8*scale);
|
||||||
|
|
||||||
int[] faceaccessory = new int[64]; /* 8x8 of face accessory */
|
|
||||||
/* Get buffered image for face at 8x8 */
|
/* Get buffered image for face at 8x8 */
|
||||||
DynmapBufferedImage face8x8 = DynmapBufferedImage.allocateBufferedImage(8, 8);
|
DynmapBufferedImage face8x8 = DynmapBufferedImage.allocateBufferedImage(8, 8);
|
||||||
Image face8x8_image = faceOriginal.getScaledInstance(8,8,BufferedImage.SCALE_SMOOTH);
|
Image face8x8_image = faceOriginal.getScaledInstance(8,8,BufferedImage.SCALE_SMOOTH);
|
||||||
|
|
|
@ -7,11 +7,11 @@ import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Random;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.dynmap.common.DynmapCommandSender;
|
import org.dynmap.common.DynmapCommandSender;
|
||||||
|
@ -26,8 +26,9 @@ public class WebAuthManager {
|
||||||
public static final String WEBAUTHFILE = "webauth.txt";
|
public static final String WEBAUTHFILE = "webauth.txt";
|
||||||
private static final String HASHSALT = "$HASH_SALT$";
|
private static final String HASHSALT = "$HASH_SALT$";
|
||||||
private static final String PWDHASH_PREFIX = "hash.";
|
private static final String PWDHASH_PREFIX = "hash.";
|
||||||
private Random rnd = new Random();
|
private SecureRandom rnd = new SecureRandom();
|
||||||
private DynmapCore core;
|
private DynmapCore core;
|
||||||
|
private String publicRegistrationURL;
|
||||||
|
|
||||||
public WebAuthManager(DynmapCore core) {
|
public WebAuthManager(DynmapCore core) {
|
||||||
this.core = core;
|
this.core = core;
|
||||||
|
@ -202,7 +203,8 @@ public class WebAuthManager {
|
||||||
pending_registrations.put(uid.toLowerCase(), regkey.toLowerCase());
|
pending_registrations.put(uid.toLowerCase(), regkey.toLowerCase());
|
||||||
sender.sendMessage("Registration pending for user ID: " + uid);
|
sender.sendMessage("Registration pending for user ID: " + uid);
|
||||||
sender.sendMessage("Registration code: " + regkey);
|
sender.sendMessage("Registration code: " + regkey);
|
||||||
sender.sendMessage("Enter ID and code on registration web page (login.html) to complete registration");
|
publicRegistrationURL = core.configuration.getString("publicURL", "index.html");
|
||||||
|
sender.sendMessage("Enter ID and code on registration web page (" + publicRegistrationURL.toString() + ") to complete registration");
|
||||||
if(other) {
|
if(other) {
|
||||||
DynmapPlayer p = core.getServer().getPlayer(uid);
|
DynmapPlayer p = core.getServer().getPlayer(uid);
|
||||||
if(p != null) {
|
if(p != null) {
|
||||||
|
|
|
@ -3,8 +3,8 @@ package org.dynmap.common;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.dynmap.Log;
|
|
||||||
import org.dynmap.hdmap.HDBlockModels;
|
import org.dynmap.hdmap.HDBlockModels;
|
||||||
|
|
||||||
/* Generic biome mapping */
|
/* Generic biome mapping */
|
||||||
|
@ -20,7 +20,7 @@ public class BiomeMap {
|
||||||
public static final BiomeMap EXTREME_HILLS = new BiomeMap(3, "EXTREME_HILLS", 0.2, 0.3, "minecraft:mountains");
|
public static final BiomeMap EXTREME_HILLS = new BiomeMap(3, "EXTREME_HILLS", 0.2, 0.3, "minecraft:mountains");
|
||||||
public static final BiomeMap FOREST = new BiomeMap(4, "FOREST", 0.7, 0.8, "minecraft:forest");
|
public static final BiomeMap FOREST = new BiomeMap(4, "FOREST", 0.7, 0.8, "minecraft:forest");
|
||||||
public static final BiomeMap TAIGA = new BiomeMap(5, "TAIGA", 0.05, 0.8, "minecraft:taiga");
|
public static final BiomeMap TAIGA = new BiomeMap(5, "TAIGA", 0.05, 0.8, "minecraft:taiga");
|
||||||
public static final BiomeMap SWAMPLAND = new BiomeMap(6, "SWAMPLAND", 0.8, 0.9, 0xE0FFAE, 0x4E0E4E, 0x4E0E4E, "minecraft:swamp");
|
public static final BiomeMap SWAMPLAND = new BiomeMap(6, "SWAMPLAND", 0.8, 0.9, 0xE0FFAE, 0x2e282a, 0x902c52, "minecraft:swamp");
|
||||||
public static final BiomeMap RIVER = new BiomeMap(7, "RIVER", "minecraft:river");
|
public static final BiomeMap RIVER = new BiomeMap(7, "RIVER", "minecraft:river");
|
||||||
public static final BiomeMap HELL = new BiomeMap(8, "HELL", 2.0, 0.0, "minecraft:nether");
|
public static final BiomeMap HELL = new BiomeMap(8, "HELL", 2.0, 0.0, "minecraft:nether");
|
||||||
public static final BiomeMap SKY = new BiomeMap(9, "SKY", "minecraft:the_end");
|
public static final BiomeMap SKY = new BiomeMap(9, "SKY", "minecraft:the_end");
|
||||||
|
@ -45,6 +45,7 @@ public class BiomeMap {
|
||||||
private int watercolormult;
|
private int watercolormult;
|
||||||
private int grassmult;
|
private int grassmult;
|
||||||
private int foliagemult;
|
private int foliagemult;
|
||||||
|
private Optional<?> biomeObj = Optional.empty();
|
||||||
private final String id;
|
private final String id;
|
||||||
private final String resourcelocation;
|
private final String resourcelocation;
|
||||||
private final int index;
|
private final int index;
|
||||||
|
@ -62,7 +63,7 @@ public class BiomeMap {
|
||||||
new BiomeMap(26, "COLD_BEACH", 0.05, 0.3, "minecraft:snowy_beach");
|
new BiomeMap(26, "COLD_BEACH", 0.05, 0.3, "minecraft:snowy_beach");
|
||||||
new BiomeMap(27, "BIRCH_FOREST", 0.6, 0.6, "minecraft:birch_forest");
|
new BiomeMap(27, "BIRCH_FOREST", 0.6, 0.6, "minecraft:birch_forest");
|
||||||
new BiomeMap(28, "BIRCH_FOREST_HILLS", 0.6, 0.6, "minecraft:birch_forest_hills");
|
new BiomeMap(28, "BIRCH_FOREST_HILLS", 0.6, 0.6, "minecraft:birch_forest_hills");
|
||||||
new BiomeMap(29, "ROOFED_FOREST", 0.7, 0.8, "minecraft:dark_forest");
|
new BiomeMap(29, "ROOFED_FOREST", 0.7, 0.8, 0xFFFFFF, 0x28340A, 0, "minecraft:dark_forest");
|
||||||
new BiomeMap(30, "COLD_TAIGA", -0.5, 0.4, "minecraft:snowy_taiga");
|
new BiomeMap(30, "COLD_TAIGA", -0.5, 0.4, "minecraft:snowy_taiga");
|
||||||
new BiomeMap(31, "COLD_TAIGA_HILLS", -0.5, 0.4, "minecraft:snowy_taiga_hills");
|
new BiomeMap(31, "COLD_TAIGA_HILLS", -0.5, 0.4, "minecraft:snowy_taiga_hills");
|
||||||
new BiomeMap(32, "MEGA_TAIGA", 0.3, 0.8, "minecraft:giant_tree_taiga");
|
new BiomeMap(32, "MEGA_TAIGA", 0.3, 0.8, "minecraft:giant_tree_taiga");
|
||||||
|
@ -70,30 +71,32 @@ public class BiomeMap {
|
||||||
new BiomeMap(34, "EXTREME_HILLS_PLUS", 0.2, 0.3, "minecraft:wooded_mountains");
|
new BiomeMap(34, "EXTREME_HILLS_PLUS", 0.2, 0.3, "minecraft:wooded_mountains");
|
||||||
new BiomeMap(35, "SAVANNA", 1.2, 0.0, "minecraft:savanna");
|
new BiomeMap(35, "SAVANNA", 1.2, 0.0, "minecraft:savanna");
|
||||||
new BiomeMap(36, "SAVANNA_PLATEAU", 1.0, 0.0, "minecraft:savanna_plateau");
|
new BiomeMap(36, "SAVANNA_PLATEAU", 1.0, 0.0, "minecraft:savanna_plateau");
|
||||||
new BiomeMap(37, "MESA", 2.0, 0.0, "minecraft:badlands");
|
new BiomeMap(37, "MESA", 2.0, 0.0, 0xFFFFFF, 0x624c46, 0x8e5e70, "minecraft:badlands");
|
||||||
new BiomeMap(38, "MESA_PLATEAU_FOREST", 2.0, 0.0, "minecraft:wooded_badlands_plateau");
|
|
||||||
new BiomeMap(39, "MESA_PLATEAU", 2.0, 0.0, "minecraft:badlands_plateau");
|
|
||||||
new BiomeMap(129, "SUNFLOWER_PLAINS", 0.8, 0.4, "minecraft:sunflower_plains");
|
new BiomeMap(129, "SUNFLOWER_PLAINS", 0.8, 0.4, "minecraft:sunflower_plains");
|
||||||
new BiomeMap(130, "DESERT_MOUNTAINS", 2.0, 0.0, "minecraft:desert_lakes");
|
new BiomeMap(130, "DESERT_MOUNTAINS", 2.0, 0.0, "minecraft:desert_lakes");
|
||||||
new BiomeMap(131, "EXTREME_HILLS_MOUNTAINS", 0.2, 0.3, "minecraft:gravelly_mountains");
|
new BiomeMap(131, "EXTREME_HILLS_MOUNTAINS", 0.2, 0.3, "minecraft:gravelly_mountains");
|
||||||
new BiomeMap(132, "FLOWER_FOREST", 0.7, 0.8, "minecraft:flower_forest");
|
new BiomeMap(132, "FLOWER_FOREST", 0.7, 0.8, "minecraft:flower_forest");
|
||||||
new BiomeMap(133, "TAIGA_MOUNTAINS", 0.05, 0.8, "minecraft:taiga_mountains");
|
new BiomeMap(133, "TAIGA_MOUNTAINS", 0.05, 0.8, "minecraft:taiga_mountains");
|
||||||
new BiomeMap(134, "SWAMPLAND_MOUNTAINS", 0.8, 0.9, 0xE0FFAE, 0x4E0E4E, 0x4E0E4E, "minecraft:swamp_hills");
|
|
||||||
new BiomeMap(140, "ICE_PLAINS_SPIKES", 0.0, 0.5, "minecraft:ice_spikes");
|
new BiomeMap(140, "ICE_PLAINS_SPIKES", 0.0, 0.5, "minecraft:ice_spikes");
|
||||||
new BiomeMap(149, "JUNGLE_MOUNTAINS", 1.2, 0.9, "minecraft:modified_jungle");
|
new BiomeMap(149, "JUNGLE_MOUNTAINS", 1.2, 0.9, "minecraft:modified_jungle");
|
||||||
new BiomeMap(151, "JUNGLE_EDGE_MOUNTAINS", 0.95, 0.8, "minecraft:modified_jungle_edge");
|
new BiomeMap(151, "JUNGLE_EDGE_MOUNTAINS", 0.95, 0.8, "minecraft:modified_jungle_edge");
|
||||||
new BiomeMap(155, "BIRCH_FOREST_MOUNTAINS", 0.6, 0.6, "minecraft:tall_birch_forest");
|
new BiomeMap(155, "BIRCH_FOREST_MOUNTAINS", 0.6, 0.6, "minecraft:tall_birch_forest");
|
||||||
new BiomeMap(156, "BIRCH_FOREST_HILLS_MOUNTAINS", 0.6, 0.6, "minecraft:tall_birch_hills");
|
new BiomeMap(156, "BIRCH_FOREST_HILLS_MOUNTAINS", 0.6, 0.6, "minecraft:tall_birch_hills");
|
||||||
new BiomeMap(157, "ROOFED_FOREST_MOUNTAINS", 0.7, 0.8, "minecraft:dark_forest_hills");
|
new BiomeMap(157, "ROOFED_FOREST_MOUNTAINS", 0.7, 0.8, 0xFFFFFF, 0x28340A, 0, "minecraft:dark_forest_hills");
|
||||||
new BiomeMap(158, "COLD_TAIGA_MOUNTAINS", -0.5, 0.4, "minecraft:snowy_taiga_mountains");
|
new BiomeMap(158, "COLD_TAIGA_MOUNTAINS", -0.5, 0.4, "minecraft:snowy_taiga_mountains");
|
||||||
new BiomeMap(160, "MEGA_SPRUCE_TAIGA", 0.25, 0.8, "minecraft:giant_spruce_taiga");
|
new BiomeMap(160, "MEGA_SPRUCE_TAIGA", 0.25, 0.8, "minecraft:giant_spruce_taiga");
|
||||||
new BiomeMap(161, "MEGA_SPRUCE_TAIGA_HILLS", 0.3, 0.8, "minecraft:giant_spruce_taiga_hills");
|
new BiomeMap(161, "MEGA_SPRUCE_TAIGA_HILLS", 0.3, 0.8, "minecraft:giant_spruce_taiga_hills");
|
||||||
new BiomeMap(162, "EXTREME_HILLS_PLUS_MOUNTAINS", 0.2, 0.3, "minecraft:modified_gravelly_mountains");
|
new BiomeMap(162, "EXTREME_HILLS_PLUS_MOUNTAINS", 0.2, 0.3, "minecraft:modified_gravelly_mountains");
|
||||||
new BiomeMap(163, "SAVANNA_MOUNTAINS", 1.2, 0.0, "minecraft:shattered_savanna");
|
new BiomeMap(163, "SAVANNA_MOUNTAINS", 1.2, 0.0, "minecraft:shattered_savanna");
|
||||||
new BiomeMap(164, "SAVANNA_PLATEAU_MOUNTAINS", 1.0, 0.0, "minecraft:shattered_savanna_plateau");
|
new BiomeMap(164, "SAVANNA_PLATEAU_MOUNTAINS", 1.0, 0.0, "minecraft:shattered_savanna_plateau");
|
||||||
new BiomeMap(165, "MESA_BRYCE", 2.0, 0.0, "minecraft:eroded_badlands");
|
new BiomeMap(165, "MESA_BRYCE", 2.0, 0.0,0xFFFFFF, 0x624c46, 0x8e5e70, "minecraft:eroded_badlands");
|
||||||
new BiomeMap(166, "MESA_PLATEAU_FOREST_MOUNTAINS", 2.0, 0.0, "minecraft:modified_wooded_badlands_plateau");
|
}
|
||||||
new BiomeMap(167, "MESA_PLATEAU_MOUNTAINS", 2.0, 0.0, "minecraft:modified_badlands_plateau");
|
if (HDBlockModels.checkVersionRange(mcver, "1.7.0-1.17.1")) {
|
||||||
|
new BiomeMap(38, "MESA_PLATEAU_FOREST", 2.0, 0.0, 0xFFFFFF, 0x624c46, 0x8e5e70, "minecraft:wooded_badlands_plateau");
|
||||||
|
new BiomeMap(39, "MESA_PLATEAU", 2.0, 0.0, 0xFFFFFF, 0x624c46, 0x8e5e70, "minecraft:badlands_plateau");
|
||||||
|
new BiomeMap(134, "SWAMPLAND_MOUNTAINS", 0.8, 0.9, 0xE0FFAE, 0x2e282a, 0x902c52, "minecraft:swamp_hills");
|
||||||
|
new BiomeMap(166, "MESA_PLATEAU_FOREST_MOUNTAINS", 2.0, 0.0,0xFFFFFF, 0x624c46, 0x8e5e70, "minecraft:modified_wooded_badlands_plateau");
|
||||||
|
new BiomeMap(167, "MESA_PLATEAU_MOUNTAINS", 2.0, 0.0,0xFFFFFF, 0x624c46, 0x8e5e70, "minecraft:modified_badlands_plateau");
|
||||||
}
|
}
|
||||||
if (HDBlockModels.checkVersionRange(mcver, "1.9.0-")) {
|
if (HDBlockModels.checkVersionRange(mcver, "1.9.0-")) {
|
||||||
new BiomeMap(127, "THE_VOID", "minecraft:the_void");
|
new BiomeMap(127, "THE_VOID", "minecraft:the_void");
|
||||||
|
@ -125,6 +128,9 @@ public class BiomeMap {
|
||||||
new BiomeMap(174, "DRIPSTONE_CAVES", "minecraft:dripstone_caves");
|
new BiomeMap(174, "DRIPSTONE_CAVES", "minecraft:dripstone_caves");
|
||||||
new BiomeMap(175, "LUSH_CAVES", "minecraft:lush_caves");
|
new BiomeMap(175, "LUSH_CAVES", "minecraft:lush_caves");
|
||||||
}
|
}
|
||||||
|
if (HDBlockModels.checkVersionRange(mcver, "1.18.0-")) {
|
||||||
|
new BiomeMap(38, "MESA_FOREST", 2.0, 0.0, 0xFFFFFF, 0x624c46, 0x8e5e70, "minecraft:wooded_badlands");
|
||||||
|
}
|
||||||
loadDone = true;
|
loadDone = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,7 +304,16 @@ public class BiomeMap {
|
||||||
public boolean isDefault() {
|
public boolean isDefault() {
|
||||||
return isDef;
|
return isDef;
|
||||||
}
|
}
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("%s(%s)", id, resourcelocation);
|
return String.format("%s(%s)", id, resourcelocation);
|
||||||
}
|
}
|
||||||
|
public @SuppressWarnings("unchecked") <T> Optional<T> getBiomeObject() {
|
||||||
|
return (Optional<T>) biomeObj;
|
||||||
|
}
|
||||||
|
public void setBiomeObject(Object biomeObj) {
|
||||||
|
this.biomeObj = Optional.of(biomeObj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,12 @@ public interface DynmapPlayer extends DynmapCommandSender {
|
||||||
* @return true if sneaking
|
* @return true if sneaking
|
||||||
*/
|
*/
|
||||||
public boolean isSneaking();
|
public boolean isSneaking();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get spectator gamemode
|
||||||
|
* @return true if gamemode spectator
|
||||||
|
*/
|
||||||
|
public boolean isSpectator();
|
||||||
/**
|
/**
|
||||||
* Get health
|
* Get health
|
||||||
* @return health points
|
* @return health points
|
||||||
|
|
|
@ -3,7 +3,6 @@ package org.dynmap.common.chunk;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.dynmap.renderer.DynmapBlockState;
|
import org.dynmap.renderer.DynmapBlockState;
|
||||||
import org.dynmap.Log;
|
|
||||||
import org.dynmap.common.BiomeMap;
|
import org.dynmap.common.BiomeMap;
|
||||||
|
|
||||||
// Generic chunk representation
|
// Generic chunk representation
|
||||||
|
|
|
@ -18,6 +18,7 @@ public class GenericChunkCache {
|
||||||
};
|
};
|
||||||
|
|
||||||
private CacheHashMap snapcache;
|
private CacheHashMap snapcache;
|
||||||
|
private final Object snapcachelock;
|
||||||
private ReferenceQueue<ChunkCacheRec> refqueue;
|
private ReferenceQueue<ChunkCacheRec> refqueue;
|
||||||
private long cache_attempts;
|
private long cache_attempts;
|
||||||
private long cache_success;
|
private long cache_success;
|
||||||
|
@ -50,6 +51,7 @@ public class GenericChunkCache {
|
||||||
* Create snapshot cache
|
* Create snapshot cache
|
||||||
*/
|
*/
|
||||||
public GenericChunkCache(int max_size, boolean softref) {
|
public GenericChunkCache(int max_size, boolean softref) {
|
||||||
|
snapcachelock = new Object();
|
||||||
snapcache = new CacheHashMap(max_size);
|
snapcache = new CacheHashMap(max_size);
|
||||||
refqueue = new ReferenceQueue<ChunkCacheRec>();
|
refqueue = new ReferenceQueue<ChunkCacheRec>();
|
||||||
this.softref = softref;
|
this.softref = softref;
|
||||||
|
@ -62,8 +64,8 @@ public class GenericChunkCache {
|
||||||
*/
|
*/
|
||||||
public void invalidateSnapshot(String w, int x, int y, int z) {
|
public void invalidateSnapshot(String w, int x, int y, int z) {
|
||||||
String key = getKey(w, x>>4, z>>4);
|
String key = getKey(w, x>>4, z>>4);
|
||||||
synchronized(snapcache) {
|
synchronized(snapcachelock) {
|
||||||
CacheRec rec = snapcache.remove(key);
|
CacheRec rec = (snapcache != null) ? snapcache.remove(key) : null;
|
||||||
if(rec != null) {
|
if(rec != null) {
|
||||||
snapcache.reverselookup.remove(rec.ref);
|
snapcache.reverselookup.remove(rec.ref);
|
||||||
rec.ref.clear();
|
rec.ref.clear();
|
||||||
|
@ -78,8 +80,8 @@ public class GenericChunkCache {
|
||||||
for(int xx = (x0>>4); xx <= (x1>>4); xx++) {
|
for(int xx = (x0>>4); xx <= (x1>>4); xx++) {
|
||||||
for(int zz = (z0>>4); zz <= (z1>>4); zz++) {
|
for(int zz = (z0>>4); zz <= (z1>>4); zz++) {
|
||||||
String key = getKey(w, xx, zz);
|
String key = getKey(w, xx, zz);
|
||||||
synchronized(snapcache) {
|
synchronized(snapcachelock) {
|
||||||
CacheRec rec = snapcache.remove(key);
|
CacheRec rec = (snapcache != null) ? snapcache.remove(key) : null;
|
||||||
if(rec != null) {
|
if(rec != null) {
|
||||||
snapcache.reverselookup.remove(rec.ref);
|
snapcache.reverselookup.remove(rec.ref);
|
||||||
rec.ref.clear();
|
rec.ref.clear();
|
||||||
|
@ -97,8 +99,8 @@ public class GenericChunkCache {
|
||||||
processRefQueue();
|
processRefQueue();
|
||||||
ChunkCacheRec ss = null;
|
ChunkCacheRec ss = null;
|
||||||
CacheRec rec;
|
CacheRec rec;
|
||||||
synchronized(snapcache) {
|
synchronized(snapcachelock) {
|
||||||
rec = snapcache.get(key);
|
rec = (snapcache != null) ? snapcache.get(key) : null;
|
||||||
if(rec != null) {
|
if(rec != null) {
|
||||||
ss = rec.ref.get();
|
ss = rec.ref.get();
|
||||||
if(ss == null) {
|
if(ss == null) {
|
||||||
|
@ -123,8 +125,8 @@ public class GenericChunkCache {
|
||||||
rec.ref = new SoftReference<ChunkCacheRec>(ss, refqueue);
|
rec.ref = new SoftReference<ChunkCacheRec>(ss, refqueue);
|
||||||
else
|
else
|
||||||
rec.ref = new WeakReference<ChunkCacheRec>(ss, refqueue);
|
rec.ref = new WeakReference<ChunkCacheRec>(ss, refqueue);
|
||||||
synchronized(snapcache) {
|
synchronized(snapcachelock) {
|
||||||
CacheRec prevrec = snapcache.put(key, rec);
|
CacheRec prevrec = (snapcache != null) ? snapcache.put(key, rec) : null;
|
||||||
if(prevrec != null) {
|
if(prevrec != null) {
|
||||||
snapcache.reverselookup.remove(prevrec.ref);
|
snapcache.reverselookup.remove(prevrec.ref);
|
||||||
}
|
}
|
||||||
|
@ -137,8 +139,8 @@ public class GenericChunkCache {
|
||||||
private void processRefQueue() {
|
private void processRefQueue() {
|
||||||
Reference<? extends ChunkCacheRec> ref;
|
Reference<? extends ChunkCacheRec> ref;
|
||||||
while((ref = refqueue.poll()) != null) {
|
while((ref = refqueue.poll()) != null) {
|
||||||
synchronized(snapcache) {
|
synchronized(snapcachelock) {
|
||||||
String k = snapcache.reverselookup.remove(ref);
|
String k = (snapcache != null) ? snapcache.reverselookup.remove(ref) : null;
|
||||||
if(k != null) {
|
if(k != null) {
|
||||||
snapcache.remove(k);
|
snapcache.remove(k);
|
||||||
}
|
}
|
||||||
|
@ -164,11 +166,13 @@ public class GenericChunkCache {
|
||||||
* Cleanup
|
* Cleanup
|
||||||
*/
|
*/
|
||||||
public void cleanup() {
|
public void cleanup() {
|
||||||
if(snapcache != null) {
|
synchronized(snapcachelock) {
|
||||||
snapcache.clear();
|
if(snapcache != null) {
|
||||||
snapcache.reverselookup.clear();
|
snapcache.clear();
|
||||||
snapcache.reverselookup = null;
|
snapcache.reverselookup.clear();
|
||||||
snapcache = null;
|
snapcache.reverselookup = null;
|
||||||
}
|
snapcache = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
package org.dynmap.common.chunk;
|
package org.dynmap.common.chunk;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.ListIterator;
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.dynmap.DynmapChunk;
|
import org.dynmap.DynmapChunk;
|
||||||
import org.dynmap.DynmapCore;
|
import org.dynmap.DynmapCore;
|
||||||
import org.dynmap.DynmapWorld;
|
import org.dynmap.DynmapWorld;
|
||||||
import org.dynmap.Log;
|
|
||||||
import org.dynmap.common.BiomeMap;
|
import org.dynmap.common.BiomeMap;
|
||||||
import org.dynmap.common.chunk.GenericChunkCache.ChunkCacheRec;
|
import org.dynmap.common.chunk.GenericChunkCache.ChunkCacheRec;
|
||||||
import org.dynmap.hdmap.HDBlockModels;
|
import org.dynmap.hdmap.HDBlockModels;
|
||||||
|
@ -24,7 +25,6 @@ import org.dynmap.utils.VisibilityLimit;
|
||||||
* Abstract container for handling map cache and map iterator, using DynmapChunks
|
* Abstract container for handling map cache and map iterator, using DynmapChunks
|
||||||
*/
|
*/
|
||||||
public abstract class GenericMapChunkCache extends MapChunkCache {
|
public abstract class GenericMapChunkCache extends MapChunkCache {
|
||||||
private static boolean init = false;
|
|
||||||
protected DynmapWorld dw;
|
protected DynmapWorld dw;
|
||||||
private int nsect;
|
private int nsect;
|
||||||
private int sectoff; // Offset for sake of negative section indexes
|
private int sectoff; // Offset for sake of negative section indexes
|
||||||
|
@ -39,6 +39,7 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
|
||||||
private int snapcnt;
|
private int snapcnt;
|
||||||
private GenericChunk[] snaparray; /* Index = (x-x_min) + ((z-z_min)*x_dim) */
|
private GenericChunk[] snaparray; /* Index = (x-x_min) + ((z-z_min)*x_dim) */
|
||||||
private boolean[][] isSectionNotEmpty; /* Indexed by snapshot index, then by section index */
|
private boolean[][] isSectionNotEmpty; /* Indexed by snapshot index, then by section index */
|
||||||
|
private AtomicInteger loadingChunks = new AtomicInteger(0); //the amount of threads loading chunks at this moment, used by async loading
|
||||||
|
|
||||||
private static final BlockStep unstep[] = { BlockStep.X_MINUS, BlockStep.Y_MINUS, BlockStep.Z_MINUS,
|
private static final BlockStep unstep[] = { BlockStep.X_MINUS, BlockStep.Y_MINUS, BlockStep.Z_MINUS,
|
||||||
BlockStep.X_PLUS, BlockStep.Y_PLUS, BlockStep.Z_PLUS };
|
BlockStep.X_PLUS, BlockStep.Y_PLUS, BlockStep.Z_PLUS };
|
||||||
|
@ -53,11 +54,13 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
|
||||||
private DynmapBlockState blk;
|
private DynmapBlockState blk;
|
||||||
private final int worldheight;
|
private final int worldheight;
|
||||||
private final int ymin;
|
private final int ymin;
|
||||||
|
private final int sealevel;
|
||||||
|
|
||||||
OurMapIterator(int x0, int y0, int z0) {
|
OurMapIterator(int x0, int y0, int z0) {
|
||||||
initialize(x0, y0, z0);
|
initialize(x0, y0, z0);
|
||||||
worldheight = dw.worldheight;
|
worldheight = dw.worldheight;
|
||||||
ymin = dw.minY;
|
ymin = dw.minY;
|
||||||
|
sealevel = dw.sealevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -180,7 +183,7 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
|
||||||
for (int dz = -1; dz <= 1; dz++) {
|
for (int dz = -1; dz <= 1; dz++) {
|
||||||
BiomeMap bm = getBiomeRel(dx, dz);
|
BiomeMap bm = getBiomeRel(dx, dz);
|
||||||
if (bm == BiomeMap.NULL) continue;
|
if (bm == BiomeMap.NULL) continue;
|
||||||
int rmult = bm.getModifiedGrassMultiplier(colormap[bm.biomeLookup()]);
|
int rmult = getGrassColor(bm, colormap, getX() + dx, getZ() + dz);
|
||||||
raccum += (rmult >> 16) & 0xFF;
|
raccum += (rmult >> 16) & 0xFF;
|
||||||
gaccum += (rmult >> 8) & 0xFF;
|
gaccum += (rmult >> 8) & 0xFF;
|
||||||
baccum += rmult & 0xFF;
|
baccum += rmult & 0xFF;
|
||||||
|
@ -211,7 +214,7 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
|
||||||
for (int dz = -1; dz <= 1; dz++) {
|
for (int dz = -1; dz <= 1; dz++) {
|
||||||
BiomeMap bm = getBiomeRel(dx, dz);
|
BiomeMap bm = getBiomeRel(dx, dz);
|
||||||
if (bm == BiomeMap.NULL) continue;
|
if (bm == BiomeMap.NULL) continue;
|
||||||
int rmult = bm.getModifiedFoliageMultiplier(colormap[bm.biomeLookup()]);
|
int rmult = getFoliageColor(bm, colormap, getX() + dx, getZ() + dz);
|
||||||
raccum += (rmult >> 16) & 0xFF;
|
raccum += (rmult >> 16) & 0xFF;
|
||||||
gaccum += (rmult >> 8) & 0xFF;
|
gaccum += (rmult >> 8) & 0xFF;
|
||||||
baccum += rmult & 0xFF;
|
baccum += rmult & 0xFF;
|
||||||
|
@ -482,7 +485,16 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
|
||||||
public final int getWorldHeight() {
|
public final int getWorldHeight() {
|
||||||
return worldheight;
|
return worldheight;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public final int getWorldYMin() {
|
||||||
|
return ymin;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get world sealevel
|
||||||
|
*/
|
||||||
|
public final int getWorldSeaLevel() {
|
||||||
|
return sealevel;
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public final long getBlockKey() {
|
public final long getBlockKey() {
|
||||||
return (((chunkindex * (worldheight - ymin)) + (y - ymin)) << 8) | (bx << 4) | bz;
|
return (((chunkindex * (worldheight - ymin)) + (y - ymin)) << 8) | (bx << 4) | bz;
|
||||||
|
@ -545,6 +557,14 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getGrassColor(BiomeMap bm, int[] colormap, int x, int z) {
|
||||||
|
return bm.getModifiedGrassMultiplier(colormap[bm.biomeLookup()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFoliageColor(BiomeMap bm, int[] colormap, int x, int z) {
|
||||||
|
return bm.getModifiedFoliageMultiplier(colormap[bm.biomeLookup()]);
|
||||||
|
}
|
||||||
|
|
||||||
private class OurEndMapIterator extends OurMapIterator {
|
private class OurEndMapIterator extends OurMapIterator {
|
||||||
OurEndMapIterator(int x0, int y0, int z0) {
|
OurEndMapIterator(int x0, int y0, int z0) {
|
||||||
super(x0, y0, z0);
|
super(x0, y0, z0);
|
||||||
|
@ -699,6 +719,14 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
|
||||||
protected abstract GenericChunk getLoadedChunk(DynmapChunk ch);
|
protected abstract GenericChunk getLoadedChunk(DynmapChunk ch);
|
||||||
// Load generic chunk from unloaded chunk
|
// Load generic chunk from unloaded chunk
|
||||||
protected abstract GenericChunk loadChunk(DynmapChunk ch);
|
protected abstract GenericChunk loadChunk(DynmapChunk ch);
|
||||||
|
// Load generic chunk from existing and already loaded chunk async
|
||||||
|
protected Supplier<GenericChunk> getLoadedChunkAsync(DynmapChunk ch) {
|
||||||
|
throw new IllegalStateException("Not implemeted");
|
||||||
|
}
|
||||||
|
// Load generic chunks from unloaded chunk async
|
||||||
|
protected Supplier<GenericChunk> loadChunkAsync(DynmapChunk ch){
|
||||||
|
throw new IllegalStateException("Not implemeted");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read NBT data from loaded chunks - needs to be called from server/world
|
* Read NBT data from loaded chunks - needs to be called from server/world
|
||||||
|
@ -756,10 +784,84 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read NBT data from loaded chunks - do not needs to be called from server/world <p>
|
||||||
|
* Will throw {@link IllegalStateException} if not supporting
|
||||||
|
*/
|
||||||
|
public void getLoadedChunksAsync() {
|
||||||
|
class SimplePair { //simple pair of the supplier that finishes read async, and a consumer that also finish his work async
|
||||||
|
final Supplier<GenericChunk> supplier;
|
||||||
|
final BiConsumer<GenericChunk, Long> consumer;
|
||||||
|
|
||||||
|
SimplePair(Supplier<GenericChunk> supplier, BiConsumer<GenericChunk, Long> consumer) {
|
||||||
|
this.supplier = supplier;
|
||||||
|
this.consumer = consumer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!dw.isLoaded()) {
|
||||||
|
isempty = true;
|
||||||
|
unloadChunks();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<SimplePair> lastApply = new ArrayList<>();
|
||||||
|
for (DynmapChunk dynmapChunk : chunks) {
|
||||||
|
long startTime = System.nanoTime();
|
||||||
|
int chunkIndex = (dynmapChunk.x - x_min) + (dynmapChunk.z - z_min) * x_dim;
|
||||||
|
if (snaparray[chunkIndex] != null)
|
||||||
|
continue; // Skip if already processed
|
||||||
|
|
||||||
|
boolean vis = isChunkVisible(dynmapChunk);
|
||||||
|
|
||||||
|
/* Check if cached chunk snapshot found */
|
||||||
|
if (tryChunkCache(dynmapChunk, vis)) {
|
||||||
|
endChunkLoad(startTime, ChunkStats.CACHED_SNAPSHOT_HIT);
|
||||||
|
}
|
||||||
|
// If chunk is loaded and not being unloaded, we're grabbing its NBT data
|
||||||
|
else {
|
||||||
|
// Get generic chunk from already loaded chunk, if we can
|
||||||
|
Supplier<GenericChunk> supplier = getLoadedChunkAsync(dynmapChunk);
|
||||||
|
long startPause = System.nanoTime();
|
||||||
|
BiConsumer<GenericChunk, Long> consumer = (ss, reloadTime) -> {
|
||||||
|
if (ss == null) return;
|
||||||
|
long pause = reloadTime - startPause;
|
||||||
|
if (vis) { // If visible
|
||||||
|
prepChunkSnapshot(dynmapChunk, ss);
|
||||||
|
} else {
|
||||||
|
if (hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN) {
|
||||||
|
ss = getStone();
|
||||||
|
} else if (hidestyle == HiddenChunkStyle.FILL_OCEAN) {
|
||||||
|
ss = getOcean();
|
||||||
|
} else {
|
||||||
|
ss = getEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snaparray[chunkIndex] = ss;
|
||||||
|
endChunkLoad(startTime - pause, ChunkStats.LOADED_CHUNKS);
|
||||||
|
|
||||||
|
};
|
||||||
|
lastApply.add(new SimplePair(supplier, consumer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//impact on the main thread should be minimal, so we plan and finish the work after main thread finished it's part
|
||||||
|
lastApply.forEach(simplePair -> {
|
||||||
|
long reloadWork = System.nanoTime();
|
||||||
|
simplePair.consumer.accept(simplePair.supplier.get(), reloadWork);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int loadChunks(int max_to_load) {
|
public int loadChunks(int max_to_load) {
|
||||||
return getLoadedChunks() + readChunks(max_to_load);
|
return getLoadedChunks() + readChunks(max_to_load);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads all chunks in the world asynchronously.
|
||||||
|
* <p>
|
||||||
|
* If it is not supported, it will throw {@link IllegalStateException}
|
||||||
|
*/
|
||||||
|
public void loadChunksAsync() {
|
||||||
|
getLoadedChunksAsync();
|
||||||
|
readChunksAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int readChunks(int max_to_load) {
|
public int readChunks(int max_to_load) {
|
||||||
|
@ -842,6 +944,102 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It loads chunks from the cache or from the world, and if the chunk is not visible, it fills it with stone, ocean or
|
||||||
|
* empty chunk
|
||||||
|
* <p>
|
||||||
|
* if it's not supported, will throw {@link IllegalStateException}
|
||||||
|
*/
|
||||||
|
public void readChunksAsync() {
|
||||||
|
class SimplePair { //pair of the chunk and the data which is readed async
|
||||||
|
private final Supplier<GenericChunk> supplier;
|
||||||
|
private final DynmapChunk chunk;
|
||||||
|
|
||||||
|
SimplePair(DynmapChunk chunk) {
|
||||||
|
this.chunk = chunk;
|
||||||
|
this.supplier = loadChunkAsync(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!dw.isLoaded()) {
|
||||||
|
isempty = true;
|
||||||
|
unloadChunks();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<DynmapChunk> chunks;
|
||||||
|
if (iterator == null) {
|
||||||
|
iterator = Collections.emptyListIterator();
|
||||||
|
chunks = new ArrayList<>(this.chunks);
|
||||||
|
} else {
|
||||||
|
chunks = new ArrayList<>();
|
||||||
|
iterator.forEachRemaining(chunks::add);
|
||||||
|
}
|
||||||
|
//if before increent was 0, means that we are the first, so we need to set this
|
||||||
|
if (loadingChunks.getAndIncrement() == 0) {
|
||||||
|
DynmapCore.setIgnoreChunkLoads(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<DynmapChunk> cached = new ArrayList<>();
|
||||||
|
List<SimplePair> notCached = new ArrayList<>();
|
||||||
|
|
||||||
|
iterator.forEachRemaining(chunks::add);
|
||||||
|
chunks.stream()
|
||||||
|
.filter(chunk -> snaparray[(chunk.x - x_min) + (chunk.z - z_min) * x_dim] == null)
|
||||||
|
.forEach(chunk -> {
|
||||||
|
if (cache.getSnapshot(dw.getName(), chunk.x, chunk.z) == null) {
|
||||||
|
notCached.add(new SimplePair(chunk));
|
||||||
|
} else {
|
||||||
|
cached.add(chunk);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cached.forEach(chunk -> {
|
||||||
|
long startTime = System.nanoTime();
|
||||||
|
tryChunkCache(chunk, isChunkVisible(chunk));
|
||||||
|
endChunkLoad(startTime, ChunkStats.CACHED_SNAPSHOT_HIT);
|
||||||
|
});
|
||||||
|
notCached.forEach(chunkSupplier -> {
|
||||||
|
long startTime = System.nanoTime();
|
||||||
|
GenericChunk chunk = chunkSupplier.supplier.get();
|
||||||
|
DynmapChunk dynmapChunk = chunkSupplier.chunk;
|
||||||
|
if (chunk != null) {
|
||||||
|
// If hidden
|
||||||
|
if (isChunkVisible(dynmapChunk)) {
|
||||||
|
// Prep snapshot
|
||||||
|
prepChunkSnapshot(dynmapChunk, chunk);
|
||||||
|
} else {
|
||||||
|
if (hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN) {
|
||||||
|
chunk = getStone();
|
||||||
|
} else if (hidestyle == HiddenChunkStyle.FILL_OCEAN) {
|
||||||
|
chunk = getOcean();
|
||||||
|
} else {
|
||||||
|
chunk = getEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snaparray[(dynmapChunk.x - x_min) + (dynmapChunk.z - z_min) * x_dim] = chunk;
|
||||||
|
endChunkLoad(startTime, ChunkStats.UNLOADED_CHUNKS);
|
||||||
|
} else {
|
||||||
|
endChunkLoad(startTime, ChunkStats.UNGENERATED_CHUNKS);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
isempty = true;
|
||||||
|
/* Fill missing chunks with empty dummy chunk */
|
||||||
|
for (int i = 0; i < snaparray.length; i++) {
|
||||||
|
if (snaparray[i] == null) {
|
||||||
|
snaparray[i] = getEmpty();
|
||||||
|
} else if (!snaparray[i].isEmpty) {
|
||||||
|
isempty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (loadingChunks.decrementAndGet() == 0) {
|
||||||
|
DynmapCore.setIgnoreChunkLoads(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if done loading
|
* Test if done loading
|
||||||
*/
|
*/
|
||||||
|
@ -1097,19 +1295,19 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
|
||||||
bitsperblock = (statelist.length * 64) / 4096;
|
bitsperblock = (statelist.length * 64) / 4096;
|
||||||
dbp = new DataBitsPacked(bitsperblock, 4096, statelist);
|
dbp = new DataBitsPacked(bitsperblock, 4096, statelist);
|
||||||
}
|
}
|
||||||
if (bitsperblock > 8) { // Not palette
|
//if (bitsperblock > 8) { // Not palette
|
||||||
for (int j = 0; j < 4096; j++) {
|
// for (int j = 0; j < 4096; j++) {
|
||||||
int v = db != null ? db.get(j) : dbp.getAt(j);
|
// int v = db != null ? db.get(j) : dbp.getAt(j);
|
||||||
sbld.xyzBlockState(j & 0xF, (j & 0xF00) >> 8, (j & 0xF0) >> 4, DynmapBlockState.getStateByGlobalIndex(v));
|
// sbld.xyzBlockState(j & 0xF, (j & 0xF00) >> 8, (j & 0xF0) >> 4, DynmapBlockState.getStateByGlobalIndex(v));
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
else {
|
//else {
|
||||||
sbld.xyzBlockStatePalette(palette); // Set palette
|
sbld.xyzBlockStatePalette(palette); // Set palette
|
||||||
for (int j = 0; j < 4096; j++) {
|
for (int j = 0; j < 4096; j++) {
|
||||||
int v = db != null ? db.get(j) : dbp.getAt(j);
|
int v = db != null ? db.get(j) : dbp.getAt(j);
|
||||||
sbld.xyzBlockStateInPalette(j & 0xF, (j & 0xF00) >> 8, (j & 0xF0) >> 4, (short)v);
|
sbld.xyzBlockStateInPalette(j & 0xF, (j & 0xF00) >> 8, (j & 0xF0) >> 4, (short)v);
|
||||||
}
|
}
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sec.contains("BlockLight")) {
|
if (sec.contains("BlockLight")) {
|
||||||
|
@ -1125,8 +1323,10 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
|
||||||
long[] bdataPacked = nbtbiomes.getLongArray("data");
|
long[] bdataPacked = nbtbiomes.getLongArray("data");
|
||||||
GenericNBTList bpalette = nbtbiomes.getList("palette", 8);
|
GenericNBTList bpalette = nbtbiomes.getList("palette", 8);
|
||||||
GenericBitStorage bdata = null;
|
GenericBitStorage bdata = null;
|
||||||
if (bdataPacked.length > 0)
|
if (bdataPacked.length > 0) {
|
||||||
bdata = nbt.makeBitStorage(bdataPacked.length, 64, bdataPacked);
|
int valsPerLong = (64 / bdataPacked.length);
|
||||||
|
bdata = nbt.makeBitStorage((64 + valsPerLong - 1) / valsPerLong, 64, bdataPacked);
|
||||||
|
}
|
||||||
for (int j = 0; j < 64; j++) {
|
for (int j = 0; j < 64; j++) {
|
||||||
int b = bdata != null ? bdata.get(j) : 0;
|
int b = bdata != null ? bdata.get(j) : 0;
|
||||||
sbld.xyzBiome(j & 0x3, (j & 0x30) >> 4, (j & 0xC) >> 2, BiomeMap.byBiomeResourceLocation(bpalette.getString(b)));
|
sbld.xyzBiome(j & 0x3, (j & 0x30) >> 4, (j & 0xC) >> 2, BiomeMap.byBiomeResourceLocation(bpalette.getString(b)));
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package org.dynmap.common.chunk;
|
package org.dynmap.common.chunk;
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
// Generic interface for accessing an NBT Composite object
|
// Generic interface for accessing an NBT Composite object
|
||||||
public interface GenericNBTList {
|
public interface GenericNBTList {
|
||||||
public int size();
|
public int size();
|
||||||
|
|
|
@ -523,6 +523,15 @@ public class OBJExport {
|
||||||
case TOP:
|
case TOP:
|
||||||
f.faceLine = String.format("f %d/%d %d/%d %d/%d %d/%d\n", v[0], uv[0], v[1], uv[1], v[2], uv[2], v[3], uv[3]);
|
f.faceLine = String.format("f %d/%d %d/%d %d/%d %d/%d\n", v[0], uv[0], v[1], uv[1], v[2], uv[2], v[3], uv[3]);
|
||||||
break;
|
break;
|
||||||
|
case TOPFLIP:
|
||||||
|
f.faceLine += String.format("f %d/%d %d/%d %d/%d %d/%d\n", v[3], uv[2], v[2], uv[3], v[1], uv[0], v[0], uv[1]);
|
||||||
|
break;
|
||||||
|
case TOPFLIPV:
|
||||||
|
f.faceLine = String.format("f %d/%d %d/%d %d/%d %d/%d\n", v[0], uv[0], v[1], uv[1], v[2], uv[2], v[3], uv[3]);
|
||||||
|
break;
|
||||||
|
case TOPFLIPHV:
|
||||||
|
f.faceLine = String.format("f %d/%d %d/%d %d/%d %d/%d\n", v[0], uv[0], v[1], uv[1], v[2], uv[2], v[3], uv[3]);
|
||||||
|
break;
|
||||||
case BOTTOM:
|
case BOTTOM:
|
||||||
f.faceLine = String.format("f %d/%d %d/%d %d/%d %d/%d\n", v[3], uv[3], v[2], uv[2], v[1], uv[1], v[0], uv[0]);
|
f.faceLine = String.format("f %d/%d %d/%d %d/%d %d/%d\n", v[3], uv[3], v[2], uv[2], v[1], uv[1], v[0], uv[0]);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -22,6 +22,8 @@ import org.json.simple.JSONObject;
|
||||||
public class CaveHDShader implements HDShader {
|
public class CaveHDShader implements HDShader {
|
||||||
private String name;
|
private String name;
|
||||||
private boolean iflit;
|
private boolean iflit;
|
||||||
|
private Color startColor;
|
||||||
|
private Color endColor;
|
||||||
private BitSet hiddenids = new BitSet();
|
private BitSet hiddenids = new BitSet();
|
||||||
|
|
||||||
private void setHidden(DynmapBlockState blk) {
|
private void setHidden(DynmapBlockState blk) {
|
||||||
|
@ -41,7 +43,8 @@ public class CaveHDShader implements HDShader {
|
||||||
public CaveHDShader(DynmapCore core, ConfigurationNode configuration) {
|
public CaveHDShader(DynmapCore core, ConfigurationNode configuration) {
|
||||||
name = (String) configuration.get("name");
|
name = (String) configuration.get("name");
|
||||||
iflit = configuration.getBoolean("onlyiflit", false);
|
iflit = configuration.getBoolean("onlyiflit", false);
|
||||||
|
startColor = configuration.getColor("startColor", null);
|
||||||
|
endColor = configuration.getColor("endColor", null);
|
||||||
for (int i = 0; i < DynmapBlockState.getGlobalIndexMax(); i++) {
|
for (int i = 0; i < DynmapBlockState.getGlobalIndexMax(); i++) {
|
||||||
DynmapBlockState bs = DynmapBlockState.getStateByGlobalIndex(i);
|
DynmapBlockState bs = DynmapBlockState.getStateByGlobalIndex(i);
|
||||||
if (bs.isAir() || bs.isWater()) {
|
if (bs.isAir() || bs.isWater()) {
|
||||||
|
@ -115,19 +118,17 @@ public class CaveHDShader implements HDShader {
|
||||||
protected MapIterator mapiter;
|
protected MapIterator mapiter;
|
||||||
protected HDMap map;
|
protected HDMap map;
|
||||||
private boolean air;
|
private boolean air;
|
||||||
private int yshift;
|
private final int sealevel;
|
||||||
|
private final int ymax, ymin;
|
||||||
final int[] lightingTable;
|
final int[] lightingTable;
|
||||||
|
|
||||||
private OurShaderState(MapIterator mapiter, HDMap map, MapChunkCache cache) {
|
private OurShaderState(MapIterator mapiter, HDMap map, MapChunkCache cache) {
|
||||||
this.mapiter = mapiter;
|
this.mapiter = mapiter;
|
||||||
this.map = map;
|
this.map = map;
|
||||||
this.color = new Color();
|
this.color = new Color();
|
||||||
int wheight = mapiter.getWorldHeight();
|
this.ymax = mapiter.getWorldHeight() - 1;
|
||||||
yshift = 0;
|
this.ymin = mapiter.getWorldYMin();
|
||||||
while(wheight > 128) {
|
this.sealevel = mapiter.getWorldSeaLevel();
|
||||||
wheight >>= 1;
|
|
||||||
yshift++;
|
|
||||||
}
|
|
||||||
if (MapManager.mapman.useBrightnessTable()) {
|
if (MapManager.mapman.useBrightnessTable()) {
|
||||||
lightingTable = cache.getWorld().getBrightnessTable();
|
lightingTable = cache.getWorld().getBrightnessTable();
|
||||||
}
|
}
|
||||||
|
@ -187,17 +188,27 @@ public class CaveHDShader implements HDShader {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int cr, cg, cb;
|
int cr, cg, cb;
|
||||||
int mult = 256;
|
int mult;
|
||||||
|
|
||||||
int ys = mapiter.getY() >> yshift;
|
int y = mapiter.getY();
|
||||||
if (ys < 64) {
|
if((startColor != null) && (endColor != null))
|
||||||
cr = 0;
|
{
|
||||||
cg = 64 + ys * 3;
|
double interp = ((double)(y - this.ymin)) / (this.ymax - this.ymin);
|
||||||
cb = 255 - ys * 4;
|
cr = (int)(((1.0 - interp) * startColor.getRed()) + (interp * endColor.getRed()));
|
||||||
} else {
|
cg = (int)(((1.0 - interp) * startColor.getGreen()) + (interp * endColor.getGreen()));
|
||||||
cr = (ys - 64) * 4;
|
cb = (int)(((1.0 - interp) * startColor.getBlue()) + (interp * endColor.getBlue()));
|
||||||
cg = 255;
|
}
|
||||||
cb = 0;
|
else
|
||||||
|
{
|
||||||
|
if (y < this.sealevel) {
|
||||||
|
cr = 0;
|
||||||
|
cg = 64 + ((192 * (y - this.ymin)) / (this.sealevel - this.ymin));
|
||||||
|
cb = 255 - (255 * (y - this.ymin)) / (this.sealevel - this.ymin);
|
||||||
|
} else {
|
||||||
|
cr = (255 * (y - this.sealevel)) / (this.ymax - this.sealevel);
|
||||||
|
cg = 255;
|
||||||
|
cb = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Figure out which color to use */
|
/* Figure out which color to use */
|
||||||
switch(ps.getLastBlockStep()) {
|
switch(ps.getLastBlockStep()) {
|
||||||
|
|
|
@ -33,21 +33,21 @@ public class ChunkStatusHDShader implements HDShader {
|
||||||
};
|
};
|
||||||
private static HashMap<String, ChunkStatusMap> statusmap = new HashMap<String, ChunkStatusMap>();
|
private static HashMap<String, ChunkStatusMap> statusmap = new HashMap<String, ChunkStatusMap>();
|
||||||
|
|
||||||
private static ChunkStatusMap[] statusvals = {
|
static {
|
||||||
new ChunkStatusMap("empty", 0xFF0000),
|
new ChunkStatusMap("empty", 0xFF0000);
|
||||||
new ChunkStatusMap("structure_starts", 0xFF1493),
|
new ChunkStatusMap("structure_starts", 0xFF1493);
|
||||||
new ChunkStatusMap("structure_references", 0xFF7F50),
|
new ChunkStatusMap("structure_references", 0xFF7F50);
|
||||||
new ChunkStatusMap("biomes", 0xFFA500),
|
new ChunkStatusMap("biomes", 0xFFA500);
|
||||||
new ChunkStatusMap("noise", 0xFFD700),
|
new ChunkStatusMap("noise", 0xFFD700);
|
||||||
new ChunkStatusMap("surface", 0xFFFF00),
|
new ChunkStatusMap("surface", 0xFFFF00);
|
||||||
new ChunkStatusMap("carvers", 0xFFEFD5),
|
new ChunkStatusMap("carvers", 0xFFEFD5);
|
||||||
new ChunkStatusMap("liquid_carvers", 0xF0E68C),
|
new ChunkStatusMap("liquid_carvers", 0xF0E68C);
|
||||||
new ChunkStatusMap("features", 0xBDB76B),
|
new ChunkStatusMap("features", 0xBDB76B);
|
||||||
new ChunkStatusMap("light", 0xDDA0DD),
|
new ChunkStatusMap("light", 0xDDA0DD);
|
||||||
new ChunkStatusMap("spawn", 0xFF00FF),
|
new ChunkStatusMap("spawn", 0xFF00FF);
|
||||||
new ChunkStatusMap("heightmaps", 0x9370DB),
|
new ChunkStatusMap("heightmaps", 0x9370DB);
|
||||||
new ChunkStatusMap("full", 0x32CD32),
|
new ChunkStatusMap("full", 0x32CD32);
|
||||||
};
|
}
|
||||||
|
|
||||||
final static Color unknown_color = new Color(255, 255, 255);
|
final static Color unknown_color = new Color(255, 255, 255);
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,6 @@ import static org.dynmap.JSONUtils.s;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
|
|
||||||
import org.dynmap.Color;
|
import org.dynmap.Color;
|
||||||
import org.dynmap.ConfigurationNode;
|
import org.dynmap.ConfigurationNode;
|
||||||
|
@ -27,15 +25,16 @@ public class ChunkVersionHDShader implements HDShader {
|
||||||
|
|
||||||
private static class DataVersionMap {
|
private static class DataVersionMap {
|
||||||
int dataVersion;
|
int dataVersion;
|
||||||
String version;
|
//String version;
|
||||||
Color defcolor;
|
Color defcolor;
|
||||||
DataVersionMap(int dv, String v, int c) {
|
DataVersionMap(int dv, String v, int c) {
|
||||||
dataVersion = dv;
|
dataVersion = dv;
|
||||||
version = v;
|
//version = v;
|
||||||
defcolor = new Color((c>>16)&0xFF, (c>>8)&0xFF, c&0xFF);
|
defcolor = new Color((c>>16)&0xFF, (c>>8)&0xFF, c&0xFF);
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// Mapping from https://minecraft.wiki/w/Data_version
|
||||||
final static DataVersionMap[] versionmap = {
|
final static DataVersionMap[] versionmap = {
|
||||||
new DataVersionMap(0, "unknown", 0x202020),
|
new DataVersionMap(0, "unknown", 0x202020),
|
||||||
new DataVersionMap(1519, "1.13.0", 0xF9E79F),
|
new DataVersionMap(1519, "1.13.0", 0xF9E79F),
|
||||||
|
@ -59,6 +58,13 @@ public class ChunkVersionHDShader implements HDShader {
|
||||||
new DataVersionMap(2730, "1.17.1", 0xEB984E),
|
new DataVersionMap(2730, "1.17.1", 0xEB984E),
|
||||||
new DataVersionMap(2860, "1.18.0", 0xA3E4D7),
|
new DataVersionMap(2860, "1.18.0", 0xA3E4D7),
|
||||||
new DataVersionMap(2865, "1.18.1", 0x48C9B0),
|
new DataVersionMap(2865, "1.18.1", 0x48C9B0),
|
||||||
|
new DataVersionMap(2975, "1.18.2", 0x38bfa5),
|
||||||
|
new DataVersionMap(3105, "1.19", 0xd56f82),
|
||||||
|
new DataVersionMap(3116, "1.19.1", 0xe196a4),
|
||||||
|
new DataVersionMap(3120, "1.19.2", 0xe7aeb8),
|
||||||
|
new DataVersionMap(3218, "1.19.3", 0xf8c0c8),
|
||||||
|
new DataVersionMap(3337, "1.19.4", 0xffb6c1),
|
||||||
|
|
||||||
};
|
};
|
||||||
final static Color unknown_color = new Color(255, 255, 255);
|
final static Color unknown_color = new Color(255, 255, 255);
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ public class CustomBlockModel extends HDBlockModel {
|
||||||
super(bstate, databits, blockset);
|
super(bstate, databits, blockset);
|
||||||
try {
|
try {
|
||||||
Class<?> cls = Class.forName(classname); /* Get class */
|
Class<?> cls = Class.forName(classname); /* Get class */
|
||||||
render = (CustomRenderer) cls.newInstance();
|
render = (CustomRenderer) cls.getDeclaredConstructor().newInstance();
|
||||||
if(render.initializeRenderer(HDBlockModels.pdf, bstate.blockName, databits, classparm) == false) {
|
if(render.initializeRenderer(HDBlockModels.pdf, bstate.blockName, databits, classparm) == false) {
|
||||||
Log.severe("Error loading custom renderer - " + classname);
|
Log.severe("Error loading custom renderer - " + classname);
|
||||||
render = null;
|
render = null;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,11 +2,9 @@ package org.dynmap.hdmap;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.List;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.dynmap.hdmap.TexturePack;
|
|
||||||
import org.dynmap.Log;
|
import org.dynmap.Log;
|
||||||
import org.dynmap.hdmap.HDBlockModels;
|
|
||||||
import org.dynmap.hdmap.TexturePack.BlockTransparency;
|
import org.dynmap.hdmap.TexturePack.BlockTransparency;
|
||||||
import org.dynmap.hdmap.TexturePack.ColorizingData;
|
import org.dynmap.hdmap.TexturePack.ColorizingData;
|
||||||
import org.dynmap.renderer.CustomColorMultiplier;
|
import org.dynmap.renderer.CustomColorMultiplier;
|
||||||
|
@ -82,40 +80,25 @@ public class HDBlockStateTextureMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add block state to table, with given block IDs and state indexes
|
// Add block state to table, with given block IDs and state indexes
|
||||||
public void addToTable(List<String> blocknames, BitSet stateidx) {
|
public void addToTable(Map<DynmapBlockState, BitSet> states) {
|
||||||
/* Add entries to lookup table */
|
/* Add entries to lookup table */
|
||||||
for (String blkname : blocknames) {
|
for (DynmapBlockState baseblk : states.keySet()) {
|
||||||
DynmapBlockState baseblk = DynmapBlockState.getBaseStateByName(blkname);
|
|
||||||
if (baseblk.isNotAir()) {
|
if (baseblk.isNotAir()) {
|
||||||
if (stateidx != null) {
|
BitSet stateidx = states.get(baseblk);
|
||||||
for (int stateid = stateidx.nextSetBit(0); stateid >= 0; stateid = stateidx.nextSetBit(stateid+1)) {
|
for (int stateid = stateidx.nextSetBit(0); stateid >= 0; stateid = stateidx.nextSetBit(stateid+1)) {
|
||||||
DynmapBlockState bs = baseblk.getState(stateid);
|
DynmapBlockState bs = baseblk.getState(stateid);
|
||||||
if (bs.isAir()) {
|
if (bs.isAir()) {
|
||||||
Log.warning("Invalid texture block state: " + blkname + ":" + stateid);
|
Log.warning("Invalid texture block state: " + baseblk.blockName + ":" + stateid);
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
if ((this.blockset != null) && (this.blockset.equals("core") == false)) {
|
|
||||||
HDBlockModels.resetIfNotBlockSet(bs, this.blockset);
|
|
||||||
}
|
|
||||||
copyToStateIndex(bs, this, null);
|
|
||||||
}
|
}
|
||||||
}
|
if ((this.blockset != null) && (this.blockset.equals("core") == false)) {
|
||||||
else { // Else, loop over all state IDs for given block
|
HDBlockModels.resetIfNotBlockSet(bs, this.blockset);
|
||||||
for (int stateid = 0; stateid < baseblk.getStateCount(); stateid++) {
|
|
||||||
DynmapBlockState bs = baseblk.getState(stateid);
|
|
||||||
if (bs.isAir()) {
|
|
||||||
Log.warning("Invalid texture block state: " + blkname + ":" + stateid);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ((this.blockset != null) && (this.blockset.equals("core") == false)) {
|
|
||||||
HDBlockModels.resetIfNotBlockSet(bs, this.blockset);
|
|
||||||
}
|
|
||||||
copyToStateIndex(bs, this, null);
|
|
||||||
}
|
}
|
||||||
|
copyToStateIndex(bs, this, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.warning("Invalid texture block name: " + blkname);
|
Log.warning("Invalid texture block name: " + baseblk.blockName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ public class HDMap extends MapType {
|
||||||
private MapType.ImageFormat imgformat;
|
private MapType.ImageFormat imgformat;
|
||||||
private int bgcolornight;
|
private int bgcolornight;
|
||||||
private int bgcolorday;
|
private int bgcolorday;
|
||||||
|
private int tilescale;
|
||||||
private String title;
|
private String title;
|
||||||
private String icon;
|
private String icon;
|
||||||
private String bg_cfg;
|
private String bg_cfg;
|
||||||
|
@ -140,6 +141,9 @@ public class HDMap extends MapType {
|
||||||
this.mapzoomin = configuration.getInteger("mapzoomin", 2);
|
this.mapzoomin = configuration.getInteger("mapzoomin", 2);
|
||||||
this.mapzoomout = configuration.getInteger("mapzoomout", this.mapzoomout);
|
this.mapzoomout = configuration.getInteger("mapzoomout", this.mapzoomout);
|
||||||
this.boostzoom = configuration.getInteger("boostzoom", 0);
|
this.boostzoom = configuration.getInteger("boostzoom", 0);
|
||||||
|
this.tilescale = configuration.getInteger("tilescale", core.getMapManager().getDefaultTileScale()); // 0 = 128, 1 = 256, ...
|
||||||
|
if (this.tilescale <= 0) this.tilescale = 0;
|
||||||
|
if (this.tilescale >= 4) this.tilescale = 4; // Limit to 2k x 2k
|
||||||
if(this.boostzoom < 0) this.boostzoom = 0;
|
if(this.boostzoom < 0) this.boostzoom = 0;
|
||||||
if(this.boostzoom > 3) this.boostzoom = 3;
|
if(this.boostzoom > 3) this.boostzoom = 3;
|
||||||
// Map zoom in must be at least as big as boost zoom
|
// Map zoom in must be at least as big as boost zoom
|
||||||
|
@ -149,6 +153,7 @@ public class HDMap extends MapType {
|
||||||
this.append_to_world = configuration.getString("append_to_world", "");
|
this.append_to_world = configuration.getString("append_to_world", "");
|
||||||
setProtected(configuration.getBoolean("protected", false));
|
setProtected(configuration.getBoolean("protected", false));
|
||||||
setTileUpdateDelay(configuration.getInteger("tileupdatedelay", -1));
|
setTileUpdateDelay(configuration.getInteger("tileupdatedelay", -1));
|
||||||
|
setReadOnly(configuration.getBoolean("readonly", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigurationNode saveConfiguration() {
|
public ConfigurationNode saveConfiguration() {
|
||||||
|
@ -167,6 +172,7 @@ public class HDMap extends MapType {
|
||||||
cn.put("mapzoomin", mapzoomin);
|
cn.put("mapzoomin", mapzoomin);
|
||||||
cn.put("mapzoomout", mapzoomout);
|
cn.put("mapzoomout", mapzoomout);
|
||||||
cn.put("boostzoom", boostzoom);
|
cn.put("boostzoom", boostzoom);
|
||||||
|
cn.put("tilescale", tilescale);
|
||||||
if(bg_cfg != null)
|
if(bg_cfg != null)
|
||||||
cn.put("background", bg_cfg);
|
cn.put("background", bg_cfg);
|
||||||
if(bg_day_cfg != null)
|
if(bg_day_cfg != null)
|
||||||
|
@ -175,6 +181,7 @@ public class HDMap extends MapType {
|
||||||
cn.put("backgroundnight", bg_night_cfg);
|
cn.put("backgroundnight", bg_night_cfg);
|
||||||
cn.put("append_to_world", append_to_world);
|
cn.put("append_to_world", append_to_world);
|
||||||
cn.put("protected", isProtected());
|
cn.put("protected", isProtected());
|
||||||
|
cn.put("readonly", isReadOnly());
|
||||||
if(this.tileupdatedelay > 0) {
|
if(this.tileupdatedelay > 0) {
|
||||||
cn.put("tileupdatedelay", this.tileupdatedelay);
|
cn.put("tileupdatedelay", this.tileupdatedelay);
|
||||||
}
|
}
|
||||||
|
@ -185,15 +192,18 @@ public class HDMap extends MapType {
|
||||||
public final HDPerspective getPerspective() { return perspective; }
|
public final HDPerspective getPerspective() { return perspective; }
|
||||||
public final HDLighting getLighting() { return lighting; }
|
public final HDLighting getLighting() { return lighting; }
|
||||||
public final int getBoostZoom() { return boostzoom; }
|
public final int getBoostZoom() { return boostzoom; }
|
||||||
|
@Override
|
||||||
|
public final int getTileSize() { return 128 << tilescale; }
|
||||||
|
public final int getTileScale() { return tilescale; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<TileFlags.TileCoord> getTileCoords(DynmapWorld w, int x, int y, int z) {
|
public List<TileFlags.TileCoord> getTileCoords(DynmapWorld w, int x, int y, int z) {
|
||||||
return perspective.getTileCoords(w, x, y, z);
|
return perspective.getTileCoords(w, x, y, z, tilescale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<TileFlags.TileCoord> getTileCoords(DynmapWorld w, int minx, int miny, int minz, int maxx, int maxy, int maxz) {
|
public List<TileFlags.TileCoord> getTileCoords(DynmapWorld w, int minx, int miny, int minz, int maxx, int maxy, int maxz) {
|
||||||
return perspective.getTileCoords(w, minx, miny, minz, maxx, maxy, maxz);
|
return perspective.getTileCoords(w, minx, miny, minz, maxx, maxy, maxz, tilescale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -270,6 +280,7 @@ public class HDMap extends MapType {
|
||||||
s(o, "mapzoomout", (world.getExtraZoomOutLevels()+mapzoomout));
|
s(o, "mapzoomout", (world.getExtraZoomOutLevels()+mapzoomout));
|
||||||
s(o, "mapzoomin", mapzoomin);
|
s(o, "mapzoomin", mapzoomin);
|
||||||
s(o, "boostzoom", boostzoom);
|
s(o, "boostzoom", boostzoom);
|
||||||
|
s(o, "tilescale", tilescale);
|
||||||
s(o, "protected", isProtected());
|
s(o, "protected", isProtected());
|
||||||
s(o, "image-format", imgformat.getFileExt());
|
s(o, "image-format", imgformat.getFileExt());
|
||||||
if(append_to_world.length() > 0)
|
if(append_to_world.length() > 0)
|
||||||
|
@ -403,6 +414,13 @@ public class HDMap extends MapType {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
public boolean setTileScale(int mzi) {
|
||||||
|
if(mzi != this.tilescale) {
|
||||||
|
this.tilescale = mzi;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
public boolean setPerspective(HDPerspective p) {
|
public boolean setPerspective(HDPerspective p) {
|
||||||
if(perspective != p) {
|
if(perspective != p) {
|
||||||
perspective = p;
|
perspective = p;
|
||||||
|
@ -450,7 +468,7 @@ public class HDMap extends MapType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addMapTiles(List<MapTile> list, DynmapWorld w, int tx, int ty) {
|
public void addMapTiles(List<MapTile> list, DynmapWorld w, int tx, int ty) {
|
||||||
list.add(new HDMapTile(w, this.perspective, tx, ty, boostzoom));
|
list.add(new HDMapTile(w, this.perspective, tx, ty, boostzoom, tilescale));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final ImageVariant[] dayVariant = { ImageVariant.STANDARD, ImageVariant.DAY };
|
private static final ImageVariant[] dayVariant = { ImageVariant.STANDARD, ImageVariant.DAY };
|
||||||
|
|
|
@ -126,10 +126,17 @@ public class HDMapManager {
|
||||||
for(MapType map : w.maps) {
|
for(MapType map : w.maps) {
|
||||||
if(map instanceof HDMap) {
|
if(map instanceof HDMap) {
|
||||||
HDMap hdmap = (HDMap)map;
|
HDMap hdmap = (HDMap)map;
|
||||||
if((hdmap.getPerspective() == tile.perspective) && (hdmap.getBoostZoom() == tile.boostzoom)) {
|
// If same perspective, at same scale (tile and boost), render together
|
||||||
|
if((hdmap.getPerspective() == tile.perspective) && (hdmap.getBoostZoom() == tile.boostzoom) && (hdmap.getTileScale() == tile.tilescale)) {
|
||||||
/* If limited to one map, and this isn't it, skip */
|
/* If limited to one map, and this isn't it, skip */
|
||||||
if((mapname != null) && (!hdmap.getName().equals(mapname)))
|
if((mapname != null) && (!hdmap.getName().equals(mapname)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Maps can be set to read-only, which means they don't get re-rendered
|
||||||
|
if (map.isReadOnly()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
shaders.add(hdmap.getShader().getStateInstance(hdmap, cache, mapiter, scale));
|
shaders.add(hdmap.getShader().getStateInstance(hdmap, cache, mapiter, scale));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,15 +12,18 @@ public class HDMapTile extends MapTile {
|
||||||
public final HDPerspective perspective;
|
public final HDPerspective perspective;
|
||||||
public final int tx, ty; /* Tile X and Tile Y are in tile coordinates (pixels/tile-size) */
|
public final int tx, ty; /* Tile X and Tile Y are in tile coordinates (pixels/tile-size) */
|
||||||
public final int boostzoom;
|
public final int boostzoom;
|
||||||
|
public final int tilescale;
|
||||||
|
|
||||||
public HDMapTile(DynmapWorld world, HDPerspective perspective, int tx, int ty, int boostzoom) {
|
public HDMapTile(DynmapWorld world, HDPerspective perspective, int tx, int ty, int boostzoom, int tilescale) {
|
||||||
super(world);
|
super(world);
|
||||||
this.perspective = perspective;
|
this.perspective = perspective;
|
||||||
this.tx = tx;
|
this.tx = tx;
|
||||||
this.ty = ty;
|
this.ty = ty;
|
||||||
this.boostzoom = boostzoom;
|
this.boostzoom = boostzoom;
|
||||||
|
this.tilescale = tilescale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used for restore of saved pending renders
|
||||||
public HDMapTile(DynmapWorld world, String parm) throws Exception {
|
public HDMapTile(DynmapWorld world, String parm) throws Exception {
|
||||||
super(world);
|
super(world);
|
||||||
|
|
||||||
|
@ -34,16 +37,22 @@ public class HDMapTile extends MapTile {
|
||||||
this.boostzoom = Integer.parseInt(parms[3]);
|
this.boostzoom = Integer.parseInt(parms[3]);
|
||||||
else
|
else
|
||||||
this.boostzoom = 0;
|
this.boostzoom = 0;
|
||||||
|
if (parms.length > 4) {
|
||||||
|
this.tilescale = Integer.parseInt(parms[4]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.tilescale = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String saveTileData() {
|
protected String saveTileData() {
|
||||||
return String.format("%d,%d,%s,%d", tx, ty, perspective.getName(), boostzoom);
|
return String.format("%d,%d,%s,%d,%d", tx, ty, perspective.getName(), boostzoom, tilescale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return tx ^ ty ^ perspective.hashCode() ^ world.hashCode() ^ boostzoom;
|
return tx ^ ty ^ perspective.hashCode() ^ world.hashCode() ^ boostzoom ^ tilescale;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -55,14 +64,17 @@ public class HDMapTile extends MapTile {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(HDMapTile o) {
|
public boolean equals(HDMapTile o) {
|
||||||
return o.tx == tx && o.ty == ty && (perspective == o.perspective) && (o.world == world) && (o.boostzoom == boostzoom);
|
return o.tx == tx && o.ty == ty && (perspective == o.perspective) && (o.world == world) && (o.boostzoom == boostzoom) && (o.tilescale == tilescale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return world.getName() + ":" + perspective.getName() + "," + tx + "," + ty + ":" + boostzoom;
|
return world.getName() + ":" + perspective.getName() + "," + tx + "," + ty + ":" + boostzoom + ":" + tilescale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTileSize() { return 128 << tilescale; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isBiomeDataNeeded() { return MapManager.mapman.hdmapman.isBiomeDataNeeded(this); }
|
public boolean isBiomeDataNeeded() { return MapManager.mapman.hdmapman.isBiomeDataNeeded(this); }
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,9 @@ public interface HDPerspective {
|
||||||
/* Get name of perspective */
|
/* Get name of perspective */
|
||||||
String getName();
|
String getName();
|
||||||
/* Get tiles invalidated by change at given location */
|
/* Get tiles invalidated by change at given location */
|
||||||
List<TileFlags.TileCoord> getTileCoords(DynmapWorld w, int x, int y, int z);
|
List<TileFlags.TileCoord> getTileCoords(DynmapWorld w, int x, int y, int z, int tilescale);
|
||||||
/* Get tiles invalidated by change at given volume, defined by 2 opposite corner locations */
|
/* Get tiles invalidated by change at given volume, defined by 2 opposite corner locations */
|
||||||
List<TileFlags.TileCoord> getTileCoords(DynmapWorld w, int minx, int miny, int minz, int maxx, int maxy, int maxz);
|
List<TileFlags.TileCoord> getTileCoords(DynmapWorld w, int minx, int miny, int minz, int maxx, int maxy, int maxz, int tilescale);
|
||||||
/* Get tiles adjacent to given tile */
|
/* Get tiles adjacent to given tile */
|
||||||
MapTile[] getAdjecentTiles(MapTile tile);
|
MapTile[] getAdjecentTiles(MapTile tile);
|
||||||
/* Get chunks needed for given tile */
|
/* Get chunks needed for given tile */
|
||||||
|
|
|
@ -53,6 +53,10 @@ public interface HDPerspectiveState {
|
||||||
* @return y coordinate
|
* @return y coordinate
|
||||||
*/
|
*/
|
||||||
int getPixelY();
|
int getPixelY();
|
||||||
|
/**
|
||||||
|
* Get current patch shade setting (false = no shadows)
|
||||||
|
*/
|
||||||
|
boolean getShade();
|
||||||
/**
|
/**
|
||||||
* Return submodel alpha value (-1 if no submodel rendered)
|
* Return submodel alpha value (-1 if no submodel rendered)
|
||||||
* @return alpha value
|
* @return alpha value
|
||||||
|
|
|
@ -8,7 +8,6 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
import org.dynmap.Client;
|
import org.dynmap.Client;
|
||||||
import org.dynmap.Color;
|
import org.dynmap.Color;
|
||||||
|
@ -19,7 +18,6 @@ import org.dynmap.Log;
|
||||||
import org.dynmap.MapManager;
|
import org.dynmap.MapManager;
|
||||||
import org.dynmap.MapTile;
|
import org.dynmap.MapTile;
|
||||||
import org.dynmap.MapType;
|
import org.dynmap.MapType;
|
||||||
import org.dynmap.MapType.ImageFormat;
|
|
||||||
import org.dynmap.MapTypeState;
|
import org.dynmap.MapTypeState;
|
||||||
import org.dynmap.markers.impl.MarkerAPIImpl;
|
import org.dynmap.markers.impl.MarkerAPIImpl;
|
||||||
import org.dynmap.renderer.DynmapBlockState;
|
import org.dynmap.renderer.DynmapBlockState;
|
||||||
|
@ -28,7 +26,6 @@ import org.dynmap.renderer.RenderPatchFactory.SideVisible;
|
||||||
import org.dynmap.storage.MapStorage;
|
import org.dynmap.storage.MapStorage;
|
||||||
import org.dynmap.storage.MapStorageTile;
|
import org.dynmap.storage.MapStorageTile;
|
||||||
import org.dynmap.utils.BlockStep;
|
import org.dynmap.utils.BlockStep;
|
||||||
import org.dynmap.utils.DynIntHashMap;
|
|
||||||
import org.dynmap.hdmap.TexturePack.BlockTransparency;
|
import org.dynmap.hdmap.TexturePack.BlockTransparency;
|
||||||
import org.dynmap.utils.DynmapBufferedImage;
|
import org.dynmap.utils.DynmapBufferedImage;
|
||||||
import org.dynmap.utils.LightLevels;
|
import org.dynmap.utils.LightLevels;
|
||||||
|
@ -47,6 +44,7 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
private final int hashcode;
|
private final int hashcode;
|
||||||
/* View angles */
|
/* View angles */
|
||||||
public final double azimuth; /* Angle in degrees from looking north (0), east (90), south (180), or west (270) */
|
public final double azimuth; /* Angle in degrees from looking north (0), east (90), south (180), or west (270) */
|
||||||
|
public final double compassazimuth; // Angle in degrees from looking north (0), east (90), for the compass (default same as azimuth)
|
||||||
public final double inclination; /* Angle in degrees from horizontal (0) to vertical (90) */
|
public final double inclination; /* Angle in degrees from horizontal (0) to vertical (90) */
|
||||||
public final double maxheight;
|
public final double maxheight;
|
||||||
public final double minheight;
|
public final double minheight;
|
||||||
|
@ -64,10 +62,6 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
/* Scale for default tiles */
|
/* Scale for default tiles */
|
||||||
private final int basemodscale;
|
private final int basemodscale;
|
||||||
|
|
||||||
/* dimensions of a map tile */
|
|
||||||
public static final int tileWidth = 128;
|
|
||||||
public static final int tileHeight = 128;
|
|
||||||
|
|
||||||
/* Maximum and minimum inclinations */
|
/* Maximum and minimum inclinations */
|
||||||
public static final double MAX_INCLINATION = 90.0;
|
public static final double MAX_INCLINATION = 90.0;
|
||||||
public static final double MIN_INCLINATION = 20.0;
|
public static final double MIN_INCLINATION = 20.0;
|
||||||
|
@ -129,12 +123,14 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
double patch_t[] = new double[2*HDBlockModels.getMaxPatchCount()];
|
double patch_t[] = new double[2*HDBlockModels.getMaxPatchCount()];
|
||||||
double patch_u[] = new double[2*HDBlockModels.getMaxPatchCount()];
|
double patch_u[] = new double[2*HDBlockModels.getMaxPatchCount()];
|
||||||
double patch_v[] = new double[2*HDBlockModels.getMaxPatchCount()];
|
double patch_v[] = new double[2*HDBlockModels.getMaxPatchCount()];
|
||||||
|
boolean patch_shade[] = new boolean[2*HDBlockModels.getMaxPatchCount()];
|
||||||
BlockStep patch_step[] = new BlockStep[2*HDBlockModels.getMaxPatchCount()];
|
BlockStep patch_step[] = new BlockStep[2*HDBlockModels.getMaxPatchCount()];
|
||||||
int patch_id[] = new int[2*HDBlockModels.getMaxPatchCount()];
|
int patch_id[] = new int[2*HDBlockModels.getMaxPatchCount()];
|
||||||
int cur_patch = -1;
|
int cur_patch = -1;
|
||||||
double cur_patch_u;
|
double cur_patch_u;
|
||||||
double cur_patch_v;
|
double cur_patch_v;
|
||||||
double cur_patch_t;
|
double cur_patch_t;
|
||||||
|
boolean cur_shade;
|
||||||
|
|
||||||
int[] subblock_xyz = new int[3];
|
int[] subblock_xyz = new int[3];
|
||||||
final MapIterator mapiter;
|
final MapIterator mapiter;
|
||||||
|
@ -410,6 +406,7 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
case TOP:
|
case TOP:
|
||||||
case TOPFLIP:
|
case TOPFLIP:
|
||||||
case TOPFLIPV:
|
case TOPFLIPV:
|
||||||
|
case TOPFLIPHV:
|
||||||
if (det < 0.000001) {
|
if (det < 0.000001) {
|
||||||
return hitcnt;
|
return hitcnt;
|
||||||
}
|
}
|
||||||
|
@ -453,6 +450,7 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
patch_t[hitcnt] = t;
|
patch_t[hitcnt] = t;
|
||||||
patch_u[hitcnt] = u;
|
patch_u[hitcnt] = u;
|
||||||
patch_v[hitcnt] = v;
|
patch_v[hitcnt] = v;
|
||||||
|
patch_shade[hitcnt] = pd.shade;
|
||||||
patch_id[hitcnt] = pd.textureindex;
|
patch_id[hitcnt] = pd.textureindex;
|
||||||
if(det > 0) {
|
if(det > 0) {
|
||||||
patch_step[hitcnt] = pd.step.opposite();
|
patch_step[hitcnt] = pd.step.opposite();
|
||||||
|
@ -462,6 +460,10 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
else if (pd.sidevis == SideVisible.TOPFLIPV) {
|
else if (pd.sidevis == SideVisible.TOPFLIPV) {
|
||||||
patch_v[hitcnt] = 1 - v;
|
patch_v[hitcnt] = 1 - v;
|
||||||
}
|
}
|
||||||
|
else if (pd.sidevis == SideVisible.TOPFLIPHV) {
|
||||||
|
patch_u[hitcnt] = 1 - u;
|
||||||
|
patch_v[hitcnt] = 1 - v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (pd.sidevis == SideVisible.FLIP) {
|
if (pd.sidevis == SideVisible.FLIP) {
|
||||||
|
@ -515,6 +517,7 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
cur_patch = patch_id[best_patch]; /* Mark this as current patch */
|
cur_patch = patch_id[best_patch]; /* Mark this as current patch */
|
||||||
cur_patch_u = patch_u[best_patch];
|
cur_patch_u = patch_u[best_patch];
|
||||||
cur_patch_v = patch_v[best_patch];
|
cur_patch_v = patch_v[best_patch];
|
||||||
|
cur_shade = patch_shade[best_patch];
|
||||||
laststep = patch_step[best_patch];
|
laststep = patch_step[best_patch];
|
||||||
cur_patch_t = best_t;
|
cur_patch_t = best_t;
|
||||||
// If the water patch, switch to water state and patch index
|
// If the water patch, switch to water state and patch index
|
||||||
|
@ -906,7 +909,7 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
* Get current texture index
|
* Get current texture index
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int getTextureIndex() {
|
public final int getTextureIndex() {
|
||||||
return cur_patch;
|
return cur_patch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -914,7 +917,7 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
* Get current U of patch intercept
|
* Get current U of patch intercept
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public double getPatchU() {
|
public final double getPatchU() {
|
||||||
return cur_patch_u;
|
return cur_patch_u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -922,10 +925,19 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
* Get current V of patch intercept
|
* Get current V of patch intercept
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public double getPatchV() {
|
public final double getPatchV() {
|
||||||
return cur_patch_v;
|
return cur_patch_v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get current patch noShadow setting (true = no shadows/lighting)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public final boolean getShade() {
|
||||||
|
// Shade if shade set OR not patch
|
||||||
|
return cur_shade || (cur_patch < 0); /* If patch hit */
|
||||||
|
}
|
||||||
|
/**
|
||||||
* Light level cache
|
* Light level cache
|
||||||
* @param index of light level (0-3)
|
* @param index of light level (0-3)
|
||||||
*/
|
*/
|
||||||
|
@ -988,10 +1000,17 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
hashcode = name.hashCode();
|
hashcode = name.hashCode();
|
||||||
}
|
}
|
||||||
double az = 90.0 + configuration.getDouble("azimuth", 135.0); /* Get azimuth (default to classic kzed POV) */
|
double az = 90.0 + configuration.getDouble("azimuth", 135.0); /* Get azimuth (default to classic kzed POV) */
|
||||||
if(az >= 360.0) {
|
if (az >= 360.0) {
|
||||||
az = az - 360.0;
|
az = az - 360.0;
|
||||||
}
|
}
|
||||||
azimuth = az;
|
azimuth = az;
|
||||||
|
// Get compass azimuth - default to same as true azimuth, but allows for override
|
||||||
|
az = 90.0 + configuration.getDouble("compassazimuth", az - 90.0); /* Get azimuth (default to classic kzed POV) */
|
||||||
|
if (az >= 360.0) {
|
||||||
|
az = az - 360.0;
|
||||||
|
}
|
||||||
|
compassazimuth = az;
|
||||||
|
|
||||||
double inc;
|
double inc;
|
||||||
inc = configuration.getDouble("inclination", 60.0);
|
inc = configuration.getDouble("inclination", 60.0);
|
||||||
if(inc > MAX_INCLINATION) inc = MAX_INCLINATION;
|
if(inc > MAX_INCLINATION) inc = MAX_INCLINATION;
|
||||||
|
@ -1031,13 +1050,14 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<TileFlags.TileCoord> getTileCoords(DynmapWorld world, int x, int y, int z) {
|
public List<TileFlags.TileCoord> getTileCoords(DynmapWorld world, int x, int y, int z, int tilescale) {
|
||||||
HashSet<TileFlags.TileCoord> tiles = new HashSet<TileFlags.TileCoord>();
|
HashSet<TileFlags.TileCoord> tiles = new HashSet<TileFlags.TileCoord>();
|
||||||
Vector3D block = new Vector3D();
|
Vector3D block = new Vector3D();
|
||||||
block.x = x;
|
block.x = x;
|
||||||
block.y = y;
|
block.y = y;
|
||||||
block.z = z;
|
block.z = z;
|
||||||
Vector3D corner = new Vector3D();
|
Vector3D corner = new Vector3D();
|
||||||
|
int tileSize = 128 << tilescale;
|
||||||
/* Loop through corners of the cube */
|
/* Loop through corners of the cube */
|
||||||
for(int i = 0; i < 2; i++) {
|
for(int i = 0; i < 2; i++) {
|
||||||
double inity = block.y;
|
double inity = block.y;
|
||||||
|
@ -1045,7 +1065,7 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
double initz = block.z;
|
double initz = block.z;
|
||||||
for(int k = 0; k < 2; k++) {
|
for(int k = 0; k < 2; k++) {
|
||||||
world_to_map.transform(block, corner); /* Get map coordinate of corner */
|
world_to_map.transform(block, corner); /* Get map coordinate of corner */
|
||||||
tiles.add(new TileFlags.TileCoord(fastFloor(corner.x/tileWidth), fastFloor(corner.y/tileHeight)));
|
tiles.add(new TileFlags.TileCoord(fastFloor(corner.x/tileSize), fastFloor(corner.y/tileSize)));
|
||||||
block.z += 1;
|
block.z += 1;
|
||||||
}
|
}
|
||||||
block.z = initz;
|
block.z = initz;
|
||||||
|
@ -1058,7 +1078,7 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<TileFlags.TileCoord> getTileCoords(DynmapWorld world, int minx, int miny, int minz, int maxx, int maxy, int maxz) {
|
public List<TileFlags.TileCoord> getTileCoords(DynmapWorld world, int minx, int miny, int minz, int maxx, int maxy, int maxz, int tilescale) {
|
||||||
ArrayList<TileFlags.TileCoord> tiles = new ArrayList<TileFlags.TileCoord>();
|
ArrayList<TileFlags.TileCoord> tiles = new ArrayList<TileFlags.TileCoord>();
|
||||||
Vector3D blocks[] = new Vector3D[] { new Vector3D(), new Vector3D() };
|
Vector3D blocks[] = new Vector3D[] { new Vector3D(), new Vector3D() };
|
||||||
blocks[0].x = minx - 1;
|
blocks[0].x = minx - 1;
|
||||||
|
@ -1074,6 +1094,7 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
int maxtilex = Integer.MIN_VALUE;
|
int maxtilex = Integer.MIN_VALUE;
|
||||||
int mintiley = Integer.MAX_VALUE;
|
int mintiley = Integer.MAX_VALUE;
|
||||||
int maxtiley = Integer.MIN_VALUE;
|
int maxtiley = Integer.MIN_VALUE;
|
||||||
|
int tileSize = 128 << tilescale;
|
||||||
/* Loop through corners of the prism */
|
/* Loop through corners of the prism */
|
||||||
for(int i = 0; i < 2; i++) {
|
for(int i = 0; i < 2; i++) {
|
||||||
corner.x = blocks[i].x;
|
corner.x = blocks[i].x;
|
||||||
|
@ -1082,8 +1103,8 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
for(int k = 0; k < 2; k++) {
|
for(int k = 0; k < 2; k++) {
|
||||||
corner.z = blocks[k].z;
|
corner.z = blocks[k].z;
|
||||||
world_to_map.transform(corner, tcorner); /* Get map coordinate of corner */
|
world_to_map.transform(corner, tcorner); /* Get map coordinate of corner */
|
||||||
int tx = fastFloor(tcorner.x/tileWidth);
|
int tx = fastFloor(tcorner.x/(tileSize << tilescale));
|
||||||
int ty = fastFloor(tcorner.y/tileWidth);
|
int ty = fastFloor(tcorner.y/(tileSize << tilescale));
|
||||||
if(mintilex > tx) mintilex = tx;
|
if(mintilex > tx) mintilex = tx;
|
||||||
if(maxtilex < tx) maxtilex = tx;
|
if(maxtilex < tx) maxtilex = tx;
|
||||||
if(mintiley > ty) mintiley = ty;
|
if(mintiley > ty) mintiley = ty;
|
||||||
|
@ -1107,14 +1128,14 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
int x = t.tx;
|
int x = t.tx;
|
||||||
int y = t.ty;
|
int y = t.ty;
|
||||||
return new MapTile[] {
|
return new MapTile[] {
|
||||||
new HDMapTile(w, this, x - 1, y - 1, t.boostzoom),
|
new HDMapTile(w, this, x - 1, y - 1, t.boostzoom, t.tilescale),
|
||||||
new HDMapTile(w, this, x + 1, y - 1, t.boostzoom),
|
new HDMapTile(w, this, x + 1, y - 1, t.boostzoom, t.tilescale),
|
||||||
new HDMapTile(w, this, x - 1, y + 1, t.boostzoom),
|
new HDMapTile(w, this, x - 1, y + 1, t.boostzoom, t.tilescale),
|
||||||
new HDMapTile(w, this, x + 1, y + 1, t.boostzoom),
|
new HDMapTile(w, this, x + 1, y + 1, t.boostzoom, t.tilescale),
|
||||||
new HDMapTile(w, this, x, y - 1, t.boostzoom),
|
new HDMapTile(w, this, x, y - 1, t.boostzoom, t.tilescale),
|
||||||
new HDMapTile(w, this, x + 1, y, t.boostzoom),
|
new HDMapTile(w, this, x + 1, y, t.boostzoom, t.tilescale),
|
||||||
new HDMapTile(w, this, x, y + 1, t.boostzoom),
|
new HDMapTile(w, this, x, y + 1, t.boostzoom, t.tilescale),
|
||||||
new HDMapTile(w, this, x - 1, y, t.boostzoom) };
|
new HDMapTile(w, this, x - 1, y, t.boostzoom, t.tilescale) };
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int corners_by_side[][] = {
|
private static final int corners_by_side[][] = {
|
||||||
|
@ -1136,6 +1157,7 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
int max_chunk_x = Integer.MIN_VALUE;
|
int max_chunk_x = Integer.MIN_VALUE;
|
||||||
int min_chunk_z = Integer.MAX_VALUE;
|
int min_chunk_z = Integer.MAX_VALUE;
|
||||||
int max_chunk_z = Integer.MIN_VALUE;
|
int max_chunk_z = Integer.MIN_VALUE;
|
||||||
|
int tileSize = tile.getTileSize();
|
||||||
|
|
||||||
/* Make corners for volume:
|
/* Make corners for volume:
|
||||||
* 0 = bottom-lower-left (xyz),
|
* 0 = bottom-lower-left (xyz),
|
||||||
|
@ -1153,8 +1175,8 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
for(int y = t.ty; y <= (t.ty+1); y++) {
|
for(int y = t.ty; y <= (t.ty+1); y++) {
|
||||||
for(int z = 0; z <= 1; z++) {
|
for(int z = 0; z <= 1; z++) {
|
||||||
corners[idx] = new Vector3D();
|
corners[idx] = new Vector3D();
|
||||||
corners[idx].x = x*tileWidth + dx;
|
corners[idx].x = x*tileSize + dx;
|
||||||
corners[idx].y = y*tileHeight + dy;
|
corners[idx].y = y*tileSize + dy;
|
||||||
corners[idx].z = (z == 1) ? t.getDynmapWorld().worldheight : t.getDynmapWorld().minY;
|
corners[idx].z = (z == 1) ? t.getDynmapWorld().worldheight : t.getDynmapWorld().minY;
|
||||||
map_to_world.transform(corners[idx]);
|
map_to_world.transform(corners[idx]);
|
||||||
/* Compute chunk coordinates of corner */
|
/* Compute chunk coordinates of corner */
|
||||||
|
@ -1208,8 +1230,9 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
Color rslt = new Color();
|
Color rslt = new Color();
|
||||||
MapIterator mapiter = cache.getIterator(0, 0, 0);
|
MapIterator mapiter = cache.getIterator(0, 0, 0);
|
||||||
DynmapWorld world = tile.getDynmapWorld();
|
DynmapWorld world = tile.getDynmapWorld();
|
||||||
|
int tileSize = tile.getTileSize();
|
||||||
int scaled = 0;
|
int scaled = 0;
|
||||||
if ((tile.boostzoom > 0) && MarkerAPIImpl.testTileForBoostMarkers(cache.getWorld(), this, tile.tx * tileWidth, tile.ty * tileHeight, tileWidth)) {
|
if ((tile.boostzoom > 0) && MarkerAPIImpl.testTileForBoostMarkers(cache.getWorld(), this, tile.tx * tileSize, tile.ty * tileSize, tileSize)) {
|
||||||
scaled = tile.boostzoom;
|
scaled = tile.boostzoom;
|
||||||
}
|
}
|
||||||
int sizescale = 1 << scaled;
|
int sizescale = 1 << scaled;
|
||||||
|
@ -1226,26 +1249,26 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
DynmapBufferedImage dayim[] = new DynmapBufferedImage[numshaders];
|
DynmapBufferedImage dayim[] = new DynmapBufferedImage[numshaders];
|
||||||
int[][] argb_buf = new int[numshaders][];
|
int[][] argb_buf = new int[numshaders][];
|
||||||
int[][] day_argb_buf = new int[numshaders][];
|
int[][] day_argb_buf = new int[numshaders][];
|
||||||
boolean isjpg[] = new boolean[numshaders];
|
boolean isOpaque[] = new boolean[numshaders];
|
||||||
int bgday[] = new int[numshaders];
|
int bgday[] = new int[numshaders];
|
||||||
int bgnight[] = new int[numshaders];
|
int bgnight[] = new int[numshaders];
|
||||||
|
|
||||||
for(int i = 0; i < numshaders; i++) {
|
for(int i = 0; i < numshaders; i++) {
|
||||||
HDLighting lighting = shaderstate[i].getLighting();
|
HDLighting lighting = shaderstate[i].getLighting();
|
||||||
im[i] = DynmapBufferedImage.allocateBufferedImage(tileWidth * sizescale, tileHeight * sizescale);
|
im[i] = DynmapBufferedImage.allocateBufferedImage(tileSize * sizescale, tileSize * sizescale);
|
||||||
argb_buf[i] = im[i].argb_buf;
|
argb_buf[i] = im[i].argb_buf;
|
||||||
if(lighting.isNightAndDayEnabled()) {
|
if(lighting.isNightAndDayEnabled()) {
|
||||||
dayim[i] = DynmapBufferedImage.allocateBufferedImage(tileWidth * sizescale, tileHeight * sizescale);
|
dayim[i] = DynmapBufferedImage.allocateBufferedImage(tileSize * sizescale, tileSize * sizescale);
|
||||||
day_argb_buf[i] = dayim[i].argb_buf;
|
day_argb_buf[i] = dayim[i].argb_buf;
|
||||||
}
|
}
|
||||||
isjpg[i] = shaderstate[i].getMap().getImageFormat() != ImageFormat.FORMAT_PNG;
|
isOpaque[i] = !shaderstate[i].getMap().getImageFormat().getEncoding().hasAlpha;
|
||||||
bgday[i] = shaderstate[i].getMap().getBackgroundARGBDay();
|
bgday[i] = shaderstate[i].getMap().getBackgroundARGBDay();
|
||||||
bgnight[i] = shaderstate[i].getMap().getBackgroundARGBNight();
|
bgnight[i] = shaderstate[i].getMap().getBackgroundARGBNight();
|
||||||
}
|
}
|
||||||
// Mark the tiles we're going to render as validated
|
// Mark the tiles we're going to render as validated
|
||||||
for (int i = 0; i < numshaders; i++) {
|
for (int i = 0; i < numshaders; i++) {
|
||||||
MapTypeState mts = world.getMapState(shaderstate[i].getMap());
|
MapTypeState mts = world.getMapState(shaderstate[i].getMap());
|
||||||
if (mts != null) {
|
if (mts != null && mts.type.isReadOnly() == false) {
|
||||||
mts.validateTile(tile.tx, tile.ty);
|
mts.validateTile(tile.tx, tile.ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1255,8 +1278,8 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
ps.top = new Vector3D();
|
ps.top = new Vector3D();
|
||||||
ps.bottom = new Vector3D();
|
ps.bottom = new Vector3D();
|
||||||
ps.direction = new Vector3D();
|
ps.direction = new Vector3D();
|
||||||
double xbase = tile.tx * tileWidth;
|
double xbase = tile.tx * tileSize;
|
||||||
double ybase = tile.ty * tileHeight;
|
double ybase = tile.ty * tileSize;
|
||||||
boolean shaderdone[] = new boolean[numshaders];
|
boolean shaderdone[] = new boolean[numshaders];
|
||||||
boolean rendered[] = new boolean[numshaders];
|
boolean rendered[] = new boolean[numshaders];
|
||||||
double height = maxheight;
|
double height = maxheight;
|
||||||
|
@ -1271,9 +1294,9 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
miny = tile.getDynmapWorld().minY;
|
miny = tile.getDynmapWorld().minY;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < tileWidth * sizescale; x++) {
|
for(int x = 0; x < tileSize * sizescale; x++) {
|
||||||
ps.px = x;
|
ps.px = x;
|
||||||
for(int y = 0; y < tileHeight * sizescale; y++) {
|
for(int y = 0; y < tileSize * sizescale; y++) {
|
||||||
ps.top.x = ps.bottom.x = xbase + (x + 0.5) / sizescale; /* Start at center of pixel at Y=height+0.5, bottom at Y=-0.5 */
|
ps.top.x = ps.bottom.x = xbase + (x + 0.5) / sizescale; /* Start at center of pixel at Y=height+0.5, bottom at Y=-0.5 */
|
||||||
ps.top.y = ps.bottom.y = ybase + (y + 0.5) / sizescale;
|
ps.top.y = ps.bottom.y = ybase + (y + 0.5) / sizescale;
|
||||||
ps.top.z = height + 0.5; ps.bottom.z = miny - 0.5;
|
ps.top.z = height + 0.5; ps.bottom.z = miny - 0.5;
|
||||||
|
@ -1301,21 +1324,21 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
}
|
}
|
||||||
shaderstate[i].getRayColor(rslt, 0);
|
shaderstate[i].getRayColor(rslt, 0);
|
||||||
int c_argb = rslt.getARGB();
|
int c_argb = rslt.getARGB();
|
||||||
if(c_argb != 0) rendered[i] = true;
|
if (c_argb != 0) rendered[i] = true;
|
||||||
if(isjpg[i] && (c_argb == 0)) {
|
if (isOpaque[i] && (c_argb == 0)) {
|
||||||
argb_buf[i][(tileHeight*sizescale-y-1)*tileWidth*sizescale + x] = bgnight[i];
|
argb_buf[i][(tileSize*sizescale-y-1)*tileSize*sizescale + x] = bgnight[i];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
argb_buf[i][(tileHeight*sizescale-y-1)*tileWidth*sizescale + x] = c_argb;
|
argb_buf[i][(tileSize*sizescale-y-1)*tileSize*sizescale + x] = c_argb;
|
||||||
}
|
}
|
||||||
if(day_argb_buf[i] != null) {
|
if (day_argb_buf[i] != null) {
|
||||||
shaderstate[i].getRayColor(rslt, 1);
|
shaderstate[i].getRayColor(rslt, 1);
|
||||||
c_argb = rslt.getARGB();
|
c_argb = rslt.getARGB();
|
||||||
if(isjpg[i] && (c_argb == 0)) {
|
if (isOpaque[i] && (c_argb == 0)) {
|
||||||
day_argb_buf[i][(tileHeight*sizescale-y-1)*tileWidth*sizescale + x] = bgday[i];
|
day_argb_buf[i][(tileSize*sizescale-y-1)*tileSize*sizescale + x] = bgday[i];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
day_argb_buf[i][(tileHeight*sizescale-y-1)*tileWidth*sizescale + x] = c_argb;
|
day_argb_buf[i][(tileSize*sizescale-y-1)*tileSize*sizescale + x] = c_argb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1436,7 +1459,7 @@ public class IsoHDPerspective implements HDPerspective {
|
||||||
s(mapObject, "scale", basemodscale);
|
s(mapObject, "scale", basemodscale);
|
||||||
s(mapObject, "worldtomap", world_to_map.toJSON());
|
s(mapObject, "worldtomap", world_to_map.toJSON());
|
||||||
s(mapObject, "maptoworld", map_to_world.toJSON());
|
s(mapObject, "maptoworld", map_to_world.toJSON());
|
||||||
int dir = (((360 + (int)(22.5+azimuth)) / 45) + 6) % 8;
|
int dir = (((360 + (int)(22.5+compassazimuth)) / 45) + 6) % 8;
|
||||||
s(mapObject, "compassview", directions[dir]);
|
s(mapObject, "compassview", directions[dir]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,7 @@ import org.dynmap.Color;
|
||||||
import org.dynmap.ConfigurationNode;
|
import org.dynmap.ConfigurationNode;
|
||||||
import org.dynmap.DynmapCore;
|
import org.dynmap.DynmapCore;
|
||||||
import org.dynmap.DynmapWorld;
|
import org.dynmap.DynmapWorld;
|
||||||
import org.dynmap.Log;
|
|
||||||
import org.dynmap.MapManager;
|
|
||||||
import org.dynmap.utils.LightLevels;
|
import org.dynmap.utils.LightLevels;
|
||||||
import org.dynmap.utils.BlockStep;
|
|
||||||
|
|
||||||
public class LightLevelHDLighting extends DefaultHDLighting {
|
public class LightLevelHDLighting extends DefaultHDLighting {
|
||||||
private final Color[] lightlevelcolors = new Color[16];
|
private final Color[] lightlevelcolors = new Color[16];
|
||||||
|
|
|
@ -4,7 +4,6 @@ import org.dynmap.Color;
|
||||||
import org.dynmap.ConfigurationNode;
|
import org.dynmap.ConfigurationNode;
|
||||||
import org.dynmap.DynmapCore;
|
import org.dynmap.DynmapCore;
|
||||||
import org.dynmap.DynmapWorld;
|
import org.dynmap.DynmapWorld;
|
||||||
import org.dynmap.Log;
|
|
||||||
import org.dynmap.MapManager;
|
import org.dynmap.MapManager;
|
||||||
import org.dynmap.utils.LightLevels;
|
import org.dynmap.utils.LightLevels;
|
||||||
import org.dynmap.utils.BlockStep;
|
import org.dynmap.utils.BlockStep;
|
||||||
|
@ -218,8 +217,8 @@ public class ShadowHDLighting extends DefaultHDLighting {
|
||||||
|
|
||||||
/* Apply lighting to given pixel colors (1 outcolor if normal, 2 if night/day) */
|
/* 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) {
|
public void applyLighting(HDPerspectiveState ps, HDShaderState ss, Color incolor, Color[] outcolor) {
|
||||||
int[] shadowscale = null;
|
int[] shadowscale = null;
|
||||||
if(smooth) {
|
if (smooth && ps.getShade()) {
|
||||||
shadowscale = ss.getLightingTable();
|
shadowscale = ss.getLightingTable();
|
||||||
if (shadowscale == null) {
|
if (shadowscale == null) {
|
||||||
shadowscale = defLightingTable;
|
shadowscale = defLightingTable;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.dynmap.hdmap;
|
package org.dynmap.hdmap;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
@ -36,6 +37,7 @@ import org.dynmap.common.DynmapCommandSender;
|
||||||
import org.dynmap.exporter.OBJExport;
|
import org.dynmap.exporter.OBJExport;
|
||||||
import org.dynmap.renderer.CustomColorMultiplier;
|
import org.dynmap.renderer.CustomColorMultiplier;
|
||||||
import org.dynmap.renderer.DynmapBlockState;
|
import org.dynmap.renderer.DynmapBlockState;
|
||||||
|
import org.dynmap.utils.BlockStateParser;
|
||||||
import org.dynmap.utils.BlockStep;
|
import org.dynmap.utils.BlockStep;
|
||||||
import org.dynmap.utils.BufferOutputStream;
|
import org.dynmap.utils.BufferOutputStream;
|
||||||
import org.dynmap.utils.DynIntHashMap;
|
import org.dynmap.utils.DynIntHashMap;
|
||||||
|
@ -481,8 +483,7 @@ public class TexturePack {
|
||||||
public static class TextureMap {
|
public static class TextureMap {
|
||||||
private Map<Integer, Integer> key_to_index = new HashMap<Integer, Integer>();
|
private Map<Integer, Integer> key_to_index = new HashMap<Integer, Integer>();
|
||||||
private List<Integer> texture_ids = new ArrayList<Integer>();
|
private List<Integer> texture_ids = new ArrayList<Integer>();
|
||||||
private List<String> blocknames = new ArrayList<String>();
|
private Map<DynmapBlockState, BitSet> states;
|
||||||
private BitSet stateids = new BitSet();
|
|
||||||
private BlockTransparency trans = BlockTransparency.OPAQUE;
|
private BlockTransparency trans = BlockTransparency.OPAQUE;
|
||||||
private int colorMult = 0;
|
private int colorMult = 0;
|
||||||
private CustomColorMultiplier custColorMult = null;
|
private CustomColorMultiplier custColorMult = null;
|
||||||
|
@ -546,14 +547,13 @@ public class TexturePack {
|
||||||
/**
|
/**
|
||||||
* Add settings for texture map
|
* Add settings for texture map
|
||||||
*/
|
*/
|
||||||
private static void addTextureIndex(String id, List<String> blocknames, BitSet stateids, BlockTransparency trans, int colorMult, CustomColorMultiplier custColorMult, String blockset) {
|
private static void addTextureIndex(String id, Map<DynmapBlockState, BitSet> states, BlockTransparency trans, int colorMult, CustomColorMultiplier custColorMult, String blockset) {
|
||||||
TextureMap idx = textmap_by_id.get(id);
|
TextureMap idx = textmap_by_id.get(id);
|
||||||
if(idx == null) { /* Add empty one, if not found */
|
if(idx == null) { /* Add empty one, if not found */
|
||||||
idx = new TextureMap();
|
idx = new TextureMap();
|
||||||
textmap_by_id.put(id, idx);
|
textmap_by_id.put(id, idx);
|
||||||
}
|
}
|
||||||
idx.blocknames = blocknames;
|
idx.states = states;
|
||||||
idx.stateids = stateids;
|
|
||||||
idx.trans = trans;
|
idx.trans = trans;
|
||||||
idx.colorMult = colorMult;
|
idx.colorMult = colorMult;
|
||||||
idx.custColorMult = custColorMult;
|
idx.custColorMult = custColorMult;
|
||||||
|
@ -563,13 +563,13 @@ public class TexturePack {
|
||||||
*/
|
*/
|
||||||
private static void processTextureMaps() {
|
private static void processTextureMaps() {
|
||||||
for(TextureMap ti : textmap_by_id.values()) {
|
for(TextureMap ti : textmap_by_id.values()) {
|
||||||
if(ti.blocknames.isEmpty()) continue;
|
if(ti.states.isEmpty()) continue;
|
||||||
int[] txtids = new int[ti.texture_ids.size()];
|
int[] txtids = new int[ti.texture_ids.size()];
|
||||||
for(int i = 0; i < txtids.length; i++) {
|
for(int i = 0; i < txtids.length; i++) {
|
||||||
txtids[i] = ti.texture_ids.get(i).intValue();
|
txtids[i] = ti.texture_ids.get(i).intValue();
|
||||||
}
|
}
|
||||||
HDBlockStateTextureMap map = new HDBlockStateTextureMap(txtids, null, ti.colorMult, ti.custColorMult, ti.blockset, true, null, ti.trans);
|
HDBlockStateTextureMap map = new HDBlockStateTextureMap(txtids, null, ti.colorMult, ti.custColorMult, ti.blockset, true, null, ti.trans);
|
||||||
map.addToTable(ti.blocknames, ti.stateids);
|
map.addToTable(ti.states);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -1255,8 +1255,13 @@ public class TexturePack {
|
||||||
/* Load image */
|
/* Load image */
|
||||||
if(is != null) {
|
if(is != null) {
|
||||||
ImageIO.setUseCache(false);
|
ImageIO.setUseCache(false);
|
||||||
img = ImageIO.read(is);
|
try {
|
||||||
if(img == null) { throw new FileNotFoundException(); }
|
img = ImageIO.read(is);
|
||||||
|
} catch (IOException iox) {
|
||||||
|
}
|
||||||
|
if (img == null) {
|
||||||
|
Log.warning(String.format("Error loading image %s from module %s", fname, modid));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(idx >= imgs.length) {
|
if(idx >= imgs.length) {
|
||||||
LoadedImage[] newimgs = new LoadedImage[idx+1];
|
LoadedImage[] newimgs = new LoadedImage[idx+1];
|
||||||
|
@ -1268,7 +1273,17 @@ public class TexturePack {
|
||||||
imgs[idx].width = img.getWidth();
|
imgs[idx].width = img.getWidth();
|
||||||
imgs[idx].height = img.getHeight();
|
imgs[idx].height = img.getHeight();
|
||||||
imgs[idx].argb = new int[imgs[idx].width * imgs[idx].height];
|
imgs[idx].argb = new int[imgs[idx].width * imgs[idx].height];
|
||||||
img.getRGB(0, 0, imgs[idx].width, imgs[idx].height, imgs[idx].argb, 0, imgs[idx].width);
|
if (img.getType() == BufferedImage.TYPE_BYTE_GRAY) { // We don't want alpha correction, apparently
|
||||||
|
float[] buffer = new float[imgs[idx].width * imgs[idx].height];
|
||||||
|
img.getData().getPixels(0, 0, imgs[idx].width, imgs[idx].height, buffer);
|
||||||
|
for (int i = 0; i < imgs[idx].argb.length; i++) {
|
||||||
|
int v = (int) buffer[i];
|
||||||
|
imgs[idx].argb[i] = 0xFF000000 | (v << 16) | (v << 8) | v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
img.getRGB(0, 0, imgs[idx].width, imgs[idx].height, imgs[idx].argb, 0, imgs[idx].width);
|
||||||
|
}
|
||||||
img.flush();
|
img.flush();
|
||||||
imgs[idx].isLoaded = true;
|
imgs[idx].isLoaded = true;
|
||||||
}
|
}
|
||||||
|
@ -1819,7 +1834,7 @@ public class TexturePack {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String line;
|
String line;
|
||||||
rdr = new LineNumberReader(new InputStreamReader(txtfile));
|
rdr = new LineNumberReader(new BufferedReader(new InputStreamReader(txtfile)));
|
||||||
while((line = rdr.readLine()) != null) {
|
while((line = rdr.readLine()) != null) {
|
||||||
if(line.startsWith("#")) {
|
if(line.startsWith("#")) {
|
||||||
}
|
}
|
||||||
|
@ -1914,15 +1929,18 @@ public class TexturePack {
|
||||||
String texturemod = null;
|
String texturemod = null;
|
||||||
String texturepath = null;
|
String texturepath = null;
|
||||||
boolean terrain_ok = true;
|
boolean terrain_ok = true;
|
||||||
|
BlockStateParser bsp = new BlockStateParser();
|
||||||
|
Map<DynmapBlockState, BitSet> bsprslt;
|
||||||
try {
|
try {
|
||||||
String line;
|
String line;
|
||||||
rdr = new LineNumberReader(new InputStreamReader(txtfile));
|
rdr = new LineNumberReader(new BufferedReader(new InputStreamReader(txtfile)));
|
||||||
while((line = rdr.readLine()) != null) {
|
while((line = rdr.readLine()) != null) {
|
||||||
boolean skip = false;
|
boolean skip = false;
|
||||||
|
int lineNum = rdr.getLineNumber();
|
||||||
if ((line.length() > 0) && (line.charAt(0) == '[')) { // If version constrained like
|
if ((line.length() > 0) && (line.charAt(0) == '[')) { // If version constrained like
|
||||||
int end = line.indexOf(']'); // Find end
|
int end = line.indexOf(']'); // Find end
|
||||||
if (end < 0) {
|
if (end < 0) {
|
||||||
Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname + ": bad version limit");
|
Log.severe("Format error - line " + lineNum + " of " + txtname + ": bad version limit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String vertst = line.substring(1, end);
|
String vertst = line.substring(1, end);
|
||||||
|
@ -1936,19 +1954,28 @@ public class TexturePack {
|
||||||
}
|
}
|
||||||
line = line.substring(end+1);
|
line = line.substring(end+1);
|
||||||
}
|
}
|
||||||
// If we're skipping due to version restriction
|
if (line.startsWith("#") || line.startsWith(";")) {
|
||||||
if (skip) {
|
skip = true;
|
||||||
}
|
}
|
||||||
else if(line.startsWith("block:")) {
|
// If we're skipping due to version restriction
|
||||||
List<String> blknames = new ArrayList<String>();
|
if (skip) continue;
|
||||||
BitSet stateids = null;
|
// Split off <type>:
|
||||||
|
int typeend = line.indexOf(':');
|
||||||
|
String typeid = "";
|
||||||
|
if (typeend >= 0) {
|
||||||
|
typeid = line.substring(0, typeend);
|
||||||
|
line = line.substring(typeend+1).trim();
|
||||||
|
}
|
||||||
|
if (typeid.equals("block")) {
|
||||||
|
// Parse block states
|
||||||
|
bsp.processLine(modname, line, lineNum, varvals);
|
||||||
|
|
||||||
int srctxtid = TXTID_TERRAINPNG;
|
int srctxtid = TXTID_TERRAINPNG;
|
||||||
if (!terrain_ok)
|
if (!terrain_ok)
|
||||||
srctxtid = TXTID_INVALID; // Mark as not usable
|
srctxtid = TXTID_INVALID; // Mark as not usable
|
||||||
int faces[] = new int[] { TILEINDEX_BLANK, TILEINDEX_BLANK, TILEINDEX_BLANK, TILEINDEX_BLANK, TILEINDEX_BLANK, TILEINDEX_BLANK };
|
int faces[] = new int[] { TILEINDEX_BLANK, TILEINDEX_BLANK, TILEINDEX_BLANK, TILEINDEX_BLANK, TILEINDEX_BLANK, TILEINDEX_BLANK };
|
||||||
int txtidx[] = new int[] { -1, -1, -1, -1, -1, -1 };
|
int txtidx[] = new int[] { -1, -1, -1, -1, -1, -1 };
|
||||||
byte layers[] = null;
|
byte layers[] = null;
|
||||||
line = line.substring(6);
|
|
||||||
BlockTransparency trans = BlockTransparency.OPAQUE;
|
BlockTransparency trans = BlockTransparency.OPAQUE;
|
||||||
int colorMult = 0;
|
int colorMult = 0;
|
||||||
int blockColorIdx = -1;
|
int blockColorIdx = -1;
|
||||||
|
@ -1962,45 +1989,16 @@ public class TexturePack {
|
||||||
if(filetoidx.containsKey(av[1]))
|
if(filetoidx.containsKey(av[1]))
|
||||||
srctxtid = filetoidx.get(av[1]);
|
srctxtid = filetoidx.get(av[1]);
|
||||||
else
|
else
|
||||||
Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname + ": bad texture " + av[1]);
|
Log.severe("Format error - line " + lineNum + " of " + txtname + ": bad texture " + av[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Build ID list : abort rest of processing if no valid values
|
bsprslt = bsp.getMatchingStates();
|
||||||
for(String a : args) {
|
|
||||||
String[] av = a.split("=");
|
if (bsprslt.size() > 0) {
|
||||||
if(av.length < 2) continue;
|
|
||||||
if(av[0].equals("id")) {
|
|
||||||
String id = getBlockName(modname, av[1]);
|
|
||||||
if (id != null) {
|
|
||||||
blknames.add(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (blknames.size() > 0) {
|
|
||||||
for(String a : args) {
|
for(String a : args) {
|
||||||
String[] av = a.split("=");
|
String[] av = a.split("=");
|
||||||
if(av.length < 2) continue;
|
if(av.length < 2) continue;
|
||||||
if(av[0].equals("data")) {
|
if(av[0].equals("top") || av[0].equals("y-") || av[0].equals("face1")) {
|
||||||
if(av[1].equals("*")) {
|
|
||||||
stateids = null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (stateids == null) { stateids = new BitSet(); }
|
|
||||||
// See if range
|
|
||||||
if (av[1].indexOf('-') >= 0) {
|
|
||||||
String[] tok = av[1].split("-");
|
|
||||||
int v1 = getIntValue(varvals, tok[0]);
|
|
||||||
int v2 = getIntValue(varvals, tok[1]);
|
|
||||||
for (int v = v1; v <= v2; v++) {
|
|
||||||
stateids.set(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
stateids.set(getIntValue(varvals,av[1]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(av[0].equals("top") || av[0].equals("y-") || av[0].equals("face1")) {
|
|
||||||
faces[BlockStep.Y_MINUS.ordinal()] = parseTextureIndex(filetoidx, srctxtid, av[1]);
|
faces[BlockStep.Y_MINUS.ordinal()] = parseTextureIndex(filetoidx, srctxtid, av[1]);
|
||||||
}
|
}
|
||||||
else if(av[0].equals("bottom") || av[0].equals("y+") || av[0].equals("face0")) {
|
else if(av[0].equals("bottom") || av[0].equals("y+") || av[0].equals("face0")) {
|
||||||
|
@ -2030,7 +2028,7 @@ public class TexturePack {
|
||||||
fid0 = fid1 = Integer.parseInt(ids[0]);
|
fid0 = fid1 = Integer.parseInt(ids[0]);
|
||||||
}
|
}
|
||||||
if((fid0 < 0) || (fid1 < fid0)) {
|
if((fid0 < 0) || (fid1 < fid0)) {
|
||||||
Log.severe("Texture mapping has invalid face index - " + av[1] + " - line " + rdr.getLineNumber() + " of " + txtname);
|
Log.severe("Texture mapping has invalid face index - " + av[1] + " - line " + lineNum + " of " + txtname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int faceToOrd[] = { BlockStep.Y_PLUS.ordinal(), BlockStep.Y_MINUS.ordinal(),
|
int faceToOrd[] = { BlockStep.Y_PLUS.ordinal(), BlockStep.Y_MINUS.ordinal(),
|
||||||
|
@ -2063,7 +2061,7 @@ public class TexturePack {
|
||||||
if(filetoidx.containsKey(av[1]))
|
if(filetoidx.containsKey(av[1]))
|
||||||
blockColorIdx = filetoidx.get(av[1]);
|
blockColorIdx = filetoidx.get(av[1]);
|
||||||
else
|
else
|
||||||
Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname + ": bad texture " + av[1]);
|
Log.severe("Format error - line " + lineNum + " of " + txtname + ": bad texture " + av[1]);
|
||||||
}
|
}
|
||||||
else if(av[0].startsWith("patch")) {
|
else if(av[0].startsWith("patch")) {
|
||||||
int patchid0, patchid1;
|
int patchid0, patchid1;
|
||||||
|
@ -2077,7 +2075,7 @@ public class TexturePack {
|
||||||
patchid0 = patchid1 = Integer.parseInt(ids[0]);
|
patchid0 = patchid1 = Integer.parseInt(ids[0]);
|
||||||
}
|
}
|
||||||
if((patchid0 < 0) || (patchid1 < patchid0)) {
|
if((patchid0 < 0) || (patchid1 < patchid0)) {
|
||||||
Log.severe("Texture mapping has invalid patch index - " + av[1] + " - line " + rdr.getLineNumber() + " of " + txtname);
|
Log.severe("Texture mapping has invalid patch index - " + av[1] + " - line " + lineNum + " of " + txtname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(faces.length <= patchid1) {
|
if(faces.length <= patchid1) {
|
||||||
|
@ -2099,7 +2097,7 @@ public class TexturePack {
|
||||||
trans = BlockTransparency.valueOf(av[1]);
|
trans = BlockTransparency.valueOf(av[1]);
|
||||||
if(trans == null) {
|
if(trans == null) {
|
||||||
trans = BlockTransparency.OPAQUE;
|
trans = BlockTransparency.OPAQUE;
|
||||||
Log.severe("Texture mapping has invalid transparency setting - " + av[1] + " - line " + rdr.getLineNumber() + " of " + txtname);
|
Log.severe("Texture mapping has invalid transparency setting - " + av[1] + " - line " + lineNum + " of " + txtname);
|
||||||
}
|
}
|
||||||
/* For leaves, base on leaf transparency setting */
|
/* For leaves, base on leaf transparency setting */
|
||||||
if(trans == BlockTransparency.LEAVES) {
|
if(trans == BlockTransparency.LEAVES) {
|
||||||
|
@ -2115,7 +2113,7 @@ public class TexturePack {
|
||||||
else if(av[0].equals("custColorMult")) {
|
else if(av[0].equals("custColorMult")) {
|
||||||
try {
|
try {
|
||||||
Class<?> cls = Class.forName(av[1]);
|
Class<?> cls = Class.forName(av[1]);
|
||||||
custColorMult = (CustomColorMultiplier)cls.newInstance();
|
custColorMult = (CustomColorMultiplier)cls.getDeclaredConstructor().newInstance();
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
Log.severe("Error loading custom color multiplier - " + av[1] + ": " + x.getMessage());
|
Log.severe("Error loading custom color multiplier - " + av[1] + ": " + x.getMessage());
|
||||||
}
|
}
|
||||||
|
@ -2127,7 +2125,7 @@ public class TexturePack {
|
||||||
for(String a : args) {
|
for(String a : args) {
|
||||||
String[] av = a.split("=");
|
String[] av = a.split("=");
|
||||||
if(av.length < 2) continue;
|
if(av.length < 2) continue;
|
||||||
if(av[0].startsWith("layer")) {
|
if (av[0].startsWith("layer")) {
|
||||||
if(layers == null) {
|
if(layers == null) {
|
||||||
layers = new byte[faces.length];
|
layers = new byte[faces.length];
|
||||||
Arrays.fill(layers, (byte)-1);
|
Arrays.fill(layers, (byte)-1);
|
||||||
|
@ -2145,21 +2143,21 @@ public class TexturePack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* If we have everything, build block */
|
/* If we have everything, build block */
|
||||||
if(blknames.size() > 0) {
|
if (bsprslt.size() > 0) {
|
||||||
Integer colorIndex = (blockColorIdx >= 0)?(blockColorIdx + IMG_CNT):null;
|
Integer colorIndex = (blockColorIdx >= 0)?(blockColorIdx + IMG_CNT):null;
|
||||||
HDBlockStateTextureMap map = new HDBlockStateTextureMap(faces, layers, colorMult, custColorMult, blockset, stdrot, colorIndex, trans);
|
HDBlockStateTextureMap map = new HDBlockStateTextureMap(faces, layers, colorMult, custColorMult, blockset, stdrot, colorIndex, trans);
|
||||||
map.addToTable(blknames, stateids);
|
map.addToTable(bsprslt);
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.severe("Texture mapping missing required parameters = line " + rdr.getLineNumber() + " of " + txtname);
|
Log.severe("Texture mapping missing required parameters = line " + lineNum + " of " + txtname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(line.startsWith("copyblock:")) {
|
else if (typeid.equals("copyblock")) {
|
||||||
List<String> blknames = new ArrayList<String>();
|
// Parse block states
|
||||||
BitSet stateids = null;
|
bsp.processLine(modname, line, lineNum, varvals);
|
||||||
line = line.substring(line.indexOf(':')+1);
|
|
||||||
String[] args = line.split(",");
|
String[] args = line.split(",");
|
||||||
String srcname = null;
|
String srcname = null;
|
||||||
int srcmeta = 0;
|
int srcmeta = 0;
|
||||||
|
@ -2167,33 +2165,7 @@ public class TexturePack {
|
||||||
for(String a : args) {
|
for(String a : args) {
|
||||||
String[] av = a.split("=");
|
String[] av = a.split("=");
|
||||||
if(av.length < 2) continue;
|
if(av.length < 2) continue;
|
||||||
if(av[0].equals("id")) {
|
if(av[0].equals("srcid")) {
|
||||||
String id = getBlockName(modname, av[1]);
|
|
||||||
if (id != null) {
|
|
||||||
blknames.add(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(av[0].equals("data")) {
|
|
||||||
if(av[1].equals("*")) {
|
|
||||||
stateids = null; // Set all
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (stateids == null) { stateids = new BitSet(); }
|
|
||||||
// See if range
|
|
||||||
if (av[1].indexOf('-') >= 0) {
|
|
||||||
String[] tok = av[1].split("-");
|
|
||||||
int v1 = getIntValue(varvals, tok[0]);
|
|
||||||
int v2 = getIntValue(varvals, tok[1]);
|
|
||||||
for (int v = v1; v <= v2; v++) {
|
|
||||||
stateids.set(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
stateids.set(getIntValue(varvals,av[1]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(av[0].equals("srcid")) {
|
|
||||||
srcname = getBlockName(modname, av[1]);
|
srcname = getBlockName(modname, av[1]);
|
||||||
}
|
}
|
||||||
else if(av[0].equals("srcmeta")) {
|
else if(av[0].equals("srcmeta")) {
|
||||||
|
@ -2203,7 +2175,7 @@ public class TexturePack {
|
||||||
trans = BlockTransparency.valueOf(av[1]);
|
trans = BlockTransparency.valueOf(av[1]);
|
||||||
if(trans == null) {
|
if(trans == null) {
|
||||||
trans = BlockTransparency.OPAQUE;
|
trans = BlockTransparency.OPAQUE;
|
||||||
Log.severe("Texture mapping has invalid transparency setting - " + av[1] + " - line " + rdr.getLineNumber() + " of " + txtname);
|
Log.severe("Texture mapping has invalid transparency setting - " + av[1] + " - line " + lineNum + " of " + txtname);
|
||||||
}
|
}
|
||||||
/* For leaves, base on leaf transparency setting */
|
/* For leaves, base on leaf transparency setting */
|
||||||
if(trans == BlockTransparency.LEAVES) {
|
if(trans == BlockTransparency.LEAVES) {
|
||||||
|
@ -2215,49 +2187,42 @@ public class TexturePack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* If we have everything, build block */
|
/* If we have everything, build block */
|
||||||
if((blknames.size() > 0) && (srcname != null)) {
|
bsprslt = bsp.getMatchingStates();
|
||||||
|
|
||||||
|
if ((bsprslt.size() > 0) && (srcname != null)) {
|
||||||
DynmapBlockState srcblk = DynmapBlockState.getStateByNameAndIndex(srcname, srcmeta);
|
DynmapBlockState srcblk = DynmapBlockState.getStateByNameAndIndex(srcname, srcmeta);
|
||||||
HDBlockStateTextureMap map = null;
|
HDBlockStateTextureMap map = null;
|
||||||
if (srcblk != null) map = HDBlockStateTextureMap.getByBlockState(srcblk);
|
if (srcblk != null) map = HDBlockStateTextureMap.getByBlockState(srcblk);
|
||||||
if (map == null) {
|
if (map == null) {
|
||||||
Log.severe("Copy of texture mapping failed = line " + rdr.getLineNumber() + " of " + txtname);
|
Log.severe("Copy of texture mapping failed = line " + lineNum + " of " + txtname);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (String blkname : blknames) {
|
for (DynmapBlockState bblk : bsprslt.keySet()) {
|
||||||
DynmapBlockState dblk = DynmapBlockState.getBaseStateByName(blkname);
|
BitSet stateids = bsprslt.get(bblk);
|
||||||
if (stateids == null) {
|
for (int stateid = stateids.nextSetBit(0); stateid >= 0; stateid = stateids.nextSetBit(stateid+1)) {
|
||||||
for (int sid = 0; sid < dblk.getStateCount(); sid++) {
|
DynmapBlockState dblk2 = bblk.getState(stateid);
|
||||||
DynmapBlockState dblk2 = dblk.getState(sid);
|
HDBlockStateTextureMap.copyToStateIndex(dblk2, map, trans);
|
||||||
HDBlockStateTextureMap.copyToStateIndex(dblk2, map, trans);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (int stateid = stateids.nextSetBit(0); stateid >= 0; stateid = stateids.nextSetBit(stateid+1)) {
|
|
||||||
DynmapBlockState dblk2 = dblk.getState(stateid);
|
|
||||||
HDBlockStateTextureMap.copyToStateIndex(dblk2, map, trans);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.severe("Texture mapping copy missing required parameters = line " + rdr.getLineNumber() + " of " + txtname);
|
Log.severe("Texture mapping copy missing required parameters = line " + lineNum + " of " + txtname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(line.startsWith("addtotexturemap:")) {
|
else if (typeid.equals("addtotexturemap")) {
|
||||||
int srctxtid = -1;
|
int srctxtid = -1;
|
||||||
String mapid = null;
|
String mapid = null;
|
||||||
line = line.substring(line.indexOf(':') + 1);
|
|
||||||
String[] args = line.split(",");
|
String[] args = line.split(",");
|
||||||
for(String a : args) {
|
for (String a : args) {
|
||||||
String[] av = a.split("=");
|
String[] av = a.split("=");
|
||||||
if(av.length < 2) continue;
|
if(av.length < 2) continue;
|
||||||
else if(av[0].equals("txtid")) {
|
else if(av[0].equals("txtid")) {
|
||||||
if(filetoidx.containsKey(av[1]))
|
if(filetoidx.containsKey(av[1]))
|
||||||
srctxtid = filetoidx.get(av[1]);
|
srctxtid = filetoidx.get(av[1]);
|
||||||
else
|
else
|
||||||
Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname);
|
Log.severe("Format error - line " + lineNum + " of " + txtname);
|
||||||
}
|
}
|
||||||
else if(av[0].equals("mapid")) {
|
else if(av[0].equals("mapid")) {
|
||||||
mapid = av[1];
|
mapid = av[1];
|
||||||
|
@ -2276,14 +2241,14 @@ public class TexturePack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.severe("Missing mapid - line " + rdr.getLineNumber() + " of " + txtname);
|
Log.severe("Missing mapid - line " + lineNum + " of " + txtname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(line.startsWith("texturemap:")) {
|
else if (typeid.equals("texturemap")) {
|
||||||
List<String> blknames = new ArrayList<String>();
|
// Parse block states
|
||||||
BitSet stateids = null;
|
bsp.processLine(modname, line, lineNum, varvals);
|
||||||
|
|
||||||
String mapid = null;
|
String mapid = null;
|
||||||
line = line.substring(line.indexOf(':') + 1);
|
|
||||||
BlockTransparency trans = BlockTransparency.OPAQUE;
|
BlockTransparency trans = BlockTransparency.OPAQUE;
|
||||||
int colorMult = 0;
|
int colorMult = 0;
|
||||||
CustomColorMultiplier custColorMult = null;
|
CustomColorMultiplier custColorMult = null;
|
||||||
|
@ -2291,40 +2256,14 @@ public class TexturePack {
|
||||||
for(String a : args) {
|
for(String a : args) {
|
||||||
String[] av = a.split("=");
|
String[] av = a.split("=");
|
||||||
if(av.length < 2) continue;
|
if(av.length < 2) continue;
|
||||||
if(av[0].equals("id")) {
|
if(av[0].equals("mapid")) {
|
||||||
String id = getBlockName(modname, av[1]);
|
|
||||||
if (id != null) {
|
|
||||||
blknames.add(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(av[0].equals("mapid")) {
|
|
||||||
mapid = av[1];
|
mapid = av[1];
|
||||||
}
|
}
|
||||||
else if(av[0].equals("data")) {
|
|
||||||
if(av[1].equals("*")) {
|
|
||||||
stateids = null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (stateids == null) { stateids = new BitSet(); }
|
|
||||||
// See if range
|
|
||||||
if (av[1].indexOf('-') >= 0) {
|
|
||||||
String[] tok = av[1].split("-");
|
|
||||||
int v1 = getIntValue(varvals, tok[0]);
|
|
||||||
int v2 = getIntValue(varvals, tok[1]);
|
|
||||||
for (int v = v1; v <= v2; v++) {
|
|
||||||
stateids.set(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
stateids.set(getIntValue(varvals,av[1]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(av[0].equals("transparency")) {
|
else if(av[0].equals("transparency")) {
|
||||||
trans = BlockTransparency.valueOf(av[1]);
|
trans = BlockTransparency.valueOf(av[1]);
|
||||||
if(trans == null) {
|
if(trans == null) {
|
||||||
trans = BlockTransparency.OPAQUE;
|
trans = BlockTransparency.OPAQUE;
|
||||||
Log.severe("Texture mapping has invalid transparency setting - " + av[1] + " - line " + rdr.getLineNumber() + " of " + txtname);
|
Log.severe("Texture mapping has invalid transparency setting - " + av[1] + " - line " + lineNum + " of " + txtname);
|
||||||
}
|
}
|
||||||
/* For leaves, base on leaf transparency setting */
|
/* For leaves, base on leaf transparency setting */
|
||||||
if(trans == BlockTransparency.LEAVES) {
|
if(trans == BlockTransparency.LEAVES) {
|
||||||
|
@ -2340,23 +2279,23 @@ public class TexturePack {
|
||||||
else if(av[0].equals("custColorMult")) {
|
else if(av[0].equals("custColorMult")) {
|
||||||
try {
|
try {
|
||||||
Class<?> cls = Class.forName(av[1]);
|
Class<?> cls = Class.forName(av[1]);
|
||||||
custColorMult = (CustomColorMultiplier)cls.newInstance();
|
custColorMult = (CustomColorMultiplier)cls.getDeclaredConstructor().newInstance();
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
Log.severe("Error loading custom color multiplier - " + av[1] + ": " + x.getMessage());
|
Log.severe("Error loading custom color multiplier - " + av[1] + ": " + x.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* If we have everything, build texture map */
|
/* If we have everything, build texture map */
|
||||||
if((blknames.size() > 0) && (mapid != null)) {
|
bsprslt = bsp.getMatchingStates();
|
||||||
addTextureIndex(mapid, blknames, stateids, trans, colorMult, custColorMult, blockset);
|
if ((bsprslt.size() > 0) && (mapid != null)) {
|
||||||
|
addTextureIndex(mapid, bsprslt, trans, colorMult, custColorMult, blockset);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.severe("Texture map missing required parameters = line " + rdr.getLineNumber() + " of " + txtname);
|
Log.severe("Texture map missing required parameters = line " + lineNum + " of " + txtname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(line.startsWith("texturefile:") || line.startsWith("texture:")) {
|
else if (typeid.equals("texturefile") || typeid.equals("texture")) {
|
||||||
boolean istxt = line.startsWith("texture:");
|
boolean istxt = typeid.equals("texture");
|
||||||
line = line.substring(line.indexOf(':')+1);
|
|
||||||
String[] args = line.split(",");
|
String[] args = line.split(",");
|
||||||
int xdim = 16, ydim = 16;
|
int xdim = 16, ydim = 16;
|
||||||
String fname = null;
|
String fname = null;
|
||||||
|
@ -2391,7 +2330,7 @@ public class TexturePack {
|
||||||
else if(aval[0].equals("format")) {
|
else if(aval[0].equals("format")) {
|
||||||
fmt = TileFileFormat.valueOf(aval[1].toUpperCase());
|
fmt = TileFileFormat.valueOf(aval[1].toUpperCase());
|
||||||
if(fmt == null) {
|
if(fmt == null) {
|
||||||
Log.severe("Invalid format type " + aval[1] + " - line " + rdr.getLineNumber() + " of " + txtname);
|
Log.severe("Invalid format type " + aval[1] + " - line " + lineNum + " of " + txtname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2411,14 +2350,11 @@ public class TexturePack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname);
|
Log.severe("Format error - line " + lineNum + " of " + txtname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(line.startsWith("#") || line.startsWith(";")) {
|
else if (typeid.equals("enabled")) { /* Test if texture file is enabled */
|
||||||
}
|
|
||||||
else if(line.startsWith("enabled:")) { /* Test if texture file is enabled */
|
|
||||||
line = line.substring(8).trim();
|
|
||||||
if(line.startsWith("true")) { /* We're enabled? */
|
if(line.startsWith("true")) { /* We're enabled? */
|
||||||
/* Nothing to do - keep processing */
|
/* Nothing to do - keep processing */
|
||||||
}
|
}
|
||||||
|
@ -2433,13 +2369,12 @@ public class TexturePack {
|
||||||
Log.info(line + " textures enabled");
|
Log.info(line + " textures enabled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(line.startsWith("var:")) { /* Test if variable declaration */
|
else if (typeid.equals("var")) { /* Test if variable declaration */
|
||||||
line = line.substring(4).trim();
|
|
||||||
String args[] = line.split(",");
|
String args[] = line.split(",");
|
||||||
for(int i = 0; i < args.length; i++) {
|
for(int i = 0; i < args.length; i++) {
|
||||||
String[] v = args[i].split("=");
|
String[] v = args[i].split("=");
|
||||||
if(v.length < 2) {
|
if(v.length < 2) {
|
||||||
Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname);
|
Log.severe("Format error - line " + lineNum + " of " + txtname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -2447,16 +2382,16 @@ public class TexturePack {
|
||||||
int parmval = config.getInteger(v[0], val); /* Read value, with applied default */
|
int parmval = config.getInteger(v[0], val); /* Read value, with applied default */
|
||||||
varvals.put(v[0], parmval); /* And save value */
|
varvals.put(v[0], parmval); /* And save value */
|
||||||
} catch (NumberFormatException nfx) {
|
} catch (NumberFormatException nfx) {
|
||||||
Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname + ": " + nfx.getMessage());
|
Log.severe("Format error - line " + lineNum + " of " + txtname + ": " + nfx.getMessage());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(line.startsWith("cfgfile:")) { /* If config file */
|
else if (typeid.equals("cfgfile")) { /* If config file */
|
||||||
if (!mod_cfg_loaded) {
|
if (!mod_cfg_loaded) {
|
||||||
mod_cfg_needed = true;
|
mod_cfg_needed = true;
|
||||||
}
|
}
|
||||||
File cfgfile = new File(line.substring(8).trim());
|
File cfgfile = new File(line);
|
||||||
ForgeConfigFile cfg = new ForgeConfigFile(cfgfile);
|
ForgeConfigFile cfg = new ForgeConfigFile(cfgfile);
|
||||||
if(cfg.load()) {
|
if(cfg.load()) {
|
||||||
cfg.addBlockIDs(varvals);
|
cfg.addBlockIDs(varvals);
|
||||||
|
@ -2464,8 +2399,8 @@ public class TexturePack {
|
||||||
mod_cfg_loaded = true;
|
mod_cfg_loaded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(line.startsWith("modname:")) {
|
else if (typeid.equals("modname")) {
|
||||||
String[] names = line.substring(8).split(",");
|
String[] names = line.split(",");
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for(String n : names) {
|
for(String n : names) {
|
||||||
String[] ntok = n.split("[\\[\\]]");
|
String[] ntok = n.split("[\\[\\]]");
|
||||||
|
@ -2494,17 +2429,16 @@ public class TexturePack {
|
||||||
}
|
}
|
||||||
if(!found) return;
|
if(!found) return;
|
||||||
}
|
}
|
||||||
else if(line.startsWith("texturemod:")) {
|
else if (typeid.equals("texturemod")) {
|
||||||
texturemod = line.substring(line.indexOf(':')+1).trim();
|
texturemod = line;
|
||||||
}
|
}
|
||||||
else if(line.startsWith("texturepath:")) {
|
else if (typeid.equals("texturepath")) {
|
||||||
texturepath = line.substring(line.indexOf(':')+1).trim();
|
texturepath = line.trim();
|
||||||
if (texturepath.charAt(texturepath.length()-1) != '/') {
|
if (texturepath.charAt(texturepath.length()-1) != '/') {
|
||||||
texturepath += "/";
|
texturepath += "/";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(line.startsWith("biome:")) {
|
else if (typeid.equals("biome")) {
|
||||||
line = line.substring(6).trim();
|
|
||||||
String args[] = line.split(",");
|
String args[] = line.split(",");
|
||||||
int id = 0;
|
int id = 0;
|
||||||
int grasscolormult = -1;
|
int grasscolormult = -1;
|
||||||
|
@ -2515,7 +2449,7 @@ public class TexturePack {
|
||||||
for(int i = 0; i < args.length; i++) {
|
for(int i = 0; i < args.length; i++) {
|
||||||
String[] v = args[i].split("=");
|
String[] v = args[i].split("=");
|
||||||
if(v.length < 2) {
|
if(v.length < 2) {
|
||||||
Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname);
|
Log.severe("Format error - line " + lineNum + " of " + txtname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(v[0].equals("id")) {
|
if(v[0].equals("id")) {
|
||||||
|
@ -2540,7 +2474,7 @@ public class TexturePack {
|
||||||
if(id > 0) {
|
if(id > 0) {
|
||||||
BiomeMap b = BiomeMap.byBiomeID(id); /* Find biome */
|
BiomeMap b = BiomeMap.byBiomeID(id); /* Find biome */
|
||||||
if(b == null) {
|
if(b == null) {
|
||||||
Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname + ": " + id);
|
Log.severe("Format error - line " + lineNum + " of " + txtname + ": " + id);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(foliagecolormult != -1)
|
if(foliagecolormult != -1)
|
||||||
|
@ -2556,14 +2490,12 @@ public class TexturePack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(line.startsWith("version:")) {
|
else if (typeid.equals("version")) {
|
||||||
line = line.substring(line.indexOf(':')+1);
|
|
||||||
if (!HDBlockModels.checkVersionRange(mcver, line)) {
|
if (!HDBlockModels.checkVersionRange(mcver, line)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(line.startsWith("noterrainpng:")) {
|
else if (typeid.equals("noterrainpng")) {
|
||||||
line = line.substring(line.indexOf(':')+1);
|
|
||||||
if (line.startsWith("true")) {
|
if (line.startsWith("true")) {
|
||||||
terrain_ok = false;
|
terrain_ok = false;
|
||||||
}
|
}
|
||||||
|
@ -2626,7 +2558,11 @@ public class TexturePack {
|
||||||
else {
|
else {
|
||||||
faceindex = laststep.ordinal();
|
faceindex = laststep.ordinal();
|
||||||
}
|
}
|
||||||
textid = map.faces[faceindex];
|
try {
|
||||||
|
textid = map.faces[faceindex];
|
||||||
|
} catch (ArrayIndexOutOfBoundsException aioob) {
|
||||||
|
textid = -1;
|
||||||
|
}
|
||||||
if (ctm != null) {
|
if (ctm != null) {
|
||||||
int mod = 0;
|
int mod = 0;
|
||||||
if(textid >= COLORMOD_MULT_INTERNAL) {
|
if(textid >= COLORMOD_MULT_INTERNAL) {
|
||||||
|
|
|
@ -202,50 +202,52 @@ public class TexturePackHDShader implements HDShader {
|
||||||
|
|
||||||
if (c.getAlpha() > 0) {
|
if (c.getAlpha() > 0) {
|
||||||
/* Scale brightness depending upon face */
|
/* Scale brightness depending upon face */
|
||||||
if (this.lightingTable != null) {
|
if (ps.getShade()) {
|
||||||
switch(ps.getLastBlockStep()) {
|
if (this.lightingTable != null) {
|
||||||
case X_MINUS:
|
switch (ps.getLastBlockStep()) {
|
||||||
case X_PLUS:
|
case X_MINUS:
|
||||||
/* 60% brightness */
|
case X_PLUS:
|
||||||
c.blendColor(0xFF999999);
|
/* 60% brightness */
|
||||||
break;
|
c.blendColor(0xFF999999);
|
||||||
case Y_MINUS:
|
break;
|
||||||
// 95% for even
|
case Y_MINUS:
|
||||||
if((mapiter.getY() & 0x01) == 0) {
|
// 95% for even
|
||||||
c.blendColor(0xFFF3F3F3);
|
if((mapiter.getY() & 0x01) == 0) {
|
||||||
}
|
c.blendColor(0xFFF3F3F3);
|
||||||
break;
|
}
|
||||||
case Y_PLUS:
|
break;
|
||||||
/* 50%*/
|
case Y_PLUS:
|
||||||
c.blendColor(0xFF808080);
|
/* 50%*/
|
||||||
break;
|
c.blendColor(0xFF808080);
|
||||||
case Z_MINUS:
|
break;
|
||||||
case Z_PLUS:
|
case Z_MINUS:
|
||||||
default:
|
case Z_PLUS:
|
||||||
/* 80%*/
|
default:
|
||||||
c.blendColor(0xFFCDCDCD);
|
/* 80%*/
|
||||||
break;
|
c.blendColor(0xFFCDCDCD);
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
switch(ps.getLastBlockStep()) {
|
else {
|
||||||
case X_MINUS:
|
switch (ps.getLastBlockStep()) {
|
||||||
case X_PLUS:
|
case X_MINUS:
|
||||||
/* 60% brightness */
|
case X_PLUS:
|
||||||
c.blendColor(0xFFA0A0A0);
|
/* 60% brightness */
|
||||||
break;
|
c.blendColor(0xFFA0A0A0);
|
||||||
case Y_MINUS:
|
break;
|
||||||
case Y_PLUS:
|
case Y_MINUS:
|
||||||
/* 85% brightness for even, 90% for even*/
|
case Y_PLUS:
|
||||||
if((mapiter.getY() & 0x01) == 0)
|
/* 85% brightness for even, 90% for even*/
|
||||||
c.blendColor(0xFFD9D9D9);
|
if((mapiter.getY() & 0x01) == 0)
|
||||||
else
|
c.blendColor(0xFFD9D9D9);
|
||||||
c.blendColor(0xFFE6E6E6);
|
else
|
||||||
break;
|
c.blendColor(0xFFE6E6E6);
|
||||||
default:
|
break;
|
||||||
break;
|
default:
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Handle light level, if needed */
|
/* Handle light level, if needed */
|
||||||
lighting.applyLighting(ps, this, c, tmpcolor);
|
lighting.applyLighting(ps, this, c, tmpcolor);
|
||||||
/* If grid scale, add it */
|
/* If grid scale, add it */
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.dynmap.hdmap;
|
package org.dynmap.hdmap;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -61,13 +62,13 @@ public class TexturePackLoader {
|
||||||
if (zf != null) {
|
if (zf != null) {
|
||||||
ZipEntry ze = zf.getEntry(rname);
|
ZipEntry ze = zf.getEntry(rname);
|
||||||
if ((ze != null) && (!ze.isDirectory())) {
|
if ((ze != null) && (!ze.isDirectory())) {
|
||||||
return zf.getInputStream(ze);
|
return new BufferedInputStream(zf.getInputStream(ze));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tpdir != null) {
|
else if (tpdir != null) {
|
||||||
File f = new File(tpdir, rname);
|
File f = new File(tpdir, rname);
|
||||||
if (f.isFile() && f.canRead()) {
|
if (f.isFile() && f.canRead()) {
|
||||||
return new FileInputStream(f);
|
return new BufferedInputStream(new FileInputStream(f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException iox) {
|
} catch (IOException iox) {
|
||||||
|
@ -75,7 +76,7 @@ public class TexturePackLoader {
|
||||||
// Fall through - load as resource from mod, if possible, or from jar
|
// Fall through - load as resource from mod, if possible, or from jar
|
||||||
InputStream is = dsi.openResource(modname, rname);
|
InputStream is = dsi.openResource(modname, rname);
|
||||||
if (is != null) {
|
if (is != null) {
|
||||||
return is;
|
return new BufferedInputStream(is);
|
||||||
}
|
}
|
||||||
if (modname != null) {
|
if (modname != null) {
|
||||||
ModSource ms = src_by_mod.get(modname);
|
ModSource ms = src_by_mod.get(modname);
|
||||||
|
@ -118,7 +119,7 @@ public class TexturePackLoader {
|
||||||
Log.warning("Resource " + rname + " for mod " + modname + " not found");
|
Log.warning("Resource " + rname + " for mod " + modname + " not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
return is;
|
return (is != null) ? new BufferedInputStream(is) : null;
|
||||||
}
|
}
|
||||||
public void close() {
|
public void close() {
|
||||||
if(zf != null) {
|
if(zf != null) {
|
||||||
|
|
|
@ -1,14 +1,7 @@
|
||||||
package org.dynmap.hdmap.renderer;
|
package org.dynmap.hdmap.renderer;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.BitSet;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.dynmap.renderer.CustomRenderer;
|
|
||||||
import org.dynmap.renderer.DynmapBlockState;
|
|
||||||
import org.dynmap.renderer.MapDataContext;
|
import org.dynmap.renderer.MapDataContext;
|
||||||
import org.dynmap.renderer.RenderPatch;
|
import org.dynmap.renderer.RenderPatch;
|
||||||
import org.dynmap.renderer.RenderPatchFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple renderer for handling single and double chests (1.13+)
|
* Simple renderer for handling single and double chests (1.13+)
|
||||||
|
|
|
@ -5,7 +5,6 @@ import java.util.BitSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.dynmap.Log;
|
|
||||||
import org.dynmap.renderer.CustomRenderer;
|
import org.dynmap.renderer.CustomRenderer;
|
||||||
import org.dynmap.renderer.MapDataContext;
|
import org.dynmap.renderer.MapDataContext;
|
||||||
import org.dynmap.renderer.RenderPatch;
|
import org.dynmap.renderer.RenderPatch;
|
||||||
|
|
|
@ -9,7 +9,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
import org.dynmap.Client;
|
import org.dynmap.Client;
|
||||||
import org.dynmap.ConfigurationNode;
|
import org.dynmap.ConfigurationNode;
|
||||||
import org.dynmap.DynmapWorld;
|
import org.dynmap.DynmapWorld;
|
||||||
import org.dynmap.Log;
|
|
||||||
import org.dynmap.MapManager;
|
import org.dynmap.MapManager;
|
||||||
import org.dynmap.hdmap.HDPerspective;
|
import org.dynmap.hdmap.HDPerspective;
|
||||||
import org.dynmap.markers.AreaMarker;
|
import org.dynmap.markers.AreaMarker;
|
||||||
|
@ -73,9 +72,9 @@ class AreaMarkerImpl implements AreaMarker, EnterExitMarker {
|
||||||
AreaMarkerImpl(String id, String lbl, boolean markup, String world, double x[], double z[], boolean persistent, MarkerSetImpl set) {
|
AreaMarkerImpl(String id, String lbl, boolean markup, String world, double x[], double z[], boolean persistent, MarkerSetImpl set) {
|
||||||
markerid = id;
|
markerid = id;
|
||||||
if(lbl != null)
|
if(lbl != null)
|
||||||
label = markup ? lbl : Client.encodeForHTML(lbl);
|
label = markup ? Client.sanitizeHTML(lbl) : Client.encodeForHTML(lbl);
|
||||||
else
|
else
|
||||||
label = markup ? id : Client.encodeForHTML(id);
|
label = markup ? Client.sanitizeHTML(id) : Client.encodeForHTML(id);
|
||||||
this.markup = markup;
|
this.markup = markup;
|
||||||
this.corners = new ArrayList<Coord>();
|
this.corners = new ArrayList<Coord>();
|
||||||
for(int i = 0; i < x.length; i++) {
|
for(int i = 0; i < x.length; i++) {
|
||||||
|
@ -119,9 +118,10 @@ class AreaMarkerImpl implements AreaMarker, EnterExitMarker {
|
||||||
* Load marker from configuration node
|
* Load marker from configuration node
|
||||||
* @param node - configuration node
|
* @param node - configuration node
|
||||||
*/
|
*/
|
||||||
boolean loadPersistentData(ConfigurationNode node) {
|
boolean loadPersistentData(ConfigurationNode node, boolean isSafe) {
|
||||||
markup = node.getBoolean("markup", false);
|
markup = node.getBoolean("markup", false);
|
||||||
label = MarkerAPIImpl.escapeForHTMLIfNeeded(node.getString("label", markerid), markup);
|
label = MarkerAPIImpl.escapeForHTMLIfNeeded(node.getString("label", markerid), markup);
|
||||||
|
if (!isSafe) label = Client.sanitizeHTML(label);
|
||||||
ytop = node.getDouble("ytop", 64.0);
|
ytop = node.getDouble("ytop", 64.0);
|
||||||
ybottom = node.getDouble("ybottom", 64.0);
|
ybottom = node.getDouble("ybottom", 64.0);
|
||||||
List<Double> xx = node.getList("x");
|
List<Double> xx = node.getList("x");
|
||||||
|
@ -134,6 +134,7 @@ class AreaMarkerImpl implements AreaMarker, EnterExitMarker {
|
||||||
world = node.getString("world", "world");
|
world = node.getString("world", "world");
|
||||||
normalized_world = DynmapWorld.normalizeWorldName(world);
|
normalized_world = DynmapWorld.normalizeWorldName(world);
|
||||||
desc = node.getString("desc", null);
|
desc = node.getString("desc", null);
|
||||||
|
if (!isSafe) desc = Client.sanitizeHTML(desc);
|
||||||
lineweight = node.getInteger("strokeWeight", -1);
|
lineweight = node.getInteger("strokeWeight", -1);
|
||||||
if(lineweight == -1) { /* Handle typo-saved value */
|
if(lineweight == -1) { /* Handle typo-saved value */
|
||||||
lineweight = node.getInteger("stokeWeight", 3);
|
lineweight = node.getInteger("stokeWeight", 3);
|
||||||
|
@ -216,12 +217,7 @@ class AreaMarkerImpl implements AreaMarker, EnterExitMarker {
|
||||||
@Override
|
@Override
|
||||||
public void setLabel(String lbl, boolean markup) {
|
public void setLabel(String lbl, boolean markup) {
|
||||||
if(markerset == null) return;
|
if(markerset == null) return;
|
||||||
if (markup) {
|
label = markup ? Client.sanitizeHTML(lbl) : Client.encodeForHTML(lbl);
|
||||||
label = lbl;
|
|
||||||
}
|
|
||||||
else { // If not markup, escape any HTML-active characters (<>&"')
|
|
||||||
label = Client.encodeForHTML(lbl);
|
|
||||||
}
|
|
||||||
this.markup = markup;
|
this.markup = markup;
|
||||||
MarkerAPIImpl.areaMarkerUpdated(this, MarkerUpdate.UPDATED);
|
MarkerAPIImpl.areaMarkerUpdated(this, MarkerUpdate.UPDATED);
|
||||||
if(ispersistent)
|
if(ispersistent)
|
||||||
|
@ -299,6 +295,7 @@ class AreaMarkerImpl implements AreaMarker, EnterExitMarker {
|
||||||
@Override
|
@Override
|
||||||
public void setDescription(String desc) {
|
public void setDescription(String desc) {
|
||||||
if(markerset == null) return;
|
if(markerset == null) return;
|
||||||
|
desc = Client.sanitizeHTML(desc);
|
||||||
if((this.desc == null) || (this.desc.equals(desc) == false)) {
|
if((this.desc == null) || (this.desc.equals(desc) == false)) {
|
||||||
this.desc = desc;
|
this.desc = desc;
|
||||||
MarkerAPIImpl.areaMarkerUpdated(this, MarkerUpdate.UPDATED);
|
MarkerAPIImpl.areaMarkerUpdated(this, MarkerUpdate.UPDATED);
|
||||||
|
|
|
@ -11,7 +11,6 @@ import org.dynmap.hdmap.HDPerspective;
|
||||||
import org.dynmap.markers.CircleMarker;
|
import org.dynmap.markers.CircleMarker;
|
||||||
import org.dynmap.markers.EnterExitMarker;
|
import org.dynmap.markers.EnterExitMarker;
|
||||||
import org.dynmap.markers.MarkerSet;
|
import org.dynmap.markers.MarkerSet;
|
||||||
import org.dynmap.markers.EnterExitMarker.EnterExitText;
|
|
||||||
import org.dynmap.markers.impl.MarkerAPIImpl.MarkerUpdate;
|
import org.dynmap.markers.impl.MarkerAPIImpl.MarkerUpdate;
|
||||||
import org.dynmap.utils.Vector3D;
|
import org.dynmap.utils.Vector3D;
|
||||||
|
|
||||||
|
@ -68,6 +67,7 @@ class CircleMarkerImpl implements CircleMarker, EnterExitMarker {
|
||||||
label = markup ? lbl : Client.encodeColorInHTML(lbl);
|
label = markup ? lbl : Client.encodeColorInHTML(lbl);
|
||||||
else
|
else
|
||||||
label = markup ? id : Client.encodeColorInHTML(id);
|
label = markup ? id : Client.encodeColorInHTML(id);
|
||||||
|
label = Client.sanitizeHTML(label);
|
||||||
this.markup = markup;
|
this.markup = markup;
|
||||||
this.x = x; this.y = y; this.z = z;
|
this.x = x; this.y = y; this.z = z;
|
||||||
this.xr = xr; this.zr = zr;
|
this.xr = xr; this.zr = zr;
|
||||||
|
@ -87,7 +87,7 @@ class CircleMarkerImpl implements CircleMarker, EnterExitMarker {
|
||||||
CircleMarkerImpl(String id, MarkerSetImpl set) {
|
CircleMarkerImpl(String id, MarkerSetImpl set) {
|
||||||
markerid = id;
|
markerid = id;
|
||||||
markerset = set;
|
markerset = set;
|
||||||
label = Client.encodeForHTML(id);
|
label = Client.sanitizeHTML(Client.encodeForHTML(id));
|
||||||
markup = false;
|
markup = false;
|
||||||
desc = null;
|
desc = null;
|
||||||
world = normalized_world = "world";
|
world = normalized_world = "world";
|
||||||
|
@ -101,9 +101,10 @@ class CircleMarkerImpl implements CircleMarker, EnterExitMarker {
|
||||||
* Load marker from configuration node
|
* Load marker from configuration node
|
||||||
* @param node - configuration node
|
* @param node - configuration node
|
||||||
*/
|
*/
|
||||||
boolean loadPersistentData(ConfigurationNode node) {
|
boolean loadPersistentData(ConfigurationNode node, boolean isSafe) {
|
||||||
markup = node.getBoolean("markup", false);
|
markup = node.getBoolean("markup", false);
|
||||||
label = MarkerAPIImpl.escapeForHTMLIfNeeded(node.getString("label", markerid), markup);
|
label = MarkerAPIImpl.escapeForHTMLIfNeeded(node.getString("label", markerid), markup);
|
||||||
|
if (!isSafe) label = Client.sanitizeHTML(label);
|
||||||
world = node.getString("world", "world");
|
world = node.getString("world", "world");
|
||||||
normalized_world = DynmapWorld.normalizeWorldName(world);
|
normalized_world = DynmapWorld.normalizeWorldName(world);
|
||||||
x = node.getDouble("x", 0);
|
x = node.getDouble("x", 0);
|
||||||
|
@ -112,6 +113,7 @@ class CircleMarkerImpl implements CircleMarker, EnterExitMarker {
|
||||||
xr = node.getDouble("xr", 0);
|
xr = node.getDouble("xr", 0);
|
||||||
zr = node.getDouble("zr", 0);
|
zr = node.getDouble("zr", 0);
|
||||||
desc = node.getString("desc", null);
|
desc = node.getString("desc", null);
|
||||||
|
if (!isSafe) desc = Client.sanitizeHTML(desc);
|
||||||
lineweight = node.getInteger("strokeWeight", -1);
|
lineweight = node.getInteger("strokeWeight", -1);
|
||||||
if(lineweight == -1) { /* Handle typo-saved value */
|
if(lineweight == -1) { /* Handle typo-saved value */
|
||||||
lineweight = node.getInteger("stokeWeight", 3);
|
lineweight = node.getInteger("stokeWeight", 3);
|
||||||
|
@ -193,6 +195,7 @@ class CircleMarkerImpl implements CircleMarker, EnterExitMarker {
|
||||||
@Override
|
@Override
|
||||||
public void setLabel(String lbl, boolean markup) {
|
public void setLabel(String lbl, boolean markup) {
|
||||||
label = markup ? lbl : Client.encodeForHTML(lbl);
|
label = markup ? lbl : Client.encodeForHTML(lbl);
|
||||||
|
label = Client.sanitizeHTML(label);
|
||||||
this.markup = markup;
|
this.markup = markup;
|
||||||
MarkerAPIImpl.circleMarkerUpdated(this, MarkerUpdate.UPDATED);
|
MarkerAPIImpl.circleMarkerUpdated(this, MarkerUpdate.UPDATED);
|
||||||
if(ispersistent)
|
if(ispersistent)
|
||||||
|
@ -263,6 +266,7 @@ class CircleMarkerImpl implements CircleMarker, EnterExitMarker {
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void setDescription(String desc) {
|
public void setDescription(String desc) {
|
||||||
|
desc = Client.sanitizeHTML(desc);
|
||||||
if((this.desc == null) || (this.desc.equals(desc) == false)) {
|
if((this.desc == null) || (this.desc.equals(desc) == false)) {
|
||||||
this.desc = desc;
|
this.desc = desc;
|
||||||
MarkerAPIImpl.circleMarkerUpdated(this, MarkerUpdate.UPDATED);
|
MarkerAPIImpl.circleMarkerUpdated(this, MarkerUpdate.UPDATED);
|
||||||
|
|
|
@ -102,14 +102,14 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
|
|
||||||
public MarkerUpdated(Marker m, boolean deleted) {
|
public MarkerUpdated(Marker m, boolean deleted) {
|
||||||
this.id = m.getMarkerID();
|
this.id = m.getMarkerID();
|
||||||
this.label = Client.sanitizeHTML(m.getLabel());
|
this.label = m.getLabel();
|
||||||
this.x = m.getX();
|
this.x = m.getX();
|
||||||
this.y = m.getY();
|
this.y = m.getY();
|
||||||
this.z = m.getZ();
|
this.z = m.getZ();
|
||||||
this.set = m.getMarkerSet().getMarkerSetID();
|
this.set = m.getMarkerSet().getMarkerSetID();
|
||||||
this.icon = m.getMarkerIcon().getMarkerIconID();
|
this.icon = m.getMarkerIcon().getMarkerIconID();
|
||||||
this.markup = true; // We are markup format all the time now
|
this.markup = true; // We are markup format all the time now
|
||||||
this.desc = Client.sanitizeHTML(m.getDescription());
|
this.desc = m.getDescription();
|
||||||
this.dim = m.getMarkerIcon().getMarkerIconSize().getSize();
|
this.dim = m.getMarkerIcon().getMarkerIconSize().getSize();
|
||||||
this.minzoom = m.getMinZoom();
|
this.minzoom = m.getMinZoom();
|
||||||
this.maxzoom = m.getMaxZoom();
|
this.maxzoom = m.getMaxZoom();
|
||||||
|
@ -153,7 +153,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
|
|
||||||
public AreaMarkerUpdated(AreaMarker m, boolean deleted) {
|
public AreaMarkerUpdated(AreaMarker m, boolean deleted) {
|
||||||
this.id = m.getMarkerID();
|
this.id = m.getMarkerID();
|
||||||
this.label = Client.sanitizeHTML(m.getLabel());
|
this.label = m.getLabel();
|
||||||
this.ytop = m.getTopY();
|
this.ytop = m.getTopY();
|
||||||
this.ybottom = m.getBottomY();
|
this.ybottom = m.getBottomY();
|
||||||
int cnt = m.getCornerCount();
|
int cnt = m.getCornerCount();
|
||||||
|
@ -168,7 +168,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
opacity = m.getLineOpacity();
|
opacity = m.getLineOpacity();
|
||||||
fillcolor = String.format("#%06X", m.getFillColor());
|
fillcolor = String.format("#%06X", m.getFillColor());
|
||||||
fillopacity = m.getFillOpacity();
|
fillopacity = m.getFillOpacity();
|
||||||
desc = Client.sanitizeHTML(m.getDescription());
|
desc = m.getDescription();
|
||||||
this.minzoom = m.getMinZoom();
|
this.minzoom = m.getMinZoom();
|
||||||
this.maxzoom = m.getMaxZoom();
|
this.maxzoom = m.getMaxZoom();
|
||||||
this.markup = true; // We are markup format all the time now
|
this.markup = true; // We are markup format all the time now
|
||||||
|
@ -211,7 +211,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
|
|
||||||
public PolyLineMarkerUpdated(PolyLineMarker m, boolean deleted) {
|
public PolyLineMarkerUpdated(PolyLineMarker m, boolean deleted) {
|
||||||
this.id = m.getMarkerID();
|
this.id = m.getMarkerID();
|
||||||
this.label = Client.sanitizeHTML(m.getLabel());
|
this.label = m.getLabel();
|
||||||
this.markup = true; // We are markup format all the time now
|
this.markup = true; // We are markup format all the time now
|
||||||
int cnt = m.getCornerCount();
|
int cnt = m.getCornerCount();
|
||||||
x = new double[cnt];
|
x = new double[cnt];
|
||||||
|
@ -225,7 +225,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
color = String.format("#%06X", m.getLineColor());
|
color = String.format("#%06X", m.getLineColor());
|
||||||
weight = m.getLineWeight();
|
weight = m.getLineWeight();
|
||||||
opacity = m.getLineOpacity();
|
opacity = m.getLineOpacity();
|
||||||
desc = Client.sanitizeHTML(m.getDescription());
|
desc = m.getDescription();
|
||||||
this.minzoom = m.getMinZoom();
|
this.minzoom = m.getMinZoom();
|
||||||
this.maxzoom = m.getMaxZoom();
|
this.maxzoom = m.getMaxZoom();
|
||||||
|
|
||||||
|
@ -271,7 +271,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
|
|
||||||
public CircleMarkerUpdated(CircleMarker m, boolean deleted) {
|
public CircleMarkerUpdated(CircleMarker m, boolean deleted) {
|
||||||
this.id = m.getMarkerID();
|
this.id = m.getMarkerID();
|
||||||
this.label = Client.sanitizeHTML(m.getLabel());
|
this.label = m.getLabel();
|
||||||
this.x = m.getCenterX();
|
this.x = m.getCenterX();
|
||||||
this.y = m.getCenterY();
|
this.y = m.getCenterY();
|
||||||
this.z = m.getCenterZ();
|
this.z = m.getCenterZ();
|
||||||
|
@ -283,7 +283,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
opacity = m.getLineOpacity();
|
opacity = m.getLineOpacity();
|
||||||
fillcolor = String.format("#%06X", m.getFillColor());
|
fillcolor = String.format("#%06X", m.getFillColor());
|
||||||
fillopacity = m.getFillOpacity();
|
fillopacity = m.getFillOpacity();
|
||||||
desc = Client.sanitizeHTML(m.getDescription());
|
desc = m.getDescription();
|
||||||
this.minzoom = m.getMinZoom();
|
this.minzoom = m.getMinZoom();
|
||||||
this.maxzoom = m.getMaxZoom();
|
this.maxzoom = m.getMaxZoom();
|
||||||
|
|
||||||
|
@ -342,7 +342,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean stop = false;
|
private boolean stop = false;
|
||||||
private Set<String> dirty_worlds = new HashSet<String>();
|
private ConcurrentHashMap<String, String> dirty_worlds = new ConcurrentHashMap<String, String>();
|
||||||
private boolean dirty_markers = false;
|
private boolean dirty_markers = false;
|
||||||
|
|
||||||
private class DoFileWrites implements Runnable {
|
private class DoFileWrites implements Runnable {
|
||||||
|
@ -350,18 +350,19 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
if(stop)
|
if(stop)
|
||||||
return;
|
return;
|
||||||
lock.readLock().lock();
|
lock.readLock().lock();
|
||||||
|
Set<String> dirty = new HashSet<String>(dirty_worlds.keySet());
|
||||||
|
dirty_worlds.clear();
|
||||||
try {
|
try {
|
||||||
/* Write markers first - drives JSON updates too */
|
/* Write markers first - drives JSON updates too */
|
||||||
if(dirty_markers) {
|
if (dirty_markers) {
|
||||||
doSaveMarkers();
|
doSaveMarkers();
|
||||||
dirty_markers = false;
|
dirty_markers = false;
|
||||||
}
|
}
|
||||||
/* Process any dirty worlds */
|
/* Process any dirty worlds */
|
||||||
if(!dirty_worlds.isEmpty()) {
|
if (!dirty.isEmpty()) {
|
||||||
for(String world : dirty_worlds) {
|
for(String world : dirty) {
|
||||||
writeMarkersFile(world);
|
writeMarkersFile(world);
|
||||||
}
|
}
|
||||||
dirty_worlds.clear();
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
lock.readLock().unlock();
|
lock.readLock().unlock();
|
||||||
|
@ -821,6 +822,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
final ConfigurationNode conf = new ConfigurationNode(api.markerpersist); /* Make configuration object */
|
final ConfigurationNode conf = new ConfigurationNode(api.markerpersist); /* Make configuration object */
|
||||||
/* First, save icon definitions */
|
/* First, save icon definitions */
|
||||||
HashMap<String, Object> icons = new HashMap<String,Object>();
|
HashMap<String, Object> icons = new HashMap<String,Object>();
|
||||||
|
conf.put("isSafe", true); // Mark as safe (sanitized)
|
||||||
for(String id : api.markericons.keySet()) {
|
for(String id : api.markericons.keySet()) {
|
||||||
MarkerIconImpl ico = api.markericons.get(id);
|
MarkerIconImpl ico = api.markericons.get(id);
|
||||||
Map<String,Object> dat = ico.getPersistentData();
|
Map<String,Object> dat = ico.getPersistentData();
|
||||||
|
@ -872,7 +874,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
private void freshenMarkerFiles() {
|
private void freshenMarkerFiles() {
|
||||||
if(MapManager.mapman != null) {
|
if(MapManager.mapman != null) {
|
||||||
for(DynmapWorld w : MapManager.mapman.worlds) {
|
for(DynmapWorld w : MapManager.mapman.worlds) {
|
||||||
dirty_worlds.add(w.getName());
|
dirty_worlds.put(w.getName(),"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -884,13 +886,14 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
ConfigurationNode conf = new ConfigurationNode(api.markerpersist); /* Make configuration object */
|
ConfigurationNode conf = new ConfigurationNode(api.markerpersist); /* Make configuration object */
|
||||||
conf.load(); /* Load persistence */
|
conf.load(); /* Load persistence */
|
||||||
lock.writeLock().lock();
|
lock.writeLock().lock();
|
||||||
|
boolean isSafe = conf.getBoolean("isSafe", false);
|
||||||
try {
|
try {
|
||||||
/* Get icons */
|
/* Get icons */
|
||||||
ConfigurationNode icons = conf.getNode("icons");
|
ConfigurationNode icons = conf.getNode("icons");
|
||||||
if(icons == null) return false;
|
if(icons == null) return false;
|
||||||
for(String id : icons.keySet()) {
|
for(String id : icons.keySet()) {
|
||||||
MarkerIconImpl ico = new MarkerIconImpl(id);
|
MarkerIconImpl ico = new MarkerIconImpl(id);
|
||||||
if(ico.loadPersistentData(icons.getNode(id))) {
|
if(ico.loadPersistentData(icons.getNode(id), isSafe)) {
|
||||||
markericons.put(id, ico);
|
markericons.put(id, ico);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -899,7 +902,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
if(sets != null) {
|
if(sets != null) {
|
||||||
for(String id: sets.keySet()) {
|
for(String id: sets.keySet()) {
|
||||||
MarkerSetImpl set = new MarkerSetImpl(id);
|
MarkerSetImpl set = new MarkerSetImpl(id);
|
||||||
if(set.loadPersistentData(sets.getNode(id))) {
|
if(set.loadPersistentData(sets.getNode(id), isSafe)) {
|
||||||
markersets.put(id, set);
|
markersets.put(id, set);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -909,7 +912,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
if(psets != null) {
|
if(psets != null) {
|
||||||
for(String id: psets.keySet()) {
|
for(String id: psets.keySet()) {
|
||||||
PlayerSetImpl set = new PlayerSetImpl(id);
|
PlayerSetImpl set = new PlayerSetImpl(id);
|
||||||
if(set.loadPersistentData(sets.getNode(id))) {
|
if(set.loadPersistentData(sets.getNode(id), isSafe)) {
|
||||||
playersets.put(id, set);
|
playersets.put(id, set);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -931,7 +934,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
static void markerUpdated(MarkerImpl marker, MarkerUpdate update) {
|
static void markerUpdated(MarkerImpl marker, MarkerUpdate update) {
|
||||||
/* Freshen marker file for the world for this marker */
|
/* Freshen marker file for the world for this marker */
|
||||||
if(api != null)
|
if(api != null)
|
||||||
api.dirty_worlds.add(marker.getNormalizedWorld());
|
api.dirty_worlds.put(marker.getNormalizedWorld(),"");
|
||||||
/* Enqueue client update */
|
/* Enqueue client update */
|
||||||
if(MapManager.mapman != null)
|
if(MapManager.mapman != null)
|
||||||
MapManager.mapman.pushUpdate(marker.getNormalizedWorld(), new MarkerUpdated(marker, update == MarkerUpdate.DELETED));
|
MapManager.mapman.pushUpdate(marker.getNormalizedWorld(), new MarkerUpdated(marker, update == MarkerUpdate.DELETED));
|
||||||
|
@ -944,7 +947,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
static void areaMarkerUpdated(AreaMarkerImpl marker, MarkerUpdate update) {
|
static void areaMarkerUpdated(AreaMarkerImpl marker, MarkerUpdate update) {
|
||||||
/* Freshen marker file for the world for this marker */
|
/* Freshen marker file for the world for this marker */
|
||||||
if(api != null)
|
if(api != null)
|
||||||
api.dirty_worlds.add(marker.getNormalizedWorld());
|
api.dirty_worlds.put(marker.getNormalizedWorld(),"");
|
||||||
/* Enqueue client update */
|
/* Enqueue client update */
|
||||||
if(MapManager.mapman != null)
|
if(MapManager.mapman != null)
|
||||||
MapManager.mapman.pushUpdate(marker.getNormalizedWorld(), new AreaMarkerUpdated(marker, update == MarkerUpdate.DELETED));
|
MapManager.mapman.pushUpdate(marker.getNormalizedWorld(), new AreaMarkerUpdated(marker, update == MarkerUpdate.DELETED));
|
||||||
|
@ -957,7 +960,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
static void polyLineMarkerUpdated(PolyLineMarkerImpl marker, MarkerUpdate update) {
|
static void polyLineMarkerUpdated(PolyLineMarkerImpl marker, MarkerUpdate update) {
|
||||||
/* Freshen marker file for the world for this marker */
|
/* Freshen marker file for the world for this marker */
|
||||||
if(api != null)
|
if(api != null)
|
||||||
api.dirty_worlds.add(marker.getNormalizedWorld());
|
api.dirty_worlds.put(marker.getNormalizedWorld(),"");
|
||||||
/* Enqueue client update */
|
/* Enqueue client update */
|
||||||
if(MapManager.mapman != null)
|
if(MapManager.mapman != null)
|
||||||
MapManager.mapman.pushUpdate(marker.getNormalizedWorld(), new PolyLineMarkerUpdated(marker, update == MarkerUpdate.DELETED));
|
MapManager.mapman.pushUpdate(marker.getNormalizedWorld(), new PolyLineMarkerUpdated(marker, update == MarkerUpdate.DELETED));
|
||||||
|
@ -970,7 +973,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
static void circleMarkerUpdated(CircleMarkerImpl marker, MarkerUpdate update) {
|
static void circleMarkerUpdated(CircleMarkerImpl marker, MarkerUpdate update) {
|
||||||
/* Freshen marker file for the world for this marker */
|
/* Freshen marker file for the world for this marker */
|
||||||
if(api != null)
|
if(api != null)
|
||||||
api.dirty_worlds.add(marker.getNormalizedWorld());
|
api.dirty_worlds.put(marker.getNormalizedWorld(),"");
|
||||||
/* Enqueue client update */
|
/* Enqueue client update */
|
||||||
if(MapManager.mapman != null)
|
if(MapManager.mapman != null)
|
||||||
MapManager.mapman.pushUpdate(marker.getNormalizedWorld(), new CircleMarkerUpdated(marker, update == MarkerUpdate.DELETED));
|
MapManager.mapman.pushUpdate(marker.getNormalizedWorld(), new CircleMarkerUpdated(marker, update == MarkerUpdate.DELETED));
|
||||||
|
@ -2173,6 +2176,10 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
sender.sendMessage("file:\"filename\" required");
|
sender.sendMessage("file:\"filename\" required");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (!validateImportFile(file)) {
|
||||||
|
sender.sendMessage("Error: '" + ARG_FILE + "' cannot include directory separators - must be just filename in " + plugin.getImportFolder().getAbsolutePath() + " directory");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if(label == null)
|
if(label == null)
|
||||||
label = id;
|
label = id;
|
||||||
MarkerIcon ico = MarkerAPIImpl.getMarkerIconImpl(id);
|
MarkerIcon ico = MarkerAPIImpl.getMarkerIconImpl(id);
|
||||||
|
@ -2181,10 +2188,9 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/* Open stream to filename */
|
/* Open stream to filename */
|
||||||
File iconf = new File(file);
|
|
||||||
FileInputStream fis = null;
|
FileInputStream fis = null;
|
||||||
try {
|
try {
|
||||||
fis = new FileInputStream(iconf);
|
fis = new FileInputStream(new File(plugin.getImportFolder(), file));
|
||||||
/* Create new icon */
|
/* Create new icon */
|
||||||
MarkerIcon mi = api.createMarkerIcon(id, label, fis);
|
MarkerIcon mi = api.createMarkerIcon(id, label, fis);
|
||||||
if(mi == null) {
|
if(mi == null) {
|
||||||
|
@ -3198,6 +3204,12 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
private static boolean validateImportFile(String fname) {
|
||||||
|
if ((fname.indexOf('/') >= 0) || (fname.indexOf('\\') >= 0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
/** Process importdesc for given item */
|
/** Process importdesc for given item */
|
||||||
private static boolean processImportDesc(DynmapCore plugin, DynmapCommandSender sender, String cmd, String commandLabel, String[] args) {
|
private static boolean processImportDesc(DynmapCore plugin, DynmapCommandSender sender, String cmd, String commandLabel, String[] args) {
|
||||||
if(args.length > 1) {
|
if(args.length > 1) {
|
||||||
|
@ -3211,13 +3223,17 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
}
|
}
|
||||||
String f = parms.get(ARG_FILE);
|
String f = parms.get(ARG_FILE);
|
||||||
if (f == null) {
|
if (f == null) {
|
||||||
sender.sendMessage("Error: no '" + ARG_FILE + "' parameter");
|
sender.sendMessage("file:\"filename\" required");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!validateImportFile(f)) {
|
||||||
|
sender.sendMessage("Error: '" + ARG_FILE + "' cannot include directory separators - must be just filename in " + plugin.getImportFolder().getAbsolutePath() + " directory");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
FileReader fr = null;
|
FileReader fr = null;
|
||||||
String val = null;
|
String val = null;
|
||||||
try {
|
try {
|
||||||
fr = new FileReader(f);
|
fr = new FileReader(new File(plugin.getImportFolder(), f));
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
char[] buf = new char[512];
|
char[] buf = new char[512];
|
||||||
int len;
|
int len;
|
||||||
|
@ -3258,13 +3274,17 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
}
|
}
|
||||||
String f = parms.get(ARG_FILE);
|
String f = parms.get(ARG_FILE);
|
||||||
if (f == null) {
|
if (f == null) {
|
||||||
sender.sendMessage("Error: no '" + ARG_FILE + "' parameter");
|
sender.sendMessage("file:\"filename\" required");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!validateImportFile(f)) {
|
||||||
|
sender.sendMessage("Error: '" + ARG_FILE + "' cannot include directory separators - must be just filename in " + plugin.getImportFolder().getAbsolutePath() + " directory");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
FileReader fr = null;
|
FileReader fr = null;
|
||||||
String val = null;
|
String val = null;
|
||||||
try {
|
try {
|
||||||
fr = new FileReader(f);
|
fr = new FileReader(new File(plugin.getImportFolder(), f));
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
char[] buf = new char[512];
|
char[] buf = new char[512];
|
||||||
int len;
|
int len;
|
||||||
|
@ -3458,7 +3478,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||||
@Override
|
@Override
|
||||||
public void triggered(DynmapWorld t) {
|
public void triggered(DynmapWorld t) {
|
||||||
/* Update markers for now-active world */
|
/* Update markers for now-active world */
|
||||||
dirty_worlds.add(t.getName());
|
dirty_worlds.put(t.getName(),"");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove icon */
|
/* Remove icon */
|
||||||
|
|
|
@ -81,7 +81,7 @@ class MarkerIconImpl implements MarkerIcon {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean loadPersistentData(ConfigurationNode node) {
|
boolean loadPersistentData(ConfigurationNode node, boolean isSafe) {
|
||||||
if(is_builtin)
|
if(is_builtin)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ class MarkerImpl implements Marker {
|
||||||
MarkerImpl(String id, MarkerSetImpl set) {
|
MarkerImpl(String id, MarkerSetImpl set) {
|
||||||
markerid = id;
|
markerid = id;
|
||||||
markerset = set;
|
markerset = set;
|
||||||
label = Client.encodeForHTML(id);
|
label = Client.sanitizeHTML(Client.encodeForHTML(id));
|
||||||
markup = false;
|
markup = false;
|
||||||
desc = null;
|
desc = null;
|
||||||
x = z = 0; y = 64; world = normalized_world = "world";
|
x = z = 0; y = 64; world = normalized_world = "world";
|
||||||
|
@ -75,15 +75,17 @@ class MarkerImpl implements Marker {
|
||||||
* Load marker from configuration node
|
* Load marker from configuration node
|
||||||
* @param node - configuration node
|
* @param node - configuration node
|
||||||
*/
|
*/
|
||||||
boolean loadPersistentData(ConfigurationNode node) {
|
boolean loadPersistentData(ConfigurationNode node, boolean isSafe) {
|
||||||
markup = node.getBoolean("markup", false);
|
markup = node.getBoolean("markup", false);
|
||||||
label = MarkerAPIImpl.escapeForHTMLIfNeeded(node.getString("label", markerid), markup);
|
label = MarkerAPIImpl.escapeForHTMLIfNeeded(node.getString("label", markerid), markup);
|
||||||
|
if (!isSafe) label = Client.sanitizeHTML(label);
|
||||||
x = node.getDouble("x", 0);
|
x = node.getDouble("x", 0);
|
||||||
y = node.getDouble("y", 64);
|
y = node.getDouble("y", 64);
|
||||||
z = node.getDouble("z", 0);
|
z = node.getDouble("z", 0);
|
||||||
world = node.getString("world", "world");
|
world = node.getString("world", "world");
|
||||||
normalized_world = DynmapWorld.normalizeWorldName(world);
|
normalized_world = DynmapWorld.normalizeWorldName(world);
|
||||||
desc = node.getString("desc", null);
|
desc = node.getString("desc", null);
|
||||||
|
if (!isSafe) desc = Client.sanitizeHTML(desc);
|
||||||
minzoom = node.getInteger("minzoom", -1);
|
minzoom = node.getInteger("minzoom", -1);
|
||||||
maxzoom = node.getInteger("maxzoom", -1);
|
maxzoom = node.getInteger("maxzoom", -1);
|
||||||
icon = MarkerAPIImpl.getMarkerIconImpl(node.getString("icon", MarkerIcon.DEFAULT));
|
icon = MarkerAPIImpl.getMarkerIconImpl(node.getString("icon", MarkerIcon.DEFAULT));
|
||||||
|
@ -168,7 +170,7 @@ class MarkerImpl implements Marker {
|
||||||
@Override
|
@Override
|
||||||
public void setLabel(String lbl, boolean markup) {
|
public void setLabel(String lbl, boolean markup) {
|
||||||
if(markerset == null) return;
|
if(markerset == null) return;
|
||||||
label = markup ? lbl : Client.encodeForHTML(lbl);
|
label = Client.sanitizeHTML(markup ? lbl : Client.encodeForHTML(lbl));
|
||||||
this.markup = markup;
|
this.markup = markup;
|
||||||
MarkerAPIImpl.markerUpdated(this, MarkerUpdate.UPDATED);
|
MarkerAPIImpl.markerUpdated(this, MarkerUpdate.UPDATED);
|
||||||
if(ispersistent)
|
if(ispersistent)
|
||||||
|
@ -239,6 +241,7 @@ class MarkerImpl implements Marker {
|
||||||
@Override
|
@Override
|
||||||
public void setDescription(String desc) {
|
public void setDescription(String desc) {
|
||||||
if(markerset == null) return;
|
if(markerset == null) return;
|
||||||
|
desc = Client.sanitizeHTML(desc);
|
||||||
if((this.desc == null) || (this.desc.equals(desc) == false)) {
|
if((this.desc == null) || (this.desc.equals(desc) == false)) {
|
||||||
this.desc = desc;
|
this.desc = desc;
|
||||||
MarkerAPIImpl.markerUpdated(this, MarkerUpdate.UPDATED);
|
MarkerAPIImpl.markerUpdated(this, MarkerUpdate.UPDATED);
|
||||||
|
|
|
@ -449,14 +449,14 @@ class MarkerSetImpl implements MarkerSet {
|
||||||
* Load marker from configuration node
|
* Load marker from configuration node
|
||||||
* @param node - configuration node
|
* @param node - configuration node
|
||||||
*/
|
*/
|
||||||
boolean loadPersistentData(ConfigurationNode node) {
|
boolean loadPersistentData(ConfigurationNode node, boolean isSafe) {
|
||||||
label = node.getString("label", setid); /* Get label */
|
label = node.getString("label", setid); /* Get label */
|
||||||
ConfigurationNode markernode = node.getNode("markers");
|
ConfigurationNode markernode = node.getNode("markers");
|
||||||
if (markernode != null) {
|
if (markernode != null) {
|
||||||
for(String id : markernode.keySet()) {
|
for(String id : markernode.keySet()) {
|
||||||
MarkerImpl marker = new MarkerImpl(id, this); /* Make and load marker */
|
MarkerImpl marker = new MarkerImpl(id, this); /* Make and load marker */
|
||||||
ConfigurationNode cfg = markernode.getNode(id);
|
ConfigurationNode cfg = markernode.getNode(id);
|
||||||
if ((cfg != null) && marker.loadPersistentData(cfg)) {
|
if ((cfg != null) && marker.loadPersistentData(cfg, isSafe)) {
|
||||||
markers.put(id, marker);
|
markers.put(id, marker);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -470,7 +470,7 @@ class MarkerSetImpl implements MarkerSet {
|
||||||
for(String id : areamarkernode.keySet()) {
|
for(String id : areamarkernode.keySet()) {
|
||||||
AreaMarkerImpl marker = new AreaMarkerImpl(id, this); /* Make and load marker */
|
AreaMarkerImpl marker = new AreaMarkerImpl(id, this); /* Make and load marker */
|
||||||
ConfigurationNode cfg = areamarkernode.getNode(id);
|
ConfigurationNode cfg = areamarkernode.getNode(id);
|
||||||
if ((cfg != null) && marker.loadPersistentData(cfg)) {
|
if ((cfg != null) && marker.loadPersistentData(cfg, isSafe)) {
|
||||||
areamarkers.put(id, marker);
|
areamarkers.put(id, marker);
|
||||||
if(marker.getBoostFlag()) {
|
if(marker.getBoostFlag()) {
|
||||||
if(boostingareamarkers == null) {
|
if(boostingareamarkers == null) {
|
||||||
|
@ -496,7 +496,7 @@ class MarkerSetImpl implements MarkerSet {
|
||||||
for(String id : linemarkernode.keySet()) {
|
for(String id : linemarkernode.keySet()) {
|
||||||
PolyLineMarkerImpl marker = new PolyLineMarkerImpl(id, this); /* Make and load marker */
|
PolyLineMarkerImpl marker = new PolyLineMarkerImpl(id, this); /* Make and load marker */
|
||||||
ConfigurationNode cfg = linemarkernode.getNode(id);
|
ConfigurationNode cfg = linemarkernode.getNode(id);
|
||||||
if ((cfg != null) && marker.loadPersistentData(cfg)) {
|
if ((cfg != null) && marker.loadPersistentData(cfg, isSafe)) {
|
||||||
linemarkers.put(id, marker);
|
linemarkers.put(id, marker);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -510,7 +510,7 @@ class MarkerSetImpl implements MarkerSet {
|
||||||
for(String id : circlemarkernode.keySet()) {
|
for(String id : circlemarkernode.keySet()) {
|
||||||
CircleMarkerImpl marker = new CircleMarkerImpl(id, this); /* Make and load marker */
|
CircleMarkerImpl marker = new CircleMarkerImpl(id, this); /* Make and load marker */
|
||||||
ConfigurationNode cfg = circlemarkernode.getNode(id);
|
ConfigurationNode cfg = circlemarkernode.getNode(id);
|
||||||
if ((cfg != null) && marker.loadPersistentData(cfg)) {
|
if ((cfg != null) && marker.loadPersistentData(cfg, isSafe)) {
|
||||||
circlemarkers.put(id, marker);
|
circlemarkers.put(id, marker);
|
||||||
if(marker.getBoostFlag()) {
|
if(marker.getBoostFlag()) {
|
||||||
if(boostingcirclemarkers == null) {
|
if(boostingcirclemarkers == null) {
|
||||||
|
|
|
@ -71,7 +71,7 @@ class PlayerSetImpl implements PlayerSet {
|
||||||
* Load marker from configuration node
|
* Load marker from configuration node
|
||||||
* @param node - configuration node
|
* @param node - configuration node
|
||||||
*/
|
*/
|
||||||
boolean loadPersistentData(ConfigurationNode node) {
|
boolean loadPersistentData(ConfigurationNode node, boolean isSafe) {
|
||||||
List<String> plist = node.getList("players");
|
List<String> plist = node.getList("players");
|
||||||
if(plist != null) {
|
if(plist != null) {
|
||||||
players.clear();
|
players.clear();
|
||||||
|
|
|
@ -53,6 +53,7 @@ class PolyLineMarkerImpl implements PolyLineMarker {
|
||||||
label = markup ? lbl : Client.encodeForHTML(lbl);
|
label = markup ? lbl : Client.encodeForHTML(lbl);
|
||||||
else
|
else
|
||||||
label = markup ? id : Client.encodeForHTML(id);
|
label = markup ? id : Client.encodeForHTML(id);
|
||||||
|
label = Client.sanitizeHTML(label);
|
||||||
this.markup = markup;
|
this.markup = markup;
|
||||||
this.corners = new ArrayList<Coord>();
|
this.corners = new ArrayList<Coord>();
|
||||||
for(int i = 0; i < x.length; i++) {
|
for(int i = 0; i < x.length; i++) {
|
||||||
|
@ -74,7 +75,7 @@ class PolyLineMarkerImpl implements PolyLineMarker {
|
||||||
PolyLineMarkerImpl(String id, MarkerSetImpl set) {
|
PolyLineMarkerImpl(String id, MarkerSetImpl set) {
|
||||||
markerid = id;
|
markerid = id;
|
||||||
markerset = set;
|
markerset = set;
|
||||||
label = Client.encodeForHTML(id);
|
label = Client.sanitizeHTML(Client.encodeForHTML(id));
|
||||||
markup = false;
|
markup = false;
|
||||||
desc = null;
|
desc = null;
|
||||||
corners = new ArrayList<Coord>();
|
corners = new ArrayList<Coord>();
|
||||||
|
@ -86,9 +87,10 @@ class PolyLineMarkerImpl implements PolyLineMarker {
|
||||||
* Load marker from configuration node
|
* Load marker from configuration node
|
||||||
* @param node - configuration node
|
* @param node - configuration node
|
||||||
*/
|
*/
|
||||||
boolean loadPersistentData(ConfigurationNode node) {
|
boolean loadPersistentData(ConfigurationNode node, boolean isSafe) {
|
||||||
markup = node.getBoolean("markup", false);
|
markup = node.getBoolean("markup", false);
|
||||||
label = MarkerAPIImpl.escapeForHTMLIfNeeded(node.getString("label", markerid), markup);
|
label = MarkerAPIImpl.escapeForHTMLIfNeeded(node.getString("label", markerid), markup);
|
||||||
|
if (!isSafe) label = Client.sanitizeHTML(label);
|
||||||
List<Double> xx = node.getList("x");
|
List<Double> xx = node.getList("x");
|
||||||
List<Double> yy = node.getList("y");
|
List<Double> yy = node.getList("y");
|
||||||
List<Double> zz = node.getList("z");
|
List<Double> zz = node.getList("z");
|
||||||
|
@ -101,6 +103,7 @@ class PolyLineMarkerImpl implements PolyLineMarker {
|
||||||
world = node.getString("world", "world");
|
world = node.getString("world", "world");
|
||||||
normalized_world = DynmapWorld.normalizeWorldName(world);
|
normalized_world = DynmapWorld.normalizeWorldName(world);
|
||||||
desc = node.getString("desc", null);
|
desc = node.getString("desc", null);
|
||||||
|
if (!isSafe) desc = Client.sanitizeHTML(desc);
|
||||||
lineweight = node.getInteger("strokeWeight", -1);
|
lineweight = node.getInteger("strokeWeight", -1);
|
||||||
if(lineweight == -1) { /* Handle typo-saved value */
|
if(lineweight == -1) { /* Handle typo-saved value */
|
||||||
lineweight = node.getInteger("stokeWeight", 3);
|
lineweight = node.getInteger("stokeWeight", 3);
|
||||||
|
@ -164,7 +167,7 @@ class PolyLineMarkerImpl implements PolyLineMarker {
|
||||||
@Override
|
@Override
|
||||||
public void setLabel(String lbl, boolean markup) {
|
public void setLabel(String lbl, boolean markup) {
|
||||||
if(markerset == null) return;
|
if(markerset == null) return;
|
||||||
label = markup ? lbl : Client.encodeForHTML(lbl);
|
label = markup ? Client.sanitizeHTML(lbl) : Client.encodeForHTML(lbl);
|
||||||
this.markup = markup;
|
this.markup = markup;
|
||||||
MarkerAPIImpl.polyLineMarkerUpdated(this, MarkerUpdate.UPDATED);
|
MarkerAPIImpl.polyLineMarkerUpdated(this, MarkerUpdate.UPDATED);
|
||||||
if(ispersistent)
|
if(ispersistent)
|
||||||
|
@ -223,6 +226,7 @@ class PolyLineMarkerImpl implements PolyLineMarker {
|
||||||
@Override
|
@Override
|
||||||
public void setDescription(String desc) {
|
public void setDescription(String desc) {
|
||||||
if(markerset == null) return;
|
if(markerset == null) return;
|
||||||
|
desc = Client.sanitizeHTML(desc);
|
||||||
if((this.desc == null) || (this.desc.equals(desc) == false)) {
|
if((this.desc == null) || (this.desc.equals(desc) == false)) {
|
||||||
this.desc = desc;
|
this.desc = desc;
|
||||||
MarkerAPIImpl.polyLineMarkerUpdated(this, MarkerUpdate.UPDATED);
|
MarkerAPIImpl.polyLineMarkerUpdated(this, MarkerUpdate.UPDATED);
|
||||||
|
|
|
@ -1,15 +1,23 @@
|
||||||
package org.dynmap.modsupport.impl;
|
package org.dynmap.modsupport.impl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.BitSet;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.dynmap.modsupport.BlockModel;
|
import org.dynmap.modsupport.BlockModel;
|
||||||
|
|
||||||
public abstract class BlockModelImpl implements BlockModel {
|
public abstract class BlockModelImpl implements BlockModel {
|
||||||
private int[] ids = new int[0];
|
private int[] ids = new int[0];
|
||||||
private String[] names = new String[0];
|
private String[] names = new String[0];
|
||||||
private int metaMask = -1;
|
private BitSet meta = null;
|
||||||
|
private List<Map<String, String>> blockstates = null;
|
||||||
protected final ModModelDefinitionImpl mdf;
|
protected final ModModelDefinitionImpl mdf;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public BlockModelImpl(int blkid, ModModelDefinitionImpl mdf) {
|
public BlockModelImpl(int blkid, ModModelDefinitionImpl mdf) {
|
||||||
addBlockID(blkid);
|
addBlockID(blkid);
|
||||||
this.mdf = mdf;
|
this.mdf = mdf;
|
||||||
|
@ -24,6 +32,7 @@ public abstract class BlockModelImpl implements BlockModel {
|
||||||
* @param blockID - block ID
|
* @param blockID - block ID
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public void addBlockID(int blockID) {
|
public void addBlockID(int blockID) {
|
||||||
if (blockID > 0) {
|
if (blockID > 0) {
|
||||||
for (int i = 0; i < ids.length; i++) {
|
for (int i = 0; i < ids.length; i++) {
|
||||||
|
@ -56,6 +65,7 @@ public abstract class BlockModelImpl implements BlockModel {
|
||||||
* @return configured IDs
|
* @return configured IDs
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public int[] getBlockIDs() {
|
public int[] getBlockIDs() {
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
@ -74,16 +84,12 @@ public abstract class BlockModelImpl implements BlockModel {
|
||||||
* @param data - value to match (-1 = all, 0-15 is meta value to match)
|
* @param data - value to match (-1 = all, 0-15 is meta value to match)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public void setMetaValue(int data) {
|
public void setMetaValue(int data) {
|
||||||
if (data < 0) { // Setting to all
|
if (meta == null) {
|
||||||
metaMask = METAMASK_ALL;
|
meta = new BitSet();
|
||||||
}
|
}
|
||||||
else if (data < 16) {
|
meta.set(data);
|
||||||
if (metaMask == METAMASK_ALL) {
|
|
||||||
metaMask = 0;
|
|
||||||
}
|
|
||||||
metaMask |= (1 << data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,12 +97,35 @@ public abstract class BlockModelImpl implements BlockModel {
|
||||||
* @return matching metadata mask: bit N is set if given metadata value matches
|
* @return matching metadata mask: bit N is set if given metadata value matches
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public int getMetaValueMask() {
|
public int getMetaValueMask() {
|
||||||
return metaMask;
|
if (meta == null) { return METAMASK_ALL; }
|
||||||
|
return (int) meta.toLongArray()[0]; // Only works for 32 flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set matching block state mapping
|
||||||
|
* Any key-value pairs included must match, while any not included are assumed to match unconditionall
|
||||||
|
* @param statemap - map of attribute value pairs
|
||||||
|
*/
|
||||||
|
public void setBlockStateMapping(Map<String, String> statemap) {
|
||||||
|
if (blockstates == null) {
|
||||||
|
blockstates = new ArrayList<Map<String, String>>();
|
||||||
|
}
|
||||||
|
Map<String, String> nmap = new HashMap<String, String>();
|
||||||
|
nmap.putAll(statemap);
|
||||||
|
blockstates.add(nmap);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get all state mappings accumulated for the block model
|
||||||
|
*/
|
||||||
|
public List<Map<String, String>> getBlockStateMappings() {
|
||||||
|
return blockstates;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract String getLine();
|
public abstract String getLine();
|
||||||
|
|
||||||
|
// This is now getting state mappings too
|
||||||
protected String getIDsAndMeta() {
|
protected String getIDsAndMeta() {
|
||||||
if ((ids.length == 0) && (names.length == 0)) {
|
if ((ids.length == 0) && (names.length == 0)) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -118,18 +147,34 @@ public abstract class BlockModelImpl implements BlockModel {
|
||||||
}
|
}
|
||||||
s += "id=%" + names[i];
|
s += "id=%" + names[i];
|
||||||
}
|
}
|
||||||
// Add meta
|
// If we have state data, favor this
|
||||||
if (this.metaMask == METAMASK_ALL) {
|
if (this.blockstates != null) {
|
||||||
s += ",data=*";
|
for (Map<String, String> rec : this.blockstates) {
|
||||||
|
// If no state, skip
|
||||||
|
if (rec.size() == 0) { continue; }
|
||||||
|
s += ",state=";
|
||||||
|
boolean first = true;
|
||||||
|
for (Entry<String, String> r : rec.entrySet()) {
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s += '/';
|
||||||
|
}
|
||||||
|
s += r.getKey() + ":" + r.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
// If we have meta data, add this next
|
||||||
for (int i = 0; i < 16; i++) {
|
if (this.meta != null) {
|
||||||
if ((metaMask & (1 << i)) != 0) {
|
for (int i = meta.nextSetBit(0); i != -1; i = meta.nextSetBit(i + 1)) {
|
||||||
s += ",data=" + i;
|
s += ",data=" + i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If neither, just state=*
|
||||||
|
if ((this.meta == null) && (this.blockstates == null)) {
|
||||||
|
s += ",state=*";
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,11 @@ package org.dynmap.modsupport.impl;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.BitSet;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.dynmap.hdmap.TexturePack;
|
import org.dynmap.hdmap.TexturePack;
|
||||||
import org.dynmap.modsupport.BlockSide;
|
import org.dynmap.modsupport.BlockSide;
|
||||||
|
@ -13,7 +18,8 @@ import org.dynmap.modsupport.TransparencyMode;
|
||||||
public class BlockTextureRecordImpl implements BlockTextureRecord {
|
public class BlockTextureRecordImpl implements BlockTextureRecord {
|
||||||
private int[] ids = new int[0];
|
private int[] ids = new int[0];
|
||||||
private String[] names = new String[0];
|
private String[] names = new String[0];
|
||||||
private int metaMask = -1;
|
private BitSet meta = null;
|
||||||
|
private List<Map<String, String>> blockstates = null;
|
||||||
private TransparencyMode transmode = TransparencyMode.OPAQUE;
|
private TransparencyMode transmode = TransparencyMode.OPAQUE;
|
||||||
|
|
||||||
private static class TexturePatch {
|
private static class TexturePatch {
|
||||||
|
@ -96,6 +102,7 @@ public class BlockTextureRecordImpl implements BlockTextureRecord {
|
||||||
TexturePack.COLORMOD_FOLIAGEMULTTONED // FOLIAGEMULTTONED
|
TexturePack.COLORMOD_FOLIAGEMULTTONED // FOLIAGEMULTTONED
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public BlockTextureRecordImpl(int blkid) {
|
public BlockTextureRecordImpl(int blkid) {
|
||||||
addBlockID(blkid);
|
addBlockID(blkid);
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
|
@ -115,6 +122,7 @@ public class BlockTextureRecordImpl implements BlockTextureRecord {
|
||||||
* @param blockID - block ID
|
* @param blockID - block ID
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public void addBlockID(int blockID) {
|
public void addBlockID(int blockID) {
|
||||||
if (blockID > 0) {
|
if (blockID > 0) {
|
||||||
for (int i = 0; i < ids.length; i++) {
|
for (int i = 0; i < ids.length; i++) {
|
||||||
|
@ -147,6 +155,7 @@ public class BlockTextureRecordImpl implements BlockTextureRecord {
|
||||||
* @return configured IDs
|
* @return configured IDs
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public int[] getBlockIDs() {
|
public int[] getBlockIDs() {
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
@ -165,16 +174,12 @@ public class BlockTextureRecordImpl implements BlockTextureRecord {
|
||||||
* @param data - value to match (-1 = all, 0-15 is meta value to match)
|
* @param data - value to match (-1 = all, 0-15 is meta value to match)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public void setMetaValue(int data) {
|
public void setMetaValue(int data) {
|
||||||
if (data < 0) { // Setting to all
|
if (meta == null) {
|
||||||
metaMask = METAMASK_ALL;
|
meta = new BitSet();
|
||||||
}
|
}
|
||||||
else if (data < 16) {
|
meta.set(data);
|
||||||
if (metaMask == METAMASK_ALL) {
|
|
||||||
metaMask = 0;
|
|
||||||
}
|
|
||||||
metaMask |= (1 << data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -182,10 +187,32 @@ public class BlockTextureRecordImpl implements BlockTextureRecord {
|
||||||
* @return matching metadata mask: bit N is set if given metadata value matches
|
* @return matching metadata mask: bit N is set if given metadata value matches
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public int getMetaValueMask() {
|
public int getMetaValueMask() {
|
||||||
return metaMask;
|
if (meta == null) { return METAMASK_ALL; }
|
||||||
|
return (int) meta.toLongArray()[0]; // Only works for 32 flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set matching block state mapping
|
||||||
|
* Any key-value pairs included must match, while any not included are assumed to match unconditionall
|
||||||
|
* @param statemap - map of attribute value pairs
|
||||||
|
*/
|
||||||
|
public void setBlockStateMapping(Map<String, String> statemap) {
|
||||||
|
if (blockstates == null) {
|
||||||
|
blockstates = new ArrayList<Map<String, String>>();
|
||||||
|
}
|
||||||
|
Map<String, String> nmap = new HashMap<String, String>();
|
||||||
|
nmap.putAll(statemap);
|
||||||
|
blockstates.add(nmap);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get all state mappings accumulated for the block model
|
||||||
|
*/
|
||||||
|
public List<Map<String, String>> getBlockStateMappings() {
|
||||||
|
return blockstates;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set transparency mode for block
|
* Set transparency mode for block
|
||||||
* @param mode - transparency mode
|
* @param mode - transparency mode
|
||||||
|
@ -503,16 +530,32 @@ public class BlockTextureRecordImpl implements BlockTextureRecord {
|
||||||
s += "id=%" + names[i];
|
s += "id=%" + names[i];
|
||||||
idcnt++;
|
idcnt++;
|
||||||
}
|
}
|
||||||
// Add meta
|
// If we have state data, favor this
|
||||||
if (this.metaMask == METAMASK_ALL) {
|
if (this.blockstates != null) {
|
||||||
s += ",data=*";
|
for (Map<String, String> rec : this.blockstates) {
|
||||||
|
if (rec.size() == 0) { continue; } // Skip if none
|
||||||
|
s += ",state=";
|
||||||
|
boolean first = true;
|
||||||
|
for (Entry<String, String> r : rec.entrySet()) {
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s += '/';
|
||||||
|
}
|
||||||
|
s += r.getKey() + ":" + r.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
// If we have meta data, add this next
|
||||||
for (int i = 0; i < 16; i++) {
|
if (this.meta != null) {
|
||||||
if ((metaMask & (1 << i)) != 0) {
|
for (int i = meta.nextSetBit(0); i != -1; i = meta.nextSetBit(i + 1)) {
|
||||||
s += ",data=" + i;
|
s += ",data=" + i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If neither, just state=*
|
||||||
|
if ((this.meta == null) && (this.blockstates == null)) {
|
||||||
|
s += ",state=*";
|
||||||
}
|
}
|
||||||
for (int i = 0; i < txtPatches.size(); i++) {
|
for (int i = 0; i < txtPatches.size(); i++) {
|
||||||
TexturePatch tp = txtPatches.get(i);
|
TexturePatch tp = txtPatches.get(i);
|
||||||
|
|
|
@ -12,6 +12,7 @@ public class BoxBlockModelImpl extends BlockModelImpl implements BoxBlockModel {
|
||||||
private double zmin = 0.0;
|
private double zmin = 0.0;
|
||||||
private double zmax = 1.0;
|
private double zmax = 1.0;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public BoxBlockModelImpl(int blkid, ModModelDefinitionImpl mdf) {
|
public BoxBlockModelImpl(int blkid, ModModelDefinitionImpl mdf) {
|
||||||
super(blkid, mdf);
|
super(blkid, mdf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,25 @@
|
||||||
package org.dynmap.modsupport.impl;
|
package org.dynmap.modsupport.impl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.BitSet;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.dynmap.DynmapCore;
|
|
||||||
import org.dynmap.modsupport.CopyBlockTextureRecord;
|
import org.dynmap.modsupport.CopyBlockTextureRecord;
|
||||||
import org.dynmap.modsupport.TransparencyMode;
|
import org.dynmap.modsupport.TransparencyMode;
|
||||||
|
|
||||||
public class CopyBlockTextureRecordImpl implements CopyBlockTextureRecord {
|
public class CopyBlockTextureRecordImpl implements CopyBlockTextureRecord {
|
||||||
private int[] ids = new int[0];
|
private int[] ids = new int[0];
|
||||||
private String[] names = new String[0];
|
private String[] names = new String[0];
|
||||||
private int metaMask = -1;
|
private BitSet meta = null;
|
||||||
|
private List<Map<String, String>> blockstates = null;
|
||||||
private final int srcid;
|
private final int srcid;
|
||||||
private final String srcname;
|
private final String srcname;
|
||||||
private final int srcmeta;
|
private final int srcmeta;
|
||||||
|
private final Map<String, String> srcstatemap;
|
||||||
private TransparencyMode mode = null;
|
private TransparencyMode mode = null;
|
||||||
|
|
||||||
private int isNumber(String v) {
|
private int isNumber(String v) {
|
||||||
|
@ -28,6 +35,7 @@ public class CopyBlockTextureRecordImpl implements CopyBlockTextureRecord {
|
||||||
this.srcid = srcid;
|
this.srcid = srcid;
|
||||||
this.srcname = null;
|
this.srcname = null;
|
||||||
this.srcmeta = srcmeta;
|
this.srcmeta = srcmeta;
|
||||||
|
this.srcstatemap = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CopyBlockTextureRecordImpl(String blkname, String srcname, int srcmeta) {
|
public CopyBlockTextureRecordImpl(String blkname, String srcname, int srcmeta) {
|
||||||
|
@ -42,6 +50,23 @@ public class CopyBlockTextureRecordImpl implements CopyBlockTextureRecord {
|
||||||
this.srcid = id;
|
this.srcid = id;
|
||||||
}
|
}
|
||||||
this.srcmeta = srcmeta;
|
this.srcmeta = srcmeta;
|
||||||
|
this.srcstatemap = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CopyBlockTextureRecordImpl(String blkname, String srcname, Map<String, String> srcstatemap) {
|
||||||
|
addBlockName(blkname);
|
||||||
|
int id = isNumber(srcname);
|
||||||
|
if (id < 0) {
|
||||||
|
this.srcname = srcname;
|
||||||
|
this.srcid = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.srcname = null;
|
||||||
|
this.srcid = id;
|
||||||
|
}
|
||||||
|
this.srcmeta = -1;
|
||||||
|
this.srcstatemap = new HashMap<String, String>();
|
||||||
|
this.srcstatemap.putAll(srcstatemap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -99,16 +124,12 @@ public class CopyBlockTextureRecordImpl implements CopyBlockTextureRecord {
|
||||||
* @param data - value to match (-1 = all, 0-15 is meta value to match)
|
* @param data - value to match (-1 = all, 0-15 is meta value to match)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public void setMetaValue(int data) {
|
public void setMetaValue(int data) {
|
||||||
if (data < 0) { // Setting to all
|
if (meta == null) {
|
||||||
metaMask = METAMASK_ALL;
|
meta = new BitSet();
|
||||||
}
|
}
|
||||||
else if (data < 16) {
|
meta.set(data);
|
||||||
if (metaMask == METAMASK_ALL) {
|
|
||||||
metaMask = 0;
|
|
||||||
}
|
|
||||||
metaMask |= (1 << data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -116,8 +137,32 @@ public class CopyBlockTextureRecordImpl implements CopyBlockTextureRecord {
|
||||||
* @return matching metadata mask: bit N is set if given metadata value matches
|
* @return matching metadata mask: bit N is set if given metadata value matches
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public int getMetaValueMask() {
|
public int getMetaValueMask() {
|
||||||
return metaMask;
|
if (meta == null) { return METAMASK_ALL; }
|
||||||
|
return (int) meta.toLongArray()[0]; // Only works for 32 flags
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set matching block state mapping
|
||||||
|
* Any key-value pairs included must match, while any not included are assumed to match unconditionall
|
||||||
|
* @param statemap - map of attribute value pairs
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setBlockStateMapping(Map<String, String> statemap) {
|
||||||
|
if (blockstates == null) {
|
||||||
|
blockstates = new ArrayList<Map<String, String>>();
|
||||||
|
}
|
||||||
|
Map<String, String> nmap = new HashMap<String, String>();
|
||||||
|
nmap.putAll(statemap);
|
||||||
|
blockstates.add(nmap);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get all state mappings accumulated for the block model
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<Map<String, String>> getBlockStateMappings() {
|
||||||
|
return blockstates;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLine() {
|
public String getLine() {
|
||||||
|
@ -143,23 +188,57 @@ public class CopyBlockTextureRecordImpl implements CopyBlockTextureRecord {
|
||||||
s += "id=%" + names[i];
|
s += "id=%" + names[i];
|
||||||
idcnt++;
|
idcnt++;
|
||||||
}
|
}
|
||||||
// Add meta
|
// If we have state data, favor this
|
||||||
if (this.metaMask == METAMASK_ALL) {
|
if (this.blockstates != null) {
|
||||||
s += ",data=*";
|
for (Map<String, String> rec : this.blockstates) {
|
||||||
|
if (rec.size() == 0) { continue; } // Skip if none
|
||||||
|
s += ",state=";
|
||||||
|
boolean first = true;
|
||||||
|
for (Entry<String, String> r : rec.entrySet()) {
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s += '/';
|
||||||
|
}
|
||||||
|
s += r.getKey() + ":" + r.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
// If we have meta data, add this next
|
||||||
for (int i = 0; i < 16; i++) {
|
if (this.meta != null) {
|
||||||
if ((metaMask & (1 << i)) != 0) {
|
for (int i = meta.nextSetBit(0); i != -1; i = meta.nextSetBit(i + 1)) {
|
||||||
s += ",data=" + i;
|
s += ",data=" + i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If neither, just state=*
|
||||||
|
if ((this.meta == null) && (this.blockstates == null)) {
|
||||||
|
s += ",state=*";
|
||||||
}
|
}
|
||||||
if (srcname != null) {
|
if (srcname != null) {
|
||||||
s += ",srcid=%" + srcname + ",srcmeta=" + srcmeta;
|
s += ",srcid=%" + srcname;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
s += ",srcid=" + srcid + ",srcmeta=" + srcmeta;
|
s += ",srcid=" + srcid;
|
||||||
}
|
}
|
||||||
|
// If source state, use it
|
||||||
|
if (this.srcstatemap != null) {
|
||||||
|
s += ",srcstate=";
|
||||||
|
boolean first = true;
|
||||||
|
for (Entry<String, String> r : this.srcstatemap.entrySet()) {
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s += '/';
|
||||||
|
}
|
||||||
|
s += r.getKey() + ":" + r.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s += ",srcmeta=" + srcmeta;
|
||||||
|
}
|
||||||
|
|
||||||
switch (this.mode) {
|
switch (this.mode) {
|
||||||
case TRANSPARENT:
|
case TRANSPARENT:
|
||||||
s += ",transparency=TRANSPARENT";
|
s += ",transparency=TRANSPARENT";
|
||||||
|
@ -174,15 +253,25 @@ public class CopyBlockTextureRecordImpl implements CopyBlockTextureRecord {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public int getSourceBlockID() {
|
public int getSourceBlockID() {
|
||||||
return srcid;
|
return srcid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public int getSourceMeta() {
|
public int getSourceMeta() {
|
||||||
return srcmeta;
|
return srcmeta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get sourc state mappings accumulated for the block model
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getSourceBlockStateMapping() {
|
||||||
|
return srcstatemap;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTransparencyMode(TransparencyMode mode) {
|
public void setTransparencyMode(TransparencyMode mode) {
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
|
@ -192,4 +281,8 @@ public class CopyBlockTextureRecordImpl implements CopyBlockTextureRecord {
|
||||||
public TransparencyMode getTransparencyMode() {
|
public TransparencyMode getTransparencyMode() {
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public String getSourceBlockName() {
|
||||||
|
return srcname;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ public class CuboidBlockModelImpl extends BlockModelImpl implements CuboidBlockM
|
||||||
private ArrayList<Cuboid> cuboids = new ArrayList<Cuboid>();
|
private ArrayList<Cuboid> cuboids = new ArrayList<Cuboid>();
|
||||||
private ArrayList<Crossed> crosseds = new ArrayList<Crossed>();
|
private ArrayList<Crossed> crosseds = new ArrayList<Crossed>();
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public CuboidBlockModelImpl(int blkid, ModModelDefinitionImpl mdf) {
|
public CuboidBlockModelImpl(int blkid, ModModelDefinitionImpl mdf) {
|
||||||
super(blkid, mdf);
|
super(blkid, mdf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.dynmap.modsupport.DoorBlockModel;
|
||||||
|
|
||||||
public class DoorBlockModelImpl extends BlockModelImpl implements DoorBlockModel {
|
public class DoorBlockModelImpl extends BlockModelImpl implements DoorBlockModel {
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public DoorBlockModelImpl(int blkid, ModModelDefinitionImpl mdf) {
|
public DoorBlockModelImpl(int blkid, ModModelDefinitionImpl mdf) {
|
||||||
super(blkid, mdf);
|
super(blkid, mdf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package org.dynmap.modsupport.impl;
|
package org.dynmap.modsupport.impl;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -26,6 +28,7 @@ import org.dynmap.renderer.RenderPatchFactory.SideVisible;
|
||||||
import org.dynmap.utils.PatchDefinition;
|
import org.dynmap.utils.PatchDefinition;
|
||||||
import org.dynmap.utils.PatchDefinitionFactory;
|
import org.dynmap.utils.PatchDefinitionFactory;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class ModModelDefinitionImpl implements ModModelDefinition {
|
public class ModModelDefinitionImpl implements ModModelDefinition {
|
||||||
private final ModTextureDefinitionImpl txtDef;
|
private final ModTextureDefinitionImpl txtDef;
|
||||||
private boolean published = false;
|
private boolean published = false;
|
||||||
|
@ -61,12 +64,14 @@ public class ModModelDefinitionImpl implements ModModelDefinition {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public VolumetricBlockModel addVolumetricModel(int blockid, int scale) {
|
public VolumetricBlockModel addVolumetricModel(int blockid, int scale) {
|
||||||
VolumetricBlockModelImpl mod = new VolumetricBlockModelImpl(blockid, this, scale);
|
VolumetricBlockModelImpl mod = new VolumetricBlockModelImpl(blockid, this, scale);
|
||||||
blkModel.add(mod);
|
blkModel.add(mod);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public VolumetricBlockModel addVolumetricModel(String blockname, int scale) {
|
public VolumetricBlockModel addVolumetricModel(String blockname, int scale) {
|
||||||
VolumetricBlockModelImpl mod = new VolumetricBlockModelImpl(blockname, this, scale);
|
VolumetricBlockModelImpl mod = new VolumetricBlockModelImpl(blockname, this, scale);
|
||||||
blkModel.add(mod);
|
blkModel.add(mod);
|
||||||
|
@ -74,6 +79,7 @@ public class ModModelDefinitionImpl implements ModModelDefinition {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public StairBlockModel addStairModel(int blockid) {
|
public StairBlockModel addStairModel(int blockid) {
|
||||||
StairBlockModelImpl mod = new StairBlockModelImpl(blockid, this);
|
StairBlockModelImpl mod = new StairBlockModelImpl(blockid, this);
|
||||||
blkModel.add(mod);
|
blkModel.add(mod);
|
||||||
|
@ -87,6 +93,7 @@ public class ModModelDefinitionImpl implements ModModelDefinition {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public WallFenceBlockModel addWallFenceModel(int blockid, FenceType type) {
|
public WallFenceBlockModel addWallFenceModel(int blockid, FenceType type) {
|
||||||
WallFenceBlockModelImpl mod = new WallFenceBlockModelImpl(blockid, this, type);
|
WallFenceBlockModelImpl mod = new WallFenceBlockModelImpl(blockid, this, type);
|
||||||
blkModel.add(mod);
|
blkModel.add(mod);
|
||||||
|
@ -100,6 +107,7 @@ public class ModModelDefinitionImpl implements ModModelDefinition {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public CuboidBlockModel addCuboidModel(int blockid) {
|
public CuboidBlockModel addCuboidModel(int blockid) {
|
||||||
CuboidBlockModelImpl mod = new CuboidBlockModelImpl(blockid, this);
|
CuboidBlockModelImpl mod = new CuboidBlockModelImpl(blockid, this);
|
||||||
blkModel.add(mod);
|
blkModel.add(mod);
|
||||||
|
@ -114,6 +122,7 @@ public class ModModelDefinitionImpl implements ModModelDefinition {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public PaneBlockModel addPaneModel(int blockid) {
|
public PaneBlockModel addPaneModel(int blockid) {
|
||||||
PaneBlockModelImpl mod = new PaneBlockModelImpl(blockid, this);
|
PaneBlockModelImpl mod = new PaneBlockModelImpl(blockid, this);
|
||||||
blkModel.add(mod);
|
blkModel.add(mod);
|
||||||
|
@ -127,6 +136,7 @@ public class ModModelDefinitionImpl implements ModModelDefinition {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public PlantBlockModel addPlantModel(int blockid) {
|
public PlantBlockModel addPlantModel(int blockid) {
|
||||||
PlantBlockModelImpl mod = new PlantBlockModelImpl(blockid, this);
|
PlantBlockModelImpl mod = new PlantBlockModelImpl(blockid, this);
|
||||||
blkModel.add(mod);
|
blkModel.add(mod);
|
||||||
|
@ -140,6 +150,7 @@ public class ModModelDefinitionImpl implements ModModelDefinition {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public BoxBlockModel addBoxModel(int blockid) {
|
public BoxBlockModel addBoxModel(int blockid) {
|
||||||
BoxBlockModelImpl mod = new BoxBlockModelImpl(blockid, this);
|
BoxBlockModelImpl mod = new BoxBlockModelImpl(blockid, this);
|
||||||
blkModel.add(mod);
|
blkModel.add(mod);
|
||||||
|
@ -153,6 +164,7 @@ public class ModModelDefinitionImpl implements ModModelDefinition {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public DoorBlockModel addDoorModel(int blockid) {
|
public DoorBlockModel addDoorModel(int blockid) {
|
||||||
DoorBlockModelImpl mod = new DoorBlockModelImpl(blockid, this);
|
DoorBlockModelImpl mod = new DoorBlockModelImpl(blockid, this);
|
||||||
blkModel.add(mod);
|
blkModel.add(mod);
|
||||||
|
@ -166,6 +178,7 @@ public class ModModelDefinitionImpl implements ModModelDefinition {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public PatchBlockModel addPatchModel(int blockid) {
|
public PatchBlockModel addPatchModel(int blockid) {
|
||||||
PatchBlockModelImpl mod = new PatchBlockModelImpl(blockid, this);
|
PatchBlockModelImpl mod = new PatchBlockModelImpl(blockid, this);
|
||||||
blkModel.add(mod);
|
blkModel.add(mod);
|
||||||
|
@ -179,6 +192,7 @@ public class ModModelDefinitionImpl implements ModModelDefinition {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public PatchBlockModel addRotatedPatchModel(int blockid,
|
public PatchBlockModel addRotatedPatchModel(int blockid,
|
||||||
PatchBlockModel model, int xrot, int yrot, int zrot) {
|
PatchBlockModel model, int xrot, int yrot, int zrot) {
|
||||||
PatchBlockModelImpl mod = new PatchBlockModelImpl(blockid, this, model, xrot, yrot, zrot);
|
PatchBlockModelImpl mod = new PatchBlockModelImpl(blockid, this, model, xrot, yrot, zrot);
|
||||||
|
@ -199,12 +213,6 @@ public class ModModelDefinitionImpl implements ModModelDefinition {
|
||||||
blkModel.add(mod);
|
blkModel.add(mod);
|
||||||
return mod;
|
return mod;
|
||||||
}
|
}
|
||||||
@Override
|
|
||||||
public ModelBlockModel addRotatedModelBlockModel(String blockname, ModelBlockModel model, int xrot, int yrot, int zrot) {
|
|
||||||
ModelBlockModelImpl mod = new ModelBlockModelImpl(blockname, this, model, xrot, yrot, zrot);
|
|
||||||
blkModel.add(mod);
|
|
||||||
return mod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPatchID(double x0, double y0, double z0, double xu,
|
public String getPatchID(double x0, double y0, double z0, double xu,
|
||||||
double yu, double zu, double xv, double yv, double zv, double umin,
|
double yu, double zu, double xv, double yv, double zv, double umin,
|
||||||
|
@ -223,8 +231,8 @@ public class ModModelDefinitionImpl implements ModModelDefinition {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getModelFacePatchID(double[] from, double[] to, BlockSide face, double[] uv, ModelBlockModel.SideRotation rot, int textureid) {
|
public String getModelFacePatchID(double[] from, double[] to, BlockSide face, double[] uv, ModelBlockModel.SideRotation rot, boolean shade, int textureid) {
|
||||||
PatchDefinition pd = pdf.getModelFace(from, to, face, uv, rot, textureid);
|
PatchDefinition pd = pdf.getModelFace(from, to, face, uv, rot, shade, textureid);
|
||||||
if (pd == null)
|
if (pd == null)
|
||||||
return null; // Invalid patch
|
return null; // Invalid patch
|
||||||
for (int i = 0; i < blkPatch.size(); i++) {
|
for (int i = 0; i < blkPatch.size(); i++) {
|
||||||
|
@ -268,9 +276,9 @@ public class ModModelDefinitionImpl implements ModModelDefinition {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
File f = new File(destdir, this.txtDef.getModID() + "-models.txt");
|
File f = new File(destdir, this.txtDef.getModID() + "-models.txt");
|
||||||
FileWriter fw = null;
|
Writer fw = null;
|
||||||
try {
|
try {
|
||||||
fw = new FileWriter(f);
|
fw = new BufferedWriter(new FileWriter(f));
|
||||||
// Write modname line
|
// Write modname line
|
||||||
String s = "modname:" + this.txtDef.getModID();
|
String s = "modname:" + this.txtDef.getModID();
|
||||||
fw.write(s + "\n\n");
|
fw.write(s + "\n\n");
|
||||||
|
@ -287,6 +295,15 @@ public class ModModelDefinitionImpl implements ModModelDefinition {
|
||||||
case TOP:
|
case TOP:
|
||||||
line += ",visibility=top";
|
line += ",visibility=top";
|
||||||
break;
|
break;
|
||||||
|
case TOPFLIP:
|
||||||
|
line += ",visibility=topflip";
|
||||||
|
break;
|
||||||
|
case TOPFLIPV:
|
||||||
|
line += ",visibility=topflipv";
|
||||||
|
break;
|
||||||
|
case TOPFLIPHV:
|
||||||
|
line += ",visibility=topfliphv";
|
||||||
|
break;
|
||||||
case FLIP:
|
case FLIP:
|
||||||
line += ",visibility=flip";
|
line += ",visibility=flip";
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package org.dynmap.modsupport.impl;
|
package org.dynmap.modsupport.impl;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.dynmap.modsupport.BigChestTextureFile;
|
import org.dynmap.modsupport.BigChestTextureFile;
|
||||||
import org.dynmap.modsupport.BiomeTextureFile;
|
import org.dynmap.modsupport.BiomeTextureFile;
|
||||||
|
@ -227,6 +230,7 @@ public class ModTextureDefinitionImpl implements ModTextureDefinition {
|
||||||
* @return block texture record: use methods to set texture use on faces/patches
|
* @return block texture record: use methods to set texture use on faces/patches
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public BlockTextureRecord addBlockTextureRecord(int blockID) {
|
public BlockTextureRecord addBlockTextureRecord(int blockID) {
|
||||||
BlockTextureRecordImpl btr = new BlockTextureRecordImpl(blockID);
|
BlockTextureRecordImpl btr = new BlockTextureRecordImpl(blockID);
|
||||||
blkTextureRec.add(btr);
|
blkTextureRec.add(btr);
|
||||||
|
@ -245,6 +249,7 @@ public class ModTextureDefinitionImpl implements ModTextureDefinition {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public CopyBlockTextureRecord addCopyBlockTextureRecord(int blockID,
|
public CopyBlockTextureRecord addCopyBlockTextureRecord(int blockID,
|
||||||
int srcBlockID, int srcMeta) {
|
int srcBlockID, int srcMeta) {
|
||||||
CopyBlockTextureRecordImpl btr = new CopyBlockTextureRecordImpl(blockID, srcBlockID, srcMeta);
|
CopyBlockTextureRecordImpl btr = new CopyBlockTextureRecordImpl(blockID, srcBlockID, srcMeta);
|
||||||
|
@ -252,6 +257,7 @@ public class ModTextureDefinitionImpl implements ModTextureDefinition {
|
||||||
return btr;
|
return btr;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public CopyBlockTextureRecord addCopyBlockTextureRecord(String blockname,
|
public CopyBlockTextureRecord addCopyBlockTextureRecord(String blockname,
|
||||||
String srcBlockName, int srcMeta) {
|
String srcBlockName, int srcMeta) {
|
||||||
CopyBlockTextureRecordImpl btr = new CopyBlockTextureRecordImpl(blockname, srcBlockName, srcMeta);
|
CopyBlockTextureRecordImpl btr = new CopyBlockTextureRecordImpl(blockname, srcBlockName, srcMeta);
|
||||||
|
@ -259,15 +265,24 @@ public class ModTextureDefinitionImpl implements ModTextureDefinition {
|
||||||
return btr;
|
return btr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CopyBlockTextureRecord addCopyBlockTextureRecord(String blockname,
|
||||||
|
String srcBlockName, Map<String, String> srcStateMap) {
|
||||||
|
CopyBlockTextureRecordImpl btr = new CopyBlockTextureRecordImpl(blockname, srcBlockName, srcStateMap);
|
||||||
|
blkCopyTextureRec.add(btr);
|
||||||
|
return btr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isPublished() {
|
public boolean isPublished() {
|
||||||
return published;
|
return published;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeToFile(File destdir) throws IOException {
|
public void writeToFile(File destdir) throws IOException {
|
||||||
File f = new File(destdir, this.modid + "-texture.txt");
|
File f = new File(destdir, this.modid + "-texture.txt");
|
||||||
FileWriter fw = null;
|
Writer fw = null;
|
||||||
try {
|
try {
|
||||||
fw = new FileWriter(f);
|
fw = new BufferedWriter(new FileWriter(f));
|
||||||
// Write modname line
|
// Write modname line
|
||||||
String s = "modname:" + this.modid;
|
String s = "modname:" + this.modid;
|
||||||
fw.write(s + "\n\n");
|
fw.write(s + "\n\n");
|
||||||
|
|
|
@ -3,10 +3,10 @@ package org.dynmap.modsupport.impl;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.dynmap.modsupport.BlockSide;
|
import org.dynmap.modsupport.BlockSide;
|
||||||
import org.dynmap.modsupport.ModelBlockModel;
|
import org.dynmap.modsupport.ModelBlockModel;
|
||||||
import org.dynmap.modsupport.ModelBlockModel.SideRotation;
|
|
||||||
|
|
||||||
public class ModelBlockModelImpl extends BlockModelImpl implements ModelBlockModel {
|
public class ModelBlockModelImpl extends BlockModelImpl implements ModelBlockModel {
|
||||||
|
|
||||||
|
@ -20,8 +20,11 @@ public class ModelBlockModelImpl extends BlockModelImpl implements ModelBlockMod
|
||||||
private double[] from = { 0, 0, 0 };
|
private double[] from = { 0, 0, 0 };
|
||||||
private double[] to = { 16, 16, 16 };
|
private double[] to = { 16, 16, 16 };
|
||||||
private double xrot = 0, yrot = 0, zrot = 0;
|
private double xrot = 0, yrot = 0, zrot = 0;
|
||||||
|
private boolean shade;
|
||||||
|
private double[] rotorigin;
|
||||||
|
private int modrotx = 0, modroty = 0, modrotz = 0;
|
||||||
@Override
|
@Override
|
||||||
public void addBlockSide(BlockSide side, double[] uv, SideRotation rot, int textureid) {
|
public void addBlockSide(BlockSide side, double[] uv, SideRotation rot, int textureid, int tintidx) {
|
||||||
ModelSide ms = new ModelSide();
|
ModelSide ms = new ModelSide();
|
||||||
ms.textureid = textureid;
|
ms.textureid = textureid;
|
||||||
if (uv != null) {
|
if (uv != null) {
|
||||||
|
@ -38,23 +41,17 @@ public class ModelBlockModelImpl extends BlockModelImpl implements ModelBlockMod
|
||||||
if (side == BlockSide.FACE_5 || side == BlockSide.X_PLUS) side = BlockSide.EAST;
|
if (side == BlockSide.FACE_5 || side == BlockSide.X_PLUS) side = BlockSide.EAST;
|
||||||
|
|
||||||
sides.put(side, ms);
|
sides.put(side, ms);
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public void addBlockSide(BlockSide side, double[] uv, SideRotation rot, int textureid) {
|
||||||
|
addBlockSide(side, uv, rot, textureid, -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private ArrayList<ModelBlockImpl> boxes = new ArrayList<ModelBlockImpl>();
|
private ArrayList<ModelBlockImpl> boxes = new ArrayList<ModelBlockImpl>();
|
||||||
private String rotsourceblockname;
|
|
||||||
private int rotsourcemetaindex;
|
|
||||||
private int xrot, yrot, zrot;
|
|
||||||
|
|
||||||
public ModelBlockModelImpl(String blkname, ModModelDefinitionImpl mdf) {
|
public ModelBlockModelImpl(String blkname, ModModelDefinitionImpl mdf) {
|
||||||
super(blkname, mdf);
|
super(blkname, mdf);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelBlockModelImpl(String blkname, ModModelDefinitionImpl mdf, ModelBlockModel mod, int xrot, int yrot, int zrot) {
|
|
||||||
super(blkname, mdf);
|
|
||||||
this.rotsourceblockname = mod.getBlockNames()[0];
|
|
||||||
this.rotsourcemetaindex = Integer.numberOfTrailingZeros(mod.getMetaValueMask());
|
|
||||||
this.xrot = xrot; this.yrot = yrot; this.zrot = zrot;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HashMap<BlockSide, String> fromBlockSide = new HashMap<BlockSide, String>();
|
private static HashMap<BlockSide, String> fromBlockSide = new HashMap<BlockSide, String>();
|
||||||
static {
|
static {
|
||||||
|
@ -62,62 +59,59 @@ public class ModelBlockModelImpl extends BlockModelImpl implements ModelBlockMod
|
||||||
fromBlockSide.put(BlockSide.BOTTOM, "d");
|
fromBlockSide.put(BlockSide.BOTTOM, "d");
|
||||||
fromBlockSide.put(BlockSide.NORTH, "n");
|
fromBlockSide.put(BlockSide.NORTH, "n");
|
||||||
fromBlockSide.put(BlockSide.SOUTH, "s");
|
fromBlockSide.put(BlockSide.SOUTH, "s");
|
||||||
fromBlockSide.put(BlockSide.WEST, "e");
|
fromBlockSide.put(BlockSide.WEST, "w");
|
||||||
fromBlockSide.put(BlockSide.EAST, "w");
|
fromBlockSide.put(BlockSide.EAST, "e");
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getLine() {
|
public String getLine() {
|
||||||
String ids = this.getIDsAndMeta();
|
String ids = this.getIDsAndMeta();
|
||||||
if (ids == null) return null;
|
if (ids == null) return null;
|
||||||
String line = String.format("patchblock:%s", ids);
|
String line;
|
||||||
// If rotating another model
|
line = String.format("modellist:%s", ids);
|
||||||
if (rotsourceblockname != null) {
|
for (ModelBlockImpl mb: boxes) {
|
||||||
line += "\npatchrotate:id=" + rotsourceblockname + ",data=" + rotsourcemetaindex;
|
line += String.format(Locale.US, ",box=%f/%f/%f", mb.from[0], mb.from[1], mb.from[2]);
|
||||||
if (xrot != 0) {
|
if (!mb.shade) { // if shade=false
|
||||||
line += ",rotx=" + xrot;
|
line += "/false";
|
||||||
}
|
}
|
||||||
if (yrot != 0) {
|
line += String.format(Locale.US, ":%f/%f/%f", mb.to[0], mb.to[1], mb.to[2]);
|
||||||
line += ",roty=" + yrot;
|
if ((mb.xrot != 0) || (mb.yrot != 0) || (mb.zrot != 0)) { // If needed, add rotation
|
||||||
}
|
line += String.format(Locale.US, "/%f/%f/%f", mb.xrot, mb.yrot, mb.zrot);
|
||||||
if (zrot != 0) {
|
// If origin also defined, add it
|
||||||
line += ",rotz=" + yrot;
|
if (mb.rotorigin != null) {
|
||||||
}
|
line += String.format(Locale.US, "/%f/%f/%f", mb.rotorigin[0], mb.rotorigin[1], mb.rotorigin[2]);
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
for (ModelBlockImpl mb: boxes) {
|
for (BlockSide bs : fromBlockSide.keySet()) {
|
||||||
line += String.format(",box=%f/%f/%f:%f/%f/%f", mb.from[0], mb.from[1], mb.from[2], mb.to[0], mb.to[1], mb.to[2]);
|
String side = fromBlockSide.get(bs);
|
||||||
if ((mb.xrot != 0) || (mb.yrot != 0) || (mb.zrot != 0)) { // If needed, add rotation
|
ModelSide mside = mb.sides.get(bs);
|
||||||
line += String.format("/%f/%f/%f", mb.xrot, mb.yrot, mb.zrot);
|
if (mside != null) {
|
||||||
}
|
String rval = side;
|
||||||
for (BlockSide bs : fromBlockSide.keySet()) {
|
switch (mside.rot) {
|
||||||
String side = fromBlockSide.get(bs);
|
case DEG0:
|
||||||
ModelSide mside = mb.sides.get(bs);
|
default:
|
||||||
if (mside != null) {
|
break;
|
||||||
String rval = side;
|
case DEG90:
|
||||||
switch (mside.rot) {
|
rval += "90";
|
||||||
case DEG0:
|
break;
|
||||||
default:
|
case DEG180:
|
||||||
break;
|
rval += "180";
|
||||||
case DEG90:
|
break;
|
||||||
rval += "90";
|
case DEG270:
|
||||||
break;
|
rval += "270";
|
||||||
case DEG180:
|
break;
|
||||||
rval += "180";
|
}
|
||||||
break;
|
if (mside.uv != null) {
|
||||||
case DEG270:
|
line += String.format(Locale.US, ":%s/%d/%f/%f/%f/%f", rval, mside.textureid, mside.uv[0], mside.uv[1], mside.uv[2], mside.uv[3]);
|
||||||
rval += "270";
|
}
|
||||||
break;
|
else {
|
||||||
}
|
line += String.format(":%s/%d", rval, mside.textureid);
|
||||||
if (mside.uv != null) {
|
}
|
||||||
line += String.format(":%s/%d/%f/%f/%f/%f", rval, mside.textureid, mside.uv[0], mside.uv[1], mside.uv[2], mside.uv[3]);
|
}
|
||||||
}
|
}
|
||||||
else {
|
if ((mb.modrotx != 0) || (mb.modroty != 0) || (mb.modrotz != 0)) {
|
||||||
line += String.format(":%s/%d", rval, mside.textureid);
|
line += String.format(":R/%d/%d/%d", mb.modrotx, mb.modroty, mb.modrotz);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
@ -135,13 +129,27 @@ public class ModelBlockModelImpl extends BlockModelImpl implements ModelBlockMod
|
||||||
* @param xrot - degrees of rotation of block around X
|
* @param xrot - degrees of rotation of block around X
|
||||||
* @param yrot - degrees of rotation of block around Y
|
* @param yrot - degrees of rotation of block around Y
|
||||||
* @param zrot - degrees of rotation of block around Z
|
* @param zrot - degrees of rotation of block around Z
|
||||||
|
* @param shade - shade setting for model
|
||||||
|
* @param rotorigin - rotation origin, if any (default [ 8, 8, 8 ](
|
||||||
|
* @param modrotx - model level rotation in degrees (0, 90, 180, 270)
|
||||||
|
* @param modroty - model level rotation in degrees (0, 90, 180, 270)
|
||||||
|
* @param modrotz - model level rotation in degrees (0, 90, 180, 270)
|
||||||
* @return model block to add faces to
|
* @return model block to add faces to
|
||||||
*/
|
*/
|
||||||
public ModelBlock addModelBlock(double[] from, double[] to, double xrot, double yrot, double zrot) {
|
@Override
|
||||||
|
public ModelBlock addModelBlock(double[] from, double[] to, double xrot, double yrot, double zrot,
|
||||||
|
boolean shade, double[] rotorigin, int modrotx, int modroty, int modrotz) {
|
||||||
ModelBlockImpl mbi = new ModelBlockImpl();
|
ModelBlockImpl mbi = new ModelBlockImpl();
|
||||||
if (from != null) { mbi.from[0] = from[0]; mbi.from[1] = from[1]; mbi.from[2] = from[2]; }
|
if (from != null) { mbi.from[0] = from[0]; mbi.from[1] = from[1]; mbi.from[2] = from[2]; }
|
||||||
if (to != null) { mbi.to[0] = to[0]; mbi.to[1] = to[1]; mbi.to[2] = to[2]; }
|
if (to != null) { mbi.to[0] = to[0]; mbi.to[1] = to[1]; mbi.to[2] = to[2]; }
|
||||||
mbi.xrot = xrot; mbi.yrot = yrot; mbi.zrot = zrot;
|
mbi.xrot = xrot; mbi.yrot = yrot; mbi.zrot = zrot;
|
||||||
|
mbi.shade = shade;
|
||||||
|
if (rotorigin != null) {
|
||||||
|
mbi.rotorigin = Arrays.copyOf(rotorigin, 3);
|
||||||
|
}
|
||||||
|
mbi.modrotx = modrotx;
|
||||||
|
mbi.modroty = modroty;
|
||||||
|
mbi.modrotz = modrotz;
|
||||||
boxes.add(mbi);
|
boxes.add(mbi);
|
||||||
return mbi;
|
return mbi;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.dynmap.modsupport.PaneBlockModel;
|
||||||
|
|
||||||
public class PaneBlockModelImpl extends BlockModelImpl implements PaneBlockModel {
|
public class PaneBlockModelImpl extends BlockModelImpl implements PaneBlockModel {
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public PaneBlockModelImpl(int blkid, ModModelDefinitionImpl mdf) {
|
public PaneBlockModelImpl(int blkid, ModModelDefinitionImpl mdf) {
|
||||||
super(blkid, mdf);
|
super(blkid, mdf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import org.dynmap.renderer.RenderPatchFactory.SideVisible;
|
||||||
public class PatchBlockModelImpl extends BlockModelImpl implements PatchBlockModel {
|
public class PatchBlockModelImpl extends BlockModelImpl implements PatchBlockModel {
|
||||||
private ArrayList<String> patches = new ArrayList<String>();
|
private ArrayList<String> patches = new ArrayList<String>();
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public PatchBlockModelImpl(int blkid, ModModelDefinitionImpl mdf) {
|
public PatchBlockModelImpl(int blkid, ModModelDefinitionImpl mdf) {
|
||||||
super(blkid, mdf);
|
super(blkid, mdf);
|
||||||
}
|
}
|
||||||
|
@ -15,6 +16,7 @@ public class PatchBlockModelImpl extends BlockModelImpl implements PatchBlockMod
|
||||||
super(blkname, mdf);
|
super(blkname, mdf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public PatchBlockModelImpl(int blkid, ModModelDefinitionImpl mdf, PatchBlockModel mod, int xrot, int yrot, int zrot) {
|
public PatchBlockModelImpl(int blkid, ModModelDefinitionImpl mdf, PatchBlockModel mod, int xrot, int yrot, int zrot) {
|
||||||
super(blkid, mdf);
|
super(blkid, mdf);
|
||||||
PatchBlockModelImpl m = (PatchBlockModelImpl) mod;
|
PatchBlockModelImpl m = (PatchBlockModelImpl) mod;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.dynmap.renderer.RenderPatchFactory.SideVisible;
|
||||||
public class PlantBlockModelImpl extends BlockModelImpl implements PlantBlockModel {
|
public class PlantBlockModelImpl extends BlockModelImpl implements PlantBlockModel {
|
||||||
private String patch0;
|
private String patch0;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public PlantBlockModelImpl(int blkid, ModModelDefinitionImpl mdf) {
|
public PlantBlockModelImpl(int blkid, ModModelDefinitionImpl mdf) {
|
||||||
super(blkid, mdf);
|
super(blkid, mdf);
|
||||||
patch0 = mdf.getPatchID(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, SideVisible.FLIP);
|
patch0 = mdf.getPatchID(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, SideVisible.FLIP);
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.dynmap.modsupport.StairBlockModel;
|
||||||
|
|
||||||
public class StairBlockModelImpl extends BlockModelImpl implements StairBlockModel {
|
public class StairBlockModelImpl extends BlockModelImpl implements StairBlockModel {
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public StairBlockModelImpl(int blkid, ModModelDefinitionImpl mdf) {
|
public StairBlockModelImpl(int blkid, ModModelDefinitionImpl mdf) {
|
||||||
super(blkid, mdf);
|
super(blkid, mdf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.dynmap.modsupport.impl;
|
||||||
|
|
||||||
import org.dynmap.modsupport.VolumetricBlockModel;
|
import org.dynmap.modsupport.VolumetricBlockModel;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public class VolumetricBlockModelImpl extends BlockModelImpl implements VolumetricBlockModel {
|
public class VolumetricBlockModelImpl extends BlockModelImpl implements VolumetricBlockModel {
|
||||||
private boolean[][][] grid;
|
private boolean[][][] grid;
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ public class WallFenceBlockModelImpl extends BlockModelImpl implements WallFence
|
||||||
private final FenceType type;
|
private final FenceType type;
|
||||||
private int[] linked = new int[0];
|
private int[] linked = new int[0];
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public WallFenceBlockModelImpl(int blkid, ModModelDefinitionImpl mdf, FenceType type) {
|
public WallFenceBlockModelImpl(int blkid, ModModelDefinitionImpl mdf, FenceType type) {
|
||||||
super(blkid, mdf);
|
super(blkid, mdf);
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
@ -23,6 +24,7 @@ public class WallFenceBlockModelImpl extends BlockModelImpl implements WallFence
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public void addLinkedBlockID(int blkid) {
|
public void addLinkedBlockID(int blkid) {
|
||||||
int len = linked.length;
|
int len = linked.length;
|
||||||
linked = Arrays.copyOf(linked, len+1);
|
linked = Arrays.copyOf(linked, len+1);
|
||||||
|
@ -30,6 +32,7 @@ public class WallFenceBlockModelImpl extends BlockModelImpl implements WallFence
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public int[] getLinkedBlockIDs() {
|
public int[] getLinkedBlockIDs() {
|
||||||
return linked;
|
return linked;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.Class;
|
import java.lang.Class;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package org.dynmap.servlet;
|
||||||
|
|
||||||
import org.dynmap.DynmapCore;
|
import org.dynmap.DynmapCore;
|
||||||
import org.dynmap.DynmapWorld;
|
import org.dynmap.DynmapWorld;
|
||||||
import org.dynmap.MapType.ImageEncoding;
|
|
||||||
import org.dynmap.PlayerFaces;
|
import org.dynmap.PlayerFaces;
|
||||||
import org.dynmap.storage.MapStorage;
|
import org.dynmap.storage.MapStorage;
|
||||||
import org.dynmap.storage.MapStorageTile;
|
import org.dynmap.storage.MapStorageTile;
|
||||||
|
|
|
@ -19,13 +19,15 @@ import javax.servlet.http.HttpSession;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.dynmap.utils.IpAddressMatcher;;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class SendMessageServlet extends HttpServlet {
|
public class SendMessageServlet extends HttpServlet {
|
||||||
protected static final Logger log = Logger.getLogger("Minecraft");
|
protected static final Logger log = Logger.getLogger("Minecraft");
|
||||||
|
@ -50,8 +52,16 @@ public class SendMessageServlet extends HttpServlet {
|
||||||
public boolean chat_perms = false;
|
public boolean chat_perms = false;
|
||||||
public int lengthlimit = 256;
|
public int lengthlimit = 256;
|
||||||
public DynmapCore core;
|
public DynmapCore core;
|
||||||
public HashSet<String> proxyaddress = new HashSet<String>();
|
public ArrayList<IpAddressMatcher> proxyaddress = new ArrayList<IpAddressMatcher>();
|
||||||
|
|
||||||
|
private boolean trustedProxy(String ip) {
|
||||||
|
for (IpAddressMatcher m : proxyaddress) {
|
||||||
|
if (m.matches(ip)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
byte[] bytes;
|
byte[] bytes;
|
||||||
|
@ -92,19 +102,13 @@ public class SendMessageServlet extends HttpServlet {
|
||||||
if ((message.name == null) || message.name.equals("")) {
|
if ((message.name == null) || message.name.equals("")) {
|
||||||
/* If from trusted proxy, check for client */
|
/* If from trusted proxy, check for client */
|
||||||
String rmtaddr = request.getRemoteAddr();
|
String rmtaddr = request.getRemoteAddr();
|
||||||
if (this.proxyaddress.contains(rmtaddr)) {
|
if (this.trustedProxy(rmtaddr)) { // If remote address is valid trusted proxy
|
||||||
/* If proxied client address, get original IP */
|
/* If proxied client address, get original IP */
|
||||||
if (request.getHeader("X-Forwarded-For") != null) {
|
if (request.getHeader("X-Forwarded-For") != null) {
|
||||||
/* If trusted proxies were chained, we get next client address till non-trusted proxy met */
|
// Split list, since addresses after first are proxy chain
|
||||||
String[] proxyAddrs = request.getHeader("X-Forwarded-For").split(", ");
|
String[] proxyAddrs = request.getHeader("X-Forwarded-For").split(",");
|
||||||
for(int i = proxyAddrs.length - 1; i >= 0; i--){
|
// We only want first - any others are proxies that our local proxy was willing to pass to us
|
||||||
if (!this.proxyaddress.contains(proxyAddrs[i])) {
|
message.name = proxyAddrs[0].trim();
|
||||||
/* use remaining addresses as name (maybe we can use the last or the first non-trusted one?) */
|
|
||||||
message.name = proxyAddrs[0]; // 0 .. i
|
|
||||||
for(int j = 1; j <= i; j++) message.name += ", " + proxyAddrs[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
message.name = String.valueOf(o.get("name"));
|
message.name = String.valueOf(o.get("name"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.dynmap.storage;
|
package org.dynmap.storage;
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
|
@ -25,13 +26,18 @@ public abstract class MapStorage {
|
||||||
private static HashMap<String, Integer> filelocks = new HashMap<String, Integer>();
|
private static HashMap<String, Integer> filelocks = new HashMap<String, Integer>();
|
||||||
private static final Integer WRITELOCK = (-1);
|
private static final Integer WRITELOCK = (-1);
|
||||||
protected File baseStandaloneDir;
|
protected File baseStandaloneDir;
|
||||||
|
protected boolean isShutdown;
|
||||||
|
|
||||||
protected long serverID;
|
protected long serverID;
|
||||||
|
|
||||||
protected MapStorage() {
|
protected MapStorage() {
|
||||||
this.serverID = 0;
|
this.serverID = 0;
|
||||||
|
this.isShutdown = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void shutdownStorage() {
|
||||||
|
this.isShutdown = true;
|
||||||
|
}
|
||||||
// Proper modulo - versus the bogus Java behavior of negative modulo for negative numerators
|
// Proper modulo - versus the bogus Java behavior of negative modulo for negative numerators
|
||||||
protected static final int modulo(int x, int y) {
|
protected static final int modulo(int x, int y) {
|
||||||
return ((x % y) + y) % y;
|
return ((x % y) + y) % y;
|
||||||
|
@ -459,7 +465,22 @@ public abstract class MapStorage {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test if storage needs static web files
|
||||||
|
public boolean needsStaticWebFiles() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Set static web file content
|
||||||
|
* @param fileid - file path
|
||||||
|
* @param buffer - content for file
|
||||||
|
* @return true if successful
|
||||||
|
*/
|
||||||
|
public boolean setStaticWebFile(String fileid, BufferOutputStream buffer) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void logSQLException(String opmsg, SQLException x) {
|
public void logSQLException(String opmsg, SQLException x) {
|
||||||
|
if (isShutdown) return;
|
||||||
Log.severe("SQLException: " + opmsg);
|
Log.severe("SQLException: " + opmsg);
|
||||||
Log.severe(" ErrorCode: " + x.getErrorCode() + ", SQLState=" + x.getSQLState());
|
Log.severe(" ErrorCode: " + x.getErrorCode() + ", SQLState=" + x.getSQLState());
|
||||||
Log.severe(" Message: " + x.getMessage());
|
Log.severe(" Message: " + x.getMessage());
|
||||||
|
@ -470,4 +491,11 @@ public abstract class MapStorage {
|
||||||
cause = cause.getCause();
|
cause = cause.getCause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class StorageShutdownException extends Exception {
|
||||||
|
private static final long serialVersionUID = 8961471920726795043L;
|
||||||
|
|
||||||
|
public StorageShutdownException() {}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package org.dynmap.storage;
|
package org.dynmap.storage;
|
||||||
|
|
||||||
import org.dynmap.MapType.ImageEncoding;
|
|
||||||
|
|
||||||
public interface MapStorageTileSearchEndCB {
|
public interface MapStorageTileSearchEndCB {
|
||||||
/**
|
/**
|
||||||
* Callback for end of tile enumeration calls
|
* Callback for end of tile enumeration calls
|
||||||
|
|
|
@ -0,0 +1,820 @@
|
||||||
|
package org.dynmap.storage.aws_s3;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.dynmap.DynmapCore;
|
||||||
|
import org.dynmap.DynmapWorld;
|
||||||
|
import org.dynmap.Log;
|
||||||
|
import org.dynmap.MapType;
|
||||||
|
import org.dynmap.MapType.ImageEncoding;
|
||||||
|
import org.dynmap.MapType.ImageVariant;
|
||||||
|
import org.dynmap.PlayerFaces.FaceType;
|
||||||
|
import org.dynmap.WebAuthManager;
|
||||||
|
import org.dynmap.storage.MapStorage;
|
||||||
|
import org.dynmap.storage.MapStorageTile;
|
||||||
|
import org.dynmap.storage.MapStorageTileEnumCB;
|
||||||
|
import org.dynmap.storage.MapStorageBaseTileEnumCB;
|
||||||
|
import org.dynmap.storage.MapStorageTileSearchEndCB;
|
||||||
|
import org.dynmap.utils.BufferInputStream;
|
||||||
|
import org.dynmap.utils.BufferOutputStream;
|
||||||
|
|
||||||
|
import io.github.linktosriram.s3lite.api.client.S3Client;
|
||||||
|
import io.github.linktosriram.s3lite.api.exception.NoSuchKeyException;
|
||||||
|
import io.github.linktosriram.s3lite.api.exception.S3Exception;
|
||||||
|
import io.github.linktosriram.s3lite.api.region.Region;
|
||||||
|
import io.github.linktosriram.s3lite.api.request.DeleteObjectRequest;
|
||||||
|
import io.github.linktosriram.s3lite.api.request.GetObjectRequest;
|
||||||
|
import io.github.linktosriram.s3lite.api.request.ListObjectsV2Request;
|
||||||
|
import io.github.linktosriram.s3lite.api.request.PutObjectRequest;
|
||||||
|
import io.github.linktosriram.s3lite.api.response.GetObjectResponse;
|
||||||
|
import io.github.linktosriram.s3lite.api.response.ListObjectsV2Response;
|
||||||
|
import io.github.linktosriram.s3lite.api.response.ResponseBytes;
|
||||||
|
import io.github.linktosriram.s3lite.api.response.S3Object;
|
||||||
|
import io.github.linktosriram.s3lite.core.auth.AwsBasicCredentials;
|
||||||
|
import io.github.linktosriram.s3lite.core.client.DefaultS3ClientBuilder;
|
||||||
|
import io.github.linktosriram.s3lite.http.spi.request.RequestBody;
|
||||||
|
import io.github.linktosriram.s3lite.http.urlconnection.URLConnectionSdkHttpClient;
|
||||||
|
|
||||||
|
public class AWSS3MapStorage extends MapStorage {
|
||||||
|
public class StorageTile extends MapStorageTile {
|
||||||
|
private final String baseKey;
|
||||||
|
private final String uri;
|
||||||
|
|
||||||
|
StorageTile(DynmapWorld world, MapType map, int x, int y,
|
||||||
|
int zoom, ImageVariant var) {
|
||||||
|
super(world, map, x, y, zoom, var);
|
||||||
|
|
||||||
|
String baseURI;
|
||||||
|
if (zoom > 0) {
|
||||||
|
baseURI = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz".substring(0, zoom) + "_" + x + "_" + y;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
baseURI = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + x + "_" + y;
|
||||||
|
}
|
||||||
|
uri = baseURI + "." + map.getImageFormat().getFileExt();
|
||||||
|
baseKey = AWSS3MapStorage.this.prefix + "tiles/" + world.getName() + "/" + uri;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean exists() {
|
||||||
|
boolean exists = false;
|
||||||
|
S3Client s3 = null;
|
||||||
|
try {
|
||||||
|
s3 = getConnection();
|
||||||
|
ListObjectsV2Request req = ListObjectsV2Request.builder().bucketName(bucketname).prefix(baseKey).maxKeys(1).build();
|
||||||
|
ListObjectsV2Response rslt = s3.listObjectsV2(req);
|
||||||
|
if ((rslt != null) && (rslt.getKeyCount() > 0))
|
||||||
|
exists = true;
|
||||||
|
} catch (S3Exception x) {
|
||||||
|
if (!x.getCode().equals("SignatureDoesNotMatch")) { // S3 behavior when no object match....
|
||||||
|
Log.severe("AWS Exception", x);
|
||||||
|
}
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
releaseConnection(s3);
|
||||||
|
}
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matchesHashCode(long hash) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TileRead read() {
|
||||||
|
S3Client s3 = null;
|
||||||
|
try {
|
||||||
|
s3 = getConnection();
|
||||||
|
GetObjectRequest req = GetObjectRequest.builder().bucketName(bucketname).key(baseKey).build();
|
||||||
|
ResponseBytes<GetObjectResponse> obj = s3.getObjectAsBytes(req);
|
||||||
|
if (obj != null) {
|
||||||
|
GetObjectResponse rsp = obj.getResponse();
|
||||||
|
TileRead tr = new TileRead();
|
||||||
|
byte[] buf = obj.getBytes();
|
||||||
|
if (buf == null) { return null; }
|
||||||
|
tr.image = new BufferInputStream(buf);
|
||||||
|
tr.format = ImageEncoding.fromContentType(rsp.getContentType());
|
||||||
|
Map<String, String> meta = rsp.getMetadata();
|
||||||
|
String v = meta.get("x-dynmap-hash");
|
||||||
|
if (v != null) {
|
||||||
|
tr.hashCode = Long.parseLong(v, 16);
|
||||||
|
}
|
||||||
|
v = meta.get("x-dynmap-ts");
|
||||||
|
if (v != null) {
|
||||||
|
tr.lastModified = Long.parseLong(v);
|
||||||
|
}
|
||||||
|
return tr;
|
||||||
|
}
|
||||||
|
} catch (NoSuchKeyException nskx) {
|
||||||
|
return null; // Nominal case if it doesn't exist
|
||||||
|
} catch (S3Exception x) {
|
||||||
|
Log.severe("AWS Exception", x);
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
} finally {
|
||||||
|
releaseConnection(s3);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean write(long hash, BufferOutputStream encImage, long timestamp) {
|
||||||
|
boolean done = false;
|
||||||
|
S3Client s3 = null;
|
||||||
|
try {
|
||||||
|
s3 = getConnection();
|
||||||
|
if (encImage == null) { // Delete?
|
||||||
|
DeleteObjectRequest req = DeleteObjectRequest.builder().bucketName(bucketname).key(baseKey).build();
|
||||||
|
s3.deleteObject(req);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PutObjectRequest req = PutObjectRequest.builder().bucketName(bucketname).key(baseKey).contentType(map.getImageFormat().getEncoding().getContentType())
|
||||||
|
.addMetadata("x-dynmap-hash", Long.toHexString(hash)).addMetadata("x-dynmap-ts", Long.toString(timestamp)).build();
|
||||||
|
s3.putObject(req, RequestBody.fromBytes(encImage.buf));
|
||||||
|
}
|
||||||
|
done = true;
|
||||||
|
} catch (S3Exception x) {
|
||||||
|
Log.severe("AWS Exception", x);
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
} finally {
|
||||||
|
releaseConnection(s3);
|
||||||
|
}
|
||||||
|
// Signal update for zoom out
|
||||||
|
if (zoom == 0) {
|
||||||
|
world.enqueueZoomOutUpdate(this);
|
||||||
|
}
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getWriteLock() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void releaseWriteLock() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getReadLock(long timeout) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void releaseReadLock() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getURI() {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enqueueZoomOutUpdate() {
|
||||||
|
world.enqueueZoomOutUpdate(this);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public MapStorageTile getZoomOutTile() {
|
||||||
|
int xx, yy;
|
||||||
|
int step = 1 << zoom;
|
||||||
|
if(x >= 0)
|
||||||
|
xx = x - (x % (2*step));
|
||||||
|
else
|
||||||
|
xx = x + (x % (2*step));
|
||||||
|
yy = -y;
|
||||||
|
if(yy >= 0)
|
||||||
|
yy = yy - (yy % (2*step));
|
||||||
|
else
|
||||||
|
yy = yy + (yy % (2*step));
|
||||||
|
yy = -yy;
|
||||||
|
return new StorageTile(world, map, xx, yy, zoom+1, var);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o instanceof StorageTile) {
|
||||||
|
StorageTile st = (StorageTile) o;
|
||||||
|
return baseKey.equals(st.baseKey);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return baseKey.hashCode();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return baseKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String bucketname;
|
||||||
|
private Region region;
|
||||||
|
private String access_key_id;
|
||||||
|
private String secret_access_key;
|
||||||
|
private String prefix;
|
||||||
|
|
||||||
|
private int POOLSIZE = 4;
|
||||||
|
private int cpoolCount = 0;
|
||||||
|
private S3Client[] cpool = new S3Client[POOLSIZE];
|
||||||
|
|
||||||
|
public AWSS3MapStorage() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean init(DynmapCore core) {
|
||||||
|
if (!super.init(core)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!core.isInternalWebServerDisabled) {
|
||||||
|
Log.severe("AWS S3 storage is not supported option with internal web server: set disable-webserver: true in configuration.txt");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (core.isLoginSupportEnabled()) {
|
||||||
|
Log.severe("AWS S3 storage is not supported option with loegin support enabled: set login-enabled: false in configuration.txt");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Get our settings
|
||||||
|
bucketname = core.configuration.getString("storage/bucketname", "dynmap");
|
||||||
|
access_key_id = core.configuration.getString("storage/aws_access_key_id", System.getenv("AWS_ACCESS_KEY_ID"));
|
||||||
|
secret_access_key = core.configuration.getString("storage/aws_secret_access_key", System.getenv("AWS_SECRET_ACCESS_KEY"));
|
||||||
|
prefix = core.configuration.getString("storage/prefix", "");
|
||||||
|
|
||||||
|
// Either use a custom region, or one of the default AWS regions
|
||||||
|
String region_name = core.configuration.getString("storage/region", "us-east-1");
|
||||||
|
String region_endpoint = core.configuration.getString("storage/override_endpoint", "");
|
||||||
|
|
||||||
|
if (region_endpoint.length() > 0) {
|
||||||
|
region = Region.of(region_name, URI.create(region_endpoint));
|
||||||
|
} else {
|
||||||
|
region = Region.fromString(region_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((prefix.length() > 0) && (prefix.charAt(prefix.length()-1) != '/')) {
|
||||||
|
prefix += '/';
|
||||||
|
}
|
||||||
|
// Now creste the access client for the S3 service
|
||||||
|
Log.info("Using AWS S3 storage: web site at S3 bucket " + bucketname + " in region " + region);
|
||||||
|
S3Client s3 = null;
|
||||||
|
try {
|
||||||
|
s3 = getConnection();
|
||||||
|
if (s3 == null) {
|
||||||
|
Log.severe("Error creating S3 access client");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Make sure bucket exists (do list)
|
||||||
|
ListObjectsV2Request listreq = ListObjectsV2Request.builder()
|
||||||
|
.bucketName(bucketname)
|
||||||
|
.maxKeys(1)
|
||||||
|
.prefix(prefix)
|
||||||
|
.build();
|
||||||
|
ListObjectsV2Response rslt = s3.listObjectsV2(listreq);
|
||||||
|
if (rslt == null) {
|
||||||
|
Log.severe("Error: cannot find or access S3 bucket");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
rslt.getContents();
|
||||||
|
} catch (S3Exception s3x) {
|
||||||
|
Log.severe("AWS Exception", s3x);
|
||||||
|
return false;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
releaseConnection(s3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapStorageTile getTile(DynmapWorld world, MapType map, int x, int y,
|
||||||
|
int zoom, ImageVariant var) {
|
||||||
|
return new StorageTile(world, map, x, y, zoom, var);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapStorageTile getTile(DynmapWorld world, String uri) {
|
||||||
|
String[] suri = uri.split("/");
|
||||||
|
if (suri.length < 2) return null;
|
||||||
|
String mname = suri[0]; // Map URI - might include variant
|
||||||
|
MapType mt = null;
|
||||||
|
ImageVariant imgvar = null;
|
||||||
|
// Find matching map type and image variant
|
||||||
|
for (int mti = 0; (mt == null) && (mti < world.maps.size()); mti++) {
|
||||||
|
MapType type = world.maps.get(mti);
|
||||||
|
ImageVariant[] var = type.getVariants();
|
||||||
|
for (int ivi = 0; (imgvar == null) && (ivi < var.length); ivi++) {
|
||||||
|
if (mname.equals(type.getPrefix() + var[ivi].variantSuffix)) {
|
||||||
|
mt = type;
|
||||||
|
imgvar = var[ivi];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mt == null) { // Not found?
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// Now, take the last section and parse out coordinates and zoom
|
||||||
|
String fname = suri[suri.length-1];
|
||||||
|
String[] coord = fname.split("[_\\.]");
|
||||||
|
if (coord.length < 3) { // 3 or 4
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int zoom = 0;
|
||||||
|
int x, y;
|
||||||
|
try {
|
||||||
|
if (coord[0].charAt(0) == 'z') {
|
||||||
|
zoom = coord[0].length();
|
||||||
|
x = Integer.parseInt(coord[1]);
|
||||||
|
y = Integer.parseInt(coord[2]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
x = Integer.parseInt(coord[0]);
|
||||||
|
y = Integer.parseInt(coord[1]);
|
||||||
|
}
|
||||||
|
return getTile(world, mt, x, y, zoom, imgvar);
|
||||||
|
} catch (NumberFormatException nfx) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void processEnumMapTiles(DynmapWorld world, MapType map, ImageVariant var, MapStorageTileEnumCB cb, MapStorageBaseTileEnumCB cbBase,
|
||||||
|
MapStorageTileSearchEndCB cbEnd) {
|
||||||
|
String basekey = prefix + "tiles/" + world.getName() + "/" + map.getPrefix() + var.variantSuffix + "/";
|
||||||
|
ListObjectsV2Request req = ListObjectsV2Request.builder().bucketName(bucketname).prefix(basekey).maxKeys(1000).build();
|
||||||
|
boolean done = false;
|
||||||
|
S3Client s3 = null;
|
||||||
|
try {
|
||||||
|
s3 = getConnection();
|
||||||
|
while (!done) {
|
||||||
|
ListObjectsV2Response result = s3.listObjectsV2(req);
|
||||||
|
List<S3Object> objects = result.getContents();
|
||||||
|
for (S3Object os : objects) {
|
||||||
|
String key = os.getKey();
|
||||||
|
key = key.substring(basekey.length()); // Strip off base
|
||||||
|
// Parse the extension
|
||||||
|
String ext = null;
|
||||||
|
int extoff = key.lastIndexOf('.');
|
||||||
|
if (extoff >= 0) {
|
||||||
|
ext = key.substring(extoff+1);
|
||||||
|
key = key.substring(0, extoff);
|
||||||
|
}
|
||||||
|
// If not valid image extension, ignore
|
||||||
|
ImageEncoding fmt = ImageEncoding.fromExt(ext);
|
||||||
|
if (fmt == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// See if zoom tile: figure out zoom level
|
||||||
|
int zoom = 0;
|
||||||
|
if (key.startsWith("z")) {
|
||||||
|
while (key.startsWith("z")) {
|
||||||
|
key = key.substring(1);
|
||||||
|
zoom++;
|
||||||
|
}
|
||||||
|
if (key.startsWith("_")) {
|
||||||
|
key = key.substring(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Split remainder to get coords
|
||||||
|
String[] coord = key.split("_");
|
||||||
|
if (coord.length == 2) { // Must be 2 to be a tile
|
||||||
|
try {
|
||||||
|
int x = Integer.parseInt(coord[0]);
|
||||||
|
int y = Integer.parseInt(coord[1]);
|
||||||
|
// Invoke callback
|
||||||
|
MapStorageTile t = new StorageTile(world, map, x, y, zoom, var);
|
||||||
|
if(cb != null)
|
||||||
|
cb.tileFound(t, fmt);
|
||||||
|
if(cbBase != null && t.zoom == 0)
|
||||||
|
cbBase.tileFound(t, fmt);
|
||||||
|
t.cleanup();
|
||||||
|
} catch (NumberFormatException nfx) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result.isTruncated()) { // If more, build continuiation request
|
||||||
|
req = ListObjectsV2Request.builder().bucketName(bucketname)
|
||||||
|
.prefix(basekey).delimiter("").maxKeys(1000).continuationToken(result.getContinuationToken()).encodingType("url").requestPayer("requester").build();
|
||||||
|
}
|
||||||
|
else { // Else, we're done
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (S3Exception x) {
|
||||||
|
if (!x.getCode().equals("SignatureDoesNotMatch")) { // S3 behavior when no object match....
|
||||||
|
Log.severe("AWS Exception", x);
|
||||||
|
Log.severe("req=" + req);
|
||||||
|
}
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
} finally {
|
||||||
|
releaseConnection(s3);
|
||||||
|
}
|
||||||
|
if(cbEnd != null) {
|
||||||
|
cbEnd.searchEnded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enumMapTiles(DynmapWorld world, MapType map, MapStorageTileEnumCB cb) {
|
||||||
|
List<MapType> mtlist;
|
||||||
|
|
||||||
|
if (map != null) {
|
||||||
|
mtlist = Collections.singletonList(map);
|
||||||
|
}
|
||||||
|
else { // Else, add all directories under world directory (for maps)
|
||||||
|
mtlist = new ArrayList<MapType>(world.maps);
|
||||||
|
}
|
||||||
|
for (MapType mt : mtlist) {
|
||||||
|
ImageVariant[] vars = mt.getVariants();
|
||||||
|
for (ImageVariant var : vars) {
|
||||||
|
processEnumMapTiles(world, mt, var, cb, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enumMapBaseTiles(DynmapWorld world, MapType map, MapStorageBaseTileEnumCB cbBase, MapStorageTileSearchEndCB cbEnd) {
|
||||||
|
List<MapType> mtlist;
|
||||||
|
|
||||||
|
if (map != null) {
|
||||||
|
mtlist = Collections.singletonList(map);
|
||||||
|
}
|
||||||
|
else { // Else, add all directories under world directory (for maps)
|
||||||
|
mtlist = new ArrayList<MapType>(world.maps);
|
||||||
|
}
|
||||||
|
for (MapType mt : mtlist) {
|
||||||
|
ImageVariant[] vars = mt.getVariants();
|
||||||
|
for (ImageVariant var : vars) {
|
||||||
|
processEnumMapTiles(world, mt, var, null, cbBase, cbEnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processPurgeMapTiles(DynmapWorld world, MapType map, ImageVariant var) {
|
||||||
|
String basekey = prefix + "tiles/" + world.getName() + "/" + map.getPrefix() + var.variantSuffix + "/";
|
||||||
|
ListObjectsV2Request req = ListObjectsV2Request.builder().bucketName(bucketname).prefix(basekey).delimiter("").maxKeys(1000).encodingType("url").requestPayer("requester").build();
|
||||||
|
S3Client s3 = null;
|
||||||
|
try {
|
||||||
|
s3 = getConnection();
|
||||||
|
boolean done = false;
|
||||||
|
while (!done) {
|
||||||
|
ListObjectsV2Response result = s3.listObjectsV2(req);
|
||||||
|
List<S3Object> objects = result.getContents();
|
||||||
|
for (S3Object os : objects) {
|
||||||
|
String key = os.getKey();
|
||||||
|
DeleteObjectRequest delreq = DeleteObjectRequest.builder().bucketName(bucketname).key(key).build();
|
||||||
|
s3.deleteObject(delreq);
|
||||||
|
}
|
||||||
|
if (result.isTruncated()) { // If more, build continuiation request
|
||||||
|
req = ListObjectsV2Request.builder().bucketName(bucketname)
|
||||||
|
.prefix(basekey).delimiter("").maxKeys(1000).continuationToken(result.getContinuationToken()).encodingType("url").requestPayer("requester").build();
|
||||||
|
}
|
||||||
|
else { // Else, we're done
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (S3Exception x) {
|
||||||
|
if (!x.getCode().equals("SignatureDoesNotMatch")) { // S3 behavior when no object match....
|
||||||
|
Log.severe("AWS Exception", x);
|
||||||
|
Log.severe("req=" + req);
|
||||||
|
}
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
} finally {
|
||||||
|
releaseConnection(s3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void purgeMapTiles(DynmapWorld world, MapType map) {
|
||||||
|
List<MapType> mtlist;
|
||||||
|
|
||||||
|
if (map != null) {
|
||||||
|
mtlist = Collections.singletonList(map);
|
||||||
|
}
|
||||||
|
else { // Else, add all directories under world directory (for maps)
|
||||||
|
mtlist = new ArrayList<MapType>(world.maps);
|
||||||
|
}
|
||||||
|
for (MapType mt : mtlist) {
|
||||||
|
ImageVariant[] vars = mt.getVariants();
|
||||||
|
for (ImageVariant var : vars) {
|
||||||
|
processPurgeMapTiles(world, mt, var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setPlayerFaceImage(String playername, FaceType facetype,
|
||||||
|
BufferOutputStream encImage) {
|
||||||
|
boolean done = false;
|
||||||
|
String baseKey = prefix + "tiles/faces/" + facetype.id + "/" + playername + ".png";
|
||||||
|
S3Client s3 = null;
|
||||||
|
try {
|
||||||
|
s3 = getConnection();
|
||||||
|
if (encImage == null) { // Delete?
|
||||||
|
DeleteObjectRequest delreq = DeleteObjectRequest.builder().bucketName(bucketname).key(baseKey).build();
|
||||||
|
s3.deleteObject(delreq);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PutObjectRequest req = PutObjectRequest.builder().bucketName(bucketname).key(baseKey).contentType("image/png").build();
|
||||||
|
s3.putObject(req, RequestBody.fromBytes(encImage.buf));
|
||||||
|
}
|
||||||
|
done = true;
|
||||||
|
} catch (S3Exception x) {
|
||||||
|
Log.severe("AWS Exception", x);
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
} finally {
|
||||||
|
releaseConnection(s3);
|
||||||
|
}
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BufferInputStream getPlayerFaceImage(String playername,
|
||||||
|
FaceType facetype) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasPlayerFaceImage(String playername, FaceType facetype) {
|
||||||
|
String baseKey = prefix + "tiles/faces/" + facetype.id + "/" + playername + ".png";
|
||||||
|
boolean exists = false;
|
||||||
|
S3Client s3 = null;
|
||||||
|
try {
|
||||||
|
s3 = getConnection();
|
||||||
|
ListObjectsV2Request req = ListObjectsV2Request.builder().bucketName(bucketname).prefix(baseKey).maxKeys(1).build();
|
||||||
|
ListObjectsV2Response rslt = s3.listObjectsV2(req);
|
||||||
|
if ((rslt != null) && (rslt.getKeyCount() > 0))
|
||||||
|
exists = true;
|
||||||
|
} catch (S3Exception x) {
|
||||||
|
if (!x.getCode().equals("SignatureDoesNotMatch")) { // S3 behavior when no object match....
|
||||||
|
Log.severe("AWS Exception", x);
|
||||||
|
}
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
} finally {
|
||||||
|
releaseConnection(s3);
|
||||||
|
}
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setMarkerImage(String markerid, BufferOutputStream encImage) {
|
||||||
|
boolean done = false;
|
||||||
|
String baseKey = prefix + "tiles/_markers_/" + markerid + ".png";
|
||||||
|
S3Client s3 = null;
|
||||||
|
try {
|
||||||
|
s3 = getConnection();
|
||||||
|
if (encImage == null) { // Delete?
|
||||||
|
DeleteObjectRequest delreq = DeleteObjectRequest.builder().bucketName(bucketname).key(baseKey).build();
|
||||||
|
s3.deleteObject(delreq);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PutObjectRequest req = PutObjectRequest.builder().bucketName(bucketname).key(baseKey).contentType("image/png").build();
|
||||||
|
s3.putObject(req, RequestBody.fromBytes(encImage.buf));
|
||||||
|
}
|
||||||
|
done = true;
|
||||||
|
} catch (S3Exception x) {
|
||||||
|
Log.severe("AWS Exception", x);
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
} finally {
|
||||||
|
releaseConnection(s3);
|
||||||
|
}
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BufferInputStream getMarkerImage(String markerid) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setMarkerFile(String world, String content) {
|
||||||
|
boolean done = false;
|
||||||
|
String baseKey = prefix + "tiles/_markers_/marker_" + world + ".json";
|
||||||
|
S3Client s3 = null;
|
||||||
|
try {
|
||||||
|
s3 = getConnection();
|
||||||
|
if (content == null) { // Delete?
|
||||||
|
DeleteObjectRequest delreq = DeleteObjectRequest.builder().bucketName(bucketname).key(baseKey).build();
|
||||||
|
s3.deleteObject(delreq);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PutObjectRequest req = PutObjectRequest.builder().bucketName(bucketname).key(baseKey).contentType("application/json").build();
|
||||||
|
s3.putObject(req, RequestBody.fromBytes(content.getBytes(StandardCharsets.UTF_8)));
|
||||||
|
}
|
||||||
|
done = true;
|
||||||
|
} catch (S3Exception x) {
|
||||||
|
Log.severe("AWS Exception", x);
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
} finally {
|
||||||
|
releaseConnection(s3);
|
||||||
|
}
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMarkerFile(String world) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
// For external web server only
|
||||||
|
public String getMarkersURI(boolean login_enabled) {
|
||||||
|
return "tiles/";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
// For external web server only
|
||||||
|
public String getTilesURI(boolean login_enabled) {
|
||||||
|
return "tiles/";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URI to use for loading configuration JSON files (for external web server only)
|
||||||
|
* @param login_enabled - selects based on login security enabled
|
||||||
|
* @return URI
|
||||||
|
*/
|
||||||
|
public String getConfigurationJSONURI(boolean login_enabled) {
|
||||||
|
return "standalone/dynmap_config.json?_={timestamp}";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* URI to use for loading update JSON files (for external web server only)
|
||||||
|
* @param login_enabled - selects based on login security enabled
|
||||||
|
* @return URI
|
||||||
|
*/
|
||||||
|
public String getUpdateJSONURI(boolean login_enabled) {
|
||||||
|
return "standalone/dynmap_{world}.json?_={timestamp}";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addPaths(StringBuilder sb, DynmapCore core) {
|
||||||
|
String p = core.getTilesFolder().getAbsolutePath();
|
||||||
|
if(!p.endsWith("/"))
|
||||||
|
p += "/";
|
||||||
|
sb.append("$tilespath = \'");
|
||||||
|
sb.append(WebAuthManager.esc(p));
|
||||||
|
sb.append("\';\n");
|
||||||
|
sb.append("$markerspath = \'");
|
||||||
|
sb.append(WebAuthManager.esc(p));
|
||||||
|
sb.append("\';\n");
|
||||||
|
|
||||||
|
// Need to call base to add webpath
|
||||||
|
super.addPaths(sb, core);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BufferInputStream getStandaloneFile(String fileid) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Cache to avoid rewriting same standalong file repeatedly
|
||||||
|
private ConcurrentHashMap<String, byte[]> standalone_cache = new ConcurrentHashMap<String, byte[]>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setStandaloneFile(String fileid, BufferOutputStream content) {
|
||||||
|
return setStaticWebFile("standalone/" + fileid, content);
|
||||||
|
}
|
||||||
|
// Test if storage needs static web files
|
||||||
|
public boolean needsStaticWebFiles() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Set static web file content
|
||||||
|
* @param fileid - file path
|
||||||
|
* @param content - content for file
|
||||||
|
* @return true if successful
|
||||||
|
*/
|
||||||
|
public boolean setStaticWebFile(String fileid, BufferOutputStream content) {
|
||||||
|
|
||||||
|
boolean done = false;
|
||||||
|
String baseKey = prefix + fileid;
|
||||||
|
S3Client s3 = null;
|
||||||
|
try {
|
||||||
|
s3 = getConnection();
|
||||||
|
byte[] cacheval = standalone_cache.get(fileid);
|
||||||
|
|
||||||
|
if (content == null) { // Delete?
|
||||||
|
if ((cacheval != null) && (cacheval.length == 0)) { // Delete cached?
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
DeleteObjectRequest delreq = DeleteObjectRequest.builder().bucketName(bucketname).key(baseKey).build();
|
||||||
|
s3.deleteObject(delreq);
|
||||||
|
standalone_cache.put(fileid, new byte[0]); // Mark in cache
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
byte[] digest = content.buf;
|
||||||
|
try {
|
||||||
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||||
|
md.update(content.buf);
|
||||||
|
digest = md.digest();
|
||||||
|
} catch (NoSuchAlgorithmException nsax) {
|
||||||
|
|
||||||
|
}
|
||||||
|
// If cached and same, just return
|
||||||
|
if (Arrays.equals(digest, cacheval)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
String ct = "text/plain";
|
||||||
|
if (fileid.endsWith(".json")) {
|
||||||
|
ct = "application/json";
|
||||||
|
}
|
||||||
|
else if (fileid.endsWith(".php")) {
|
||||||
|
ct = "application/x-httpd-php";
|
||||||
|
}
|
||||||
|
else if (fileid.endsWith(".html")) {
|
||||||
|
ct = "text/html";
|
||||||
|
}
|
||||||
|
else if (fileid.endsWith(".css")) {
|
||||||
|
ct = "text/css";
|
||||||
|
}
|
||||||
|
else if (fileid.endsWith(".js")) {
|
||||||
|
ct = "application/x-javascript";
|
||||||
|
}
|
||||||
|
PutObjectRequest req = PutObjectRequest.builder().bucketName(bucketname).key(baseKey).contentType(ct).build();
|
||||||
|
s3.putObject(req, RequestBody.fromBytes(content.buf));
|
||||||
|
standalone_cache.put(fileid, digest);
|
||||||
|
}
|
||||||
|
done = true;
|
||||||
|
} catch (S3Exception x) {
|
||||||
|
Log.severe("AWS Exception", x);
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
} finally {
|
||||||
|
releaseConnection(s3);
|
||||||
|
}
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
private S3Client getConnection() throws S3Exception, StorageShutdownException {
|
||||||
|
S3Client c = null;
|
||||||
|
if (isShutdown) throw new StorageShutdownException();
|
||||||
|
synchronized (cpool) {
|
||||||
|
while (c == null) {
|
||||||
|
for (int i = 0; i < cpool.length; i++) { // See if available connection
|
||||||
|
if (cpool[i] != null) { // Found one
|
||||||
|
c = cpool[i];
|
||||||
|
cpool[i] = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c == null) {
|
||||||
|
if (cpoolCount < POOLSIZE) { // Still more we can have
|
||||||
|
c = new DefaultS3ClientBuilder()
|
||||||
|
.credentialsProvider(() -> AwsBasicCredentials.create(access_key_id, secret_access_key))
|
||||||
|
.region(region)
|
||||||
|
.httpClient(URLConnectionSdkHttpClient.create())
|
||||||
|
.build();
|
||||||
|
if (c == null) {
|
||||||
|
Log.severe("Error creating S3 access client");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
cpoolCount++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
cpool.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void releaseConnection(S3Client c) {
|
||||||
|
if (c == null) return;
|
||||||
|
synchronized (cpool) {
|
||||||
|
for (int i = 0; i < POOLSIZE; i++) {
|
||||||
|
if (cpool[i] == null) {
|
||||||
|
cpool[i] = c;
|
||||||
|
c = null; // Mark it recovered (no close needed
|
||||||
|
cpool.notifyAll();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c != null) { // If broken, just toss it
|
||||||
|
try {
|
||||||
|
c.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
cpoolCount--; // And reduce count
|
||||||
|
cpool.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,7 +44,7 @@ public class FileTreeMapStorage extends MapStorage {
|
||||||
super(world, map, x, y, zoom, var);
|
super(world, map, x, y, zoom, var);
|
||||||
String baseURI;
|
String baseURI;
|
||||||
if (zoom > 0) {
|
if (zoom > 0) {
|
||||||
baseURI = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + "zzzzzzzzzzzzzzzz".substring(0, zoom) + "_" + x + "_" + y;
|
baseURI = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz".substring(0, zoom) + "_" + x + "_" + y;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
baseURI = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + x + "_" + y;
|
baseURI = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + x + "_" + y;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -5,6 +5,7 @@ import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
import java.sql.DatabaseMetaData;
|
||||||
import java.sql.DriverManager;
|
import java.sql.DriverManager;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
|
@ -48,6 +49,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
protected int port;
|
protected int port;
|
||||||
private static final int POOLSIZE = 5;
|
private static final int POOLSIZE = 5;
|
||||||
private Connection[] cpool = new Connection[POOLSIZE];
|
private Connection[] cpool = new Connection[POOLSIZE];
|
||||||
|
private long[] cpoolLastUseTS = new long[POOLSIZE]; // Time when last returned to pool
|
||||||
|
private static final long IDLE_TIMEOUT = 60000; // Use 60 second timeout
|
||||||
private int cpoolCount = 0;
|
private int cpoolCount = 0;
|
||||||
private static final Charset UTF8 = Charset.forName("UTF-8");
|
private static final Charset UTF8 = Charset.forName("UTF-8");
|
||||||
|
|
||||||
|
@ -61,7 +64,7 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
mapkey = getMapKey(world, map, var);
|
mapkey = getMapKey(world, map, var);
|
||||||
|
|
||||||
if (zoom > 0) {
|
if (zoom > 0) {
|
||||||
uri = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + "zzzzzzzzzzzzzzzz".substring(0, zoom) + "_" + x + "_" + y + "." + map.getImageFormat().getFileExt();
|
uri = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz".substring(0, zoom) + "_" + x + "_" + y + "." + map.getImageFormat().getFileExt();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uri = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + x + "_" + y + "." + map.getImageFormat().getFileExt();
|
uri = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + x + "_" + y + "." + map.getImageFormat().getFileExt();
|
||||||
|
@ -84,6 +87,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile exists error", x);
|
logSQLException("Tile exists error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -109,6 +114,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile matches hash error", x);
|
logSQLException("Tile matches hash error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -132,13 +139,19 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
rslt.format = MapType.ImageEncoding.fromOrd(rs.getInt("Format"));
|
rslt.format = MapType.ImageEncoding.fromOrd(rs.getInt("Format"));
|
||||||
byte[] img = rs.getBytes("NewImage");
|
byte[] img = rs.getBytes("NewImage");
|
||||||
if (img == null) img = rs.getBytes("Image");
|
if (img == null) img = rs.getBytes("Image");
|
||||||
rslt.image = new BufferInputStream(img);
|
if (img == null) {
|
||||||
|
rslt = null;
|
||||||
|
} else {
|
||||||
|
rslt.image = new BufferInputStream(img);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
stmt.close();
|
stmt.close();
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile read error", x);
|
logSQLException("Tile read error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -195,6 +208,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile write error", x);
|
logSQLException("Tile write error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -326,6 +341,10 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
cfgfile.delete(); // Zap file (in case we left junk from last time)
|
cfgfile.delete(); // Zap file (in case we left junk from last time)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// During initial startup, this can happen before baseStandaloneDir is setup
|
||||||
|
if (!baseStandaloneDir.exists()) {
|
||||||
|
baseStandaloneDir.mkdirs();
|
||||||
|
}
|
||||||
FileWriter fw = null;
|
FileWriter fw = null;
|
||||||
try {
|
try {
|
||||||
fw = new FileWriter(cfgfile);
|
fw = new FileWriter(cfgfile);
|
||||||
|
@ -366,6 +385,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
Connection c = null;
|
Connection c = null;
|
||||||
try {
|
try {
|
||||||
c = getConnection(); // Get connection (create DB if needed)
|
c = getConnection(); // Get connection (create DB if needed)
|
||||||
|
DatabaseMetaData md = c.getMetaData();
|
||||||
|
Log.info("Connected to " + md.getDatabaseProductName() + " v" + md.getDatabaseMajorVersion() + "." + md.getDatabaseMinorVersion());
|
||||||
Statement stmt = c.createStatement();
|
Statement stmt = c.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery( "SELECT level FROM " + tableSchemaVersion + ";");
|
ResultSet rs = stmt.executeQuery( "SELECT level FROM " + tableSchemaVersion + ";");
|
||||||
if (rs.next()) {
|
if (rs.next()) {
|
||||||
|
@ -375,6 +396,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
stmt.close();
|
stmt.close();
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
if (c != null) { releaseConnection(c, err); }
|
if (c != null) { releaseConnection(c, err); }
|
||||||
}
|
}
|
||||||
|
@ -414,6 +437,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Error loading map table", x);
|
logSQLException("Error loading map table", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
c = null;
|
c = null;
|
||||||
|
@ -453,6 +478,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Error updating Maps table", x);
|
logSQLException("Error updating Maps table", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -477,13 +504,17 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
doUpdate(c, "CREATE TABLE " + tableMarkerIcons + " (IconName VARCHAR(128) PRIMARY KEY NOT NULL, Image MEDIUMBLOB)");
|
doUpdate(c, "CREATE TABLE " + tableMarkerIcons + " (IconName VARCHAR(128) PRIMARY KEY NOT NULL, Image MEDIUMBLOB)");
|
||||||
doUpdate(c, "CREATE TABLE " + tableMarkerFiles + " (FileName VARCHAR(128) PRIMARY KEY NOT NULL, Content MEDIUMTEXT)");
|
doUpdate(c, "CREATE TABLE " + tableMarkerFiles + " (FileName VARCHAR(128) PRIMARY KEY NOT NULL, Content MEDIUMTEXT)");
|
||||||
doUpdate(c, "CREATE TABLE " + tableStandaloneFiles + " (FileName VARCHAR(128) NOT NULL, ServerID BIGINT NOT NULL DEFAULT 0, Content MEDIUMTEXT, PRIMARY KEY (FileName, ServerID))");
|
doUpdate(c, "CREATE TABLE " + tableStandaloneFiles + " (FileName VARCHAR(128) NOT NULL, ServerID BIGINT NOT NULL DEFAULT 0, Content MEDIUMTEXT, PRIMARY KEY (FileName, ServerID))");
|
||||||
|
doUpdate(c, "CREATE INDEX " + tableMaps + "_idx ON " + tableMaps + "(WorldID, MapID, Variant, ServerID)");
|
||||||
doUpdate(c, "CREATE TABLE " + tableSchemaVersion + " (level INT PRIMARY KEY NOT NULL)");
|
doUpdate(c, "CREATE TABLE " + tableSchemaVersion + " (level INT PRIMARY KEY NOT NULL)");
|
||||||
doUpdate(c, "INSERT INTO " + tableSchemaVersion + " (level) VALUES (4)");
|
doUpdate(c, "INSERT INTO " + tableSchemaVersion + " (level) VALUES (6)");
|
||||||
version = 5; // Initial - we have all the following updates already
|
version = 6; // Initial - we have all the following updates already
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Error creating tables", x);
|
logSQLException("Error creating tables", x);
|
||||||
err = true;
|
err = true;
|
||||||
return false;
|
return false;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
c = null;
|
c = null;
|
||||||
|
@ -498,9 +529,12 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
doUpdate(c, "UPDATE " + tableSchemaVersion + " SET level=2 WHERE level = 1;");
|
doUpdate(c, "UPDATE " + tableSchemaVersion + " SET level=2 WHERE level = 1;");
|
||||||
version = 2;
|
version = 2;
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Error updating tables to version=1", x);
|
logSQLException("Error updating tables to version=2", x);
|
||||||
err = true;
|
err = true;
|
||||||
return false;
|
return false;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
c = null;
|
c = null;
|
||||||
|
@ -516,9 +550,12 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
doUpdate(c, "UPDATE " + tableSchemaVersion + " SET level=3 WHERE level = 2;");
|
doUpdate(c, "UPDATE " + tableSchemaVersion + " SET level=3 WHERE level = 2;");
|
||||||
version = 3;
|
version = 3;
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Error updating tables to version=2", x);
|
logSQLException("Error updating tables to version=3", x);
|
||||||
err = true;
|
err = true;
|
||||||
return false;
|
return false;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
c = null;
|
c = null;
|
||||||
|
@ -534,9 +571,12 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
doUpdate(c, "UPDATE " + tableSchemaVersion + " SET level=4 WHERE level = 3;");
|
doUpdate(c, "UPDATE " + tableSchemaVersion + " SET level=4 WHERE level = 3;");
|
||||||
version = 4;
|
version = 4;
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Error updating tables to version=3", x);
|
logSQLException("Error updating tables to version=4", x);
|
||||||
err = true;
|
err = true;
|
||||||
return false;
|
return false;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
c = null;
|
c = null;
|
||||||
|
@ -546,13 +586,53 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
try {
|
try {
|
||||||
Log.info("Updating database schema from version = " + version);
|
Log.info("Updating database schema from version = " + version);
|
||||||
c = getConnection();
|
c = getConnection();
|
||||||
doUpdate(c, "ALTER TABLE " + tableTiles + " ADD COLUMN NewImage MEDIUMBLOB, ALGORITHM=INPLACE, LOCK=NONE");
|
DatabaseMetaData md = c.getMetaData();
|
||||||
|
// See if we are recovering from bug where version was still set to 4 when NewImage was added initialli
|
||||||
|
PreparedStatement stmt = c.prepareStatement("SHOW COLUMNS FROM " + tableTiles + " WHERE Field = 'NewImage';");
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
boolean inplace = false;
|
||||||
|
if (rs.next()) { // Got nothing?
|
||||||
|
inplace = true;
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
stmt.close();
|
||||||
|
if (!inplace) {
|
||||||
|
try {
|
||||||
|
doUpdate(c, "ALTER TABLE " + tableTiles + " ADD COLUMN NewImage MEDIUMBLOB, ALGORITHM=INPLACE, LOCK=NONE");
|
||||||
|
} catch (SQLException x) {
|
||||||
|
Log.info("Updating tiles table using legacy method - this might take a while and may need a lot of database space...");
|
||||||
|
doUpdate(c, "ALTER TABLE " + tableTiles + " ADD COLUMN NewImage MEDIUMBLOB");
|
||||||
|
Log.info("Legacy tile update completed");
|
||||||
|
}
|
||||||
|
}
|
||||||
doUpdate(c, "UPDATE " + tableSchemaVersion + " SET level=5 WHERE level = 4;");
|
doUpdate(c, "UPDATE " + tableSchemaVersion + " SET level=5 WHERE level = 4;");
|
||||||
version = 5;
|
version = 5;
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Error updating tables to version=3", x);
|
logSQLException("Error updating tables to version=5", x);
|
||||||
err = true;
|
err = true;
|
||||||
return false;
|
return false;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
releaseConnection(c, err);
|
||||||
|
c = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (version == 5) {
|
||||||
|
try {
|
||||||
|
Log.info("Updating database schema from version = " + version);
|
||||||
|
c = getConnection();
|
||||||
|
doUpdate(c, "CREATE INDEX " + tableMaps + "_idx ON " + tableMaps + "(WorldID, MapID, Variant, ServerID)");
|
||||||
|
doUpdate(c, "UPDATE " + tableSchemaVersion + " SET level=6 WHERE level = 5;");
|
||||||
|
version = 6;
|
||||||
|
} catch (SQLException x) {
|
||||||
|
logSQLException("Error updating tables to version=5", x);
|
||||||
|
err = true;
|
||||||
|
return false;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
c = null;
|
c = null;
|
||||||
|
@ -565,15 +645,26 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Connection getConnection() throws SQLException {
|
private Connection getConnection() throws SQLException, StorageShutdownException {
|
||||||
Connection c = null;
|
Connection c = null;
|
||||||
|
if (isShutdown) { throw new StorageShutdownException(); }
|
||||||
synchronized (cpool) {
|
synchronized (cpool) {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
while (c == null) {
|
while (c == null) {
|
||||||
for (int i = 0; i < cpool.length; i++) { // See if available connection
|
for (int i = 0; i < cpool.length; i++) { // See if available connection
|
||||||
if (cpool[i] != null) { // Found one
|
if (cpool[i] != null) { // Found one
|
||||||
c = cpool[i];
|
// If in pool too long, close it and move on
|
||||||
cpool[i] = null;
|
if ((now - cpoolLastUseTS[i]) > IDLE_TIMEOUT) {
|
||||||
break;
|
try { cpool[i].close(); } catch (SQLException x) {}
|
||||||
|
cpool[i] = null;
|
||||||
|
cpoolCount--;
|
||||||
|
}
|
||||||
|
else { // Else, use the connection
|
||||||
|
c = cpool[i];
|
||||||
|
cpool[i] = null;
|
||||||
|
cpoolLastUseTS[i] = now;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
|
@ -606,6 +697,7 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
for (int i = 0; i < POOLSIZE; i++) {
|
for (int i = 0; i < POOLSIZE; i++) {
|
||||||
if (cpool[i] == null) {
|
if (cpool[i] == null) {
|
||||||
cpool[i] = c;
|
cpool[i] = c;
|
||||||
|
cpoolLastUseTS[i] = System.currentTimeMillis(); // Record last use time
|
||||||
c = null; // Mark it recovered (no close needed
|
c = null; // Mark it recovered (no close needed
|
||||||
cpool.notifyAll();
|
cpool.notifyAll();
|
||||||
break;
|
break;
|
||||||
|
@ -717,9 +809,10 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
c = getConnection();
|
c = getConnection();
|
||||||
// Query tiles for given mapkey
|
Statement stmt = c.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, //we want to stream our resultset one row at a time, we are not interessted in going back
|
||||||
Statement stmt = c.createStatement();
|
java.sql.ResultSet.CONCUR_READ_ONLY); //since we do not handle the entire resultset in memory -> tell the statement that we are going to work read only
|
||||||
ResultSet rs = stmt.executeQuery("SELECT x,y,zoom,Format FROM " + tableTiles + " WHERE MapID=" + mapkey + ";");
|
stmt.setFetchSize(100); //we can change the jdbc "retrieval chunk size". Basicly we limit how much rows are kept in memory. Bigger value = less network calls to DB, but more memory consumption
|
||||||
|
ResultSet rs = stmt.executeQuery(String.format("SELECT x,y,zoom,Format FROM %s WHERE MapID=%d;", tableTiles, mapkey)); //we do the query, but do not set any limit / offset. Since data is not kept in memory, just streamed from DB this should not be a problem, only the rows from setFetchSize are kept in memory.
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
StorageTile st = new StorageTile(world, map, rs.getInt("x"), rs.getInt("y"), rs.getInt("zoom"), var);
|
StorageTile st = new StorageTile(world, map, rs.getInt("x"), rs.getInt("y"), rs.getInt("zoom"), var);
|
||||||
final MapType.ImageEncoding encoding = MapType.ImageEncoding.fromOrd(rs.getInt("Format"));
|
final MapType.ImageEncoding encoding = MapType.ImageEncoding.fromOrd(rs.getInt("Format"));
|
||||||
|
@ -729,13 +822,15 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
cbBase.tileFound(st, encoding);
|
cbBase.tileFound(st, encoding);
|
||||||
st.cleanup();
|
st.cleanup();
|
||||||
}
|
}
|
||||||
if(cbEnd != null)
|
|
||||||
cbEnd.searchEnded();
|
|
||||||
rs.close();
|
rs.close();
|
||||||
stmt.close();
|
stmt.close();
|
||||||
|
if(cbEnd != null)
|
||||||
|
cbEnd.searchEnded();
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile enum error", x);
|
logSQLException("Tile enum error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -774,6 +869,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile purge error", x);
|
logSQLException("Tile purge error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -813,6 +910,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Face write error", x);
|
logSQLException("Face write error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -840,6 +939,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Face reqd error", x);
|
logSQLException("Face reqd error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -865,6 +966,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Face exists error", x);
|
logSQLException("Face exists error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -912,6 +1015,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Marker write error", x);
|
logSQLException("Marker write error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
if (rs != null) { try { rs.close(); } catch (SQLException sx) {} }
|
if (rs != null) { try { rs.close(); } catch (SQLException sx) {} }
|
||||||
if (stmt != null) { try { stmt.close(); } catch (SQLException sx) {} }
|
if (stmt != null) { try { stmt.close(); } catch (SQLException sx) {} }
|
||||||
|
@ -939,6 +1044,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Marker read error", x);
|
logSQLException("Marker read error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -985,6 +1092,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Marker file write error", x);
|
logSQLException("Marker file write error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
if (rs != null) { try { rs.close(); } catch (SQLException sx) {} }
|
if (rs != null) { try { rs.close(); } catch (SQLException sx) {} }
|
||||||
if (stmt != null) { try { stmt.close(); } catch (SQLException sx) {} }
|
if (stmt != null) { try { stmt.close(); } catch (SQLException sx) {} }
|
||||||
|
@ -1012,6 +1121,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Marker file read error", x);
|
logSQLException("Marker file read error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -1068,6 +1179,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Standalone file read error", x);
|
logSQLException("Standalone file read error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -1118,6 +1231,8 @@ public class MySQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Standalone file write error", x);
|
logSQLException("Standalone file write error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
if (rs != null) { try { rs.close(); } catch (SQLException sx) {} }
|
if (rs != null) { try { rs.close(); } catch (SQLException sx) {} }
|
||||||
if (stmt != null) { try { stmt.close(); } catch (SQLException sx) {} }
|
if (stmt != null) { try { stmt.close(); } catch (SQLException sx) {} }
|
||||||
|
|
|
@ -27,7 +27,6 @@ import org.dynmap.storage.MapStorageBaseTileEnumCB;
|
||||||
import org.dynmap.storage.MapStorageTile;
|
import org.dynmap.storage.MapStorageTile;
|
||||||
import org.dynmap.storage.MapStorageTileEnumCB;
|
import org.dynmap.storage.MapStorageTileEnumCB;
|
||||||
import org.dynmap.storage.MapStorageTileSearchEndCB;
|
import org.dynmap.storage.MapStorageTileSearchEndCB;
|
||||||
import org.dynmap.storage.mysql.MySQLMapStorage.StorageTile;
|
|
||||||
import org.dynmap.utils.BufferInputStream;
|
import org.dynmap.utils.BufferInputStream;
|
||||||
import org.dynmap.utils.BufferOutputStream;
|
import org.dynmap.utils.BufferOutputStream;
|
||||||
|
|
||||||
|
@ -50,6 +49,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
private int port;
|
private int port;
|
||||||
private static final int POOLSIZE = 5;
|
private static final int POOLSIZE = 5;
|
||||||
private Connection[] cpool = new Connection[POOLSIZE];
|
private Connection[] cpool = new Connection[POOLSIZE];
|
||||||
|
private long[] cpoolLastUseTS = new long[POOLSIZE]; // Time when last returned to pool
|
||||||
|
private static final long IDLE_TIMEOUT = 60000; // Use 60 second timeout
|
||||||
private int cpoolCount = 0;
|
private int cpoolCount = 0;
|
||||||
private static final Charset UTF8 = Charset.forName("UTF-8");
|
private static final Charset UTF8 = Charset.forName("UTF-8");
|
||||||
|
|
||||||
|
@ -65,7 +66,7 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
mapkey = getMapKey(world, map, var);
|
mapkey = getMapKey(world, map, var);
|
||||||
|
|
||||||
if (zoom > 0) {
|
if (zoom > 0) {
|
||||||
uri = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + "zzzzzzzzzzzzzzzz".substring(0, zoom) + "_" + x + "_" + y + "." + map.getImageFormat().getFileExt();
|
uri = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz".substring(0, zoom) + "_" + x + "_" + y + "." + map.getImageFormat().getFileExt();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uri = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + x + "_" + y + "." + map.getImageFormat().getFileExt();
|
uri = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + x + "_" + y + "." + map.getImageFormat().getFileExt();
|
||||||
|
@ -88,6 +89,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile exists error", x);
|
logSQLException("Tile exists error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -113,6 +116,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile matches hash error", x);
|
logSQLException("Tile matches hash error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -135,13 +140,19 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
rslt.lastModified = rs.getLong("LastUpdate");
|
rslt.lastModified = rs.getLong("LastUpdate");
|
||||||
rslt.format = MapType.ImageEncoding.fromOrd(rs.getInt("Format"));
|
rslt.format = MapType.ImageEncoding.fromOrd(rs.getInt("Format"));
|
||||||
byte[] img = rs.getBytes("Image");
|
byte[] img = rs.getBytes("Image");
|
||||||
rslt.image = new BufferInputStream(img);
|
if (img == null) {
|
||||||
|
rslt = null;
|
||||||
|
} else {
|
||||||
|
rslt.image = new BufferInputStream(img);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
stmt.close();
|
stmt.close();
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile read error", x);
|
logSQLException("Tile read error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -198,6 +209,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile write error", x);
|
logSQLException("Tile write error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -313,6 +326,10 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
cfgfile.delete(); // Zap file (in case we left junk from last time)
|
cfgfile.delete(); // Zap file (in case we left junk from last time)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// During initial startup, this can happen before baseStandaloneDir is setup
|
||||||
|
if (!baseStandaloneDir.exists()) {
|
||||||
|
baseStandaloneDir.mkdirs();
|
||||||
|
}
|
||||||
FileWriter fw = null;
|
FileWriter fw = null;
|
||||||
try {
|
try {
|
||||||
fw = new FileWriter(cfgfile);
|
fw = new FileWriter(cfgfile);
|
||||||
|
@ -363,6 +380,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
stmt.close();
|
stmt.close();
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
if (c != null) { releaseConnection(c, err); }
|
if (c != null) { releaseConnection(c, err); }
|
||||||
}
|
}
|
||||||
|
@ -400,6 +419,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Error loading map table", x);
|
logSQLException("Error loading map table", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
c = null;
|
c = null;
|
||||||
|
@ -439,6 +460,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Error updating Maps table", x);
|
logSQLException("Error updating Maps table", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -463,13 +486,17 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
doUpdate(c, "CREATE TABLE " + tableMarkerIcons + " (IconName VARCHAR(128) PRIMARY KEY NOT NULL, Image BYTEA)");
|
doUpdate(c, "CREATE TABLE " + tableMarkerIcons + " (IconName VARCHAR(128) PRIMARY KEY NOT NULL, Image BYTEA)");
|
||||||
doUpdate(c, "CREATE TABLE " + tableMarkerFiles + " (FileName VARCHAR(128) PRIMARY KEY NOT NULL, Content BYTEA)");
|
doUpdate(c, "CREATE TABLE " + tableMarkerFiles + " (FileName VARCHAR(128) PRIMARY KEY NOT NULL, Content BYTEA)");
|
||||||
doUpdate(c, "CREATE TABLE " + tableStandaloneFiles + " (FileName VARCHAR(128) NOT NULL, ServerID BIGINT NOT NULL DEFAULT 0, Content BYTEA, PRIMARY KEY (FileName, ServerID))");
|
doUpdate(c, "CREATE TABLE " + tableStandaloneFiles + " (FileName VARCHAR(128) NOT NULL, ServerID BIGINT NOT NULL DEFAULT 0, Content BYTEA, PRIMARY KEY (FileName, ServerID))");
|
||||||
|
doUpdate(c, "CREATE INDEX " + tableMaps + "_idx ON " + tableMaps + "(WorldID, MapID, Variant, ServerID)");
|
||||||
doUpdate(c, "CREATE TABLE " + tableSchemaVersion + " (level INT PRIMARY KEY NOT NULL)");
|
doUpdate(c, "CREATE TABLE " + tableSchemaVersion + " (level INT PRIMARY KEY NOT NULL)");
|
||||||
doUpdate(c, "INSERT INTO " + tableSchemaVersion + " (level) VALUES (3)");
|
doUpdate(c, "INSERT INTO " + tableSchemaVersion + " (level) VALUES (4)");
|
||||||
version = 3; // initialzed to current schema
|
version = 4; // initialzed to current schema
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Error creating tables", x);
|
logSQLException("Error creating tables", x);
|
||||||
err = true;
|
err = true;
|
||||||
return false;
|
return false;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
c = null;
|
c = null;
|
||||||
|
@ -487,6 +514,9 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
logSQLException("Error upgrading tables to version=2", x);
|
logSQLException("Error upgrading tables to version=2", x);
|
||||||
err = true;
|
err = true;
|
||||||
return false;
|
return false;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
c = null;
|
c = null;
|
||||||
|
@ -505,6 +535,28 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
logSQLException("Error upgrading tables to version=3", x);
|
logSQLException("Error upgrading tables to version=3", x);
|
||||||
err = true;
|
err = true;
|
||||||
return false;
|
return false;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
releaseConnection(c, err);
|
||||||
|
c = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (version == 3) {
|
||||||
|
try {
|
||||||
|
Log.info("Updating database schema from version = " + version);
|
||||||
|
c = getConnection();
|
||||||
|
doUpdate(c, "CREATE INDEX " + tableMaps + "_idx ON " + tableMaps + "(WorldID, MapID, Variant, ServerID)");
|
||||||
|
doUpdate(c, "UPDATE " + tableSchemaVersion + " SET level=4 WHERE level = 3;");
|
||||||
|
version = 4;
|
||||||
|
} catch (SQLException x) {
|
||||||
|
logSQLException("Error upgrading tables to version=4", x);
|
||||||
|
err = true;
|
||||||
|
return false;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
c = null;
|
c = null;
|
||||||
|
@ -517,15 +569,26 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Connection getConnection() throws SQLException {
|
private Connection getConnection() throws SQLException, StorageShutdownException {
|
||||||
Connection c = null;
|
Connection c = null;
|
||||||
|
if (isShutdown) throw new StorageShutdownException();
|
||||||
synchronized (cpool) {
|
synchronized (cpool) {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
while (c == null) {
|
while (c == null) {
|
||||||
for (int i = 0; i < cpool.length; i++) { // See if available connection
|
for (int i = 0; i < cpool.length; i++) { // See if available connection
|
||||||
if (cpool[i] != null) { // Found one
|
if (cpool[i] != null) { // Found one
|
||||||
c = cpool[i];
|
// If in pool too long, close it and move on
|
||||||
cpool[i] = null;
|
if ((now - cpoolLastUseTS[i]) > IDLE_TIMEOUT) {
|
||||||
break;
|
try { cpool[i].close(); } catch (SQLException x) {}
|
||||||
|
cpool[i] = null;
|
||||||
|
cpoolCount--;
|
||||||
|
}
|
||||||
|
else { // Else, use the connection
|
||||||
|
c = cpool[i];
|
||||||
|
cpool[i] = null;
|
||||||
|
cpoolLastUseTS[i] = now;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
|
@ -557,6 +620,7 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
for (int i = 0; i < POOLSIZE; i++) {
|
for (int i = 0; i < POOLSIZE; i++) {
|
||||||
if (cpool[i] == null) {
|
if (cpool[i] == null) {
|
||||||
cpool[i] = c;
|
cpool[i] = c;
|
||||||
|
cpoolLastUseTS[i] = System.currentTimeMillis(); // Record last use time
|
||||||
c = null; // Mark it recovered (no close needed
|
c = null; // Mark it recovered (no close needed
|
||||||
cpool.notifyAll();
|
cpool.notifyAll();
|
||||||
break;
|
break;
|
||||||
|
@ -651,25 +715,36 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
c = getConnection();
|
c = getConnection();
|
||||||
// Query tiles for given mapkey
|
boolean done = false;
|
||||||
Statement stmt = c.createStatement();
|
int offset = 0;
|
||||||
ResultSet rs = stmt.executeQuery("SELECT x,y,zoom,Format FROM " + tableTiles + " WHERE MapID=" + mapkey + ";");
|
int limit = 100;
|
||||||
while (rs.next()) {
|
while (!done) {
|
||||||
StorageTile st = new StorageTile(world, map, rs.getInt("x"), rs.getInt("y"), rs.getInt("zoom"), var);
|
// Query tiles for given mapkey
|
||||||
final MapType.ImageEncoding encoding = MapType.ImageEncoding.fromOrd(rs.getInt("Format"));
|
Statement stmt = c.createStatement();
|
||||||
if(cb != null)
|
ResultSet rs = stmt.executeQuery(String.format("SELECT x,y,zoom,Format FROM %s WHERE MapID=%d OFFSET %d LIMIT %d;", tableTiles, mapkey, offset, limit));
|
||||||
cb.tileFound(st, encoding);
|
int cnt = 0;
|
||||||
if(cbBase != null && st.zoom == 0)
|
while (rs.next()) {
|
||||||
cbBase.tileFound(st, encoding);
|
StorageTile st = new StorageTile(world, map, rs.getInt("x"), rs.getInt("y"), rs.getInt("zoom"), var);
|
||||||
st.cleanup();
|
final MapType.ImageEncoding encoding = MapType.ImageEncoding.fromOrd(rs.getInt("Format"));
|
||||||
|
if(cb != null)
|
||||||
|
cb.tileFound(st, encoding);
|
||||||
|
if(cbBase != null && st.zoom == 0)
|
||||||
|
cbBase.tileFound(st, encoding);
|
||||||
|
st.cleanup();
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
stmt.close();
|
||||||
|
if (cnt < limit) done = true;
|
||||||
|
offset += cnt;
|
||||||
}
|
}
|
||||||
if(cbEnd != null)
|
if(cbEnd != null)
|
||||||
cbEnd.searchEnded();
|
cbEnd.searchEnded();
|
||||||
rs.close();
|
|
||||||
stmt.close();
|
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile enum error", x);
|
logSQLException("Tile enum error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -724,6 +799,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile purge error", x);
|
logSQLException("Tile purge error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -763,6 +840,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Face write error", x);
|
logSQLException("Face write error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -790,6 +869,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Face read error", x);
|
logSQLException("Face read error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -815,6 +896,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Face exists error", x);
|
logSQLException("Face exists error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -862,6 +945,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Marker write error", x);
|
logSQLException("Marker write error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
if (rs != null) { try { rs.close(); } catch (SQLException sx) {} }
|
if (rs != null) { try { rs.close(); } catch (SQLException sx) {} }
|
||||||
if (stmt != null) { try { stmt.close(); } catch (SQLException sx) {} }
|
if (stmt != null) { try { stmt.close(); } catch (SQLException sx) {} }
|
||||||
|
@ -889,6 +974,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Marker read error", x);
|
logSQLException("Marker read error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -935,6 +1022,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Marker file write error", x);
|
logSQLException("Marker file write error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
if (rs != null) { try { rs.close(); } catch (SQLException sx) {} }
|
if (rs != null) { try { rs.close(); } catch (SQLException sx) {} }
|
||||||
if (stmt != null) { try { stmt.close(); } catch (SQLException sx) {} }
|
if (stmt != null) { try { stmt.close(); } catch (SQLException sx) {} }
|
||||||
|
@ -962,6 +1051,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Marker file read error", x);
|
logSQLException("Marker file read error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -1018,6 +1109,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Standalone file read error", x);
|
logSQLException("Standalone file read error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -1068,6 +1161,8 @@ public class PostgreSQLMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Standalone file write error", x);
|
logSQLException("Standalone file write error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
if (rs != null) { try { rs.close(); } catch (SQLException sx) {} }
|
if (rs != null) { try { rs.close(); } catch (SQLException sx) {} }
|
||||||
if (stmt != null) { try { stmt.close(); } catch (SQLException sx) {} }
|
if (stmt != null) { try { stmt.close(); } catch (SQLException sx) {} }
|
||||||
|
|
|
@ -31,8 +31,10 @@ import org.dynmap.utils.BufferOutputStream;
|
||||||
public class SQLiteMapStorage extends MapStorage {
|
public class SQLiteMapStorage extends MapStorage {
|
||||||
private String connectionString;
|
private String connectionString;
|
||||||
private String databaseFile;
|
private String databaseFile;
|
||||||
private static final int POOLSIZE = 5;
|
private static final int POOLSIZE = 1; // SQLite is really not thread safe... 1 at a time works best
|
||||||
private Connection[] cpool = new Connection[POOLSIZE];
|
private Connection[] cpool = new Connection[POOLSIZE];
|
||||||
|
private long[] cpoolLastUseTS = new long[POOLSIZE]; // Time when last returned to pool
|
||||||
|
private static final long IDLE_TIMEOUT = 60000; // Use 60 second timeout
|
||||||
private int cpoolCount = 0;
|
private int cpoolCount = 0;
|
||||||
private static final Charset UTF8 = Charset.forName("UTF-8");
|
private static final Charset UTF8 = Charset.forName("UTF-8");
|
||||||
|
|
||||||
|
@ -46,7 +48,7 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
mapkey = getMapKey(world, map, var);
|
mapkey = getMapKey(world, map, var);
|
||||||
|
|
||||||
if (zoom > 0) {
|
if (zoom > 0) {
|
||||||
uri = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + "zzzzzzzzzzzzzzzz".substring(0, zoom) + "_" + x + "_" + y + "." + map.getImageFormat().getFileExt();
|
uri = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz".substring(0, zoom) + "_" + x + "_" + y + "." + map.getImageFormat().getFileExt();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uri = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + x + "_" + y + "." + map.getImageFormat().getFileExt();
|
uri = map.getPrefix() + var.variantSuffix + "/"+ (x >> 5) + "_" + (y >> 5) + "/" + x + "_" + y + "." + map.getImageFormat().getFileExt();
|
||||||
|
@ -70,6 +72,8 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile exists error", x);
|
logSQLException("Tile exists error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -96,6 +100,8 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile matches hash error", x);
|
logSQLException("Tile matches hash error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -125,13 +131,19 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
// Trim trailing zeros from padding by BLOB field
|
// Trim trailing zeros from padding by BLOB field
|
||||||
while((len > 0) && (img[len-1] == '\0')) len--;
|
while((len > 0) && (img[len-1] == '\0')) len--;
|
||||||
}
|
}
|
||||||
rslt.image = new BufferInputStream(img, len);
|
if (img == null) {
|
||||||
|
rslt = null;
|
||||||
|
} else {
|
||||||
|
rslt.image = new BufferInputStream(img, len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
stmt.close();
|
stmt.close();
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile read error", x);
|
logSQLException("Tile read error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -191,6 +203,8 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile write error", x);
|
logSQLException("Tile write error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -269,6 +283,7 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
@Override
|
@Override
|
||||||
public boolean init(DynmapCore core) {
|
public boolean init(DynmapCore core) {
|
||||||
if (!super.init(core)) {
|
if (!super.init(core)) {
|
||||||
|
isShutdown = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
File dbfile = core.getFile(core.configuration.getString("storage/dbfile", "dynmap.db"));
|
File dbfile = core.getFile(core.configuration.getString("storage/dbfile", "dynmap.db"));
|
||||||
|
@ -281,6 +296,7 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
return initializeTables();
|
return initializeTables();
|
||||||
} catch (ClassNotFoundException cnfx) {
|
} catch (ClassNotFoundException cnfx) {
|
||||||
Log.severe("SQLite-JDBC classes not found - sqlite data source not usable");
|
Log.severe("SQLite-JDBC classes not found - sqlite data source not usable");
|
||||||
|
isShutdown = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,6 +317,8 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
stmt.close();
|
stmt.close();
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
if (c != null) { releaseConnection(c, err); }
|
if (c != null) { releaseConnection(c, err); }
|
||||||
}
|
}
|
||||||
|
@ -339,6 +357,8 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Error loading map table", x);
|
logSQLException("Error loading map table", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
c = null;
|
c = null;
|
||||||
|
@ -378,6 +398,8 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Error updating Maps table", x);
|
logSQLException("Error updating Maps table", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -401,13 +423,18 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
doUpdate(c, "CREATE TABLE Faces (PlayerName STRING NOT NULL, TypeID INT NOT NULL, Image BLOB, ImageLen INT, PRIMARY KEY(PlayerName, TypeID))");
|
doUpdate(c, "CREATE TABLE Faces (PlayerName STRING NOT NULL, TypeID INT NOT NULL, Image BLOB, ImageLen INT, PRIMARY KEY(PlayerName, TypeID))");
|
||||||
doUpdate(c, "CREATE TABLE MarkerIcons (IconName STRING PRIMARY KEY NOT NULL, Image BLOB, ImageLen INT)");
|
doUpdate(c, "CREATE TABLE MarkerIcons (IconName STRING PRIMARY KEY NOT NULL, Image BLOB, ImageLen INT)");
|
||||||
doUpdate(c, "CREATE TABLE MarkerFiles (FileName STRING PRIMARY KEY NOT NULL, Content CLOB)");
|
doUpdate(c, "CREATE TABLE MarkerFiles (FileName STRING PRIMARY KEY NOT NULL, Content CLOB)");
|
||||||
|
// Add index, since SQLite execution planner is stupid and scans Tiles table instead of using short Maps table...
|
||||||
|
doUpdate(c, "CREATE INDEX MapIndex ON Maps(WorldID, MapID, Variant)");
|
||||||
doUpdate(c, "CREATE TABLE SchemaVersion (level INT PRIMARY KEY NOT NULL)");
|
doUpdate(c, "CREATE TABLE SchemaVersion (level INT PRIMARY KEY NOT NULL)");
|
||||||
doUpdate(c, "INSERT INTO SchemaVersion (level) VALUES (2)");
|
doUpdate(c, "INSERT INTO SchemaVersion (level) VALUES (3)");
|
||||||
version = 2; // Initializes to current schema
|
version = 3; // Initializes to current schema
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Error creating tables", x);
|
logSQLException("Error creating tables", x);
|
||||||
err = true;
|
err = true;
|
||||||
return false;
|
return false;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
c = null;
|
c = null;
|
||||||
|
@ -426,6 +453,29 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
logSQLException("Error updating tables to version=2", x);
|
logSQLException("Error updating tables to version=2", x);
|
||||||
err = true;
|
err = true;
|
||||||
return false;
|
return false;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
releaseConnection(c, err);
|
||||||
|
c = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (version == 2) {
|
||||||
|
try {
|
||||||
|
Log.info("Updating database schema from version = " + version);
|
||||||
|
c = getConnection();
|
||||||
|
// Add index, since SQLite execution planner is stupid and scans Tiles table instead of using short Maps table...
|
||||||
|
doUpdate(c, "CREATE INDEX MapIndex ON Maps(WorldID, MapID, Variant)");
|
||||||
|
doUpdate(c, "UPDATE SchemaVersion SET level=3");
|
||||||
|
version = 2;
|
||||||
|
} catch (SQLException x) {
|
||||||
|
logSQLException("Error updating tables to version=3", x);
|
||||||
|
err = true;
|
||||||
|
return false;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
c = null;
|
c = null;
|
||||||
|
@ -438,14 +488,28 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Connection getConnection() throws SQLException {
|
private Connection getConnection() throws SQLException, StorageShutdownException {
|
||||||
Connection c = null;
|
Connection c = null;
|
||||||
|
if (isShutdown) {
|
||||||
|
throw new StorageShutdownException();
|
||||||
|
}
|
||||||
synchronized (cpool) {
|
synchronized (cpool) {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
while (c == null) {
|
while (c == null) {
|
||||||
for (int i = 0; i < cpool.length; i++) { // See if available connection
|
for (int i = 0; i < cpool.length; i++) { // See if available connection
|
||||||
if (cpool[i] != null) { // Found one
|
if (cpool[i] != null) { // Found one
|
||||||
c = cpool[i];
|
// If in pool too long, close it and move on
|
||||||
cpool[i] = null;
|
if ((now - cpoolLastUseTS[i]) > IDLE_TIMEOUT) {
|
||||||
|
try { cpool[i].close(); } catch (SQLException x) {}
|
||||||
|
cpool[i] = null;
|
||||||
|
cpoolCount--;
|
||||||
|
}
|
||||||
|
else { // Else, use the connection
|
||||||
|
c = cpool[i];
|
||||||
|
cpool[i] = null;
|
||||||
|
cpoolLastUseTS[i] = now;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
|
@ -469,6 +533,7 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
|
|
||||||
private static Connection configureConnection(Connection conn) throws SQLException {
|
private static Connection configureConnection(Connection conn) throws SQLException {
|
||||||
final Statement statement = conn.createStatement();
|
final Statement statement = conn.createStatement();
|
||||||
|
statement.execute("PRAGMA auto_vacuum = FULL;");
|
||||||
statement.execute("PRAGMA journal_mode = WAL;");
|
statement.execute("PRAGMA journal_mode = WAL;");
|
||||||
statement.close();
|
statement.close();
|
||||||
return conn;
|
return conn;
|
||||||
|
@ -481,6 +546,7 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
for (int i = 0; i < POOLSIZE; i++) {
|
for (int i = 0; i < POOLSIZE; i++) {
|
||||||
if (cpool[i] == null) {
|
if (cpool[i] == null) {
|
||||||
cpool[i] = c;
|
cpool[i] = c;
|
||||||
|
cpoolLastUseTS[i] = System.currentTimeMillis(); // Record last use time
|
||||||
c = null; // Mark it recovered (no close needed
|
c = null; // Mark it recovered (no close needed
|
||||||
cpool.notifyAll();
|
cpool.notifyAll();
|
||||||
break;
|
break;
|
||||||
|
@ -593,27 +659,39 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
c = getConnection();
|
boolean done = false;
|
||||||
// Query tiles for given mapkey
|
int offset = 0;
|
||||||
Statement stmt = c.createStatement();
|
int limit = 100;
|
||||||
//ResultSet rs = stmt.executeQuery("SELECT x,y,zoom,Format FROM Tiles WHERE MapID=" + mapkey + ";");
|
while (!done) {
|
||||||
ResultSet rs = doExecuteQuery(stmt, "SELECT x,y,zoom,Format FROM Tiles WHERE MapID=" + mapkey + ";");
|
c = getConnection(); // Do inside loop - single threaded sqlite will have issues otherwise....
|
||||||
while (rs.next()) {
|
// Query tiles for given mapkey
|
||||||
StorageTile st = new StorageTile(world, map, rs.getInt("x"), rs.getInt("y"), rs.getInt("zoom"), var);
|
Statement stmt = c.createStatement();
|
||||||
final MapType.ImageEncoding encoding = MapType.ImageEncoding.fromOrd(rs.getInt("Format"));
|
ResultSet rs = doExecuteQuery(stmt, String.format("SELECT x,y,zoom,Format FROM Tiles WHERE MapID=%d LIMIT %d OFFSET %d;", mapkey, limit, offset));
|
||||||
if(cb != null)
|
int cnt = 0;
|
||||||
cb.tileFound(st, encoding);
|
while (rs.next()) {
|
||||||
if(cbBase != null && st.zoom == 0)
|
StorageTile st = new StorageTile(world, map, rs.getInt("x"), rs.getInt("y"), rs.getInt("zoom"), var);
|
||||||
cbBase.tileFound(st, encoding);
|
final MapType.ImageEncoding encoding = MapType.ImageEncoding.fromOrd(rs.getInt("Format"));
|
||||||
st.cleanup();
|
if(cb != null)
|
||||||
|
cb.tileFound(st, encoding);
|
||||||
|
if(cbBase != null && st.zoom == 0)
|
||||||
|
cbBase.tileFound(st, encoding);
|
||||||
|
st.cleanup();
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
stmt.close();
|
||||||
|
if (cnt < limit) done = true;
|
||||||
|
offset += cnt;
|
||||||
|
releaseConnection(c, err);
|
||||||
|
c = null;
|
||||||
}
|
}
|
||||||
if(cbEnd != null)
|
if(cbEnd != null)
|
||||||
cbEnd.searchEnded();
|
cbEnd.searchEnded();
|
||||||
rs.close();
|
|
||||||
stmt.close();
|
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile enum error", x);
|
logSQLException("Tile enum error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -651,6 +729,8 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Tile purge error", x);
|
logSQLException("Tile purge error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -693,6 +773,8 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Face write error", x);
|
logSQLException("Face write error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -727,6 +809,8 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Face read error", x);
|
logSQLException("Face read error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -753,6 +837,8 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Face exists error", x);
|
logSQLException("Face exists error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -804,6 +890,8 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Marker write error", x);
|
logSQLException("Marker write error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
if (rs != null) { try { rs.close(); } catch (SQLException sx) {} }
|
if (rs != null) { try { rs.close(); } catch (SQLException sx) {} }
|
||||||
if (stmt != null) { try { stmt.close(); } catch (SQLException sx) {} }
|
if (stmt != null) { try { stmt.close(); } catch (SQLException sx) {} }
|
||||||
|
@ -838,6 +926,8 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Marker read error", x);
|
logSQLException("Marker read error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -885,6 +975,8 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Marker file write error", x);
|
logSQLException("Marker file write error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
if (rs != null) { try { rs.close(); } catch (SQLException sx) {} }
|
if (rs != null) { try { rs.close(); } catch (SQLException sx) {} }
|
||||||
if (stmt != null) { try { stmt.close(); } catch (SQLException sx) {} }
|
if (stmt != null) { try { stmt.close(); } catch (SQLException sx) {} }
|
||||||
|
@ -913,6 +1005,8 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
logSQLException("Marker file read error", x);
|
logSQLException("Marker file read error", x);
|
||||||
err = true;
|
err = true;
|
||||||
|
} catch (StorageShutdownException x) {
|
||||||
|
err = true;
|
||||||
} finally {
|
} finally {
|
||||||
releaseConnection(c, err);
|
releaseConnection(c, err);
|
||||||
}
|
}
|
||||||
|
@ -985,4 +1079,11 @@ public class SQLiteMapStorage extends MapStorage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void logSQLException(String opmsg, SQLException x) {
|
||||||
|
// Ignore interrupted
|
||||||
|
if (x.getMessage().equals("Interrupted")) return;
|
||||||
|
|
||||||
|
super.logSQLException(opmsg, x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,236 @@
|
||||||
|
package org.dynmap.utils;
|
||||||
|
|
||||||
|
import org.dynmap.Log;
|
||||||
|
import org.dynmap.renderer.DynmapBlockState;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.BitSet;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
// Utility class used for parsing block name and block state identity from lines in model and texture files
|
||||||
|
public class BlockStateParser {
|
||||||
|
private HashMap<DynmapBlockState, BitSet> basestates;
|
||||||
|
private ArrayList<String> badtokens;
|
||||||
|
private String modid;
|
||||||
|
private int linenum;
|
||||||
|
private boolean filtered;
|
||||||
|
|
||||||
|
public BlockStateParser() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process new line into list of matching states Produce list of block states
|
||||||
|
* matching the fields in the provided line (specifically the portion after the
|
||||||
|
* '<type>:" prefix) at the stsrt of the line. Processes id=<block ID> or
|
||||||
|
* id=<nlock Name> or id=<modid>:<blockName> as block identifier data=<N> or
|
||||||
|
* data=<N>-<N2> as selecting matching states of identified blocks by ordered
|
||||||
|
* index of their block states (analog to metadata>
|
||||||
|
* state=<id:val>/<id2:val2>/... as selecting matching states (based on all
|
||||||
|
* states where given id=val values match)
|
||||||
|
*
|
||||||
|
* @return success or no
|
||||||
|
*/
|
||||||
|
public boolean processLine(String modid, String line, int linenum, Map<String, Integer> varMap) {
|
||||||
|
boolean success = true;
|
||||||
|
String tokens[] = line.split(","); // Split on the commas
|
||||||
|
this.basestates = new HashMap<DynmapBlockState, BitSet>();
|
||||||
|
this.badtokens = new ArrayList<String>();
|
||||||
|
this.modid = modid;
|
||||||
|
this.linenum = linenum;
|
||||||
|
this.filtered = false;
|
||||||
|
// Loop through and process id= tokens
|
||||||
|
for (String token : tokens) {
|
||||||
|
int idx = token.indexOf("="); // Find equals
|
||||||
|
if (idx < 0)
|
||||||
|
continue; // Skip token without equals
|
||||||
|
String fieldid = token.substring(0, idx); // Split off left of equals
|
||||||
|
String args = token.substring(idx + 1); // And rest of token after equals
|
||||||
|
// Just do IDs first (need block names to get to states
|
||||||
|
if (fieldid.equals("id")) {
|
||||||
|
if (!handleBlockName(args)) {
|
||||||
|
badtokens.add(token);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Loop through and process data= and state= tokens
|
||||||
|
for (String token : tokens) {
|
||||||
|
int idx = token.indexOf("="); // Find equals
|
||||||
|
if (idx < 0)
|
||||||
|
continue; // Skip token without equals
|
||||||
|
String fieldid = token.substring(0, idx); // Split off left of equals
|
||||||
|
String args = token.substring(idx + 1); // And rest of token after equals
|
||||||
|
// Check for data=
|
||||||
|
if (fieldid.equals("data")) {
|
||||||
|
if (!handleBlockData(args, varMap)) {
|
||||||
|
badtokens.add(token);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If state=
|
||||||
|
else if (fieldid.equals("state")) {
|
||||||
|
if (!handleBlockState(args)) {
|
||||||
|
badtokens.add(token);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If unfiltered, add all states for all blocks
|
||||||
|
if (!filtered) {
|
||||||
|
// Now loop through base states and add matching indexes
|
||||||
|
for (DynmapBlockState bs : basestates.keySet()) {
|
||||||
|
int cnt = bs.getStateCount();
|
||||||
|
BitSet bits = basestates.get(bs);
|
||||||
|
for (int idx = 0; idx < cnt; idx++) {
|
||||||
|
bits.set(bs.getState(idx).stateIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Log.info(String.format("processLine(%s)=%b, basestates=%s", line, success,
|
||||||
|
// basestates));
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return matching results from last processLine call
|
||||||
|
public Map<DynmapBlockState, BitSet> getMatchingStates() {
|
||||||
|
return basestates;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return bad tokens from last processLine call
|
||||||
|
public List<String> getBadTokens() {
|
||||||
|
return badtokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean handleBlockName(String blockname) {
|
||||||
|
char c = blockname.charAt(0);
|
||||||
|
if (Character.isLetter(c) || (c == '%') || (c == '&')) {
|
||||||
|
String orig = blockname;
|
||||||
|
if ((c == '%') || (c == '&')) {
|
||||||
|
blockname = blockname.substring(1);
|
||||||
|
}
|
||||||
|
if (blockname.indexOf(':') < 0) {
|
||||||
|
blockname = modid + ":" + blockname;
|
||||||
|
}
|
||||||
|
// Now find the base block state
|
||||||
|
DynmapBlockState bs = DynmapBlockState.getBaseStateByName(blockname);
|
||||||
|
// Bad if we failed
|
||||||
|
if (bs == null) {
|
||||||
|
Log.warning(String.format("id=%s on line %d does not match valid blockName", orig, linenum));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
basestates.put(bs, new BitSet());
|
||||||
|
return true;
|
||||||
|
} else { // Numbers not support anymore
|
||||||
|
Log.warning(String.format("id=%s on line %d invalid format (numbers not supported anymore)", blockname,
|
||||||
|
linenum));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean handleBlockData(String data, Map<String, Integer> varMap) {
|
||||||
|
try {
|
||||||
|
if (data.equals("*")) {
|
||||||
|
filtered = false;
|
||||||
|
} else {
|
||||||
|
int split = data.indexOf('-'); // See if range of data
|
||||||
|
int m0, m1;
|
||||||
|
if (split > 0) {
|
||||||
|
String start = data.substring(0, split);
|
||||||
|
String end = data.substring(split + 1);
|
||||||
|
m0 = getIntValue(varMap, start);
|
||||||
|
m1 = getIntValue(varMap, end);
|
||||||
|
} else {
|
||||||
|
m0 = m1 = getIntValue(varMap, data);
|
||||||
|
}
|
||||||
|
filtered = true;
|
||||||
|
// Now loop through base states and add matching indexes
|
||||||
|
for (DynmapBlockState bs : basestates.keySet()) {
|
||||||
|
int cnt = bs.getStateCount();
|
||||||
|
BitSet bits = basestates.get(bs);
|
||||||
|
for (int idx = m0; (idx <= m1) && (idx < cnt); idx++) {
|
||||||
|
bits.set(bs.getState(idx).stateIndex);
|
||||||
|
}
|
||||||
|
if ((m1 >= cnt) || (m0 >= cnt)) {
|
||||||
|
Log.warning(String.format("data=%s on line %d exceeds state count for %s", data, linenum,
|
||||||
|
bs.blockName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (NumberFormatException x) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean handleBlockState(String data) {
|
||||||
|
boolean success = true;
|
||||||
|
if (data.equals("*")) {
|
||||||
|
filtered = false;
|
||||||
|
} else {
|
||||||
|
String[] split = data.split("/"); // Split on pairs
|
||||||
|
String[] attribs = new String[split.length];
|
||||||
|
String[] vals = new String[split.length];
|
||||||
|
for (int i = 0; i < split.length; i++) {
|
||||||
|
String[] av = split[i].split(":");
|
||||||
|
if (av.length == 2) {
|
||||||
|
attribs[i] = av[0];
|
||||||
|
vals[i] = av[1];
|
||||||
|
} else {
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filtered = true;
|
||||||
|
// Now loop through base states and add matching indexes
|
||||||
|
if (success) {
|
||||||
|
for (DynmapBlockState bs : basestates.keySet()) {
|
||||||
|
int cnt = bs.getStateCount();
|
||||||
|
BitSet bits = basestates.get(bs);
|
||||||
|
for (int idx = 0; idx < cnt; idx++) {
|
||||||
|
DynmapBlockState s = bs.getState(idx);
|
||||||
|
boolean match = true;
|
||||||
|
for (int i = 0; match && (i < attribs.length); i++) {
|
||||||
|
if (!s.isStateMatch(attribs[i], vals[i])) {
|
||||||
|
match = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match) {
|
||||||
|
bits.set(idx); // Set matching state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!success) {
|
||||||
|
Log.warning(String.format("Bad block state %s for line %s", data, linenum));
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Integer getIntValue(Map<String, Integer> vars, String val) throws NumberFormatException {
|
||||||
|
char c = val.charAt(0);
|
||||||
|
if (Character.isLetter(c) || (c == '%') || (c == '&')) {
|
||||||
|
int off = val.indexOf('+');
|
||||||
|
int offset = 0;
|
||||||
|
if (off > 0) {
|
||||||
|
offset = Integer.valueOf(val.substring(off + 1));
|
||||||
|
val = val.substring(0, off);
|
||||||
|
}
|
||||||
|
Integer v = vars.get(val);
|
||||||
|
if (v == null) {
|
||||||
|
if ((c == '%') || (c == '&')) { // block/item unique IDs
|
||||||
|
vars.put(val, 0);
|
||||||
|
v = 0;
|
||||||
|
} else {
|
||||||
|
throw new NumberFormatException("invalid ID - " + val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((offset != 0) && (v.intValue() > 0))
|
||||||
|
v = v.intValue() + offset;
|
||||||
|
return v;
|
||||||
|
} else {
|
||||||
|
return Integer.valueOf(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ public class DataBitsPacked {
|
||||||
private final long[] values;
|
private final long[] values;
|
||||||
private final int bitsperrec;
|
private final int bitsperrec;
|
||||||
private final long valuemask;
|
private final long valuemask;
|
||||||
private final int length;
|
public final int length;
|
||||||
|
|
||||||
public static int calcLongCount(int i, int j) {
|
public static int calcLongCount(int i, int j) {
|
||||||
if (j == 0) {
|
if (j == 0) {
|
||||||
|
|
|
@ -107,68 +107,126 @@ public class ImageIOManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BufferOutputStream imageIOEncode(BufferedImage img, ImageFormat fmt) {
|
public static BufferOutputStream imageIOEncode(BufferedImage img, ImageFormat fmt) {
|
||||||
BufferOutputStream bos = new BufferOutputStream();
|
if(isRequiredJDKVersion(17,-1,-1)){
|
||||||
|
return imageIOEncodeUnsafe(img, fmt); //we can skip Thread safety for more performance
|
||||||
|
}
|
||||||
synchronized(imageioLock) {
|
synchronized(imageioLock) {
|
||||||
try {
|
return imageIOEncodeUnsafe(img, fmt);
|
||||||
ImageIO.setUseCache(false); /* Don't use file cache - too small to be worth it */
|
}
|
||||||
|
}
|
||||||
fmt = validateFormat(fmt);
|
private static BufferOutputStream imageIOEncodeUnsafe(BufferedImage img, ImageFormat fmt) {
|
||||||
|
BufferOutputStream bos = new BufferOutputStream();
|
||||||
if(fmt.getEncoding() == ImageEncoding.JPG) {
|
try {
|
||||||
WritableRaster raster = img.getRaster();
|
ImageIO.setUseCache(false); /* Don't use file cache - too small to be worth it */
|
||||||
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
|
fmt = validateFormat(fmt);
|
||||||
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 null;
|
|
||||||
}
|
|
||||||
ImageWriteParam iwp = writer.getDefaultWriteParam();
|
|
||||||
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
|
||||||
iwp.setCompressionQuality(fmt.getQuality());
|
|
||||||
|
|
||||||
ImageOutputStream ios;
|
if(fmt.getEncoding() == ImageEncoding.JPG) {
|
||||||
ios = ImageIO.createImageOutputStream(bos);
|
WritableRaster raster = img.getRaster();
|
||||||
writer.setOutput(ios);
|
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);
|
||||||
|
|
||||||
writer.write(null, new IIOImage(rgbBuffer, null, null), iwp);
|
// Find a jpeg writer
|
||||||
writer.dispose();
|
ImageWriter writer = null;
|
||||||
|
Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName("jpg");
|
||||||
rgbBuffer.flush();
|
if (iter.hasNext()) {
|
||||||
|
writer = iter.next();
|
||||||
}
|
}
|
||||||
else if (fmt.getEncoding() == ImageEncoding.WEBP) {
|
if(writer == null) {
|
||||||
doWEBPEncode(img, fmt, bos);
|
Log.severe("No JPEG ENCODER - Java VM does not support JPEG encoding");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
else {
|
ImageWriteParam iwp = writer.getDefaultWriteParam();
|
||||||
ImageIO.write(img, fmt.getFileExt(), bos); /* Write to byte array stream - prevent bogus I/O errors */
|
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
||||||
}
|
iwp.setCompressionQuality(fmt.getQuality());
|
||||||
} catch (IOException iox) {
|
|
||||||
Log.info("Error encoding image - " + iox.getMessage());
|
ImageOutputStream ios;
|
||||||
return null;
|
ios = ImageIO.createImageOutputStream(bos);
|
||||||
|
writer.setOutput(ios);
|
||||||
|
|
||||||
|
writer.write(null, new IIOImage(rgbBuffer, null, null), iwp);
|
||||||
|
writer.dispose();
|
||||||
|
|
||||||
|
rgbBuffer.flush();
|
||||||
}
|
}
|
||||||
|
else if (fmt.getEncoding() == ImageEncoding.WEBP) {
|
||||||
|
doWEBPEncode(img, fmt, bos);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ImageIO.write(img, fmt.getFileExt(), bos); /* Write to byte array stream - prevent bogus I/O errors */
|
||||||
|
}
|
||||||
|
} catch (IOException iox) {
|
||||||
|
Log.info("Error encoding image - " + iox.getMessage());
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return bos;
|
return bos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BufferedImage imageIODecode(MapStorageTile.TileRead tr) throws IOException {
|
public static BufferedImage imageIODecode(MapStorageTile.TileRead tr) throws IOException {
|
||||||
|
if(isRequiredJDKVersion(17,-1,-1)){
|
||||||
|
return imageIODecodeUnsafe(tr); //we can skip Thread safety for more performance
|
||||||
|
}
|
||||||
synchronized(imageioLock) {
|
synchronized(imageioLock) {
|
||||||
ImageIO.setUseCache(false); /* Don't use file cache - too small to be worth it */
|
return imageIODecodeUnsafe(tr);
|
||||||
if (tr.format == ImageEncoding.WEBP) {
|
|
||||||
return doWEBPDecode(tr.image);
|
|
||||||
}
|
|
||||||
return ImageIO.read(tr.image);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static BufferedImage imageIODecodeUnsafe(MapStorageTile.TileRead tr) throws IOException {
|
||||||
|
ImageIO.setUseCache(false); /* Don't use file cache - too small to be worth it */
|
||||||
|
if (tr.format == ImageEncoding.WEBP) {
|
||||||
|
return doWEBPDecode(tr.image);
|
||||||
|
}
|
||||||
|
return ImageIO.read(tr.image);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the current JDK is running at least a specific version
|
||||||
|
* targetMinor and targetBuild can be set to -1, if the java.version only provides a Major release this will then only check for the major release
|
||||||
|
* @param targetMajor the required minimum major version
|
||||||
|
* @param targetMinor the required minimum minor version
|
||||||
|
* @param targetBuild the required minimum build version
|
||||||
|
* @return true if the current JDK version is the required minimum version
|
||||||
|
*/
|
||||||
|
private static boolean isRequiredJDKVersion(int targetMajor, int targetMinor, int targetBuild){
|
||||||
|
String javaVersion = System.getProperty("java.version");
|
||||||
|
String[] versionParts = javaVersion.split("\\.");
|
||||||
|
if(versionParts.length < 3){
|
||||||
|
if(versionParts.length == 1
|
||||||
|
&& targetMinor == -1
|
||||||
|
&& targetBuild == -1
|
||||||
|
&& parseInt(versionParts[0], -1) >= targetMajor){
|
||||||
|
return true;//we only have a major version and thats ok
|
||||||
|
}
|
||||||
|
return false; //can not evaluate
|
||||||
|
}
|
||||||
|
int major = parseInt(versionParts[0], -1);
|
||||||
|
int minor = parseInt(versionParts[1], -1);
|
||||||
|
int build = parseInt(versionParts[2], -1);
|
||||||
|
if(major != -1 && major >= targetMajor &&
|
||||||
|
minor != -1 && minor >= targetMinor &&
|
||||||
|
build != -1 && build >= targetBuild
|
||||||
|
){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a string to int, with a dynamic fallback value if not parsable
|
||||||
|
* @param input the String to parse
|
||||||
|
* @param fallback the Fallback value to use
|
||||||
|
* @return the parsed integer or the fallback value if unparsable
|
||||||
|
*/
|
||||||
|
private static int parseInt(String input, int fallback){
|
||||||
|
int output = fallback;
|
||||||
|
try{
|
||||||
|
output = Integer.parseInt(input);
|
||||||
|
} catch (NumberFormatException e) {}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
package org.dynmap.utils;
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2019 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches a request based on IP Address or subnet mask matching against the remote
|
||||||
|
* address.
|
||||||
|
* <p>
|
||||||
|
* Both IPv6 and IPv4 addresses are supported, but a matcher which is configured with an
|
||||||
|
* IPv4 address will never match a request which returns an IPv6 address, and vice-versa.
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @since 3.0.2
|
||||||
|
*
|
||||||
|
* Slightly modified by omidzk to have zero dependency to any frameworks other than the JRE.
|
||||||
|
*/
|
||||||
|
public final class IpAddressMatcher {
|
||||||
|
private final int nMaskBits;
|
||||||
|
private final InetAddress requiredAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a specific IP address or a range specified using the IP/Netmask (e.g.
|
||||||
|
* 192.168.1.0/24 or 202.24.0.0/14).
|
||||||
|
*
|
||||||
|
* @param ipAddress the address or range of addresses from which the request must
|
||||||
|
* come.
|
||||||
|
*/
|
||||||
|
public IpAddressMatcher(String ipAddress) {
|
||||||
|
|
||||||
|
if (ipAddress.indexOf('/') > 0) {
|
||||||
|
String[] addressAndMask = ipAddress.split("/");
|
||||||
|
ipAddress = addressAndMask[0];
|
||||||
|
nMaskBits = Integer.parseInt(addressAndMask[1]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nMaskBits = -1;
|
||||||
|
}
|
||||||
|
requiredAddress = parseAddress(ipAddress);
|
||||||
|
assert (requiredAddress.getAddress().length * 8 >= nMaskBits) :
|
||||||
|
String.format("IP address %s is too short for bitmask of length %d",
|
||||||
|
ipAddress, nMaskBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matches(String address) {
|
||||||
|
InetAddress remoteAddress = parseAddress(address);
|
||||||
|
|
||||||
|
if (!requiredAddress.getClass().equals(remoteAddress.getClass())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nMaskBits < 0) {
|
||||||
|
return remoteAddress.equals(requiredAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] remAddr = remoteAddress.getAddress();
|
||||||
|
byte[] reqAddr = requiredAddress.getAddress();
|
||||||
|
|
||||||
|
int nMaskFullBytes = nMaskBits / 8;
|
||||||
|
byte finalByte = (byte) (0xFF00 >> (nMaskBits & 0x07));
|
||||||
|
|
||||||
|
// System.out.println("Mask is " + new sun.misc.HexDumpEncoder().encode(mask));
|
||||||
|
|
||||||
|
for (int i = 0; i < nMaskFullBytes; i++) {
|
||||||
|
if (remAddr[i] != reqAddr[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finalByte != 0) {
|
||||||
|
return (remAddr[nMaskFullBytes] & finalByte) == (reqAddr[nMaskFullBytes] & finalByte);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private InetAddress parseAddress(String address) {
|
||||||
|
try {
|
||||||
|
return InetAddress.getByName(address);
|
||||||
|
}
|
||||||
|
catch (UnknownHostException e) {
|
||||||
|
throw new IllegalArgumentException("Failed to parse address" + address, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -106,10 +106,18 @@ public interface MapIterator extends MapDataContext {
|
||||||
*/
|
*/
|
||||||
BlockStep getLastStep();
|
BlockStep getLastStep();
|
||||||
/**
|
/**
|
||||||
* Get world height
|
* Get world height (yMax+1)
|
||||||
* @return height
|
* @return height
|
||||||
*/
|
*/
|
||||||
int getWorldHeight();
|
int getWorldHeight();
|
||||||
|
/**
|
||||||
|
* Get world bottom (yMin)
|
||||||
|
*/
|
||||||
|
int getWorldYMin();
|
||||||
|
/**
|
||||||
|
* Get world sealevel
|
||||||
|
*/
|
||||||
|
int getWorldSeaLevel();
|
||||||
/**
|
/**
|
||||||
* Get block key for current position (unique ID for block within cache being iterated)
|
* Get block key for current position (unique ID for block within cache being iterated)
|
||||||
* @return block key
|
* @return block key
|
||||||
|
|
|
@ -29,6 +29,7 @@ public class PatchDefinition implements RenderPatch {
|
||||||
public SideVisible sidevis; /* Which side is visible */
|
public SideVisible sidevis; /* Which side is visible */
|
||||||
public int textureindex;
|
public int textureindex;
|
||||||
public BlockStep step; /* Best approximation of orientation of surface, from top (positive determinent) */
|
public BlockStep step; /* Best approximation of orientation of surface, from top (positive determinent) */
|
||||||
|
public boolean shade; // If false, patch is not shaded
|
||||||
private int hc;
|
private int hc;
|
||||||
/* Offset vector of middle of block */
|
/* Offset vector of middle of block */
|
||||||
private static final Vector3D offsetCenter = new Vector3D(0.5,0.5,0.5);
|
private static final Vector3D offsetCenter = new Vector3D(0.5,0.5,0.5);
|
||||||
|
@ -45,6 +46,7 @@ public class PatchDefinition implements RenderPatch {
|
||||||
v = new Vector3D();
|
v = new Vector3D();
|
||||||
sidevis = SideVisible.BOTH;
|
sidevis = SideVisible.BOTH;
|
||||||
textureindex = 0;
|
textureindex = 0;
|
||||||
|
shade = true;
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
PatchDefinition(PatchDefinition pd) {
|
PatchDefinition(PatchDefinition pd) {
|
||||||
|
@ -68,6 +70,7 @@ public class PatchDefinition implements RenderPatch {
|
||||||
this.sidevis = pd.sidevis;
|
this.sidevis = pd.sidevis;
|
||||||
this.textureindex = pd.textureindex;
|
this.textureindex = pd.textureindex;
|
||||||
this.step = pd.step;
|
this.step = pd.step;
|
||||||
|
this.shade = pd.shade;
|
||||||
this.hc = pd.hc;
|
this.hc = pd.hc;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -110,6 +113,7 @@ public class PatchDefinition implements RenderPatch {
|
||||||
vmaxatumax = orig.vmaxatumax;
|
vmaxatumax = orig.vmaxatumax;
|
||||||
vminatumax = orig.vminatumax;
|
vminatumax = orig.vminatumax;
|
||||||
sidevis = orig.sidevis;
|
sidevis = orig.sidevis;
|
||||||
|
shade = orig.shade;
|
||||||
this.textureindex = (textureindex < 0) ? orig.textureindex : textureindex;
|
this.textureindex = (textureindex < 0) ? orig.textureindex : textureindex;
|
||||||
u = new Vector3D();
|
u = new Vector3D();
|
||||||
v = new Vector3D();
|
v = new Vector3D();
|
||||||
|
@ -140,7 +144,7 @@ public class PatchDefinition implements RenderPatch {
|
||||||
public void update(double x0, double y0, double z0, double xu,
|
public void update(double x0, double y0, double z0, double xu,
|
||||||
double yu, double zu, double xv, double yv, double zv, double umin,
|
double yu, double zu, double xv, double yv, double zv, double umin,
|
||||||
double umax, double vmin, double vmax, SideVisible sidevis,
|
double umax, double vmin, double vmax, SideVisible sidevis,
|
||||||
int textureids, double vminatumax, double vmaxatumax) {
|
int textureids, double vminatumax, double vmaxatumax, boolean shade) {
|
||||||
this.x0 = x0;
|
this.x0 = x0;
|
||||||
this.y0 = y0;
|
this.y0 = y0;
|
||||||
this.z0 = z0;
|
this.z0 = z0;
|
||||||
|
@ -158,6 +162,7 @@ public class PatchDefinition implements RenderPatch {
|
||||||
this.vminatumax = vminatumax;
|
this.vminatumax = vminatumax;
|
||||||
this.sidevis = sidevis;
|
this.sidevis = sidevis;
|
||||||
this.textureindex = textureids;
|
this.textureindex = textureids;
|
||||||
|
this.shade = shade;
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
public void update() {
|
public void update() {
|
||||||
|
@ -211,70 +216,38 @@ public class PatchDefinition implements RenderPatch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private boolean outOfRange(double v) {
|
||||||
|
return (v < -1.0) || (v > 2.0);
|
||||||
|
}
|
||||||
public boolean validate() {
|
public boolean validate() {
|
||||||
boolean good = true;
|
boolean good = true;
|
||||||
if((x0 < -1.0) || (x0 > 2.0)) {
|
// Compute visible corners to see if we're inside cube
|
||||||
Log.severe("Invalid x0=" + x0);
|
double xx0 = x0 + (xu - x0) * umin + (xv - x0) * vmin;
|
||||||
good = false;
|
double xx1 = x0 + (xu - x0) * vmin + (xv - x0) * vmax;
|
||||||
|
double xx2 = x0 + (xu - x0) * umax + (xv - x0) * vmin;
|
||||||
|
double xx3 = x0 + (xu - x0) * vmax + (xv - x0) * vmax;;
|
||||||
|
if (outOfRange(xx0) || outOfRange(xx1) || outOfRange(xx2) || outOfRange(xx3)) {
|
||||||
|
Log.verboseinfo(String.format("Invalid visible range xu=[%f:%f], xv=[%f:%f]", xx0, xx2, xx1, xx3));
|
||||||
|
good = false;
|
||||||
}
|
}
|
||||||
if((y0 < -1.0) || (y0 > 2.0)) {
|
double yy0 = y0 + (yu - y0) * umin + (yv - y0) * vmin;
|
||||||
Log.severe("Invalid y0=" + y0);
|
double yy1 = y0 + (yu - y0) * vmin + (yv - y0) * vmax;
|
||||||
good = false;
|
double yy2 = y0 + (yu - y0) * umax + (yv - y0) * vmin;
|
||||||
|
double yy3 = y0 + (yu - y0) * vmax + (yv - y0) * vmax;;
|
||||||
|
if (outOfRange(yy0) || outOfRange(yy1) || outOfRange(yy2) || outOfRange(yy3)) {
|
||||||
|
Log.verboseinfo(String.format("Invalid visible range yu=[%f:%f], yv=[%f:%f]", yy0, yy2, yy1, yy3));
|
||||||
|
good = false;
|
||||||
}
|
}
|
||||||
if((z0 < -1.0) || (z0 > 2.0)) {
|
double zz0 = z0 + (zu - z0) * umin + (zv - z0) * vmin;
|
||||||
Log.severe("Invalid z0=" + z0);
|
double zz1 = z0 + (zu - z0) * vmin + (zv - z0) * vmax;
|
||||||
good = false;
|
double zz2 = z0 + (zu - z0) * umax + (zv - z0) * vmin;
|
||||||
}
|
double zz3 = z0 + (zu - z0) * vmax + (zv - z0) * vmax;
|
||||||
if((xu < -1.0) || (xu > 2.0)) {
|
if (outOfRange(zz0) || outOfRange(zz1) || outOfRange(zz2) || outOfRange(zz3)) {
|
||||||
Log.severe("Invalid xu=" + xu);
|
Log.verboseinfo(String.format("Invalid visible range zu=[%f:%f], zv=[%f:%f]", zz0, zz2, zz1, zz3));
|
||||||
good = false;
|
good = false;
|
||||||
}
|
|
||||||
if((yu < -1.0) || (yu > 2.0)) {
|
|
||||||
Log.severe("Invalid yu=" + yu);
|
|
||||||
good = false;
|
|
||||||
}
|
|
||||||
if((zu < -1.0) || (zu > 2.0)) {
|
|
||||||
Log.severe("Invalid zu=" + zu);
|
|
||||||
good = false;
|
|
||||||
}
|
|
||||||
if((xv < -1.0) || (xv > 2.0)) {
|
|
||||||
Log.severe("Invalid xv=" + xv);
|
|
||||||
good = false;
|
|
||||||
}
|
|
||||||
if((yv < -1.0) || (yv > 2.0)) {
|
|
||||||
Log.severe("Invalid yv=" + yv);
|
|
||||||
good = false;
|
|
||||||
}
|
|
||||||
if((zv < -1.0) || (zv > 2.0)) {
|
|
||||||
Log.severe("Invalid zv=" + zv);
|
|
||||||
good = false;
|
|
||||||
}
|
|
||||||
if((umin < 0.0) || (umin > umax)) {
|
|
||||||
Log.severe("Invalid umin=" + umin);
|
|
||||||
good = false;
|
|
||||||
}
|
|
||||||
if((vmin < 0.0) || (vmin > vmax)) {
|
|
||||||
Log.severe("Invalid vmin=" + vmin);
|
|
||||||
good = false;
|
|
||||||
}
|
|
||||||
if(umax > 1.0) {
|
|
||||||
Log.severe("Invalid umax=" + umax);
|
|
||||||
good = false;
|
|
||||||
}
|
|
||||||
if(vmax > 1.0) {
|
|
||||||
Log.severe("Invalid vmax=" + vmax);
|
|
||||||
good = false;
|
|
||||||
}
|
|
||||||
if ((vminatumax < 0.0) || (vminatumax > vmaxatumax)) {
|
|
||||||
Log.severe("Invalid vminatumax=" + vminatumax);
|
|
||||||
good = false;
|
|
||||||
}
|
|
||||||
if(vmaxatumax > 1.0) {
|
|
||||||
Log.severe("Invalid vmaxatumax=" + vmaxatumax);
|
|
||||||
good = false;
|
|
||||||
}
|
}
|
||||||
if (!good) {
|
if (!good) {
|
||||||
Log.warning("Patch not valid: " + toString());
|
Log.verboseinfo("Bad patch: " + this);
|
||||||
}
|
}
|
||||||
return good;
|
return good;
|
||||||
}
|
}
|
||||||
|
@ -291,7 +264,8 @@ public class PatchDefinition implements RenderPatch {
|
||||||
(umin == p.umin) && (umax == p.umax) &&
|
(umin == p.umin) && (umax == p.umax) &&
|
||||||
(vmin == p.vmin) && (vmax == p.vmax) &&
|
(vmin == p.vmin) && (vmax == p.vmax) &&
|
||||||
(vmaxatumax == p.vmaxatumax) &&
|
(vmaxatumax == p.vmaxatumax) &&
|
||||||
(vminatumax == p.vminatumax) && (sidevis == p.sidevis)) {
|
(vminatumax == p.vminatumax) && (sidevis == p.sidevis) &&
|
||||||
|
(shade == p.shade)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,8 +281,8 @@ public class PatchDefinition implements RenderPatch {
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("xyz0=%f/%f/%f,xyzU=%f/%f/%f,xyzV=%f/%f/%f,minU=%f,maxU=%f,vMin=%f/%f,vmax=%f/%f,side=%s,txtidx=%d",
|
return String.format("xyz0=%f/%f/%f,xyzU=%f/%f/%f,xyzV=%f/%f/%f,minU=%f,maxU=%f,vMin=%f/%f,vmax=%f/%f,side=%s,txtidx=%d,shade=%b",
|
||||||
x0, y0, z0, xu, yu, zu, xv, yv, zv, umin, umax, vmin, vminatumax, vmax, vmaxatumax, sidevis, textureindex);
|
x0, y0, z0, xu, yu, zu, xv, yv, zv, umin, umax, vmin, vminatumax, vmax, vmaxatumax, sidevis, textureindex, shade);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -324,8 +298,9 @@ public class PatchDefinition implements RenderPatch {
|
||||||
// @param face - which face (determines use of xyz-min vs xyz-max
|
// @param face - which face (determines use of xyz-min vs xyz-max
|
||||||
// @param uv - bounds on UV (umin, vmin, umax, vmax): if undefined, default based on face range (minecraft UV is relative to top left corner of texture)
|
// @param uv - bounds on UV (umin, vmin, umax, vmax): if undefined, default based on face range (minecraft UV is relative to top left corner of texture)
|
||||||
// @param rot - texture rotation (default 0 - DEG0, DEG90, DEG180, DEG270)
|
// @param rot - texture rotation (default 0 - DEG0, DEG90, DEG180, DEG270)
|
||||||
|
// @param shade - if false, no shadows on patch
|
||||||
// @param textureid - texture ID
|
// @param textureid - texture ID
|
||||||
public void updateModelFace(double[] from, double[] to, BlockSide face, double[] uv, ModelBlockModel.SideRotation rot, int textureid) {
|
public void updateModelFace(double[] from, double[] to, BlockSide face, double[] uv, ModelBlockModel.SideRotation rot, boolean shade, int textureid) {
|
||||||
if (rot == null) rot = ModelBlockModel.SideRotation.DEG0;
|
if (rot == null) rot = ModelBlockModel.SideRotation.DEG0;
|
||||||
// Compute corners of the face
|
// Compute corners of the face
|
||||||
Vector3D lowleft;
|
Vector3D lowleft;
|
||||||
|
@ -337,9 +312,12 @@ public class PatchDefinition implements RenderPatch {
|
||||||
boolean flipU = false, flipV = false;
|
boolean flipU = false, flipV = false;
|
||||||
if (uv != null) { // MC V is top down, so flip
|
if (uv != null) { // MC V is top down, so flip
|
||||||
patchuv = new double[] { uv[0] / 16.0, 1 - uv[3] / 16.0, uv[2] / 16.0, 1 - uv[1] / 16.0 };
|
patchuv = new double[] { uv[0] / 16.0, 1 - uv[3] / 16.0, uv[2] / 16.0, 1 - uv[1] / 16.0 };
|
||||||
if (patchuv[0] > patchuv[2]) { flipU = true; double save = patchuv[0]; patchuv[0] = patchuv[2]; patchuv[2] = save; }
|
// if (patchuv[0] > patchuv[2]) { flipU = true; double save = patchuv[0]; patchuv[0] = patchuv[2]; patchuv[2] = save; }
|
||||||
if (patchuv[1] > patchuv[3]) { flipV = true; double save = patchuv[1]; patchuv[1] = patchuv[3]; patchuv[3] = save; }
|
// if (patchuv[1] > patchuv[3]) { flipV = true; double save = patchuv[1]; patchuv[1] = patchuv[3]; patchuv[3] = save; }
|
||||||
|
if (patchuv[0] > patchuv[2]) { flipU = true; patchuv[0] = 1.0 - patchuv[0]; patchuv[2] = 1.0 - patchuv[2]; }
|
||||||
|
if (patchuv[1] > patchuv[3]) { flipV = true; patchuv[1] = 1.0 - patchuv[1]; patchuv[3] = 1.0 - patchuv[3]; }
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (face) {
|
switch (face) {
|
||||||
case BOTTOM:
|
case BOTTOM:
|
||||||
case FACE_0:
|
case FACE_0:
|
||||||
|
@ -448,7 +426,6 @@ public class PatchDefinition implements RenderPatch {
|
||||||
upleft = upright;
|
upleft = upright;
|
||||||
upright = save;
|
upright = save;
|
||||||
}
|
}
|
||||||
//System.out.println(String.format("ll=%s, lr=%s, ul=%s, ur=%s", lowleft, lowright, upleft, upright));
|
|
||||||
// Compute texture origin, based on corners and patchuv
|
// Compute texture origin, based on corners and patchuv
|
||||||
Vector3D txtorig = new Vector3D();
|
Vector3D txtorig = new Vector3D();
|
||||||
Vector3D txtU = new Vector3D();
|
Vector3D txtU = new Vector3D();
|
||||||
|
@ -460,12 +437,12 @@ public class PatchDefinition implements RenderPatch {
|
||||||
double du = patchuv[2] - patchuv[0];
|
double du = patchuv[2] - patchuv[0];
|
||||||
txtU.set(lowright).subtract(lowleft); // vector along U
|
txtU.set(lowright).subtract(lowleft); // vector along U
|
||||||
double uScale = txtU.length() / du;
|
double uScale = txtU.length() / du;
|
||||||
txtU.scale(uScale / du); // Compute full U vect
|
txtU.scale(uScale / txtU.length()); // Compute full U vect
|
||||||
// Compute V axis
|
// Compute V axis
|
||||||
double dv = patchuv[3] - patchuv[1];
|
double dv = patchuv[3] - patchuv[1];
|
||||||
txtV.set(upleft).subtract(lowleft); // vector along V
|
txtV.set(upleft).subtract(lowleft); // vector along V
|
||||||
double vScale = txtV.length() / dv;
|
double vScale = txtV.length() / dv;
|
||||||
txtV.scale(vScale / dv); // Compute full V vect
|
txtV.scale(vScale / txtV.length()); // Compute full V vect
|
||||||
// Compute texture origin
|
// Compute texture origin
|
||||||
txtorig.set(txtU).scale(-patchuv[0]).add(lowleft);
|
txtorig.set(txtU).scale(-patchuv[0]).add(lowleft);
|
||||||
wrk.set(txtV).scale(-patchuv[1]);
|
wrk.set(txtV).scale(-patchuv[1]);
|
||||||
|
@ -474,9 +451,8 @@ public class PatchDefinition implements RenderPatch {
|
||||||
txtU.add(txtorig); // And add it for full U
|
txtU.add(txtorig); // And add it for full U
|
||||||
txtV.add(txtorig); // And add it to compute full V
|
txtV.add(txtorig); // And add it to compute full V
|
||||||
}
|
}
|
||||||
// System.out.println(String.format("txtO=%s, txtU=%s, txtV=%s, uv=%f/%f/%f/%f", txtorig, txtU, txtV, patchuv[0], patchuv[1], patchuv[2],
|
|
||||||
// patchuv[3]));
|
|
||||||
update(txtorig.x, txtorig.y, txtorig.z, txtU.x, txtU.y, txtU.z, txtV.x, txtV.y, txtV.z,
|
update(txtorig.x, txtorig.y, txtorig.z, txtU.x, txtU.y, txtU.z, txtV.x, txtV.y, txtV.z,
|
||||||
patchuv[0], patchuv[2], patchuv[1], patchuv[3], flipU ? SideVisible.TOPFLIP : (flipV ? SideVisible.TOPFLIPV : SideVisible.TOP), textureid, patchuv[1], patchuv[3]);
|
patchuv[0], patchuv[2], patchuv[1], patchuv[3], flipU ? (flipV ? SideVisible.TOPFLIPHV : SideVisible.TOPFLIP) : (flipV ? SideVisible.TOPFLIPV : SideVisible.TOP), textureid,
|
||||||
|
patchuv[1], patchuv[3], shade);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,6 @@ import org.dynmap.modsupport.BlockSide;
|
||||||
import org.dynmap.modsupport.ModelBlockModel;
|
import org.dynmap.modsupport.ModelBlockModel;
|
||||||
import org.dynmap.renderer.RenderPatch;
|
import org.dynmap.renderer.RenderPatch;
|
||||||
import org.dynmap.renderer.RenderPatchFactory;
|
import org.dynmap.renderer.RenderPatchFactory;
|
||||||
import org.dynmap.renderer.RenderPatchFactory.SideVisible;
|
|
||||||
import org.dynmap.Log;
|
|
||||||
|
|
||||||
public class PatchDefinitionFactory implements RenderPatchFactory {
|
public class PatchDefinitionFactory implements RenderPatchFactory {
|
||||||
private HashMap<PatchDefinition,PatchDefinition> patches = new HashMap<PatchDefinition,PatchDefinition>();
|
private HashMap<PatchDefinition,PatchDefinition> patches = new HashMap<PatchDefinition,PatchDefinition>();
|
||||||
|
@ -30,30 +28,30 @@ public class PatchDefinitionFactory implements RenderPatchFactory {
|
||||||
double yu, double zu, double xv, double yv, double zv, double umin,
|
double yu, double zu, double xv, double yv, double zv, double umin,
|
||||||
double umax, double vmin, double vmax, SideVisible sidevis,
|
double umax, double vmin, double vmax, SideVisible sidevis,
|
||||||
int textureids) {
|
int textureids) {
|
||||||
return getPatch(x0, y0, z0, xu, yu, zu,xv, yv, zv, umin, umax, vmin, vmax, sidevis, textureids, vmin, vmax);
|
return getPatch(x0, y0, z0, xu, yu, zu,xv, yv, zv, umin, umax, vmin, vmax, sidevis, textureids, vmin, vmax, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RenderPatch getPatch(double x0, double y0, double z0, double xu,
|
public RenderPatch getPatch(double x0, double y0, double z0, double xu,
|
||||||
double yu, double zu, double xv, double yv, double zv,
|
double yu, double zu, double xv, double yv, double zv,
|
||||||
double uplusvmax, SideVisible sidevis, int textureids) {
|
double uplusvmax, SideVisible sidevis, int textureids) {
|
||||||
return getPatch(x0, y0, z0, xu, yu, zu,xv, yv, zv, 0.0, uplusvmax, 0.0, uplusvmax, sidevis, textureids, 0.0, 0.0);
|
return getPatch(x0, y0, z0, xu, yu, zu,xv, yv, zv, 0.0, uplusvmax, 0.0, uplusvmax, sidevis, textureids, 0.0, 0.0, true);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public PatchDefinition getPatch(double x0, double y0, double z0, double xu,
|
public PatchDefinition getPatch(double x0, double y0, double z0, double xu,
|
||||||
double yu, double zu, double xv, double yv, double zv, double umin,
|
double yu, double zu, double xv, double yv, double zv, double umin,
|
||||||
double umax, double vmin, double vminatumax, double vmax, double vmaxatumax, SideVisible sidevis,
|
double umax, double vmin, double vminatumax, double vmax, double vmaxatumax, SideVisible sidevis,
|
||||||
int textureids) {
|
int textureids) {
|
||||||
return getPatch(x0, y0, z0, xu, yu, zu,xv, yv, zv, umin, umax, vmin, vmax, sidevis, textureids, vminatumax, vmaxatumax);
|
return getPatch(x0, y0, z0, xu, yu, zu,xv, yv, zv, umin, umax, vmin, vmax, sidevis, textureids, vminatumax, vmaxatumax, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PatchDefinition getPatch(double x0, double y0, double z0, double xu,
|
public PatchDefinition getPatch(double x0, double y0, double z0, double xu,
|
||||||
double yu, double zu, double xv, double yv, double zv, double umin,
|
double yu, double zu, double xv, double yv, double zv, double umin,
|
||||||
double umax, double vmin, double vmax, SideVisible sidevis,
|
double umax, double vmin, double vmax, SideVisible sidevis,
|
||||||
int textureids, double vminatumax, double vmaxatumax) {
|
int textureids, double vminatumax, double vmaxatumax, boolean shade) {
|
||||||
synchronized(lock) {
|
synchronized(lock) {
|
||||||
lookup.update(x0, y0, z0, xu, yu, zu, xv, yv, zv, umin,
|
lookup.update(x0, y0, z0, xu, yu, zu, xv, yv, zv, umin,
|
||||||
umax, vmin, vmax, sidevis, textureids, vminatumax, vmaxatumax);
|
umax, vmin, vmax, sidevis, textureids, vminatumax, vmaxatumax, shade);
|
||||||
if(lookup.validate() == false)
|
if(lookup.validate() == false)
|
||||||
return null;
|
return null;
|
||||||
PatchDefinition pd2 = patches.get(lookup); /* See if in cache already */
|
PatchDefinition pd2 = patches.get(lookup); /* See if in cache already */
|
||||||
|
@ -66,10 +64,10 @@ public class PatchDefinitionFactory implements RenderPatchFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PatchDefinition getModelFace(double[] from, double[] to, BlockSide face, double[] uv, ModelBlockModel.SideRotation rot, int textureid) {
|
public PatchDefinition getModelFace(double[] from, double[] to, BlockSide face, double[] uv, ModelBlockModel.SideRotation rot, boolean shade, int textureid) {
|
||||||
synchronized(lock) {
|
synchronized(lock) {
|
||||||
lookup.updateModelFace(from, to, face, uv, rot, textureid);
|
lookup.updateModelFace(from, to, face, uv, rot, shade, textureid);
|
||||||
if(lookup.validate() == false)
|
if(lookup.validate() == false)
|
||||||
return null;
|
return null;
|
||||||
PatchDefinition pd2 = patches.get(lookup); /* See if in cache already */
|
PatchDefinition pd2 = patches.get(lookup); /* See if in cache already */
|
||||||
|
@ -198,24 +196,26 @@ public class PatchDefinitionFactory implements RenderPatchFactory {
|
||||||
return TexturePack.getTextureMapLength(id);
|
return TexturePack.getTextureMapLength(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
// public static void main(String[] args) {
|
||||||
PatchDefinitionFactory fact = new PatchDefinitionFactory();
|
// PatchDefinition pd;
|
||||||
PatchDefinition pd;
|
//
|
||||||
BlockSide[] faces = { BlockSide.NORTH, BlockSide.EAST, BlockSide.SOUTH, BlockSide.WEST, BlockSide.TOP, BlockSide.BOTTOM };
|
// // box=0.000000/3.000000/9.000000:2.000000/6.000000/13.000000:
|
||||||
// campfire log:box=1/0/0:5/4/16:n/0/0/4/4/8:e/0/0/1/16/5:s/0/0/4/4/8:w/0/16/0/0/4:u90/0/0/0/16/4:d90/0/0/0/16/4
|
// // w/0/13.000000/7.000000/15.000000/10.000000:d/0/0.000000/9.000000/2.000000/13.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/0.000000/9.000000/2.000000/13.000000:R/0/180/0
|
||||||
double[][] uvs = { { 0, 4, 4, 8 }, { 0, 1, 16, 5 }, { 0, 4, 4, 8 }, { 16, 0, 0, 4 }, { 0, 0, 16, 4 }, { 0, 0, 16, 4 } };
|
// BlockSide[] faces = { BlockSide.WEST, BlockSide.BOTTOM, BlockSide.EAST, BlockSide.TOP };
|
||||||
ModelBlockModel.SideRotation[] rots = { ModelBlockModel.SideRotation.DEG0, ModelBlockModel.SideRotation.DEG0, ModelBlockModel.SideRotation.DEG0,
|
// // campfire log:box=1/0/0:5/4/16:n/0/0/4/4/8:e/0/0/1/16/5:s/0/0/4/4/8:w/0/16/0/0/4:u90/0/0/0/16/4:d90/0/0/0/16/4
|
||||||
ModelBlockModel.SideRotation.DEG0, ModelBlockModel.SideRotation.DEG90, ModelBlockModel.SideRotation.DEG90 };
|
// double[][] uvs = { { 13, 7, 15, 10 }, { 0, 9, 2, 13 }, { 13, 7, 15, 10 }, { 0, 9, 2, 13 } };
|
||||||
double[] from = { 1, 0, 0 };
|
// ModelBlockModel.SideRotation[] rots = { ModelBlockModel.SideRotation.DEG0, ModelBlockModel.SideRotation.DEG0, ModelBlockModel.SideRotation.DEG0,
|
||||||
double[] to = { 5, 4, 16 };
|
// ModelBlockModel.SideRotation.DEG0 };
|
||||||
|
// double[] from = { 0, 3, 9 };
|
||||||
// Do normal faces, default limits
|
// double[] to = { 2, 6, 13 };
|
||||||
pd = new PatchDefinition();
|
//
|
||||||
for (int i = 0; i < faces.length; i++) {
|
// // Do normal faces, default limits
|
||||||
pd.updateModelFace(from, to, faces[i], uvs[i], rots[i], 0);
|
// pd = new PatchDefinition();
|
||||||
System.out.println("Log " + faces[i] + ": " + pd);
|
// for (int i = 0; i < faces.length; i++) {
|
||||||
}
|
// pd.updateModelFace(from, to, faces[i], uvs[i], rots[i], true, 0);
|
||||||
|
// System.out.println("Log " + faces[i] + ": " + pd);
|
||||||
|
// }
|
||||||
|
//
|
||||||
// // Do normal faces, default limits
|
// // Do normal faces, default limits
|
||||||
// pd = new PatchDefinition();
|
// pd = new PatchDefinition();
|
||||||
// for (BlockSide face : faces) {
|
// for (BlockSide face : faces) {
|
||||||
|
@ -234,6 +234,6 @@ public class PatchDefinitionFactory implements RenderPatchFactory {
|
||||||
// pd.updateModelFace(from, toquarter, face, new double[] { 4, 4, 12, 12 }, 0);
|
// pd.updateModelFace(from, toquarter, face, new double[] { 4, 4, 12, 12 }, 0);
|
||||||
// System.out.println("Full cube, middle half of texture " + face + ": " + pd);
|
// System.out.println("Full cube, middle half of texture " + face + ": " + pd);
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,11 @@ public class RoundVisibilityLimit implements VisibilityLimit {
|
||||||
else
|
else
|
||||||
chunk_corner_z = chunk_z * 16 + 15;
|
chunk_corner_z = chunk_z * 16 + 15;
|
||||||
|
|
||||||
return (chunk_corner_x - x_center) * (chunk_corner_x - x_center) + (chunk_corner_z - z_center) * (chunk_corner_z - z_center) < radius * radius;
|
// By gmfamily - Use long representation of the distance between tested chunk and center of tested limit
|
||||||
|
// to avoid int overflow while computing the distance compared to limit radius using square delta value
|
||||||
|
long chunk_delta_x = chunk_corner_x - x_center;
|
||||||
|
long chunk_delta_z = chunk_corner_z - z_center;
|
||||||
|
return chunk_delta_x * chunk_delta_x + chunk_delta_z * chunk_delta_z < (long) radius * radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -11,18 +11,27 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class HandlerRouter extends AbstractHandler {
|
public class HandlerRouter extends AbstractHandler {
|
||||||
|
|
||||||
PathMap pathMap = new PathMap();
|
PathMap<HandlerOrServlet> pathMap = new PathMap<HandlerOrServlet>();
|
||||||
|
|
||||||
|
private static class HandlerOrServlet {
|
||||||
|
Servlet servlet;
|
||||||
|
Handler handler;
|
||||||
|
HandlerOrServlet(Servlet s) { servlet = s; handler = null; }
|
||||||
|
HandlerOrServlet(Handler h) { servlet = null; handler = h; }
|
||||||
|
};
|
||||||
|
|
||||||
public HandlerRouter() {
|
public HandlerRouter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addHandler(String path, Handler handler) {
|
public void addHandler(String path, Handler handler) {
|
||||||
pathMap.put(path, handler);
|
pathMap.put(path, new HandlerOrServlet(handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addServlet(String path, Servlet servlet) {
|
public void addServlet(String path, Servlet servlet) {
|
||||||
pathMap.put(path, servlet);
|
pathMap.put(path, new HandlerOrServlet(servlet));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
|
@ -32,7 +41,7 @@ public class HandlerRouter extends AbstractHandler {
|
||||||
@Override
|
@Override
|
||||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||||
String pathInfo = request.getPathInfo();
|
String pathInfo = request.getPathInfo();
|
||||||
PathMap.MappedEntry e = pathMap.getMatch(pathInfo);
|
PathMap.MappedEntry<HandlerOrServlet> e = pathMap.getMatch(pathInfo);
|
||||||
String mappedPath = e.getMapped();
|
String mappedPath = e.getMapped();
|
||||||
|
|
||||||
String childPathInfo = pathInfo;
|
String childPathInfo = pathInfo;
|
||||||
|
@ -45,13 +54,12 @@ public class HandlerRouter extends AbstractHandler {
|
||||||
org.eclipse.jetty.server.Request r = (org.eclipse.jetty.server.Request)request;
|
org.eclipse.jetty.server.Request r = (org.eclipse.jetty.server.Request)request;
|
||||||
r.setPathInfo(childPathInfo);
|
r.setPathInfo(childPathInfo);
|
||||||
|
|
||||||
Object o = e.getValue();
|
HandlerOrServlet o = e.getValue();
|
||||||
if (o instanceof Handler) {
|
if (o.handler != null) {
|
||||||
Handler h = (Handler)o;
|
o.handler.handle(target, baseRequest, request, response);
|
||||||
h.handle(target, baseRequest, request, response);
|
}
|
||||||
} else if (o instanceof Servlet) {
|
else if (o.servlet != null) {
|
||||||
Servlet s = (Servlet)o;
|
o.servlet.service(request, response);
|
||||||
s.service(request, response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r.setPathInfo(pathInfo);
|
r.setPathInfo(pathInfo);
|
||||||
|
|
|
@ -1,274 +0,0 @@
|
||||||
# Old v1.4 files
|
|
||||||
renderdata/ForgottenNature-models.txt
|
|
||||||
renderdata/ForgottenNature-texture.txt
|
|
||||||
renderdata/MineFactoryReloaded-models.txt
|
|
||||||
renderdata/MineFactoryReloaded-texture.txt
|
|
||||||
renderdata/PamHCApple-models.txt
|
|
||||||
renderdata/PamHCApple-texture.txt
|
|
||||||
renderdata/PamHCBean-models.txt
|
|
||||||
renderdata/PamHCBean-texture.txt
|
|
||||||
renderdata/PamHCBellpepper-models.txt
|
|
||||||
renderdata/PamHCBellpepper-texture.txt
|
|
||||||
renderdata/PamHCBlackberry-models.txt
|
|
||||||
renderdata/PamHCBlackberry-texture.txt
|
|
||||||
renderdata/PamHCBlueberry-models.txt
|
|
||||||
renderdata/PamHCBlueberry-texture.txt
|
|
||||||
renderdata/PamHCCandle-models.txt
|
|
||||||
renderdata/PamHCCandle-texture.txt
|
|
||||||
renderdata/PamHCCherry-models.txt
|
|
||||||
renderdata/PamHCCherry-texture.txt
|
|
||||||
renderdata/PamHCChilipepper-models.txt
|
|
||||||
renderdata/PamHCChilipepper-texture.txt
|
|
||||||
renderdata/PamHCCorn-models.txt
|
|
||||||
renderdata/PamHCCorn-texture.txt
|
|
||||||
renderdata/PamHCCotton-models.txt
|
|
||||||
renderdata/PamHCCotton-texture.txt
|
|
||||||
renderdata/PamHCCranberry-models.txt
|
|
||||||
renderdata/PamHCCranberry-texture.txt
|
|
||||||
renderdata/PamHCCucumber-models.txt
|
|
||||||
renderdata/PamHCCucumber-texture.txt
|
|
||||||
renderdata/PamHCGrape-models.txt
|
|
||||||
renderdata/PamHCGrape-texture.txt
|
|
||||||
renderdata/PamHCKiwi-models.txt
|
|
||||||
renderdata/PamHCKiwi-texture.txt
|
|
||||||
renderdata/PamHCLemon-models.txt
|
|
||||||
renderdata/PamHCLemon-texture.txt
|
|
||||||
renderdata/PamHCLettuce-models.txt
|
|
||||||
renderdata/PamHCLettuce-texture.txt
|
|
||||||
renderdata/PamHCOnion-models.txt
|
|
||||||
renderdata/PamHCOnion-texture.txt
|
|
||||||
renderdata/PamHCPeanut-models.txt
|
|
||||||
renderdata/PamHCPeanut-texture.txt
|
|
||||||
renderdata/PamHCRaspberry-models.txt
|
|
||||||
renderdata/PamHCRaspberry-texture.txt
|
|
||||||
renderdata/PamHCRice-models.txt
|
|
||||||
renderdata/PamHCRice-texture.txt
|
|
||||||
renderdata/PamHCSalt-texture.txt
|
|
||||||
renderdata/PamHCSpiceleaf-models.txt
|
|
||||||
renderdata/PamHCSpiceleaf-texture.txt
|
|
||||||
renderdata/PamHCStrawberry-models.txt
|
|
||||||
renderdata/PamHCStrawberry-texture.txt
|
|
||||||
renderdata/PamHCSunflower-models.txt
|
|
||||||
renderdata/PamHCSunflower-texture.txt
|
|
||||||
renderdata/PamHCTomato-models.txt
|
|
||||||
renderdata/PamHCTomato-texture.txt
|
|
||||||
renderdata/PamHCWhitemushroom-models.txt
|
|
||||||
renderdata/PamHCWhitemushroom-texture.txt
|
|
||||||
renderdata/PamWeeeFlowers-models.txt
|
|
||||||
renderdata/PamWeeeFlowers-texture.txt
|
|
||||||
renderdata/SoulShards-models.txt
|
|
||||||
renderdata/SoulShards-texture.txt
|
|
||||||
renderdata/Thaumcraft3-models.txt
|
|
||||||
renderdata/Thaumcraft3-texture.txt
|
|
||||||
renderdata/thermalexpansion-models.txt
|
|
||||||
renderdata/thermalexpansion-texture.txt
|
|
||||||
# Old 1.5 files
|
|
||||||
renderdata/archimedes-texture.txt
|
|
||||||
renderdata/bc-additionalpipes-texture.txt
|
|
||||||
renderdata/bc-models.txt
|
|
||||||
renderdata/bc-texture.txt
|
|
||||||
renderdata/BetterWorldsCoreBlocks-models.txt
|
|
||||||
renderdata/BetterWorldsCoreBlocks-texture.txt
|
|
||||||
renderdata/BetterWorldsCorners-models.txt
|
|
||||||
renderdata/BetterWorldsCorners-texture.txt
|
|
||||||
renderdata/BetterWorldsIntCorners-models.txt
|
|
||||||
renderdata/BetterWorldsIntCorners-texture.txt
|
|
||||||
renderdata/BetterWorldsPlantsAndFood-models.txt
|
|
||||||
renderdata/BetterWorldsPlantsAndFood-texture.txt
|
|
||||||
renderdata/BetterWorldsSlopes-models.txt
|
|
||||||
renderdata/BetterWorldsSlopes-texture.txt
|
|
||||||
renderdata/Biomes-O-Plenty-models.txt
|
|
||||||
renderdata/Biomes-O-Plenty-texture.txt
|
|
||||||
renderdata/ColoredBlocks-models.txt
|
|
||||||
renderdata/ColoredBlocks-texture.txt
|
|
||||||
renderdata/computercraft-texture.txt
|
|
||||||
renderdata/ee2-models.txt
|
|
||||||
renderdata/ee2-texture.txt
|
|
||||||
renderdata/enderstorage-texture.txt
|
|
||||||
renderdata/enterstorage-models.txt
|
|
||||||
renderdata/extrabees-texture.txt
|
|
||||||
renderdata/extrabiomesxl-bunyan-texture.txt
|
|
||||||
renderdata/extrabiomesxl-models.txt
|
|
||||||
renderdata/extrabiomesxl-texture.txt
|
|
||||||
renderdata/extrabiomesxl3-models.txt
|
|
||||||
renderdata/extrabiomesxl3-texture.txt
|
|
||||||
renderdata/FancyFences-models.txt
|
|
||||||
renderdata/FancyFences-texture.txt
|
|
||||||
renderdata/forestry-models.txt
|
|
||||||
renderdata/forestry-texture.txt
|
|
||||||
renderdata/gregslighting-texture.txt
|
|
||||||
renderdata/GregTech-models.txt
|
|
||||||
renderdata/GregTech-texture.txt
|
|
||||||
renderdata/ic2-advancedmachines-texture.txt
|
|
||||||
renderdata/ic2-advpowermanagement-texture.txt
|
|
||||||
renderdata/ic2-advsolarpanels-texture.txt
|
|
||||||
renderdata/ic2-chargingbench-texture.txt
|
|
||||||
renderdata/ic2-compactsolars-texture.txt
|
|
||||||
renderdata/ic2-models.txt
|
|
||||||
renderdata/ic2-nuclearcontrol-models.txt
|
|
||||||
renderdata/ic2-nuclearcontrol-texture.txt
|
|
||||||
renderdata/ic2-powerconverters-texture.txt
|
|
||||||
renderdata/ic2-texture.txt
|
|
||||||
renderdata/ironchest-models.txt
|
|
||||||
renderdata/ironchest-texture.txt
|
|
||||||
renderdata/lctrees-models.txt
|
|
||||||
renderdata/lctrees-texture.txt
|
|
||||||
renderdata/MetallurgyBase-texture.txt
|
|
||||||
renderdata/MetallurgyCore-texture.txt
|
|
||||||
renderdata/MetallurgyEnder-texture.txt
|
|
||||||
renderdata/MetallurgyFantasy-texture.txt
|
|
||||||
renderdata/MetallurgyNether-texture.txt
|
|
||||||
renderdata/MetallurgyPrecious-texture.txt
|
|
||||||
renderdata/MetallurgyUtility-texture.txt
|
|
||||||
renderdata/millenaire-models.txt
|
|
||||||
renderdata/millenaire-texture.txt
|
|
||||||
renderdata/mystcraft-texture.txt
|
|
||||||
renderdata/netherores-texture.txt
|
|
||||||
renderdata/ObsidiPlates-models.txt
|
|
||||||
renderdata/ObsidiPlates-texture.txt
|
|
||||||
renderdata/railcraft-models.txt
|
|
||||||
renderdata/railcraft-texture.txt
|
|
||||||
renderdata/railcraft6-models.txt
|
|
||||||
renderdata/railcraft6-texture.txt
|
|
||||||
renderdata/rp2-lighting-texture.txt
|
|
||||||
renderdata/rp2-logic-models.txt
|
|
||||||
renderdata/rp2-logic-texture.txt
|
|
||||||
renderdata/rp2-machine-models.txt
|
|
||||||
renderdata/rp2-machine-texture.txt
|
|
||||||
renderdata/rp2-models.txt
|
|
||||||
renderdata/rp2-texture.txt
|
|
||||||
renderdata/rp2-world-models.txt
|
|
||||||
renderdata/rp2-world-texture.txt
|
|
||||||
renderdata/superslopes-models.txt
|
|
||||||
renderdata/superslopes-texture.txt
|
|
||||||
renderdata/superslopes4-corners-models.txt
|
|
||||||
renderdata/superslopes4-corners-texture.txt
|
|
||||||
renderdata/superslopes4-intcorners-models.txt
|
|
||||||
renderdata/superslopes4-intcorners-texture.txt
|
|
||||||
renderdata/superslopes4-slopes-models.txt
|
|
||||||
renderdata/superslopes4-slopes-texture.txt
|
|
||||||
renderdata/superslopes4-slopres-texture.txt
|
|
||||||
renderdata/TFCraft-models.txt
|
|
||||||
renderdata/TFCraft-texture.txt
|
|
||||||
renderdata/Tropicraft-models.txt
|
|
||||||
renderdata/Tropicraft-texture.txt
|
|
||||||
renderdata/tubestuff-texture.txt
|
|
||||||
renderdata/TwilightForest-models.txt
|
|
||||||
renderdata/TwilightForest-texture.txt
|
|
||||||
renderdata/XyCraft-models.txt
|
|
||||||
renderdata/XyCraft-texture.txt
|
|
||||||
# Old 1.5.1 files
|
|
||||||
renderdata/1.5.1/ForgottenNature-models.txt
|
|
||||||
renderdata/1.5.1/ForgottenNature-texture.txt
|
|
||||||
renderdata/1.5.1/ThermalExpansion-models.txt
|
|
||||||
renderdata/1.5.1/ThermalExpansion-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCApple-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCApple-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCBean-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCBean-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCBellpepper-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCBellpepper-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCBlackberry-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCBlackberry-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCBlueberry-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCBlueberry-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCCandle-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCCandle-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCCherry-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCCherry-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCChilipepper-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCChilipepper-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCCorn-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCCorn-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCCotton-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCCotton-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCCranberry-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCCranberry-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCCucumber-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCCucumber-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCGrape-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCGrape-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCKiwi-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCKiwi-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCLemon-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCLemon-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCLettuce-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCLettuce-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCOnion-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCOnion-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCPeanut-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCPeanut-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCRaspberry-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCRaspberry-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCRice-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCRice-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCSalt-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCSpiceleaf-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCSpiceleaf-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCStrawberry-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCStrawberry-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCSunflower-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCSunflower-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCTomato-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCTomato-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCTurnip-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCTurnip-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCWhitemushroom-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamHCWhitemushroom-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamWeeeFlowers-models.txt
|
|
||||||
renderdata/1.5.1/PamHC/PamWeeeFlowers-texture.txt
|
|
||||||
renderdata/1.5.1/PamHC
|
|
||||||
renderdata/1.5.1
|
|
||||||
# Old 1.5.2 files
|
|
||||||
renderdata/1.5.2/Biomes-O-Plenty-0.5.8-models.txt
|
|
||||||
renderdata/1.5.2/Biomes-O-Plenty-0.5.8-texture.txt
|
|
||||||
renderdata/1.5.2/Biomes-O-Plenty-models.txt
|
|
||||||
renderdata/1.5.2/Biomes-O-Plenty-texture.txt
|
|
||||||
renderdata/1.5.2/Chisel-models.txt
|
|
||||||
renderdata/1.5.2/Chisel-texture.txt
|
|
||||||
renderdata/1.5.2/extrautilities-models.txt
|
|
||||||
renderdata/1.5.2/extrautilities-texture.txt
|
|
||||||
renderdata/1.5.2/immibisMicroblocks-models.txt
|
|
||||||
renderdata/1.5.2/immibisMicroblocks-texture.txt
|
|
||||||
renderdata/1.5.2/MineFactoryReloaded-models.txt
|
|
||||||
renderdata/1.5.2/MineFactoryReloaded-texture.txt
|
|
||||||
renderdata/1.5.2/Natura-models.txt
|
|
||||||
renderdata/1.5.2/Natura-texture.txt
|
|
||||||
renderdata/1.5.2/NumiRP-texture.txt
|
|
||||||
renderdata/1.5.2/SlabCraft-models.txt
|
|
||||||
renderdata/1.5.2/SlabCraft-texture.txt
|
|
||||||
renderdata/1.5.2/SoulShards-models.txt
|
|
||||||
renderdata/1.5.2/SoulShards-texture.txt
|
|
||||||
renderdata/1.5.2/StairCraft-models.txt
|
|
||||||
renderdata/1.5.2/StairCraft-texture.txt
|
|
||||||
renderdata/1.5.2/TConstruct-models.txt
|
|
||||||
renderdata/1.5.2/TConstruct-texture.txt
|
|
||||||
renderdata/1.5.2/Thaumcraft3-models.txt
|
|
||||||
renderdata/1.5.2/Thaumcraft3-texture.txt
|
|
||||||
renderdata/1.5.2/UndergroundBiomes-models.txt
|
|
||||||
renderdata/1.5.2/UndergroundBiomes-texture.txt
|
|
||||||
renderdata/1.5.2
|
|
||||||
# Old 1.6.2 files
|
|
||||||
renderdata/1.6.2/Artifice-models.txt
|
|
||||||
renderdata/1.6.2/Artifice-texture.txt
|
|
||||||
renderdata/1.6.2/Biomes-O-Plenty-0.5.8-models.txt
|
|
||||||
renderdata/1.6.2/Biomes-O-Plenty-0.5.8-texture.txt
|
|
||||||
renderdata/1.6.2/Biomes-O-Plenty-0.5.9-models.txt
|
|
||||||
renderdata/1.6.2/Biomes-O-Plenty-0.5.9-texture.txt
|
|
||||||
renderdata/1.6.2/Biomes-O-Plenty-models.txt
|
|
||||||
renderdata/1.6.2/Biomes-O-Plenty-texture.txt
|
|
||||||
renderdata/1.6.2/BuildCraft-models.txt
|
|
||||||
renderdata/1.6.2/BuildCraft-texture.txt
|
|
||||||
renderdata/1.6.2/coralmod-models.txt
|
|
||||||
renderdata/1.6.2/coralmod-texture.txt
|
|
||||||
renderdata/1.6.2/ExtrabiomesXL-models.txt
|
|
||||||
renderdata/1.6.2/ExtrabiomesXL-texture.txt
|
|
||||||
renderdata/1.6.2/railcraft8-models.txt
|
|
||||||
renderdata/1.6.2/railcraft8-texture.txt
|
|
||||||
renderdata/1.6.2
|
|
||||||
# Old 1.6.4 files
|
|
||||||
renderdata/1.6.4/GalacticraftCore-models.txt
|
|
||||||
renderdata/1.6.4/GalacticraftCore-texture.txt
|
|
||||||
renderdata/1.6.4/GalacticraftMars-models.txt
|
|
||||||
renderdata/1.6.4/GalacticraftMars-texture.txt
|
|
||||||
renderdata/1.6.4
|
|
|
@ -411,7 +411,7 @@
|
||||||
|
|
||||||
.dynmap .sublist .item > a {
|
.dynmap .sublist .item > a {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
text-indent: -99999px;
|
text-indent: -99999px;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
@ -570,6 +570,14 @@
|
||||||
transition: all 0.6s ease-in-out 0s;
|
transition: all 0.6s ease-in-out 0s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* do not animate player movements when zooming */
|
||||||
|
.dynmap .leaflet-zoom-anim .leaflet-zoom-animated.playerMarker {
|
||||||
|
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||||
|
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||||
|
-o-transition: transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||||
|
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||||
|
}
|
||||||
|
|
||||||
.dynmap .playerIcon {
|
.dynmap .playerIcon {
|
||||||
margin-top: -16px;
|
margin-top: -16px;
|
||||||
margin-left: -16px;
|
margin-left: -16px;
|
||||||
|
@ -806,10 +814,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.chatinput {
|
.chatinput {
|
||||||
|
position: absolute;
|
||||||
width: 608px;
|
width: 608px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
|
bottom: 8px;
|
||||||
outline: none;
|
outline: none;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background-color: #000000;
|
background-color: #000000;
|
||||||
|
@ -829,6 +837,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.loginbutton {
|
.loginbutton {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0px;
|
||||||
|
right: 4px;
|
||||||
color: #000;
|
color: #000;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
|
@ -905,15 +916,15 @@
|
||||||
|
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: rgba(0,0,0,0.6);
|
background: rgba(0,0,0,0.6);
|
||||||
padding: 2px;
|
padding: 2px 6px;
|
||||||
|
|
||||||
-moz-border-radius: 3px;
|
-moz-border-radius: 3px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dynmap .mapMarker .markerName16x16 {
|
.dynmap .mapMarker .markerName16x16 {
|
||||||
top: -6px;
|
top: -12px;
|
||||||
left: 10px;
|
left: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dynmap .mapMarker .markerName8x8 {
|
.dynmap .mapMarker .markerName8x8 {
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<browserconfig>
|
||||||
|
<msapplication>
|
||||||
|
<tile>
|
||||||
|
<square150x150logo src="images/icons/mstile-150x150.png"/>
|
||||||
|
<TileColor>#ffffff</TileColor>
|
||||||
|
</tile>
|
||||||
|
</msapplication>
|
||||||
|
</browserconfig>
|
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
|
@ -0,0 +1,112 @@
|
||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="200.000000pt" height="200.000000pt" viewBox="0 0 200.000000 200.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
<metadata>
|
||||||
|
Created by potrace 1.14, written by Peter Selinger 2001-2017
|
||||||
|
</metadata>
|
||||||
|
<g transform="translate(0.000000,200.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M1205 1970 c3 -5 8 -10 11 -10 2 0 4 5 4 10 0 6 -5 10 -11 10 -5 0
|
||||||
|
-7 -4 -4 -10z"/>
|
||||||
|
<path d="M1170 1940 c0 -4 7 -10 15 -14 8 -3 15 -10 15 -15 0 -6 -7 -8 -15 -5
|
||||||
|
-8 4 -15 1 -15 -5 0 -6 6 -11 13 -11 6 0 12 -12 13 -28 2 -51 15 -103 25 -97
|
||||||
|
5 4 7 11 3 17 -5 8 -8 40 -13 144 -1 13 -41 27 -41 14z"/>
|
||||||
|
<path d="M1250 1880 c-21 -21 -28 -80 -10 -80 6 0 10 9 10 19 0 11 8 26 18 33
|
||||||
|
18 14 26 48 11 48 -5 0 -18 -9 -29 -20z"/>
|
||||||
|
<path d="M701 1785 c-18 -8 -44 -15 -58 -15 -17 0 -24 -5 -22 -17 3 -34 -1
|
||||||
|
-41 -21 -36 -11 3 -20 9 -20 14 0 5 -10 9 -23 9 -27 0 -77 -21 -77 -33 0 -13
|
||||||
|
-27 -37 -42 -37 -10 0 -12 -11 -10 -40 2 -22 9 -40 16 -40 6 0 17 -9 24 -20 7
|
||||||
|
-11 19 -20 28 -20 11 0 14 -8 12 -26 -3 -29 -17 -39 -61 -49 -15 -3 -25 -10
|
||||||
|
-22 -15 3 -5 -21 -14 -54 -21 l-60 -11 5 -42 c56 -444 70 -582 62 -587 -5 -3
|
||||||
|
-4 -41 3 -97 9 -73 9 -95 -1 -107 -10 -12 -9 -15 4 -15 10 0 15 -4 11 -9 -3
|
||||||
|
-5 5 -17 17 -27 18 -12 19 -15 4 -10 -14 5 -17 2 -12 -9 3 -8 9 -22 13 -31 4
|
||||||
|
-12 2 -15 -8 -12 -8 2 -15 16 -17 31 -5 39 -25 50 -49 27 -12 -10 -23 -17 -26
|
||||||
|
-14 -2 3 -7 -2 -10 -10 -4 -9 -2 -18 3 -21 6 -4 10 -13 10 -22 0 -13 -3 -13
|
||||||
|
-15 -3 -17 14 -38 2 -56 -32 -9 -16 -6 -18 27 -13 21 2 41 10 46 17 7 12 9 11
|
||||||
|
12 -11 0 -5 4 -13 8 -16 4 -4 3 -16 -3 -26 -9 -17 -6 -19 27 -14 21 2 41 10
|
||||||
|
46 17 6 9 10 7 14 -9 7 -25 34 -32 34 -9 0 10 14 16 43 18 41 3 42 4 45 43 2
|
||||||
|
22 7 44 12 49 5 5 58 -26 129 -77 66 -48 125 -87 130 -87 16 0 13 17 -4 24
|
||||||
|
-23 8 -21 105 3 122 20 15 52 18 52 5 0 -5 10 -13 22 -17 19 -6 20 -7 4 -16
|
||||||
|
-12 -7 -14 -13 -7 -22 8 -10 4 -16 -14 -24 -38 -17 -33 -50 11 -68 36 -15 36
|
||||||
|
-16 15 -30 -14 -11 -21 -26 -21 -50 0 -19 -4 -34 -10 -34 -5 0 -10 5 -10 10 0
|
||||||
|
6 -4 10 -8 10 -4 0 -8 -11 -8 -25 0 -31 7 -31 38 0 l25 25 48 -35 c36 -25 52
|
||||||
|
-31 61 -24 7 6 18 8 24 4 6 -4 20 1 30 10 11 10 26 14 38 11 16 -5 19 -2 17
|
||||||
|
25 -2 29 7 37 112 115 62 46 113 88 113 92 0 11 196 153 232 169 15 7 28 17
|
||||||
|
28 23 0 6 4 9 9 6 15 -9 40 28 43 64 2 25 -1 35 -12 35 -37 2 -49 16 -43 48 3
|
||||||
|
18 12 37 19 43 8 6 12 19 8 28 -3 9 -1 16 4 16 12 0 10 34 -3 63 -9 22 11 155
|
||||||
|
28 175 7 9 11 48 9 110 -1 67 2 102 12 116 7 12 17 44 20 71 l7 51 -45 12
|
||||||
|
c-25 6 -46 16 -46 22 0 5 -7 10 -15 10 -9 0 -15 9 -15 21 0 13 -8 23 -21 26
|
||||||
|
-12 3 -16 9 -10 12 6 4 13 21 17 38 5 28 3 31 -25 36 -17 4 -38 4 -46 1 -18
|
||||||
|
-7 -20 -55 -3 -72 8 -8 8 -15 -3 -28 -10 -12 -24 -15 -59 -11 -24 3 -52 1 -62
|
||||||
|
-4 -14 -7 -19 0 -33 44 -10 28 -33 82 -52 120 -35 67 -36 67 -78 67 -41 0 -43
|
||||||
|
-1 -60 -47 -10 -27 -27 -63 -37 -81 -18 -29 -24 -32 -52 -27 -57 12 -66 16
|
||||||
|
-66 35 0 28 -11 51 -21 44 -5 -3 -9 -21 -9 -40 0 -48 -16 -43 -24 8 -5 29 -10
|
||||||
|
38 -15 29 -5 -8 -7 -27 -4 -42 3 -20 -1 -31 -11 -35 -9 -3 -16 -13 -16 -21 0
|
||||||
|
-11 -6 -14 -22 -9 -13 3 -38 6 -56 6 l-33 0 3 48 c3 42 6 47 28 50 23 3 25 7
|
||||||
|
24 49 -1 39 -5 48 -25 55 -13 5 -27 16 -32 24 -10 18 -42 17 -86 -1z m-5 -131
|
||||||
|
c6 -7 16 -14 23 -14 14 0 15 -86 1 -95 -6 -4 -33 -7 -60 -8 -27 -1 -52 -6 -56
|
||||||
|
-10 -17 -17 -34 -6 -34 22 0 63 11 90 41 96 20 5 26 11 22 22 -5 13 -1 15 23
|
||||||
|
9 16 -4 34 -14 40 -22z m509 6 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10
|
||||||
|
4 10 3 0 8 -4 11 -10z m-167 -97 c46 -6 52 -18 23 -50 -17 -18 -24 -19 -60
|
||||||
|
-10 -49 13 -54 25 -8 21 17 -2 23 -1 12 2 -11 3 -27 8 -35 11 -8 3 -21 7 -29
|
||||||
|
7 -8 1 -16 6 -18 13 -5 13 33 23 57 15 8 -2 34 -7 58 -9z m167 -73 c3 -5 1
|
||||||
|
-10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m211 -15 c-21
|
||||||
|
-16 -32 -13 -21 4 3 6 14 11 23 11 15 -1 15 -2 -2 -15z m-786 -21 c0 -31 -23
|
||||||
|
-28 -28 4 -2 15 2 22 12 22 11 0 16 -9 16 -26z m583 -6 c6 -22 1 -38 -11 -38
|
||||||
|
-10 0 -31 48 -24 55 12 12 30 4 35 -17z m137 -8 c-8 -5 -13 -10 -10 -11 3 0
|
||||||
|
14 -2 25 -5 64 -13 156 -23 169 -18 9 3 16 1 16 -5 0 -6 -7 -11 -15 -11 -8 0
|
||||||
|
-15 -7 -15 -15 0 -8 -4 -15 -10 -15 -5 0 -10 4 -10 9 0 5 -15 12 -32 16 -95
|
||||||
|
23 -159 33 -180 27 -26 -6 -23 11 5 24 29 15 79 18 57 4z m-262 -19 c19 -12
|
||||||
|
10 -47 -11 -43 -18 3 -23 -13 -7 -23 12 -7 4 -25 -11 -25 -5 0 -9 14 -9 30 0
|
||||||
|
17 -5 30 -11 30 -5 0 -7 5 -4 10 4 6 11 8 16 5 5 -4 9 1 9 9 0 18 8 20 28 7z
|
||||||
|
m52 -71 l-8 -35 -1 31 c-1 17 2 34 6 37 11 12 12 3 3 -33z m80 24 c0 -8 -4
|
||||||
|
-12 -10 -9 -5 3 -10 10 -10 16 0 5 5 9 10 9 6 0 10 -7 10 -16z m-605 -27 c6
|
||||||
|
-7 55 -28 110 -47 55 -18 107 -40 116 -47 8 -7 21 -13 28 -13 10 0 11 -10 7
|
||||||
|
-35 -6 -32 -3 -39 23 -63 22 -18 31 -36 31 -57 0 -16 7 -43 15 -59 8 -15 15
|
||||||
|
-35 15 -42 0 -8 6 -14 14 -14 7 0 19 -7 26 -15 7 -8 8 -15 3 -15 -6 0 -22 -11
|
||||||
|
-37 -25 -23 -21 -30 -23 -46 -12 -11 6 -20 19 -20 29 0 9 -9 19 -20 23 -12 4
|
||||||
|
-24 21 -30 45 -6 22 -15 42 -20 45 -6 3 -10 13 -10 20 0 18 -31 55 -45 55 -6
|
||||||
|
0 -15 15 -20 32 -8 26 -20 37 -55 51 l-46 19 -33 -31 -33 -31 7 -113 c8 -130
|
||||||
|
10 -133 75 -204 11 -13 20 -35 21 -50 1 -28 15 -74 35 -106 14 -23 51 -30 58
|
||||||
|
-10 5 11 14 14 36 10 16 -4 32 -2 35 2 3 5 16 8 30 6 14 -1 28 2 31 6 8 13 48
|
||||||
|
11 62 -3 7 -7 12 -25 12 -40 0 -21 5 -28 20 -28 16 0 20 7 20 33 0 17 7 41 15
|
||||||
|
51 8 11 15 28 15 38 0 9 8 25 19 35 10 10 21 39 25 68 6 51 26 87 26 48 0 -12
|
||||||
|
-4 -25 -10 -28 -5 -3 -10 -21 -10 -39 0 -20 -8 -40 -20 -51 -11 -10 -20 -25
|
||||||
|
-20 -34 0 -9 -7 -26 -15 -38 -9 -12 -15 -26 -14 -30 5 -31 -3 -55 -21 -60 -12
|
||||||
|
-3 -20 -14 -20 -25 0 -17 5 -19 28 -14 26 6 26 6 8 -9 -11 -8 -23 -15 -28 -15
|
||||||
|
-4 0 -8 -10 -8 -22 0 -18 -2 -20 -9 -9 -5 8 -21 16 -35 18 -20 3 -27 -2 -32
|
||||||
|
-21 -8 -35 -38 -42 -72 -17 l-29 20 -26 -32 c-25 -31 -26 -31 -46 -13 -11 10
|
||||||
|
-20 21 -19 25 2 19 -5 33 -37 65 -19 20 -35 43 -35 52 0 8 -7 29 -16 45 -8 17
|
||||||
|
-13 37 -10 45 8 22 -12 65 -43 94 -16 14 -31 39 -34 55 -3 17 -13 62 -21 100
|
||||||
|
-23 112 -22 268 3 314 8 14 11 38 8 59 -6 34 -6 34 26 28 18 -3 37 -12 42 -19z
|
||||||
|
m593 -36 c15 -47 15 -51 1 -51 -5 0 -7 5 -3 11 4 7 -3 19 -16 29 -15 11 -21
|
||||||
|
23 -17 34 10 26 23 18 35 -23z m69 17 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3
|
||||||
|
4 -12 1 -19z m-36 -51 c-13 -13 -15 11 -4 40 7 16 8 15 11 -6 2 -13 -1 -28 -7
|
||||||
|
-34z m396 1 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m-72 -43
|
||||||
|
c-2 -31 -8 -61 -13 -68 -6 -7 -14 -47 -18 -90 -4 -43 -10 -80 -15 -83 -12 -7
|
||||||
|
2 165 17 210 7 22 11 44 8 48 -5 8 13 38 22 38 1 0 1 -25 -1 -55z m-48 -17
|
||||||
|
c-3 -7 -5 -2 -5 12 0 14 2 19 5 13 2 -7 2 -19 0 -25z m-130 -34 c2 -5 -24 -20
|
||||||
|
-57 -33 -54 -21 -81 -50 -47 -51 6 0 4 -5 -6 -11 -14 -8 -22 -8 -30 0 -14 14
|
||||||
|
-18 69 -6 77 5 3 9 -3 9 -13 0 -14 2 -15 9 -4 5 8 7 21 4 30 -4 14 -3 14 6 1
|
||||||
|
9 -13 15 -12 53 2 45 17 60 18 65 2z m-153 -131 c-4 -16 -10 -30 -13 -33 -3
|
||||||
|
-3 -6 -11 -7 -17 -2 -30 -4 -36 -11 -30 -10 10 -32 -13 -27 -28 3 -7 1 -16 -5
|
||||||
|
-20 -17 -10 -24 21 -11 44 8 16 8 21 -1 21 -7 0 -9 3 -5 8 4 4 12 7 18 7 6 0
|
||||||
|
12 8 14 18 3 21 32 57 46 57 4 0 5 -12 2 -27z m306 -79 c0 -8 -5 -12 -10 -9
|
||||||
|
-6 4 -8 11 -5 16 9 14 15 11 15 -7z m-996 -248 c8 -18 22 -40 33 -47 10 -8 18
|
||||||
|
-20 17 -26 -1 -7 -2 -17 -3 -23 0 -5 -5 -10 -10 -10 -5 0 -7 9 -4 20 3 11 1
|
||||||
|
20 -4 20 -4 0 -17 15 -27 34 -10 19 -25 37 -33 40 -8 3 -11 10 -8 16 11 18 25
|
||||||
|
10 39 -24z m566 -5 c0 -17 -4 -33 -10 -36 -5 -3 -10 -21 -10 -40 0 -40 -8 -65
|
||||||
|
-22 -65 -10 0 -4 70 13 133 12 44 29 49 29 8z m-626 -26 c19 -28 21 -44 4 -27
|
||||||
|
-7 7 -17 8 -30 1 -14 -7 -18 -6 -18 6 0 8 5 15 10 15 6 0 10 5 10 11 0 5 -4 7
|
||||||
|
-10 4 -5 -3 -10 -1 -10 4 0 20 28 11 44 -14z m6 -60 c11 -13 10 -14 -4 -9 -9
|
||||||
|
3 -16 10 -16 15 0 13 6 11 20 -6z m-50 1 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1
|
||||||
|
-10 4 0 6 5 11 10 11 6 0 10 -2 10 -4z m180 -102 c0 -28 -2 -32 -13 -23 -14
|
||||||
|
14 -10 72 4 63 5 -3 9 -21 9 -40z m-216 -90 c17 -16 21 -34 9 -34 -17 1 -45
|
||||||
|
29 -38 39 8 14 11 14 29 -5z m651 -153 c-6 -5 -25 10 -25 20 0 5 6 4 14 -3 8
|
||||||
|
-7 12 -15 11 -17z"/>
|
||||||
|
<path d="M579 1193 c-13 -16 -12 -17 4 -4 9 7 17 15 17 17 0 8 -8 3 -21 -13z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 7.6 KiB |
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"short_name": "",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "android-chrome-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"theme_color": "#ffffff",
|
||||||
|
"background_color": "#ffffff"
|
||||||
|
}
|
|
@ -10,9 +10,17 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
|
||||||
<!-- These 2 lines make us fullscreen on apple mobile products - remove if you don't like that -->
|
<!-- These 2 lines make us fullscreen on apple mobile products - remove if you don't like that -->
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||||
|
|
||||||
<link rel="icon" href="images/dynmap.ico" type="image/ico" />
|
<link rel="apple-touch-icon" sizes="180x180" href="images/icons/apple-touch-icon.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="images/icons/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="images/icons/favicon-16x16.png">
|
||||||
|
<link rel="manifest" href="images/icons/site.webmanifest">
|
||||||
|
<link rel="mask-icon" href="images/icons/safari-pinned-tab.svg" color="#000000">
|
||||||
|
<link rel="shortcut icon" href="images/icons/favicon.ico">
|
||||||
|
<meta name="msapplication-TileColor" content="#000000">
|
||||||
|
<meta name="msapplication-config" content="images/icons/browserconfig.xml">
|
||||||
|
<meta name="theme-color" content="#000000">
|
||||||
|
|
||||||
<script type="text/javascript" src="js/jquery-3.5.1.js?_=${version}-${buildnumber}"></script>
|
<script type="text/javascript" src="js/jquery-3.5.1.js?_=${version}-${buildnumber}"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="css/leaflet.css?_=${version}-${buildnumber}" />
|
<link rel="stylesheet" type="text/css" href="css/leaflet.css?_=${version}-${buildnumber}" />
|
||||||
|
@ -54,4 +62,4 @@
|
||||||
|
|
||||||
<div id="mcmap"></div>
|
<div id="mcmap"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue