mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-12-24 17:49:16 +00:00
Compare commits
2106 Commits
1.3.3
...
2.2.18-1.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
141ca76647 | ||
|
|
94557830f5 | ||
|
|
49acb7faba | ||
|
|
1904f67662 | ||
|
|
5b2bf38344 | ||
|
|
494c38a153 | ||
|
|
dd4b85cbfe | ||
|
|
8f7b54a5a4 | ||
|
|
cec502340e | ||
|
|
64e27c7fb0 | ||
|
|
b2bbd31548 | ||
|
|
17df92a07c | ||
|
|
2b749b5ab7 | ||
|
|
28e3402d88 | ||
|
|
d96bb061e0 | ||
|
|
e6def804f8 | ||
|
|
a5be48c07c | ||
|
|
fe3909f594 | ||
|
|
f37d91a530 | ||
|
|
614ef78771 | ||
|
|
fb294fc03c | ||
|
|
8c7e7c3d48 | ||
|
|
98b6280652 | ||
|
|
7c4c2d6382 | ||
|
|
1a29ea302e | ||
|
|
be39fce741 | ||
|
|
4fed2e6e5f | ||
|
|
14ae5809b0 | ||
|
|
0f66aa47c9 | ||
|
|
cf85d300f4 | ||
|
|
91d60e56df | ||
|
|
1d3681beb4 | ||
|
|
0b403cf329 | ||
|
|
8ba75899e3 | ||
|
|
4d4ed72159 | ||
|
|
b72bf072b3 | ||
|
|
4edcb54b31 | ||
|
|
eae7fc0e53 | ||
|
|
fddacd4410 | ||
|
|
de6c4b9a30 | ||
|
|
6990e34138 | ||
|
|
d9883697ef | ||
|
|
05a26ff8b2 | ||
|
|
84bb082d44 | ||
|
|
a0db94d84f | ||
|
|
0367b4ecd7 | ||
|
|
dbc425dce6 | ||
|
|
116c017c6d | ||
|
|
9c387475f0 | ||
|
|
0765c21cef | ||
|
|
2871038584 | ||
|
|
340885f939 | ||
|
|
1e32e47f54 | ||
|
|
3c759f3b01 | ||
|
|
6615f34d20 | ||
|
|
3a4aac1ee4 | ||
|
|
4d6c092615 | ||
|
|
93421a1dc9 | ||
|
|
209458a856 | ||
|
|
82bd94620e | ||
|
|
af9f017871 | ||
|
|
2f8922ea87 | ||
|
|
0ea936f3fe | ||
|
|
d1870ee0a8 | ||
|
|
d2151690ad | ||
|
|
dff373e7d5 | ||
|
|
0aec2a664f | ||
|
|
723b696393 | ||
|
|
f5f89eb4e4 | ||
|
|
df15332c7f | ||
|
|
61d9e5a869 | ||
|
|
9628b66a97 | ||
|
|
5e041366d4 | ||
|
|
3ecae8d72c | ||
|
|
5709ce9d82 | ||
|
|
ce3c334ac5 | ||
|
|
2ed5aa8730 | ||
|
|
8480a63dda | ||
|
|
132a1695f3 | ||
|
|
21775630c3 | ||
|
|
eac2ef7c6d | ||
|
|
386997f646 | ||
|
|
637b90ad62 | ||
|
|
95d755c2ec | ||
|
|
781aeebef6 | ||
|
|
5e133fd51a | ||
|
|
85f62a3b9d | ||
|
|
a32de58c8b | ||
|
|
1cb2ea6c17 | ||
|
|
6a37ab7af2 | ||
|
|
e0f0aaf767 | ||
|
|
3d7c5b050a | ||
|
|
6bc57c255f | ||
|
|
b82edfe688 | ||
|
|
6b32eb3441 | ||
|
|
23a07fa8a5 | ||
|
|
b019faedd2 | ||
|
|
4430433a10 | ||
|
|
f52cd29e7b | ||
|
|
6a44e593a6 | ||
|
|
f7065fe034 | ||
|
|
0a247956f7 | ||
|
|
03836acded | ||
|
|
b5fb277982 | ||
|
|
e523d3c166 | ||
|
|
41477e4aa6 | ||
|
|
fbaf42a8c4 | ||
|
|
1c3668047b | ||
|
|
7d78c69b6e | ||
|
|
43bd96a679 | ||
|
|
a87c83dae2 | ||
|
|
490d2b69e3 | ||
|
|
7eac936431 | ||
|
|
588b261d52 | ||
|
|
daf2cf02b3 | ||
|
|
b9d97f2434 | ||
|
|
1467dc963d | ||
|
|
89bf687fc4 | ||
|
|
2e7c80562b | ||
|
|
5d54b82be0 | ||
|
|
2ae1df4d42 | ||
|
|
26782e6f0c | ||
|
|
cc84d5b562 | ||
|
|
8bb1efdca3 | ||
|
|
7a5794c8e2 | ||
|
|
9dd20661f5 | ||
|
|
ad0ab66711 | ||
|
|
82396b5145 | ||
|
|
246e974dc1 | ||
|
|
203b6a4b4f | ||
|
|
f204f3a209 | ||
|
|
ba8e060370 | ||
|
|
c51172acbc | ||
|
|
39100a5011 | ||
|
|
fcee61a703 | ||
|
|
ce8cc2cf37 | ||
|
|
3b5bdcfb51 | ||
|
|
4d67e97973 | ||
|
|
da09f4d6d8 | ||
|
|
dbc7e2e0bf | ||
|
|
dd804b6665 | ||
|
|
33eb878834 | ||
|
|
2a2c456011 | ||
|
|
05a12f3899 | ||
|
|
eb04710f71 | ||
|
|
257760453e | ||
|
|
d11baeb08a | ||
|
|
47d322c993 | ||
|
|
d316207a61 | ||
|
|
e6daabbb47 | ||
|
|
53156449f1 | ||
|
|
e3d4c32d03 | ||
|
|
9cd5c39bbe | ||
|
|
a1fbf25465 | ||
|
|
ec74037f05 | ||
|
|
fff650b766 | ||
|
|
bae2a18e24 | ||
|
|
fd8a7ebb4c | ||
|
|
4a3a1491d4 | ||
|
|
9aa2c5ed8a | ||
|
|
d5699a7472 | ||
|
|
df98f8f626 | ||
|
|
d37b298f07 | ||
|
|
62f7fc17d1 | ||
|
|
6e4929246d | ||
|
|
909461975a | ||
|
|
dec191e5e7 | ||
|
|
07b0cd6f5a | ||
|
|
b7a892ecfe | ||
|
|
79d16102fa | ||
|
|
67efdb47aa | ||
|
|
751c233b49 | ||
|
|
f51734fea0 | ||
|
|
516a7111a7 | ||
|
|
1e3ff59b26 | ||
|
|
4c48f812d5 | ||
|
|
a63a6f751f | ||
|
|
923860a90b | ||
|
|
5a4ca2f907 | ||
|
|
ccc2ed0806 | ||
|
|
44c707e059 | ||
|
|
e7c458de3f | ||
|
|
11b05b10a4 | ||
|
|
d133ac0088 | ||
|
|
8951fcdebd | ||
|
|
ecbd5677ce | ||
|
|
e31b9c1a28 | ||
|
|
faa7b7c742 | ||
|
|
d08f326477 | ||
|
|
6500ed2075 | ||
|
|
56eb775a0f | ||
|
|
e225bcfb96 | ||
|
|
4be6abe416 | ||
|
|
c3de8b33de | ||
|
|
5658d6709c | ||
|
|
192538a741 | ||
|
|
b8b9d7bf8c | ||
|
|
1db8603910 | ||
|
|
1c5774fca5 | ||
|
|
0b332b06b6 | ||
|
|
0be9b049a3 | ||
|
|
6993639cc0 | ||
|
|
74172e3123 | ||
|
|
6e1c4f682e | ||
|
|
af0d282a1f | ||
|
|
09bf15fa05 | ||
|
|
43f7d95b4c | ||
|
|
8b536b1775 | ||
|
|
60a7f4bc35 | ||
|
|
0ed0e0c983 | ||
|
|
f4b1ca9f21 | ||
|
|
609104cfa8 | ||
|
|
935d11b433 | ||
|
|
e9eeb8335d | ||
|
|
4a2f42437f | ||
|
|
51b0693c99 | ||
|
|
185b366d8d | ||
|
|
a40e533068 | ||
|
|
5b3918fcb1 | ||
|
|
d315e99b63 | ||
|
|
8090ba0259 | ||
|
|
584400d011 | ||
|
|
124ad23a95 | ||
|
|
6b59aa38ae | ||
|
|
03554eb372 | ||
|
|
dabfe41f29 | ||
|
|
6e2c6fc51e | ||
|
|
d81986bcc5 | ||
|
|
ea17e916b8 | ||
|
|
ce56224038 | ||
|
|
9978932391 | ||
|
|
2ebc9e0deb | ||
|
|
7ddc621009 | ||
|
|
aa4e574eef | ||
|
|
15bc964fcc | ||
|
|
99713ac964 | ||
|
|
f9a6bd1343 | ||
|
|
f4bee872e1 | ||
|
|
be99b286b3 | ||
|
|
c7d5212f82 | ||
|
|
75726b3d34 | ||
|
|
8d7e76ed81 | ||
|
|
01b08b2297 | ||
|
|
cf51581ac1 | ||
|
|
d99fd56995 | ||
|
|
d149051c27 | ||
|
|
660aaa87ca | ||
|
|
4010f03b05 | ||
|
|
e2d2dcf337 | ||
|
|
b11aaf3f0c | ||
|
|
30ae065cb4 | ||
|
|
7f5b0559aa | ||
|
|
851954efb2 | ||
|
|
b8c6a459a6 | ||
|
|
4523089440 | ||
|
|
217fe47878 | ||
|
|
525e3db24a | ||
|
|
c3cac7d8c7 | ||
|
|
a92717bb1d | ||
|
|
9dc32eada2 | ||
|
|
d1644c0454 | ||
|
|
81ce84b3f1 | ||
|
|
18a8a405e0 | ||
|
|
07840b3b55 | ||
|
|
f639c5b14e | ||
|
|
a6851554e8 | ||
|
|
6859b83fe0 | ||
|
|
699da3cd26 | ||
|
|
6d429ef57b | ||
|
|
0bc7c20106 | ||
|
|
d8f83d09ee | ||
|
|
43874d35ec | ||
|
|
5a186e4b02 | ||
|
|
70b3ac21ef | ||
|
|
7f24782aee | ||
|
|
009835c17f | ||
|
|
18db39d480 | ||
|
|
5956c358d0 | ||
|
|
f18232eb6c | ||
|
|
ac69d57de0 | ||
|
|
9297d4a7d2 | ||
|
|
e6fd4e2255 | ||
|
|
c0fa6db602 | ||
|
|
d61d732a75 | ||
|
|
e9c0ac3c6b | ||
|
|
e071ecc1d7 | ||
|
|
14f6ef3da0 | ||
|
|
edac6d1f22 | ||
|
|
525dfab3e3 | ||
|
|
0b77986034 | ||
|
|
f0ab72db92 | ||
|
|
6243555db1 | ||
|
|
abefb652c1 | ||
|
|
483e3ff800 | ||
|
|
0642e5a67e | ||
|
|
9553aa6e15 | ||
|
|
090fb1a33e | ||
|
|
c4896a1c07 | ||
|
|
5f165d0a89 | ||
|
|
df2c1ca6f2 | ||
|
|
5e41b6c471 | ||
|
|
1d3fff08ed | ||
|
|
73ffcbcb41 | ||
|
|
510535fdd4 | ||
|
|
4ade79a307 | ||
|
|
954abb974e | ||
|
|
8f3093ea2b | ||
|
|
2ead5b3c40 | ||
|
|
47cab96d10 | ||
|
|
7cfcebf0f5 | ||
|
|
12e310f1fe | ||
|
|
f28b855189 | ||
|
|
43ed3aba41 | ||
|
|
1da4ee04d3 | ||
|
|
17b5e4015d | ||
|
|
1a8b8b7232 | ||
|
|
fd2e8cfa8a | ||
|
|
ccd05c04a5 | ||
|
|
e70edffaa3 | ||
|
|
3ecaaf33b6 | ||
|
|
c424ea52fa | ||
|
|
ebb1aaeefd | ||
|
|
f2d1f7bf52 | ||
|
|
deb42da38e | ||
|
|
43df2a754d | ||
|
|
d468d0ca28 | ||
|
|
e586d0aecf | ||
|
|
8e36fed7bf | ||
|
|
2e3bf585ea | ||
|
|
f57ad5a888 | ||
|
|
47fa31515d | ||
|
|
7e45c17078 | ||
|
|
32a0fc9b17 | ||
|
|
62c2757afc | ||
|
|
7a7596fb7b | ||
|
|
708b0d6365 | ||
|
|
daf1a1baa2 | ||
|
|
59150a655a | ||
|
|
5594ad1ce3 | ||
|
|
f12bd1368f | ||
|
|
6921ad49db | ||
|
|
4430fd21f5 | ||
|
|
64d8f22757 | ||
|
|
2a73524a19 | ||
|
|
bfd7a02c9d | ||
|
|
b108a0164a | ||
|
|
9f1aa916e4 | ||
|
|
5144a2a2df | ||
|
|
c9c2deae1a | ||
|
|
b220db9d85 | ||
|
|
f9e3d96673 | ||
|
|
6c2b65055b | ||
|
|
5fa1efb1f2 | ||
|
|
6b5d4fc557 | ||
|
|
369b125c52 | ||
|
|
732e049252 | ||
|
|
cdb419c3f1 | ||
|
|
2dde426df6 | ||
|
|
8c00499e76 | ||
|
|
32dac5fbe2 | ||
|
|
0d3f8de811 | ||
|
|
90b8747775 | ||
|
|
5333d23ad8 | ||
|
|
e38e11b890 | ||
|
|
79303c90d7 | ||
|
|
4eac0978ed | ||
|
|
aef5b9a057 | ||
|
|
c65b951493 | ||
|
|
75385e5c01 | ||
|
|
ad19baf1f6 | ||
|
|
fb7acbac0a | ||
|
|
7cd752ceb7 | ||
|
|
9df288e7e3 | ||
|
|
26396bbe1a | ||
|
|
a21850e85f | ||
|
|
b19358914a | ||
|
|
5a296f2d06 | ||
|
|
755c84039a | ||
|
|
136ea44509 | ||
|
|
ba758470fc | ||
|
|
878c39413a | ||
|
|
a63a3a8fa5 | ||
|
|
6a2e1f0271 | ||
|
|
21f1ecfa15 | ||
|
|
9c5966c49c | ||
|
|
ffc1d01a0a | ||
|
|
e66e6e0b51 | ||
|
|
b40a86e114 | ||
|
|
ef23d6d51a | ||
|
|
4fea28b313 | ||
|
|
5502fa4584 | ||
|
|
0e2ae6840b | ||
|
|
3a4493c914 | ||
|
|
66deda7c76 | ||
|
|
44beeec1d7 | ||
|
|
824f74a4ce | ||
|
|
8d72d2b3a4 | ||
|
|
876f1231ee | ||
|
|
ffbf395074 | ||
|
|
550b513f6b | ||
|
|
3f4ee39ca9 | ||
|
|
a4887ec3c3 | ||
|
|
f1185d8f34 | ||
|
|
030b2998eb | ||
|
|
3f8ae692ff | ||
|
|
07df92d75c | ||
|
|
8bbf98979e | ||
|
|
24408e53a3 | ||
|
|
f8160e254b | ||
|
|
ff9b585b29 | ||
|
|
095f413147 | ||
|
|
3dd1162a59 | ||
|
|
436225e341 | ||
|
|
ca89073537 | ||
|
|
7663145821 | ||
|
|
eed75eea58 | ||
|
|
194955770e | ||
|
|
3c3820cb38 | ||
|
|
fc25a328bf | ||
|
|
c7e857506d | ||
|
|
d343cd4f08 | ||
|
|
b4aa1b74ab | ||
|
|
b043c5eade | ||
|
|
c1a6ca80f5 | ||
|
|
a010ef0f60 | ||
|
|
1240632dae | ||
|
|
87df6e08ca | ||
|
|
d7ad947cbb | ||
|
|
434e7f75fa | ||
|
|
6f6e74e015 | ||
|
|
24f3176b1b | ||
|
|
2d0df240f4 | ||
|
|
def658ccc6 | ||
|
|
676b35fb1c | ||
|
|
18a1a693b5 | ||
|
|
617a797743 | ||
|
|
e1711b5d03 | ||
|
|
28ef4a0b2b | ||
|
|
8ee17150b8 | ||
|
|
b52017625d | ||
|
|
60ac9dfca2 | ||
|
|
c671735e84 | ||
|
|
29e5247131 | ||
|
|
f5c533094e | ||
|
|
06a8e08244 | ||
|
|
30eda70dda | ||
|
|
38ec4cc3ce | ||
|
|
435271becf | ||
|
|
991bb12c80 | ||
|
|
b8b643ebdf | ||
|
|
42ad8ba1ee | ||
|
|
9f425cce4c | ||
|
|
8be08acfa2 | ||
|
|
6422772530 | ||
|
|
a008a425ec | ||
|
|
0936015d84 | ||
|
|
488a59df2e | ||
|
|
5bf1533067 | ||
|
|
77024cd651 | ||
|
|
d0e209b2eb | ||
|
|
d934fc181c | ||
|
|
2ca6235b5d | ||
|
|
a271ed000e | ||
|
|
4d64ad8bb8 | ||
|
|
66a717b927 | ||
|
|
79114a90f5 | ||
|
|
4427748b8b | ||
|
|
ae9b8326a4 | ||
|
|
619c240e62 | ||
|
|
19889e7d6f | ||
|
|
107d1fc8ff | ||
|
|
636fddd642 | ||
|
|
13532a1f0a | ||
|
|
e1ace2ba08 | ||
|
|
96f0c1d148 | ||
|
|
03ecf8fe82 | ||
|
|
1c03a7fc5c | ||
|
|
85fe65612e | ||
|
|
88469f6141 | ||
|
|
d81ba4a8c8 | ||
|
|
734c0a37f7 | ||
|
|
7becca450a | ||
|
|
f2a5489363 | ||
|
|
c7a8cb566b | ||
|
|
a80031c3c5 | ||
|
|
b6d9eb3dcc | ||
|
|
4a594a8e4f | ||
|
|
384a28c517 | ||
|
|
57ef3842e9 | ||
|
|
5b509466e6 | ||
|
|
7019947083 | ||
|
|
5ddc9243dd | ||
|
|
1dd89597fd | ||
|
|
2ac1de4ae9 | ||
|
|
1f783ddf44 | ||
|
|
bee920f96a | ||
|
|
333e158ca5 | ||
|
|
67baf07efc | ||
|
|
4ba8ecd3fd | ||
|
|
aee42cdecc | ||
|
|
adb2a32fda | ||
|
|
d2c373b27d | ||
|
|
b0060bcb82 | ||
|
|
4f63db3f70 | ||
|
|
0d356514f2 | ||
|
|
6ce37944a7 | ||
|
|
8ef75f7c34 | ||
|
|
bf2da499d6 | ||
|
|
ef2fe6a775 | ||
|
|
2ac84f14be | ||
|
|
5078becbb3 | ||
|
|
e19784a429 | ||
|
|
1628652264 | ||
|
|
668c7d301b | ||
|
|
d56a63e712 | ||
|
|
8070b211ab | ||
|
|
5ed59d0282 | ||
|
|
70223cfcd6 | ||
|
|
7d0ff90b01 | ||
|
|
ecc09a710a | ||
|
|
846b4faefa | ||
|
|
66da382789 | ||
|
|
3378723bdd | ||
|
|
56723330b3 | ||
|
|
08e2244975 | ||
|
|
f9e934fa1a | ||
|
|
30eacc5019 | ||
|
|
3ba7c18288 | ||
|
|
958a09b280 | ||
|
|
cc66e7e7c8 | ||
|
|
7f58e0413c | ||
|
|
3c256ddc5d | ||
|
|
d2f8e62ecc | ||
|
|
5ce479b1af | ||
|
|
be2b893a3f | ||
|
|
32994ce4af | ||
|
|
0c6a43fe0a | ||
|
|
81e0376102 | ||
|
|
f21306a19d | ||
|
|
5f3dcac8e1 | ||
|
|
600bf94044 | ||
|
|
3b38b69034 | ||
|
|
faa8f0f9b6 | ||
|
|
125624b09e | ||
|
|
7186afda93 | ||
|
|
ee542abb5d | ||
|
|
c7638a6485 | ||
|
|
16795871c3 | ||
|
|
54eff0e27f | ||
|
|
0a85521028 | ||
|
|
587af255a6 | ||
|
|
06326f4d55 | ||
|
|
b73f9798e4 | ||
|
|
7ef5031717 | ||
|
|
ba30258ee6 | ||
|
|
940a65cac0 | ||
|
|
7878b05030 | ||
|
|
16eb63d2ea | ||
|
|
8539bc5ade | ||
|
|
02f357a88d | ||
|
|
92f72b45d5 | ||
|
|
7755b19abc | ||
|
|
6b62ba1c5b | ||
|
|
2514aa2e3c | ||
|
|
82982c54f9 | ||
|
|
726718a6f5 | ||
|
|
1609e232a2 | ||
|
|
fda2e265af | ||
|
|
5c19ae0e94 | ||
|
|
f01b3caeb1 | ||
|
|
9e7262660f | ||
|
|
4489197d01 | ||
|
|
3d411fc6f3 | ||
|
|
d4f26577a5 | ||
|
|
c744f761a1 | ||
|
|
7224ca43f3 | ||
|
|
b95cea35a2 | ||
|
|
d891791929 | ||
|
|
826b0ad4ce | ||
|
|
c99c61cc7a | ||
|
|
5eb57de264 | ||
|
|
976cfdbbc2 | ||
|
|
a7aea8d1ed | ||
|
|
9caa89b733 | ||
|
|
e42515c1ea | ||
|
|
901169775d | ||
|
|
3d86540d1d | ||
|
|
6cb97d067e | ||
|
|
ad323ebf2b | ||
|
|
18efedf7c5 | ||
|
|
4eaf4ff26b | ||
|
|
b1d2ac7822 | ||
|
|
87e6e583a6 | ||
|
|
2897e1a3ad | ||
|
|
dfd5a7c21d | ||
|
|
093f6411c7 | ||
|
|
845bea522b | ||
|
|
d0175f9c39 | ||
|
|
0b1d59e398 | ||
|
|
93bcb8994f | ||
|
|
ecee464b34 | ||
|
|
42789fcc24 | ||
|
|
f26b36f3e8 | ||
|
|
9f09052900 | ||
|
|
95a7ba0785 | ||
|
|
ef4a3b405d | ||
|
|
7096fcd43e | ||
|
|
eeab12ed86 | ||
|
|
ca961e8498 | ||
|
|
40b0a37110 | ||
|
|
6daf0861c9 | ||
|
|
03bc1e722e | ||
|
|
ce94c5e237 | ||
|
|
88aad1e107 | ||
|
|
c4fe14bd45 | ||
|
|
2191b539e3 | ||
|
|
dcd3495564 | ||
|
|
30559841d5 | ||
|
|
0dc0d5c981 | ||
|
|
3b981e2818 | ||
|
|
47bfc74ba9 | ||
|
|
8858e1bce8 | ||
|
|
04be430b8c | ||
|
|
d46351b866 | ||
|
|
d3ec29aa42 | ||
|
|
357abee462 | ||
|
|
c86a040768 | ||
|
|
d9e7dc158d | ||
|
|
46591968c0 | ||
|
|
bb7c256ecf | ||
|
|
d239ed1c9f | ||
|
|
604dece366 | ||
|
|
8b55f20684 | ||
|
|
8bf12ff32c | ||
|
|
0596482a8d | ||
|
|
b5a77aa62a | ||
|
|
5db27d9d93 | ||
|
|
a630e4937b | ||
|
|
96d27d17ce | ||
|
|
742b848f42 | ||
|
|
57884e3400 | ||
|
|
40459f4e01 | ||
|
|
a461072113 | ||
|
|
0105931414 | ||
|
|
c0b7b871ba | ||
|
|
1250c94600 | ||
|
|
ccbd5b17d3 | ||
|
|
2fd3abbb14 | ||
|
|
5bc019d3d3 | ||
|
|
91c24d5501 | ||
|
|
cd7f192fba | ||
|
|
7d0555fb67 | ||
|
|
3864708cf1 | ||
|
|
ef22a58631 | ||
|
|
acf4fa106f | ||
|
|
5a5704ee0b | ||
|
|
7e65416f10 | ||
|
|
2d7bc59db4 | ||
|
|
930469a006 | ||
|
|
c657ba52ad | ||
|
|
46499512eb | ||
|
|
c2779570fa | ||
|
|
750dc609bb | ||
|
|
1037183f4c | ||
|
|
979f959291 | ||
|
|
86cfe0465c | ||
|
|
61d461eea5 | ||
|
|
ff1733225a | ||
|
|
784fca98c8 | ||
|
|
1f0ebd8ba1 | ||
|
|
2e645f04e7 | ||
|
|
debe8eb81c | ||
|
|
2e8f8f258d | ||
|
|
697f40595e | ||
|
|
37404b6619 | ||
|
|
4b3a016d70 | ||
|
|
ed2af5f9b4 | ||
|
|
5418ab52b7 | ||
|
|
61037af138 | ||
|
|
f86cd11d74 | ||
|
|
e46b335dc0 | ||
|
|
79299112eb | ||
|
|
3d5bee3a2c | ||
|
|
466cc84c16 | ||
|
|
27f9e2ea9f | ||
|
|
593e10eec2 | ||
|
|
5d5b8b78d4 | ||
|
|
620c4087bc | ||
|
|
c5bf0e0cb7 | ||
|
|
7f7d53e00a | ||
|
|
073466bd6a | ||
|
|
151e88046d | ||
|
|
c3b1d6735e | ||
|
|
e3a5da64a5 | ||
|
|
3c4599423d | ||
|
|
2bb1f27e07 | ||
|
|
e3adbbbd0b | ||
|
|
5e6838bdc9 | ||
|
|
fc6720e090 | ||
|
|
e29f671363 | ||
|
|
6e501c7b8a | ||
|
|
7dd3cc6f9f | ||
|
|
f346f080ee | ||
|
|
9f19e585db | ||
|
|
bc74487301 | ||
|
|
693baa8cef | ||
|
|
9ae60d4859 | ||
|
|
281efef207 | ||
|
|
d893537ae6 | ||
|
|
986de265fe | ||
|
|
d25633e213 | ||
|
|
0c8c7157f6 | ||
|
|
e393442df9 | ||
|
|
fc94fe30d0 | ||
|
|
1065079be6 | ||
|
|
e426172b18 | ||
|
|
effe93286a | ||
|
|
2a669618a2 | ||
|
|
44cd0e1e10 | ||
|
|
621155f06f | ||
|
|
6c116e261d | ||
|
|
bcc89d91f7 | ||
|
|
8e874afbd5 | ||
|
|
9421cd0b2d | ||
|
|
37c46042c3 | ||
|
|
c5429f0515 | ||
|
|
f0375ca446 | ||
|
|
b34bac9b5e | ||
|
|
f42e418346 | ||
|
|
a060c01f58 | ||
|
|
f41686fab4 | ||
|
|
be88d584cf | ||
|
|
80aa87935d | ||
|
|
405073cca9 | ||
|
|
22cb831138 | ||
|
|
95c8c75789 | ||
|
|
e8e3cadeff | ||
|
|
8123ba9a01 | ||
|
|
5aa6c98dc1 | ||
|
|
8e16b8e4a8 | ||
|
|
90f0a5eac6 | ||
|
|
892d3be144 | ||
|
|
164242ae4b | ||
|
|
07b8c5087b | ||
|
|
abba2e969b | ||
|
|
0a4b57ea01 | ||
|
|
422ecb758f | ||
|
|
20f953b9cb | ||
|
|
d2f1488ef1 | ||
|
|
a3aedd5fad | ||
|
|
e2d07f7e78 | ||
|
|
3aa0fac852 | ||
|
|
238243a7d4 | ||
|
|
9533b62ebf | ||
|
|
d06445e04b | ||
|
|
69255a938b | ||
|
|
773f24238f | ||
|
|
548ed4a1f0 | ||
|
|
76bf764262 | ||
|
|
075882b7b0 | ||
|
|
d25299e1ba | ||
|
|
0160d42302 | ||
|
|
6ca7a013d6 | ||
|
|
60ed93e13b | ||
|
|
747e2e2e27 | ||
|
|
16d1694a78 | ||
|
|
17e74d9ed2 | ||
|
|
923a42e9a3 | ||
|
|
bac66dfbf9 | ||
|
|
6895c0b392 | ||
|
|
ef08319670 | ||
|
|
1aee758f87 | ||
|
|
3d0eca9432 | ||
|
|
93936a7498 | ||
|
|
8e873ccd00 | ||
|
|
7a188af002 | ||
|
|
aaffeb9fac | ||
|
|
67711bcb0d | ||
|
|
f93c158caa | ||
|
|
c74d05a47b | ||
|
|
f867c0f8a1 | ||
|
|
98d024295e | ||
|
|
963d3de709 | ||
|
|
e20fa7f3a2 | ||
|
|
719d262a00 | ||
|
|
9ad9f28f33 | ||
|
|
6ac4a405b5 | ||
|
|
64fbdff13d | ||
|
|
65011f42da | ||
|
|
d763967d4b | ||
|
|
44c807aedd | ||
|
|
6e6bb72245 | ||
|
|
ca96b45637 | ||
|
|
d8ff7786df | ||
|
|
35ed07e0ba | ||
|
|
7b002606bf | ||
|
|
ac0d0a6680 | ||
|
|
e5033cceec | ||
|
|
b5d7e2969f | ||
|
|
6b4bd90bfa | ||
|
|
b2aff55160 | ||
|
|
569c34bca0 | ||
|
|
e63c966756 | ||
|
|
43f9efb9e4 | ||
|
|
82666d62ef | ||
|
|
72b62481a7 | ||
|
|
9cf13e320a | ||
|
|
c8c4a0f61b | ||
|
|
801c44389e | ||
|
|
fbdb060e10 | ||
|
|
09edc78bdc | ||
|
|
6951817088 | ||
|
|
2a22d25975 | ||
|
|
875adc8bdf | ||
|
|
b8b914a99c | ||
|
|
59401d27ca | ||
|
|
26cb21f541 | ||
|
|
49154759c0 | ||
|
|
abc07968e5 | ||
|
|
d28899ae84 | ||
|
|
04c44de145 | ||
|
|
7997d52df5 | ||
|
|
f3d899cbf5 | ||
|
|
e540596c20 | ||
|
|
b1aa7a8e88 | ||
|
|
3eef5b2c02 | ||
|
|
443aa0040c | ||
|
|
48c1db6a8a | ||
|
|
b9f2530e2f | ||
|
|
3cb7c0206a | ||
|
|
a7360f1145 | ||
|
|
c4e3c4b34f | ||
|
|
ae763ae25d | ||
|
|
dd0b4f27d4 | ||
|
|
faf5bcb32b | ||
|
|
93f2c83c0e | ||
|
|
63b5545502 | ||
|
|
31c99517d7 | ||
|
|
2e3a2ff69a | ||
|
|
4aa2c83e03 | ||
|
|
376d7a8878 | ||
|
|
dd5f55f4fc | ||
|
|
d2806c7ec0 | ||
|
|
2db34f4d49 | ||
|
|
a451189d83 | ||
|
|
f3a2be4a06 | ||
|
|
dddd97bc22 | ||
|
|
8e53be6810 | ||
|
|
d24b9ec0ae | ||
|
|
d8900341ac | ||
|
|
0465d047e7 | ||
|
|
cf1f3677ae | ||
|
|
354b02612d | ||
|
|
f06d5b806a | ||
|
|
49385a08ad | ||
|
|
d07c8c8851 | ||
|
|
803c3678e3 | ||
|
|
3118f743a0 | ||
|
|
2fa5c7eca4 | ||
|
|
a09829ed4b | ||
|
|
cf3d92d6e1 | ||
|
|
524b63e88c | ||
|
|
0a930db7d6 | ||
|
|
e6338bbde1 | ||
|
|
e4f7dd21b6 | ||
|
|
b0bae93d06 | ||
|
|
9b93a5cd04 | ||
|
|
3142717154 | ||
|
|
3dcfacfeed | ||
|
|
a51f5fefc4 | ||
|
|
fcc3bbf9b6 | ||
|
|
109390d21e | ||
|
|
c7dd91ef90 | ||
|
|
3d15abfdae | ||
|
|
a9caaefd16 | ||
|
|
261c786a10 | ||
|
|
a5270ccea8 | ||
|
|
08865dc218 | ||
|
|
3f50767e48 | ||
|
|
8ff5887955 | ||
|
|
2aa240337c | ||
|
|
44d75d9955 | ||
|
|
3b61b87501 | ||
|
|
04de362bc9 | ||
|
|
e06175f600 | ||
|
|
fe78d4f1e7 | ||
|
|
4a1de4c0da | ||
|
|
22b77411ec | ||
|
|
3f730ead84 | ||
|
|
d52d70a014 | ||
|
|
0a7b485514 | ||
|
|
151c384313 | ||
|
|
8586d44d7e | ||
|
|
5c8b600cb1 | ||
|
|
afd67d2f00 | ||
|
|
125a3fdc5e | ||
|
|
9963ff9c8e | ||
|
|
8547ea4c6a | ||
|
|
fd434e8b21 | ||
|
|
1524866432 | ||
|
|
19fa9390ff | ||
|
|
a335050332 | ||
|
|
8aa9ecffc5 | ||
|
|
ef02e5169d | ||
|
|
ba31a56949 | ||
|
|
6b7bd75b18 | ||
|
|
013d6625d5 | ||
|
|
ca228ca23e | ||
|
|
1dce68212f | ||
|
|
2683c2433b | ||
|
|
2929800a9f | ||
|
|
c1b04ace78 | ||
|
|
04a54dbc2a | ||
|
|
e7c1f31315 | ||
|
|
62f6917d81 | ||
|
|
babefc7bd3 | ||
|
|
a09c9f4a2e | ||
|
|
5876598ca0 | ||
|
|
f45d643739 | ||
|
|
c1ba176e27 | ||
|
|
9b3013c51a | ||
|
|
a746720a6e | ||
|
|
a95c61c1d8 | ||
|
|
d5da8e4e2b | ||
|
|
861e11a713 | ||
|
|
23ac209c05 | ||
|
|
8df789ae34 | ||
|
|
432e95e4ec | ||
|
|
401ed0a7a5 | ||
|
|
dae6957093 | ||
|
|
7b6405fba7 | ||
|
|
6dc3e74607 | ||
|
|
617066340b | ||
|
|
2dd6db352f | ||
|
|
56e13641df | ||
|
|
9d62113388 | ||
|
|
47b4a6c498 | ||
|
|
7dfe3a1c59 | ||
|
|
44acfc7ec8 | ||
|
|
7933f5e357 | ||
|
|
858c5a27ad | ||
|
|
28e41a0ae9 | ||
|
|
ae79f9be66 | ||
|
|
4a6d58c36e | ||
|
|
5bf6687f1f | ||
|
|
beb80f0422 | ||
|
|
0e86d6fbdb | ||
|
|
2a8e4f19af | ||
|
|
6ed8b6d058 | ||
|
|
33812b3f4a | ||
|
|
b62e542801 | ||
|
|
0080110fad | ||
|
|
19ef661457 | ||
|
|
7946221f0b | ||
|
|
203a42c043 | ||
|
|
d3998dd03b | ||
|
|
e752a48343 | ||
|
|
71955b777b | ||
|
|
d686d07d53 | ||
|
|
72b4c9c6ab | ||
|
|
4b991ab67a | ||
|
|
59399124fa | ||
|
|
3eb4962d7d | ||
|
|
42d3b4c326 | ||
|
|
f3931567f9 | ||
|
|
154adafbcb | ||
|
|
4a1e511262 | ||
|
|
3fc907e50f | ||
|
|
bbf441c3b4 | ||
|
|
bbf660d80e | ||
|
|
a1c3bc26c9 | ||
|
|
fc73e0e482 | ||
|
|
e7727afbe8 | ||
|
|
de5ce2660d | ||
|
|
2e661cb2f8 | ||
|
|
ebeaad0b4e | ||
|
|
ce60c048f8 | ||
|
|
6795ff7db9 | ||
|
|
931f1fb27d | ||
|
|
74625a8d65 | ||
|
|
03e8ccee7d | ||
|
|
01b9e4cb55 | ||
|
|
b5d5014ba2 | ||
|
|
4f7bfd14c0 | ||
|
|
7347300f05 | ||
|
|
aa6bdd2786 | ||
|
|
db0aeeabbd | ||
|
|
9aa426ed56 | ||
|
|
30f9348c26 | ||
|
|
baf76c51f9 | ||
|
|
6abef569e8 | ||
|
|
ade88a6055 | ||
|
|
11d0274a1b | ||
|
|
957de5d6f7 | ||
|
|
f5f4c5c672 | ||
|
|
5924495035 | ||
|
|
c486f65e74 | ||
|
|
b19a7d45d8 | ||
|
|
7f7397f684 | ||
|
|
39142909f6 | ||
|
|
23f5b84c5e | ||
|
|
630b6e6313 | ||
|
|
4396ca9420 | ||
|
|
5286a69c34 | ||
|
|
059d5542c9 | ||
|
|
a09e77a17d | ||
|
|
5a236e3bea | ||
|
|
aba5add7f9 | ||
|
|
a4190672d3 | ||
|
|
10da9182d1 | ||
|
|
2de5bc2855 | ||
|
|
b32db945be | ||
|
|
44d02e6dfd | ||
|
|
fc096dc6fa | ||
|
|
1d52bbde58 | ||
|
|
1a049e854b | ||
|
|
5b15ef81f5 | ||
|
|
05088c1063 | ||
|
|
04c09efd75 | ||
|
|
2c0576099a | ||
|
|
27b49f9d7e | ||
|
|
6a247c425a | ||
|
|
7910034916 | ||
|
|
c56e5d17be | ||
|
|
522eabce5e | ||
|
|
0e4b874994 | ||
|
|
319cc8a5f9 | ||
|
|
b5c26392e1 | ||
|
|
7d53c55cc1 | ||
|
|
3e30994541 | ||
|
|
a669fcba7a | ||
|
|
851053fd9a | ||
|
|
b71a87e803 | ||
|
|
c72658d21a | ||
|
|
d0b8c59769 | ||
|
|
583b74fb7e | ||
|
|
cf6f28aa3e | ||
|
|
f3ece64635 | ||
|
|
6343b7087d | ||
|
|
e279dc4cea | ||
|
|
fc5763c8e8 | ||
|
|
9e32fcda88 | ||
|
|
7fe8c7b547 | ||
|
|
38329514f9 | ||
|
|
37705dfc71 | ||
|
|
e8e7e3144f | ||
|
|
0da229e8f4 | ||
|
|
1029b2523d | ||
|
|
477b520cf0 | ||
|
|
d54fdf5452 | ||
|
|
bfb47aba87 | ||
|
|
d241a57d38 | ||
|
|
01479a82de | ||
|
|
198820d95d | ||
|
|
86741a4e95 | ||
|
|
7d859661ba | ||
|
|
d04c95514e | ||
|
|
e6e3953a85 | ||
|
|
104f1232f3 | ||
|
|
b55bf6e6c1 | ||
|
|
d79af8fcc2 | ||
|
|
ff05429f58 | ||
|
|
0dbabe629a | ||
|
|
3348d46b5a | ||
|
|
aff1a245c2 | ||
|
|
51802f71a5 | ||
|
|
32f34f1444 | ||
|
|
b7309ccdf1 | ||
|
|
8abaac56ff | ||
|
|
a462ab98e9 | ||
|
|
af602a414a | ||
|
|
67e426354c | ||
|
|
e2f8e31fa0 | ||
|
|
d67cce4184 | ||
|
|
ca63b412cb | ||
|
|
89e372c229 | ||
|
|
4ae5b49764 | ||
|
|
1057f32b34 | ||
|
|
e3948eb4ba | ||
|
|
6d363235a5 | ||
|
|
fb50b4fa78 | ||
|
|
85fbaa2b97 | ||
|
|
1440453640 | ||
|
|
e364959d25 | ||
|
|
89642e71b5 | ||
|
|
d8413b3b7d | ||
|
|
92ba038af7 | ||
|
|
2ac2cc2ebf | ||
|
|
990ed86283 | ||
|
|
953d702ed6 | ||
|
|
1fa828ad1a | ||
|
|
9f16fa189f | ||
|
|
a7e78cc3fb | ||
|
|
353c40cc46 | ||
|
|
3a7c8d660c | ||
|
|
b2c9108ffc | ||
|
|
ef447e2ba1 | ||
|
|
85f0b37b03 | ||
|
|
9f6cdfcd11 | ||
|
|
376477767b | ||
|
|
f1376be2e0 | ||
|
|
5e57ec0e67 | ||
|
|
15721f1279 | ||
|
|
e8fe58438d | ||
|
|
8ef04b1ad0 | ||
|
|
a3d6776c02 | ||
|
|
e7a529257a | ||
|
|
714afabf30 | ||
|
|
f1df8d07bb | ||
|
|
a18c4b6449 | ||
|
|
2099342352 | ||
|
|
50ee2727a2 | ||
|
|
571e918ee0 | ||
|
|
7c5d8721c0 | ||
|
|
b5984a965e | ||
|
|
0e0bd94251 | ||
|
|
a9d2d52c1e | ||
|
|
b7c67a16d9 | ||
|
|
35615526a1 | ||
|
|
c43ce52e78 | ||
|
|
61a313f24b | ||
|
|
d71393cead | ||
|
|
64bb6714a3 | ||
|
|
f8336d6adb | ||
|
|
30245f4aed | ||
|
|
a861652d6f | ||
|
|
5fe5ba78da | ||
|
|
8fa9977617 | ||
|
|
0df2dd3ce2 | ||
|
|
80893f2592 | ||
|
|
91cf10541b | ||
|
|
aaccfdee44 | ||
|
|
a8449de731 | ||
|
|
9d98641a94 | ||
|
|
4f13227d9e | ||
|
|
70e9ee0dd1 | ||
|
|
d43932a9d2 | ||
|
|
7118261fee | ||
|
|
89b171db36 | ||
|
|
1c4778790a | ||
|
|
d20d1488de | ||
|
|
c969f277ee | ||
|
|
cf4a77af75 | ||
|
|
4042592420 | ||
|
|
a750241ec3 | ||
|
|
8ab79ec1ae | ||
|
|
a9289df93f | ||
|
|
f6c42c4b53 | ||
|
|
bfb121938a | ||
|
|
20d26d4bcd | ||
|
|
474b851275 | ||
|
|
5c541275c5 | ||
|
|
486e92dfc9 | ||
|
|
959ce3bc92 | ||
|
|
3866c740e9 | ||
|
|
a65a85fb67 | ||
|
|
c921b7bb1c | ||
|
|
7acf2d80d2 | ||
|
|
01b2d6cb39 | ||
|
|
e2665e3cbe | ||
|
|
9b95094207 | ||
|
|
59b637c317 | ||
|
|
52963e8e80 | ||
|
|
43f42ac917 | ||
|
|
0352951d8c | ||
|
|
fe334d0aed | ||
|
|
f2371d8735 | ||
|
|
3c9608efbd | ||
|
|
8dff3b55c9 | ||
|
|
b42b6303ae | ||
|
|
263e6d5cca | ||
|
|
5b5622b4a7 | ||
|
|
e328bf616f | ||
|
|
52ba831b1c | ||
|
|
12b1016d66 | ||
|
|
a471bfec6a | ||
|
|
3b6d3116bd | ||
|
|
5c0c680f56 | ||
|
|
3af8f4772f | ||
|
|
10b2593389 | ||
|
|
cf67d58236 | ||
|
|
748227319c | ||
|
|
94c18e835a | ||
|
|
cfb5693ffe | ||
|
|
3e1f3d5a51 | ||
|
|
c0bf529a6b | ||
|
|
f951ee1f91 | ||
|
|
e8ac971f9e | ||
|
|
b1278aff2e | ||
|
|
c26c14227c | ||
|
|
ce36bcc951 | ||
|
|
1134cd7788 | ||
|
|
7920d2225c | ||
|
|
d0faaf2d53 | ||
|
|
fc60878c25 | ||
|
|
1b941536d0 | ||
|
|
4215bfc6fe | ||
|
|
22d215b2c7 | ||
|
|
69eb7979c1 | ||
|
|
0f0c24d31b | ||
|
|
30c5a0d9cd | ||
|
|
93e0773758 | ||
|
|
c92e64afbd | ||
|
|
6ba9dc74d8 | ||
|
|
f69c244080 | ||
|
|
f1b4a973a8 | ||
|
|
efe49ee4c1 | ||
|
|
51573cb9f5 | ||
|
|
f6ab374718 | ||
|
|
7ace88ae0d | ||
|
|
5f5e04506c | ||
|
|
9a58e121e8 | ||
|
|
7153347d67 | ||
|
|
611ccd9605 | ||
|
|
0befa2eb39 | ||
|
|
b0677bb66d | ||
|
|
f476f1447c | ||
|
|
c8907232da | ||
|
|
864ca81d1d | ||
|
|
636427ac6b | ||
|
|
3d68caed6b | ||
|
|
4f7e25038c | ||
|
|
ba0a95ed26 | ||
|
|
0cd25be408 | ||
|
|
c6fa0ddde3 | ||
|
|
b64a9b7a44 | ||
|
|
326bf39bed | ||
|
|
ac4c37ba48 | ||
|
|
305017d523 | ||
|
|
19d1c552fe | ||
|
|
7d6908d146 | ||
|
|
9cf399f956 | ||
|
|
a0b4450e5b | ||
|
|
9d983a7c96 | ||
|
|
89be08bc58 | ||
|
|
6dcf3e15da | ||
|
|
e66cb9479f | ||
|
|
bd8d9cc3aa | ||
|
|
9453b86907 | ||
|
|
ecf9441fae | ||
|
|
70b659acbe | ||
|
|
2ebb9f2763 | ||
|
|
1231b13dfd | ||
|
|
bebad4d361 | ||
|
|
ed5a1887f4 | ||
|
|
342e689825 | ||
|
|
c5c1a9b25b | ||
|
|
7637905de2 | ||
|
|
ec780b7b93 | ||
|
|
3728c59f1d | ||
|
|
4442d9a706 | ||
|
|
8928b35f30 | ||
|
|
fca189ee4c | ||
|
|
d0fb3dde66 | ||
|
|
fc4377abaf | ||
|
|
97a62752c6 | ||
|
|
87e1e55da7 | ||
|
|
5410cda182 | ||
|
|
ee240ca201 | ||
|
|
98ffa0a256 | ||
|
|
2f450b7ea0 | ||
|
|
099b50dbfa | ||
|
|
ece7a443fe | ||
|
|
984f2669b8 | ||
|
|
9b94b9e3fe | ||
|
|
a781bcb7f4 | ||
|
|
b596f38ab5 | ||
|
|
f2b4d6f829 | ||
|
|
d2d2dc64db | ||
|
|
5b8171a719 | ||
|
|
838ad5ec1a | ||
|
|
3d16323e33 | ||
|
|
ba25eaa788 | ||
|
|
747412e522 | ||
|
|
059ff25d8e | ||
|
|
831143427d | ||
|
|
de51d4860e | ||
|
|
6569038777 | ||
|
|
075aec3ac0 | ||
|
|
734847db68 | ||
|
|
a99f2b78a1 | ||
|
|
037473f2e1 | ||
|
|
378f735e9f | ||
|
|
4cdac76ca5 | ||
|
|
9ed3c8a6bb | ||
|
|
252d289a8d | ||
|
|
832bad1fee | ||
|
|
d5b99316e5 | ||
|
|
3723c5dae5 | ||
|
|
7c3fa7aef5 | ||
|
|
4ee31db7a0 | ||
|
|
0d8cb7393c | ||
|
|
0d3d0a8da1 | ||
|
|
e45eb7f2be | ||
|
|
128e5c414c | ||
|
|
5a70d98c71 | ||
|
|
69d4215397 | ||
|
|
722190305b | ||
|
|
428d4859da | ||
|
|
9455860554 | ||
|
|
eb4b42c089 | ||
|
|
79b3d7359a | ||
|
|
c95ea19da1 | ||
|
|
a8b3f2af14 | ||
|
|
2b8ccc38bb | ||
|
|
baebadb7a6 | ||
|
|
f73db056f2 | ||
|
|
429ac1e71c | ||
|
|
07cd91dda4 | ||
|
|
956f61e775 | ||
|
|
14fc2d2c70 | ||
|
|
9c07240948 | ||
|
|
7e2260578e | ||
|
|
7f2d781241 | ||
|
|
df05ade4a7 | ||
|
|
e4b45e512f | ||
|
|
623bb52fd8 | ||
|
|
ab809dabf8 | ||
|
|
2ebf26c156 | ||
|
|
1ffc598fd4 | ||
|
|
0495d954bc | ||
|
|
cc6a7a6a72 | ||
|
|
b081bbb444 | ||
|
|
69cbb262ba | ||
|
|
ba2a398da3 | ||
|
|
a8a87e7f79 | ||
|
|
2ffd1e6e47 | ||
|
|
efaebb43aa | ||
|
|
d201350a08 | ||
|
|
81184d77fe | ||
|
|
b9d60e0018 | ||
|
|
f50ac49ede | ||
|
|
70d8b8a88a | ||
|
|
535f1b5988 | ||
|
|
366c903f84 | ||
|
|
1781ff36c6 | ||
|
|
4e131d9a54 | ||
|
|
7f6fec5530 | ||
|
|
2d43014029 | ||
|
|
33ea66ea88 | ||
|
|
b74e449efd | ||
|
|
afd4820713 | ||
|
|
8e032fa26a | ||
|
|
897669a069 | ||
|
|
03ea78b40b | ||
|
|
18465cf6cb | ||
|
|
ac6ccd2dc7 | ||
|
|
fb32d11d64 | ||
|
|
ec75e911bd | ||
|
|
603f032e28 | ||
|
|
cf76e43898 | ||
|
|
a0df548dd3 | ||
|
|
dff6048a07 | ||
|
|
478d465cb6 | ||
|
|
271f308c36 | ||
|
|
956958fa0e | ||
|
|
6a68da0559 | ||
|
|
6683eee49a | ||
|
|
f258d5f932 | ||
|
|
600995a220 | ||
|
|
803dfed9f7 | ||
|
|
771cb45b49 | ||
|
|
a2a7689881 | ||
|
|
e9f4c3d0c7 | ||
|
|
a5ef5769b9 | ||
|
|
9d251f94e5 | ||
|
|
d1e8d52f5c | ||
|
|
14d2ae0c0e | ||
|
|
dafa3bde8b | ||
|
|
cb923cef47 | ||
|
|
93888aeed3 | ||
|
|
c41e34e9d8 | ||
|
|
154aea7a61 | ||
|
|
bc53cd1aa4 | ||
|
|
ef51aa7e98 | ||
|
|
705c5ce790 | ||
|
|
26dee50e68 | ||
|
|
be3d7ef11d | ||
|
|
ef5897969f | ||
|
|
d9cd0257ba | ||
|
|
95bb8cb1e5 | ||
|
|
e1aa2f651a | ||
|
|
03c535e80d | ||
|
|
6f9c4f220e | ||
|
|
6f3813b685 | ||
|
|
510dde6923 | ||
|
|
a7761c1867 | ||
|
|
a2af965bad | ||
|
|
28b6ed500b | ||
|
|
6991fa39cc | ||
|
|
274469d299 | ||
|
|
a0b8581ec5 | ||
|
|
b844a0e98d | ||
|
|
e5f14ac176 | ||
|
|
a1110a847d | ||
|
|
a3889fe369 | ||
|
|
bd93918d9b | ||
|
|
421a6ba143 | ||
|
|
f091256edb | ||
|
|
c0e4733eb8 | ||
|
|
e636a6ad58 | ||
|
|
071617bfc5 | ||
|
|
8a079c98cc | ||
|
|
fa95f96a6d | ||
|
|
c198abe5ac | ||
|
|
ef5ba0f1d1 | ||
|
|
fff7cd53cc | ||
|
|
64ce5138e1 | ||
|
|
3c07e7a0d8 | ||
|
|
a1510ffcb5 | ||
|
|
1b96bce44f | ||
|
|
294a5e39a6 | ||
|
|
65fdd6e25f | ||
|
|
6d2ef1f985 | ||
|
|
14af19873c | ||
|
|
2f5dd470d2 | ||
|
|
dc4592ae4d | ||
|
|
baa3cfa636 | ||
|
|
ad324df937 | ||
|
|
f2b301cb17 | ||
|
|
6e369ea787 | ||
|
|
f640abda91 | ||
|
|
77f8f11d99 | ||
|
|
12b4c27468 | ||
|
|
75f3073cbf | ||
|
|
5eddfaed98 | ||
|
|
89b4fdef56 | ||
|
|
6f08c1f758 | ||
|
|
1155789a75 | ||
|
|
8c4a74179d | ||
|
|
bdbc94e54a | ||
|
|
30f880361e | ||
|
|
c5ac347538 | ||
|
|
008da9467f | ||
|
|
ee78249c2f | ||
|
|
412c67b47a | ||
|
|
f4191ad984 | ||
|
|
ea8d1100ac | ||
|
|
20e8c033cc | ||
|
|
ff2d10e0e1 | ||
|
|
672c39e58d | ||
|
|
36d3849118 | ||
|
|
43d7dfde4c | ||
|
|
51a056b3d7 | ||
|
|
6e22d6687c | ||
|
|
369fdf07e2 | ||
|
|
8c6c1b3ccc | ||
|
|
160bdf5472 | ||
|
|
18c70002cb | ||
|
|
4b8cfd9fdd | ||
|
|
ffa5fd5b2a | ||
|
|
9fb4798c77 | ||
|
|
a6039278c3 | ||
|
|
c50702c83b | ||
|
|
d4c1e62c72 | ||
|
|
488c609109 | ||
|
|
0a6e24104e | ||
|
|
d6acac0208 | ||
|
|
b02f61ef21 | ||
|
|
eb82b44726 | ||
|
|
ca035f9447 | ||
|
|
19aa3c0854 | ||
|
|
93675d90bb | ||
|
|
0d90c1d960 | ||
|
|
d826f968b5 | ||
|
|
f682d7489f | ||
|
|
649b1adfdd | ||
|
|
3d67ea736f | ||
|
|
ba88f837fe | ||
|
|
6728703473 | ||
|
|
55521afe35 | ||
|
|
8820b02406 | ||
|
|
e79ba6117b | ||
|
|
668d29a9d7 | ||
|
|
6b97acdb50 | ||
|
|
9a11021560 | ||
|
|
ee18217520 | ||
|
|
16de60f82d | ||
|
|
8cd94f976c | ||
|
|
9ab0662cbf | ||
|
|
5cceed1fd7 | ||
|
|
03a1b51bd7 | ||
|
|
1edf567ea7 | ||
|
|
fa73eddf50 | ||
|
|
1923ae6f4b | ||
|
|
229f3dc061 | ||
|
|
cc95042a94 | ||
|
|
302f54971d | ||
|
|
dff88403b5 | ||
|
|
cd3f9af232 | ||
|
|
b217162cad | ||
|
|
7d24a61ae8 | ||
|
|
ca1b37dbcf | ||
|
|
0e887fb2ea | ||
|
|
a122adf05d | ||
|
|
04fc1e25e4 | ||
|
|
cff402affb | ||
|
|
e1e0368f8c | ||
|
|
8ee39d3822 | ||
|
|
e2b533db64 | ||
|
|
fc5db74f16 | ||
|
|
42e62a3698 | ||
|
|
62f03356ca | ||
|
|
25bb0912fb | ||
|
|
beff1d8d42 | ||
|
|
7dc56cc075 | ||
|
|
394d653978 | ||
|
|
742fa27029 | ||
|
|
18b962dc57 | ||
|
|
233a179dad | ||
|
|
9cc76c5ee6 | ||
|
|
401ba40373 | ||
|
|
6dad50aab1 | ||
|
|
9a43f868aa | ||
|
|
294e9bb590 | ||
|
|
d101311109 | ||
|
|
e0e920bfe0 | ||
|
|
3a090d7c1d | ||
|
|
dc851d856d | ||
|
|
2f8fe43ea3 | ||
|
|
959f96dd74 | ||
|
|
6620d2d023 | ||
|
|
408742494a | ||
|
|
f7ae9c06d8 | ||
|
|
b4c0d8e829 | ||
|
|
b2a410d6cf | ||
|
|
16fa453163 | ||
|
|
fc678684f5 | ||
|
|
8f7db7e52f | ||
|
|
e9d6cf278a | ||
|
|
d1c6f5f98e | ||
|
|
48f581525e | ||
|
|
8d967856b5 | ||
|
|
ee83cf2989 | ||
|
|
cb304d35e2 | ||
|
|
65185c5854 | ||
|
|
91526674be | ||
|
|
3e11ff65db | ||
|
|
4a3ac17a2f | ||
|
|
2283f1ddc9 | ||
|
|
ae78887746 | ||
|
|
9de4bf839f | ||
|
|
295e51181b | ||
|
|
287e3a0090 | ||
|
|
4d150e71a3 | ||
|
|
0debbc263e | ||
|
|
a9e5e40a54 | ||
|
|
cf61080980 | ||
|
|
3e33731cf0 | ||
|
|
d7cda90acd | ||
|
|
9a7dcc8c1a | ||
|
|
d477121790 | ||
|
|
60e7a21e39 | ||
|
|
b915ca2add | ||
|
|
e90ef7aaee | ||
|
|
e918daaa9b | ||
|
|
83b4f645db | ||
|
|
1797df7017 | ||
|
|
3beda9c201 | ||
|
|
68e6bd668c | ||
|
|
696cf61fe9 | ||
|
|
7fe56766fc | ||
|
|
1e62f8c951 | ||
|
|
82b995f96f | ||
|
|
05aa0c2482 | ||
|
|
bca5f4bec4 | ||
|
|
8b599f78c0 | ||
|
|
38776e74bc | ||
|
|
21ce09a5b5 | ||
|
|
5fabec6a42 | ||
|
|
64f361d4b1 | ||
|
|
f8ae842971 | ||
|
|
ca01d6efb8 | ||
|
|
498ab6d165 | ||
|
|
8e8524ccc8 | ||
|
|
714936f710 | ||
|
|
11c0477a34 | ||
|
|
4f65c6bbcc | ||
|
|
c7ee183fe4 | ||
|
|
80545ce1f2 | ||
|
|
c80edcfe9f | ||
|
|
74318fb3c0 | ||
|
|
83a8942724 | ||
|
|
48f57068d8 | ||
|
|
3f85916764 | ||
|
|
ab0f544267 | ||
|
|
14e16c874e | ||
|
|
7fb87ad67f | ||
|
|
1b85417ae6 | ||
|
|
8d41e6fece | ||
|
|
ab2906991d | ||
|
|
ac85c75cc4 | ||
|
|
7f1fae307c | ||
|
|
cce41082a1 | ||
|
|
902a489b04 | ||
|
|
30006fe520 | ||
|
|
2ce1bb9c3f | ||
|
|
c468fa2a95 | ||
|
|
06ef342953 | ||
|
|
02121105de | ||
|
|
e24788157a | ||
|
|
63905c608e | ||
|
|
69127e6952 | ||
|
|
87a84f02a3 | ||
|
|
0b5bea9965 | ||
|
|
0d5e3a080c | ||
|
|
a4ba07de99 | ||
|
|
970a5ec763 | ||
|
|
6f338c44c4 | ||
|
|
f360fadd3f | ||
|
|
846fa4722b | ||
|
|
9752f1d492 | ||
|
|
ce2d386b7e | ||
|
|
993d433d03 | ||
|
|
ede344db3a | ||
|
|
6c397da1f8 | ||
|
|
1d9862fe11 | ||
|
|
2d3db00639 | ||
|
|
7269233134 | ||
|
|
27be0ad808 | ||
|
|
51e875694c | ||
|
|
92d64d77c5 | ||
|
|
579e9e0b8c | ||
|
|
25b9c491c3 | ||
|
|
8f1b48b0ab | ||
|
|
611d3c3b63 | ||
|
|
3a658e10f1 | ||
|
|
92a182e5a8 | ||
|
|
954f0cc26f | ||
|
|
5e0b4e1be6 | ||
|
|
c72511da6a | ||
|
|
15c65ad4e1 | ||
|
|
d06657e2ff | ||
|
|
5dae1ee34f | ||
|
|
88a5d33bad | ||
|
|
42e02a6129 | ||
|
|
7d56164882 | ||
|
|
3e60ad21bf | ||
|
|
55c4e9635a | ||
|
|
101d0212a7 | ||
|
|
f0338b5247 | ||
|
|
80136b4aff | ||
|
|
f0a89e99f5 | ||
|
|
09f830c315 | ||
|
|
ace92f8be0 | ||
|
|
7e08f495a7 | ||
|
|
a8299b4f54 | ||
|
|
bdb00b8d58 | ||
|
|
4e18127371 | ||
|
|
e5165e6fba | ||
|
|
77dc237549 | ||
|
|
e3cc04f538 | ||
|
|
322d1ad75c | ||
|
|
4767903a07 | ||
|
|
0064ce97f0 | ||
|
|
71f067f678 | ||
|
|
8f37dc8570 | ||
|
|
b15b640652 | ||
|
|
3e892f30ca | ||
|
|
20f3efced9 | ||
|
|
25bcd0f2a9 | ||
|
|
d990bf794a | ||
|
|
aa25feb57e | ||
|
|
b203fc7c68 | ||
|
|
9298e045d3 | ||
|
|
e3255588d3 | ||
|
|
514f23cf4d | ||
|
|
ab206b2abf | ||
|
|
2f8a65d364 | ||
|
|
a30e47d094 | ||
|
|
0a78a87a17 | ||
|
|
886ec9c574 | ||
|
|
434fe894bc | ||
|
|
cde9dbe406 | ||
|
|
c5262f188e | ||
|
|
8f57364547 | ||
|
|
eb193f230b | ||
|
|
6a868f975e | ||
|
|
66a8db598f | ||
|
|
bfa13583e3 | ||
|
|
d865e646b9 | ||
|
|
f630537897 | ||
|
|
aaf7ae8fc3 | ||
|
|
52cba23190 | ||
|
|
c48c74a0cf | ||
|
|
9c6c27909d | ||
|
|
3ba3e5cf76 | ||
|
|
df4040a96a | ||
|
|
6932e468cf | ||
|
|
a82279b068 | ||
|
|
0ae7b9c120 | ||
|
|
72f86069a2 | ||
|
|
509c32db70 | ||
|
|
7fa45c0658 | ||
|
|
4e81a6af83 | ||
|
|
66d3eb3400 | ||
|
|
7e36cb76ba | ||
|
|
fc47651c33 | ||
|
|
6948d70d94 | ||
|
|
eee2db8ad9 | ||
|
|
318a36a831 | ||
|
|
4d90bd9e31 | ||
|
|
4e81151e11 | ||
|
|
18195b778a | ||
|
|
326bddad2a | ||
|
|
f4b41a43cf | ||
|
|
38c762f775 | ||
|
|
9833d466c4 | ||
|
|
4d965333ef | ||
|
|
a6ec18690d | ||
|
|
d3fe0b48d8 | ||
|
|
35220e1c4d | ||
|
|
de7bc9870d | ||
|
|
680a3a5d13 | ||
|
|
cf8612c99f | ||
|
|
e817d3355c | ||
|
|
53b7f33ec4 | ||
|
|
5ed9a29f81 | ||
|
|
89406c4754 | ||
|
|
b27b26837f | ||
|
|
0595008fce | ||
|
|
d6b2e019c7 | ||
|
|
25cfb1f5c0 | ||
|
|
10a159b315 | ||
|
|
60c113b0e8 | ||
|
|
ec4330aea7 | ||
|
|
f263fe30a4 | ||
|
|
0ec2f68a96 | ||
|
|
1156b909eb | ||
|
|
9ed246e482 | ||
|
|
c342c5c4f6 | ||
|
|
3b7ef5b262 | ||
|
|
79bf3d8d4f | ||
|
|
cfe91a8722 | ||
|
|
c3e2d34372 | ||
|
|
56b6ee5d2a | ||
|
|
3f34ac1c75 | ||
|
|
be5015d16b | ||
|
|
2c1d4cfc40 | ||
|
|
5bf75e122c | ||
|
|
aa51048990 | ||
|
|
6d117f824d | ||
|
|
0a591e748f | ||
|
|
be2cb5d2f2 | ||
|
|
280ec22348 | ||
|
|
f9a815bba6 | ||
|
|
1534dcc932 | ||
|
|
e19ae7af59 | ||
|
|
1726d6f59e | ||
|
|
756f395158 | ||
|
|
90d2cf4970 | ||
|
|
37e70fd5bb | ||
|
|
126481833b | ||
|
|
b2630cfb49 | ||
|
|
579e2e95e3 | ||
|
|
6580436900 | ||
|
|
a0ecf72a1c | ||
|
|
bc3aaa94de | ||
|
|
482ca5ed15 | ||
|
|
66894c2e8a | ||
|
|
5d5a1fadd9 | ||
|
|
2d531c3a15 | ||
|
|
e4da11727a | ||
|
|
309f97b443 | ||
|
|
98240e910e | ||
|
|
6d79d3d1f8 | ||
|
|
def4e19359 | ||
|
|
6cfd055bec | ||
|
|
1208b25b66 | ||
|
|
b25bf70224 | ||
|
|
7ecb139dba | ||
|
|
2a7720852a | ||
|
|
627eb556cb | ||
|
|
e251155f4f | ||
|
|
4e9c44e574 | ||
|
|
5b662df7cd | ||
|
|
802574fb44 | ||
|
|
51f3334711 | ||
|
|
254b5c963b | ||
|
|
d5f64a79b2 | ||
|
|
dd54a714cb | ||
|
|
d40e9e3d73 | ||
|
|
d5066adb4b | ||
|
|
f933aae562 | ||
|
|
db65a80a7f | ||
|
|
2f9658fa22 | ||
|
|
ab06365a81 | ||
|
|
2bc27bd6f5 | ||
|
|
078ac1abe4 | ||
|
|
05259eb0d2 | ||
|
|
8c272ea032 | ||
|
|
f58f29389c | ||
|
|
854b137820 | ||
|
|
fb8b5ac6b6 | ||
|
|
35106f5e67 | ||
|
|
a5ea58dbf7 | ||
|
|
b4ddc8e5fc | ||
|
|
2223405e79 | ||
|
|
7260e0d0f5 | ||
|
|
44cf7f7330 | ||
|
|
465ceab271 | ||
|
|
fa818d50d1 | ||
|
|
deb75df77a | ||
|
|
aae47e103b | ||
|
|
957dbecb3d | ||
|
|
75fe59ef79 | ||
|
|
63ba5cf39d | ||
|
|
8a0b7fbc47 | ||
|
|
ea9fb5bcb0 | ||
|
|
21d8ceacf0 | ||
|
|
986cf025a0 | ||
|
|
85b936ead2 | ||
|
|
f241679087 | ||
|
|
6618cdc0ad | ||
|
|
fe2de5d8ae | ||
|
|
bd954e7292 | ||
|
|
86367298cc | ||
|
|
08346a2326 | ||
|
|
1bb9090434 | ||
|
|
879bcdf8d8 | ||
|
|
1b7658d8f9 | ||
|
|
d635705449 | ||
|
|
af1b17cb98 | ||
|
|
944ef83805 | ||
|
|
20b3e95b4f | ||
|
|
c2de0dd613 | ||
|
|
2a7f5f55b0 | ||
|
|
a03539ad8b | ||
|
|
c420a8a686 | ||
|
|
8d6a2e8882 | ||
|
|
8da9156bb5 | ||
|
|
ffc8a5188d | ||
|
|
4eb1117659 | ||
|
|
b4602c1e48 | ||
|
|
80ede42191 | ||
|
|
ea6937c0ac | ||
|
|
2f99ba8526 | ||
|
|
16324e16c7 | ||
|
|
c2e1ecf5b1 | ||
|
|
cd353217d6 | ||
|
|
6903f67f0f | ||
|
|
487dab793a | ||
|
|
4cd3f9bd38 | ||
|
|
f581e76057 | ||
|
|
312aa856ad | ||
|
|
6f4363e95b | ||
|
|
595ba92f06 | ||
|
|
df9114d7b0 | ||
|
|
1496d0e482 | ||
|
|
92f5783f35 | ||
|
|
da1895125a | ||
|
|
bcdd470567 | ||
|
|
7cd0070d90 | ||
|
|
8217949fa2 | ||
|
|
4bdf1553c9 | ||
|
|
6fd5d38cd8 | ||
|
|
8a737104ef | ||
|
|
a608da759b | ||
|
|
c828625cc1 | ||
|
|
7ead247fcb | ||
|
|
7a62af78d0 | ||
|
|
9896d6e6b2 | ||
|
|
9c376183e0 | ||
|
|
e5cc9a3cbf | ||
|
|
985979ab14 | ||
|
|
377a4c2284 | ||
|
|
24242db981 | ||
|
|
73a4152b5d | ||
|
|
b5eb094566 | ||
|
|
71140381e0 | ||
|
|
22387b2610 | ||
|
|
da53a7d469 | ||
|
|
b9b30f9f53 | ||
|
|
c984eb9b8c | ||
|
|
eef548f6a1 | ||
|
|
2da8ffb8cd | ||
|
|
8188c21641 | ||
|
|
19dca8c5bb | ||
|
|
5de5b6047a | ||
|
|
695c4159dc | ||
|
|
2624315bd5 | ||
|
|
fff6e50702 | ||
|
|
753b69726a | ||
|
|
df273aca7e | ||
|
|
9e9feb5980 | ||
|
|
e71eb465fb | ||
|
|
e9f2550a26 | ||
|
|
12bfd98011 | ||
|
|
2b45056842 | ||
|
|
c86fdf07db | ||
|
|
385ffd5b27 | ||
|
|
ad6b746124 | ||
|
|
57e8b59db6 | ||
|
|
ecb869695e | ||
|
|
c99c7ee6c9 | ||
|
|
d3c47fe1a4 | ||
|
|
1c21b23e8e | ||
|
|
bb55cd3c42 | ||
|
|
4a74190241 | ||
|
|
586f9594fb | ||
|
|
e68facfd51 | ||
|
|
7d423fa49d | ||
|
|
886553a923 | ||
|
|
ff4a00d103 | ||
|
|
dbdf8a97ae | ||
|
|
2433e31db0 | ||
|
|
5538aac732 | ||
|
|
c05f169d54 | ||
|
|
24aaefe342 | ||
|
|
c167e881fb | ||
|
|
9a8c22f487 | ||
|
|
fd8077a5cd | ||
|
|
6dd196a7a6 | ||
|
|
bdfe14e278 | ||
|
|
1c7b318c3f | ||
|
|
a6acc30eea | ||
|
|
c54a849243 | ||
|
|
1f2871f649 | ||
|
|
147d5902ed | ||
|
|
ec47ca1983 | ||
|
|
6ca6fc6989 | ||
|
|
f29015426f | ||
|
|
57f09fd64d | ||
|
|
2477ee4952 | ||
|
|
2bd7fd2aa7 | ||
|
|
bc5529ded8 | ||
|
|
b05736e4fb | ||
|
|
6a187881c0 | ||
|
|
d1accc4e09 | ||
|
|
e7e130460e | ||
|
|
d33a02f6cd | ||
|
|
8f6c511598 | ||
|
|
7fb04d51ae | ||
|
|
64d5275554 | ||
|
|
76041a9f55 | ||
|
|
502f7de040 | ||
|
|
a86512e807 | ||
|
|
2e19dbe05f | ||
|
|
18d8f07242 | ||
|
|
fb0ff734d7 | ||
|
|
13a5482f91 | ||
|
|
4a5794ad5f | ||
|
|
7652aca406 | ||
|
|
f1dfb1c952 | ||
|
|
b4f866be03 | ||
|
|
4fed35d189 | ||
|
|
c3cff6a911 | ||
|
|
91f718f39d | ||
|
|
e4ea01cfd2 | ||
|
|
dd7d5a46e8 | ||
|
|
3be4b08bb0 | ||
|
|
2fde7b7879 | ||
|
|
60777e5714 | ||
|
|
9d7fcc4987 | ||
|
|
95ed1c3ac3 | ||
|
|
7e285969a7 | ||
|
|
083f1be766 | ||
|
|
d39ed3c03f | ||
|
|
a068bda34f | ||
|
|
559f37e5d2 | ||
|
|
d50b7de668 | ||
|
|
35c5191a4d | ||
|
|
6df6296cd1 | ||
|
|
b88a565344 | ||
|
|
d98bc1ec63 | ||
|
|
74886db10d | ||
|
|
48e4fd8088 | ||
|
|
54c7f896ad | ||
|
|
ccd14e6505 | ||
|
|
dc33534478 | ||
|
|
83d79e23d5 | ||
|
|
151f99e343 | ||
|
|
ccea63f1e2 | ||
|
|
1019419d85 | ||
|
|
a234823d0a | ||
|
|
d2015845e8 | ||
|
|
1857cca081 | ||
|
|
195bbf4652 | ||
|
|
af76d937e1 | ||
|
|
885780a92b | ||
|
|
547bfe26d7 | ||
|
|
bc87fdde1f | ||
|
|
6fc8324337 | ||
|
|
5103d91db0 | ||
|
|
b67ab5ecd3 | ||
|
|
3aa085f17e | ||
|
|
1b9a78827a | ||
|
|
3299e0fa6a | ||
|
|
79e12c8dd8 | ||
|
|
ced33114cc | ||
|
|
294324e31b | ||
|
|
1b27d652af | ||
|
|
e98209249f | ||
|
|
9ddf09e187 | ||
|
|
73e975cfa1 | ||
|
|
a942ea6ee2 | ||
|
|
38ca7c030f | ||
|
|
7d59edc8a5 | ||
|
|
7d05450244 | ||
|
|
8e5ba70706 | ||
|
|
d43c40fc59 | ||
|
|
02ce707546 | ||
|
|
4a11ed6dc4 | ||
|
|
72d07fc3fb | ||
|
|
9b910b26a9 | ||
|
|
4a9be7b4a5 | ||
|
|
34958c654f | ||
|
|
bf91156182 | ||
|
|
b774b6920d | ||
|
|
56f6143873 | ||
|
|
7ba051c7ff | ||
|
|
63f5c240a4 | ||
|
|
ba91e433c3 | ||
|
|
2818b207db | ||
|
|
0527066a4c | ||
|
|
a48400535f | ||
|
|
fa201d21e2 | ||
|
|
c9222ff6f6 | ||
|
|
a45d311339 | ||
|
|
b59278601c | ||
|
|
b48a913fbf | ||
|
|
a0ef779aee | ||
|
|
861ff636b1 | ||
|
|
bbce4bdeb0 | ||
|
|
df0ceb4850 | ||
|
|
b1e45756dd | ||
|
|
4b52878dc1 | ||
|
|
62a4f18866 | ||
|
|
b00faf3930 | ||
|
|
d6ddb2b247 | ||
|
|
900510e7f2 | ||
|
|
7370af0084 | ||
|
|
9644693de3 | ||
|
|
b6bc269505 | ||
|
|
82161c10f8 | ||
|
|
c939033031 | ||
|
|
8c8c040fb3 | ||
|
|
48a07e2b34 | ||
|
|
7bdfbb17b5 | ||
|
|
492646edc3 | ||
|
|
975096b221 | ||
|
|
0c4c790a65 | ||
|
|
012539b5d3 | ||
|
|
f4cd9f27e4 | ||
|
|
449c2322b8 | ||
|
|
7efdcdc592 | ||
|
|
356aa27f70 | ||
|
|
a579c7882f | ||
|
|
3077cf6bb5 | ||
|
|
7c46ee50a4 | ||
|
|
1d37910bd4 | ||
|
|
5555ff2ac1 | ||
|
|
2ad93d79f5 | ||
|
|
6d32fe743b | ||
|
|
f2dd96c3bf | ||
|
|
9b4384d3e6 | ||
|
|
c1831e58f5 | ||
|
|
991f241209 | ||
|
|
b565cf4be1 | ||
|
|
8a5e1cd4f1 | ||
|
|
4445121023 | ||
|
|
1421869094 | ||
|
|
24480ef13a | ||
|
|
73bd7991bb | ||
|
|
6e74761977 | ||
|
|
a7f7a226d6 | ||
|
|
491cdc5fef | ||
|
|
98fe47d085 | ||
|
|
2290627c5f | ||
|
|
656d436028 | ||
|
|
cff8e822f2 | ||
|
|
5dfd46f809 | ||
|
|
97a6395ddd | ||
|
|
5226106ff0 | ||
|
|
5e838e3f10 | ||
|
|
574860f117 | ||
|
|
c19857d463 | ||
|
|
6741d58bec | ||
|
|
eb806dbca5 | ||
|
|
7d8aa683ff | ||
|
|
3bceaa7a2f | ||
|
|
bfa45b66ac | ||
|
|
e39b89859f | ||
|
|
1f14a01994 | ||
|
|
91310ce98c | ||
|
|
94dcfbf197 | ||
|
|
d2b4b8b279 | ||
|
|
aaa9495ceb | ||
|
|
a8b75c9b13 | ||
|
|
f21685e81d | ||
|
|
e24a7f887a | ||
|
|
54b5ab6d79 | ||
|
|
361b2ed7c7 | ||
|
|
cee6c7c999 | ||
|
|
3e5efd4090 | ||
|
|
10b8ba1ec8 | ||
|
|
be90380775 | ||
|
|
3b2e775698 | ||
|
|
01ba90689f | ||
|
|
e53fa82c46 | ||
|
|
48ccbfd860 | ||
|
|
601d4e1f48 | ||
|
|
7fce3bdd25 | ||
|
|
4b1bccd4b5 | ||
|
|
28e809f92f | ||
|
|
866e0e3fa9 |
64
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
64
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
name: Iris Bug Report
|
||||
description: File a bug report for Iris
|
||||
labels: [ bug ]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to fill this out!
|
||||
If this does not work for you, feel free to use the [blank](https://github.com/VolmitSoftware/Iris/issues/new) format.
|
||||
- type: textarea
|
||||
id: how
|
||||
attributes:
|
||||
label: Problem
|
||||
description: Please give a text description of how you reached the problem
|
||||
value: |
|
||||
1. Install Iris...
|
||||
2. Do this...
|
||||
3. Do that...
|
||||
4. Observe the error...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what
|
||||
attributes:
|
||||
label: Solution
|
||||
description: Explain where you think the problem comes from (optional)
|
||||
placeholder: The code to place a is missing b and c...
|
||||
validations:
|
||||
required: false
|
||||
- type: dropdown
|
||||
id: mcversion
|
||||
attributes:
|
||||
label: Minecraft Version
|
||||
description: What version of Minecraft is the server on?
|
||||
options:
|
||||
- 1.14.X
|
||||
- 1.15.X
|
||||
- 1.16.X
|
||||
- 1.17
|
||||
- 1.17.1
|
||||
- 1.18
|
||||
- 1.19
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: irisversion
|
||||
attributes:
|
||||
label: Iris Version
|
||||
description: What version of Iris are you running? (see console)
|
||||
placeholder: DO NOT SAY "LATEST"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: logs
|
||||
attributes:
|
||||
label: Log
|
||||
description: Paste a full log. Always use [mclogs](https://mclo.gs) Or [Pastebin](https://pastebin.com/). Must not be a crash report. Must be a full log. Must not be a screenshot of a log.
|
||||
placeholder: https://mslog.gs/...
|
||||
validations:
|
||||
required: true
|
||||
- type: markdown
|
||||
id: thanks
|
||||
attributes:
|
||||
value: "Thank you for filling out the form! We will be with you soon. Please do not ask support to review your report."
|
||||
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,34 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: Bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots or Video Recordings**
|
||||
If applicable, add screenshots or video recordings to help explain your problem.
|
||||
|
||||
**Server and Plugin Informations**
|
||||
- Installed plugins:
|
||||
- Iris Version:
|
||||
- Server Platform and Version [eg: PaperSpigot 1.16.3 #240]:
|
||||
- Operating System (if applicable):
|
||||
- Server Logs:
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here, server timings reports, Iris dump information, complete console log etc. Please do not make Pastebin dumps or screenshot expire.
|
||||
46
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
46
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
name: Iris Feature Request
|
||||
description: File a feature request for Iris. If you want to report a bug this is not the place.
|
||||
labels: [ feature ]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to fill this out!
|
||||
If this does not work for you, feel free to use the [blank](https://github.com/VolmitSoftware/Iris/issues/new) format.
|
||||
- type: dropdown
|
||||
id: arc
|
||||
attributes:
|
||||
label: Adding, Removing, or Changing
|
||||
description: What are you doing
|
||||
options:
|
||||
- Adding
|
||||
- Removing
|
||||
- Changing
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: atype
|
||||
attributes:
|
||||
label: Type of Modification
|
||||
description: What is it for?
|
||||
value: I want to ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: desc
|
||||
attributes:
|
||||
label: What are you trying to modify
|
||||
description: Give as detailed of a description as you can for the modification that you want done (include pictures if applicable)
|
||||
value: The way I would implement this is ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: alternative
|
||||
attributes:
|
||||
label: Alternatives
|
||||
description: What alternatives have you considered?
|
||||
value: If this could not be implemented I would ...
|
||||
- type: markdown
|
||||
id: thanks
|
||||
attributes:
|
||||
value: "Thank you for filling out the form! We will be with you soon. Please do not ask support to review your report."
|
||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: Enhancement, Addition
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
127
.gitignore
vendored
127
.gitignore
vendored
@@ -1,125 +1,12 @@
|
||||
# User-specific stuff
|
||||
|
||||
build/
|
||||
|
||||
.gradle/
|
||||
|
||||
.idea/
|
||||
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Package Files #
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
*~
|
||||
|
||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||
.fuse_hidden*
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
# .nfs files are created when an open file is removed but is still being accessed
|
||||
.nfs*
|
||||
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
collection/
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
target/
|
||||
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
.mvn/timing.properties
|
||||
.mvn/wrapper/maven-wrapper.jar
|
||||
.flattened-pom.xml
|
||||
|
||||
# Common working directory
|
||||
run/
|
||||
|
||||
.gradle
|
||||
**/build/
|
||||
!src/**/build/
|
||||
|
||||
# Ignore Gradle GUI config
|
||||
gradle-app.setting
|
||||
|
||||
# Cache of project
|
||||
.gradletasknamecache
|
||||
|
||||
# Custom folders
|
||||
release/
|
||||
src/main/java/com/volmit/iris/util/uniques/
|
||||
|
||||
97
Iris.iml
97
Iris.iml
@@ -1,97 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="minecraft" name="Minecraft">
|
||||
<configuration>
|
||||
<autoDetectTypes>
|
||||
<platformType>SPIGOT</platformType>
|
||||
<platformType>BUKKIT</platformType>
|
||||
</autoDetectTypes>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
||||
<output url="file://$MODULE_DIR$/target/classes" />
|
||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Maven: io.timeandspace:smoothie-map:2.0.2" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.timeandspace:jpsg-core:1.4" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.checkerframework:checker-qual:2.11.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.spigotmc:spigot-api:1.16.1-R0.1-SNAPSHOT" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: commons-lang:commons-lang:2.6" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:21.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.md-5:bungeecord-chat:1.16-R0.3" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.yaml:snakeyaml:1.26" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.papermc:paperlib:1.0.5" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.bukkit.craftbukkit:1.16.3:1.16.3" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.bukkit.craftbukkit:1.16.4:1.16.4" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.bergerkiller.bukkit:BKCommonLib:1.16.4-v2" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.sk89q.worldedit:worldedit-bukkit:7.2.0-SNAPSHOT" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.sk89q.worldedit:worldedit-core:7.2.0-SNAPSHOT" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.sk89q.worldedit.worldedit-libs:core:7.2.0-SNAPSHOT" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: de.schlichtherle:truezip:6.8.3" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-profile-default_2.13:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.scala-lang:scala-library:2.13.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-driver-http:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-kernel-spec:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truecommons:truecommons-annotations:2.5.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:annotations:3.0.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truecommons:truecommons-cio:2.5.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truecommons:truecommons-io:2.5.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truecommons:truecommons-services:2.5.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truecommons:truecommons-logging:2.5.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: javax.inject:javax.inject:1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.apache.httpcomponents:httpclient:4.5.10" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.apache.httpcomponents:httpcore:4.4.12" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: commons-codec:commons-codec:1.11" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.slf4j:jcl-over-slf4j:1.7.28" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-driver-odf:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-comp-zipdriver:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-comp-zip:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.bouncycastle:bcprov-jdk15on:1.63" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-driver-tar:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-comp-tardriver:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.apache.commons:commons-compress:1.19" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-driver-tar-bzip2:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-driver-tar-gzip:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-driver-tar-xz:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.tukaani:xz:1.8" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-driver-zip-raes:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-profile-base_2.13:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-access-swing:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-access:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-driver-file:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-driver-jar:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-driver-zip:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-comp-ibm437:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truevfs:truevfs-kernel-impl_2.13:0.12.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truecommons:truecommons-key-console:2.5.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truecommons:truecommons-key-default:2.5.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truecommons:truecommons-key-swing:2.5.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truecommons:truecommons-key-macosx:2.5.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truecommons:truecommons-key-spec:2.5.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.truecommons:truecommons-shed:2.5.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.java.dev.jna:jna:4.1.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.mozilla:rhino-runtime:1.7.12" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.antlr:antlr4-runtime:4.7.2" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.sk89q.worldedit.worldedit-libs:bukkit:7.2.0-SNAPSHOT" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.apache.logging.log4j:log4j-slf4j-impl:2.8.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.apache.logging.log4j:log4j-api:2.8.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.bstats:bstats-bukkit:1.7" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: it.unimi.dsi:fastutil:8.2.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: io.lumine.xikage:MythicMobs:4.9.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.github.ben-manes.caffeine:caffeine:2.8.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.4.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.projectlombok:lombok:1.18.10" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.gson:gson:2.8.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.zeroturnaround:zt-zip:1.14" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.6.6" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
519
LICENSE.md
519
LICENSE.md
@@ -1,35 +1,518 @@
|
||||
VOLMIT SOFTWARE PUBLIC LICENSE
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Version 1.2, 13 March 2021
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
|
||||
|
||||
Copyright :copyright: 2021 Andrew Baker
|
||||
Preamble
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
The GNU General Public License is a free, copyleft license for software and other kinds of works.
|
||||
|
||||
0. Definitions
|
||||
The licenses for most software and other practical works are designed to take away your freedom to share and change the
|
||||
works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all
|
||||
versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use
|
||||
the GNU General Public License for most of our software; it applies also to any other work released this way by its
|
||||
authors. You can apply it to your programs, too.
|
||||
|
||||
"License" refers to this file. An updated version is available at <https://github.com/VolmitSoftware/Licenses>. The version at <https://github.com/VolmitSoftware/Licenses> is always correct and up-to-date.
|
||||
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make
|
||||
sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive
|
||||
source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and
|
||||
that you know you can do these things.
|
||||
|
||||
"Author" refers to the person Andrew Baker <andrew@andrewcbaker.net>.
|
||||
To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights.
|
||||
Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it:
|
||||
responsibilities to respect the freedom of others.
|
||||
|
||||
"Repository" refers to the location at which the software protected under this License is stored.
|
||||
For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients
|
||||
the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must
|
||||
show them these terms so they know their rights.
|
||||
|
||||
"Content" refers to the files and folders inside of the Repository.
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute
|
||||
and/or modify it.
|
||||
|
||||
"Copyright" refers to the laws on intellectual property and the legal rights automatically granted to the Author during the creation of the Content.
|
||||
For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software.
|
||||
For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems
|
||||
will not be attributed erroneously to authors of previous versions.
|
||||
|
||||
"Modify" refers to editing the Content as well as creating programs or code which depends on the Content to run.
|
||||
Some devices are designed to deny users access to install or run modified versions of the software inside them, although
|
||||
the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the
|
||||
software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely
|
||||
where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we stand ready to extend this provision to those
|
||||
domains in future versions of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
"Compile" refers to the act of building the Content into an executable file such as a JAR file.
|
||||
Finally, every program is threatened constantly by software patents. States should not allow patents to restrict
|
||||
development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger
|
||||
that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
1. You may freely copy, Modify, distribute, create derivative works, or distribute derivative works of the Content as long as you obey the unmodified License that is supplied with the Content.
|
||||
The precise terms and conditions for copying, distribution and modification follow.
|
||||
|
||||
2. You may not copy, Modify, or distribute the Content in such a way that it will, directly or indirectly, generate revenue without explicit, written permission from the Author.
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
3. You may not host publicly available download links to Compiled versions of the Content unless you are using less than 5% of the original Content in a Repository of your own.
|
||||
0. Definitions.
|
||||
|
||||
4. For any conditions not outlined in the License, refer to your country or state laws for Copyright.
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
5. If you do not agree to any of the above conditions you must delete the Content in its entirety as well as all copies of the Content and derivative works of the Content that you have made.
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
|
||||
|
||||
END TERMS AND CONDITIONS
|
||||
"The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "
|
||||
Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission,
|
||||
other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a
|
||||
work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily
|
||||
liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy.
|
||||
Propagation includes copying, distribution (with or without modification), making available to the public, and in some
|
||||
countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction
|
||||
with a user through a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright
|
||||
notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the extent that warranties are provided), that
|
||||
licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a
|
||||
list of user commands or options, such as a menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means
|
||||
any non-source form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body,
|
||||
or, in the case of interfaces specified for a particular programming language, one that is widely used among developers
|
||||
working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in
|
||||
the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to
|
||||
enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is
|
||||
available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used
|
||||
to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (
|
||||
for an executable work) run the object code and to modify the work, including scripts to control those activities.
|
||||
However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs
|
||||
which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding
|
||||
Source includes interface definition files associated with source files for the work, and the source code for shared
|
||||
libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data
|
||||
communication or control flow between those subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users can regenerate automatically from other parts of the
|
||||
Corresponding Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided
|
||||
the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program.
|
||||
The output from running a covered work is covered by this License only if the output, given its content, constitutes a
|
||||
covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not convey, without conditions so long as your license
|
||||
otherwise remains in force. You may convey covered works to others for the sole purpose of having them make
|
||||
modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do not control copyright. Those thus making or running
|
||||
the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that
|
||||
prohibit them from making any copies of your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not
|
||||
allowed; section 10 makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling
|
||||
obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or
|
||||
restricting circumvention of such measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the
|
||||
extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you
|
||||
disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users,
|
||||
your or third parties' legal rights to forbid circumvention of technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating
|
||||
that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices
|
||||
of the absence of any warranty; and give all recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for
|
||||
a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source
|
||||
code under the terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent works, which are not by their nature extensions of
|
||||
the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or
|
||||
distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the
|
||||
compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause
|
||||
this License to apply to the other parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License, in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library,
|
||||
need not be included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used
|
||||
for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In
|
||||
determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a
|
||||
particular product received by a particular user, "normally used" refers to a typical or common use of that class of
|
||||
product, regardless of the status of the particular user or of the way in which the particular user actually uses, or
|
||||
expects or is expected to use, the product. A product is a consumer product regardless of whether the product has
|
||||
substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of
|
||||
the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods, procedures, authorization keys, or other information
|
||||
required to install and execute modified versions of a covered work in that User Product from a modified version of its
|
||||
Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code
|
||||
is in no case prevented or interfered with solely because modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the
|
||||
conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to
|
||||
the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding
|
||||
Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not
|
||||
apply if neither you nor any third party retains the ability to install modified object code on the User Product (for
|
||||
example, the work has been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a requirement to continue to provide support
|
||||
service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product
|
||||
in which it has been modified or installed. Access to a network may be denied when the modification itself materially
|
||||
and adversely affects the operation of the network or violates the rules and protocols for communication across the
|
||||
network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format
|
||||
that is publicly documented (and with an implementation available to the public in source code form), and must require
|
||||
no special password or key for unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of
|
||||
its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were
|
||||
included in this License, to the extent that they are valid under applicable law. If additional permissions apply only
|
||||
to part of the Program, that part may be used separately under those permissions, but the entire Program remains
|
||||
governed by this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or
|
||||
from any part of it. (Additional permissions may be written to require their own removal in certain cases when you
|
||||
modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have
|
||||
or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by
|
||||
the copyright holders of that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the
|
||||
Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with
|
||||
a term that is a further restriction, you may remove that term. If a license document contains a further restriction but
|
||||
permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of
|
||||
that license document, provided that the further restriction does not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a
|
||||
statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as
|
||||
exceptions; the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to
|
||||
propagate or modify it is void, and will automatically terminate your rights under this License (including any patent
|
||||
licenses granted under the third paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your license from a particular copyright holder is
|
||||
reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b)
|
||||
permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days
|
||||
after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you
|
||||
of the violation by some reasonable means, this is the first time you have received notice of violation of this
|
||||
License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the
|
||||
notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the licenses of parties who have received copies or
|
||||
rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not
|
||||
qualify to receive new licenses for the same material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a
|
||||
covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not
|
||||
require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered
|
||||
work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run,
|
||||
modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third
|
||||
parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or
|
||||
subdividing an organization, or merging organizations. If propagation of a covered work results from an entity
|
||||
transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work
|
||||
the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with
|
||||
reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For
|
||||
example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License,
|
||||
and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using,
|
||||
selling, offering for sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the
|
||||
Program is based. The work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already
|
||||
acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or
|
||||
selling its contributor version, but do not include claims that would be infringed only as a consequence of further
|
||||
modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent
|
||||
sublicenses in a manner consistent with the requirements of this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential
|
||||
patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its
|
||||
contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not
|
||||
to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a
|
||||
patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not
|
||||
available for anyone to copy, free of charge and under the terms of this License, through a publicly available network
|
||||
server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available,
|
||||
or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a
|
||||
manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "
|
||||
Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in
|
||||
a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in
|
||||
that country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring
|
||||
conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing
|
||||
them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is
|
||||
automatically extended to all recipients of the covered work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of,
|
||||
or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You
|
||||
may not convey a covered work if you are a party to an arrangement with a third party that is in the business of
|
||||
distributing software, under which you make payment to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a
|
||||
discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from
|
||||
those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered
|
||||
work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to
|
||||
infringement that may otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this
|
||||
License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to
|
||||
satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence
|
||||
you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further
|
||||
conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License
|
||||
would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work
|
||||
licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the
|
||||
resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special
|
||||
requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply
|
||||
to the combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to
|
||||
time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new
|
||||
problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the
|
||||
GNU General Public License "or any later version" applies to it, you have the option of following the terms and
|
||||
conditions either of that numbered version or of any later version published by the Free Software Foundation. If the
|
||||
Program does not specify a version number of the GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used,
|
||||
that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the
|
||||
Program.
|
||||
|
||||
Later license versions may give you additional or different permissions. However, no additional obligations are imposed
|
||||
on any author or copyright holder as a result of your choosing to follow a later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING
|
||||
THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR
|
||||
IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU
|
||||
ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO
|
||||
MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
|
||||
INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO
|
||||
LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM
|
||||
TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to
|
||||
their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil
|
||||
liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program
|
||||
in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve
|
||||
this is to make it free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to
|
||||
most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer
|
||||
to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of
|
||||
course, your program's commands might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for
|
||||
the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is
|
||||
a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If
|
||||
this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
|
||||
76
README.md
76
README.md
@@ -1,3 +1,77 @@
|
||||
# Iris
|
||||
|
||||
The master branch is for the latest version of minecraft.
|
||||
|
||||
# [Support](https://discord.gg/3xxPTpT) **|** [Documentation](https://docs.volmit.com/iris/) **|** [Git](https://github.com/IrisDimensions)
|
||||

|
||||
|
||||
# Building
|
||||
|
||||
Building Iris is fairly simple, though you will need to setup a few things if your system has never been used for java
|
||||
development.
|
||||
|
||||
Consider supporting our development by buying Iris on spigot! We work hard to make Iris the best it can be for everyone.
|
||||
|
||||
### Command Line Builds
|
||||
|
||||
1. Install [Java JDK 17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)
|
||||
2. Set the JDK installation path to `JAVA_HOME` as an environment variable.
|
||||
* Windows
|
||||
1. Start > Type `env` and press Enter
|
||||
2. Advanced > Environment Variables
|
||||
3. Under System Variables, click `New...`
|
||||
4. Variable Name: `JAVA_HOME`
|
||||
5. Variable Value: `C:\Program Files\Java\jdk-17.0.1` (verify this exists after installing java don't just copy
|
||||
the example text)
|
||||
* MacOS
|
||||
1. Run `/usr/libexec/java_home -V` and look for Java 17
|
||||
2. Run `sudo nano ~/.zshenv`
|
||||
3. Add `export JAVA_HOME=$(/usr/libexec/java_home)` as a new line
|
||||
4. Use `CTRL + X`, then Press `Y`, Then `ENTER`
|
||||
5. Quit & Reopen Terminal and verify with `echo $JAVA_HOME`. It should print a directory
|
||||
3. If this is your first time building Iris for MC 1.18+ run `gradlew setup` inside the root Iris project folder.
|
||||
Otherwise, skip this step. Grab a coffee, this may take up to 5 minutes depending on your cpu & internet connection.
|
||||
4. Once the project has setup, run `gradlew iris`
|
||||
5. The Iris jar will be placed in `Iris/build/Iris-XXX-XXX.jar` Enjoy! Consider supporting us by buying it on spigot!
|
||||
|
||||
### IDE Builds (for development)
|
||||
|
||||
* Run `gradlew setup` any time you get dependency issues with craftbukkit
|
||||
* Configure ITJ Gradle to use JDK 17 (in settings, search for gradle)
|
||||
* Add a build line in the build.gradle for your own build task to directly compile Iris into your plugins folder if you
|
||||
prefer.
|
||||
* Resync the project & run your newly created task (under the development folder in gradle tasks!)
|
||||
|
||||
# Iris Toolbelt
|
||||
|
||||
Everyone needs a tool-belt.
|
||||
|
||||
```java
|
||||
package com.volmit.iris.core.tools;
|
||||
|
||||
// Get IrisDataManager from a world
|
||||
IrisToolbelt.access(anyWorld).getCompound().getData();
|
||||
|
||||
// Get Default Engine from world
|
||||
IrisToolbelt.access(anyWorld).getCompound().getDefaultEngine();
|
||||
|
||||
// Get the engine at the given height
|
||||
IrisToolbelt.access(anyWorld).getCompound().getEngineForHeight(68);
|
||||
|
||||
// IS THIS THING ON?
|
||||
boolean yes=IrisToolbelt.isIrisWorld(world);
|
||||
|
||||
// GTFO for worlds (moves players to any other world, just not this one)
|
||||
IrisToolbelt.evacuate(world);
|
||||
|
||||
IrisAccess access=IrisToolbelt.createWorld() // If you like builders...
|
||||
.name("myWorld") // The world name
|
||||
.dimension("terrifyinghands")
|
||||
.seed(69133742) // The world seed
|
||||
.headless(true) // Headless make gen go fast
|
||||
.pregen(PregenTask // Define a pregen job to run
|
||||
.builder()
|
||||
.center(new Position2(0,0)) // REGION coords (1 region = 32x32 chunks)
|
||||
.radius(4) // Radius in REGIONS. Rad of 4 means a 9x9 Region map.
|
||||
.build())
|
||||
.create();
|
||||
```
|
||||
|
||||
321
build.gradle
Normal file
321
build.gradle
Normal file
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'java-library'
|
||||
id "io.freefair.lombok" version "6.3.0"
|
||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
||||
id "de.undercouch.download" version "5.0.1"
|
||||
}
|
||||
|
||||
version '2.2.18-1.19.2' // Needs to be version specific
|
||||
def nmsVersion = "1.19.2" //[NMS]
|
||||
def apiVersion = '1.19'
|
||||
def specialSourceVersion = '1.11.0' //[NMS]
|
||||
def spigotJarVersion = '1.19.2-R0.1-SNAPSHOT' //[NMS]
|
||||
def name = getRootProject().getName() // Defined in settings.gradle
|
||||
def main = 'com.volmit.iris.Iris'
|
||||
|
||||
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
|
||||
// ======================== WINDOWS =============================
|
||||
registerCustomOutputTask('Cyberpwn', 'C://Users/cyberpwn/Documents/development/server/plugins')
|
||||
registerCustomOutputTask('Psycho', 'D://Dan/MinecraftDevelopment/server/plugins')
|
||||
registerCustomOutputTask('ArcaneArts', 'C://Users/arcane/Documents/development/server/plugins')
|
||||
registerCustomOutputTask('Coco', 'D://Documents/MC/plugins')
|
||||
registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins')
|
||||
registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19.2/plugins')
|
||||
// ========================== UNIX ==============================
|
||||
registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins')
|
||||
registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Desktop/REMOTES/RemoteMinecraft/plugins')
|
||||
// ==============================================================
|
||||
|
||||
/**
|
||||
* Gradle is weird sometimes, we need to delete the plugin yml from the build folder to actually filter properly.
|
||||
*/
|
||||
file(jar.archiveFile.get().getAsFile().getParentFile().getParentFile().getParentFile().getAbsolutePath() + '/build/resources/main/plugin.yml').delete()
|
||||
|
||||
/**
|
||||
* Expand properties into plugin yml
|
||||
*/
|
||||
processResources {
|
||||
filesMatching('**/plugin.yml') {
|
||||
expand(
|
||||
'name': name.toString(),
|
||||
'version': version.toString(),
|
||||
'main': main.toString(),
|
||||
'apiversion': apiVersion.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unified repo
|
||||
*/
|
||||
repositories {
|
||||
mavenLocal {
|
||||
content {
|
||||
includeGroup("org.bukkit")
|
||||
includeGroup("org.spigotmc")
|
||||
}
|
||||
}
|
||||
maven { url "https://arcanearts.jfrog.io/artifactory/archives" }
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* We need parameter meta for the decree command system
|
||||
*/
|
||||
compileJava {
|
||||
options.compilerArgs << '-parameters'
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure Iris for shading
|
||||
*/
|
||||
shadowJar {
|
||||
//minimize()
|
||||
append("plugin.yml")
|
||||
relocate 'com.dfsek.paralithic', 'com.volmit.iris.util.paralithic'
|
||||
relocate 'io.papermc.lib', 'com.volmit.iris.util.paper'
|
||||
relocate 'net.kyori', 'com.volmit.iris.util.kyori'
|
||||
dependencies {
|
||||
include(dependency('io.papermc:paperlib'))
|
||||
include(dependency('com.dfsek:Paralithic'))
|
||||
include(dependency('net.kyori:'))
|
||||
}
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy.cacheChangingModulesFor 60, 'minutes'
|
||||
resolutionStrategy.cacheDynamicVersionsFor 60, 'minutes'
|
||||
}
|
||||
|
||||
/**
|
||||
* Dependencies.
|
||||
*
|
||||
* Provided or classpath dependencies are not shaded and are available on the runtime classpath
|
||||
*
|
||||
* Shaded dependencies are not available at runtime, nor are they available on mvn central so they
|
||||
* need to be shaded into the jar (increasing binary size)
|
||||
*
|
||||
* Dynamically loaded dependencies are defined in the plugin.yml (updating these must be updated in the
|
||||
* plugin.yml also, otherwise they wont be available). These do not increase binary size). Only declare
|
||||
* these dependencies if they are available on mvn central.
|
||||
*/
|
||||
dependencies {
|
||||
// Provided or Classpath
|
||||
compileOnly 'org.projectlombok:lombok:1.18.24'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.24'
|
||||
implementation 'org.spigotmc:spigot-api:1.19.2-R0.1-SNAPSHOT'
|
||||
implementation 'me.clip:placeholderapi:2.11.1'
|
||||
implementation 'io.th0rgal:oraxen:1.94.0'
|
||||
implementation 'org.bukkit:craftbukkit:1.19.2-R0.1-SNAPSHOT:remapped-mojang' //[NMS]
|
||||
implementation 'com.github.LoneDev6:api-itemsadder:3.1.0b'
|
||||
|
||||
// Shaded
|
||||
implementation 'com.dfsek:Paralithic:0.4.0'
|
||||
implementation 'io.papermc:paperlib:1.0.5'
|
||||
implementation "net.kyori:adventure-text-minimessage:4.11.0"
|
||||
implementation 'net.kyori:adventure-platform-bukkit:4.1.0'
|
||||
implementation 'net.kyori:adventure-api:4.11.0'
|
||||
|
||||
// Dynamically Loaded
|
||||
implementation 'io.timeandspace:smoothie-map:2.0.2'
|
||||
implementation 'it.unimi.dsi:fastutil:8.5.8'
|
||||
implementation 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2'
|
||||
implementation 'org.zeroturnaround:zt-zip:1.14'
|
||||
implementation 'com.google.code.gson:gson:2.9.0'
|
||||
implementation 'org.ow2.asm:asm:9.2'
|
||||
implementation 'com.google.guava:guava:31.1-jre'
|
||||
implementation 'bsf:bsf:2.4.0'
|
||||
implementation 'rhino:js:1.7R2'
|
||||
implementation 'com.github.ben-manes.caffeine:caffeine:3.0.6'
|
||||
implementation 'org.apache.commons:commons-lang3:3.12.0'
|
||||
}
|
||||
|
||||
if (JavaVersion.current().toString() != "17") {
|
||||
System.err.println()
|
||||
System.err.println("=========================================================================================================")
|
||||
System.err.println("You must run gradle on Java 17. You are using " + JavaVersion.current())
|
||||
System.err.println()
|
||||
System.err.println("=== For IDEs ===")
|
||||
System.err.println("1. Configure the project for Java 17")
|
||||
System.err.println("2. Configure the bundled gradle to use Java 17 in settings")
|
||||
System.err.println()
|
||||
System.err.println("=== For Command Line (gradlew) ===")
|
||||
System.err.println("1. Install JDK 17 from https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html")
|
||||
System.err.println("2. Set JAVA_HOME environment variable to the new jdk installation folder such as C:\\Program Files\\Java\\jdk-17.0.1")
|
||||
System.err.println("3. Open a new command prompt window to get the new environment variables if need be.")
|
||||
System.err.println("=========================================================================================================")
|
||||
System.err.println()
|
||||
System.exit(69);
|
||||
}
|
||||
|
||||
def buildToolsJar = new File(buildDir, "buildtools/BuildTools.jar");
|
||||
def specialSourceJar = new File(buildDir, "specialsource/SpecialSource.jar");
|
||||
def buildToolsFolder = new File(buildDir, "buildtools");
|
||||
def specialSourceFolder = new File(buildDir, "specialsource");
|
||||
def buildToolsHint = new File(buildDir, "buildtools/craftbukkit-" + nmsVersion + ".jar");
|
||||
def outputShadeJar = new File(buildDir, "libs/Iris-" + version + "-all.jar");
|
||||
def ssiJar = new File(buildDir, "specialsource/Iris-" + version + "-all.jar");
|
||||
def ssobfJar = new File(buildDir, "specialsource/Iris-" + version + "-rmo.jar");
|
||||
def ssJar = new File(buildDir, "specialsource/Iris-" + version + "-rma.jar");
|
||||
def homePath = System.properties['user.home']
|
||||
def m2 = new File(homePath + "/.m2/repository")
|
||||
def m2s = m2.getAbsolutePath();
|
||||
|
||||
// ======================== Building Mapped Jars =============================
|
||||
task downloadBuildtools(type: Download) {
|
||||
group "remapping"
|
||||
src 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar'
|
||||
dest buildToolsJar
|
||||
onlyIf {
|
||||
!buildToolsJar.exists()
|
||||
}
|
||||
}
|
||||
|
||||
task downloadSpecialSource(type: Download) {
|
||||
group "remapping"
|
||||
src 'https://repo.maven.apache.org/maven2/net/md-5/SpecialSource/' + specialSourceVersion + '/SpecialSource-'+specialSourceVersion+'-shaded.jar'
|
||||
dest specialSourceJar
|
||||
onlyIf {
|
||||
!specialSourceJar.exists()
|
||||
}
|
||||
}
|
||||
|
||||
task executeBuildTools(dependsOn: downloadBuildtools, type: JavaExec)
|
||||
{
|
||||
group "remapping"
|
||||
classpath = files(buildToolsJar)
|
||||
workingDir = buildToolsFolder
|
||||
args = [
|
||||
"--rev",
|
||||
nmsVersion,
|
||||
"--compile",
|
||||
"craftbukkit",
|
||||
"--remap"
|
||||
]
|
||||
onlyIf {
|
||||
!buildToolsHint.exists()
|
||||
}
|
||||
}
|
||||
|
||||
task copyBuildToSpecialSource(type: Copy)
|
||||
{
|
||||
group "remapping"
|
||||
from outputShadeJar
|
||||
into specialSourceFolder
|
||||
dependsOn(downloadSpecialSource, shadowJar)
|
||||
}
|
||||
|
||||
task specialSourceRemapObfuscate(type: JavaExec)
|
||||
{
|
||||
group "remapping"
|
||||
dependsOn(copyBuildToSpecialSource, downloadSpecialSource, shadowJar)
|
||||
workingDir = specialSourceFolder
|
||||
classpath = files(specialSourceJar,
|
||||
new File(m2s + "/org/spigotmc/spigot/" + spigotJarVersion + "/spigot-" + spigotJarVersion + "-remapped-mojang.jar"))
|
||||
mainClass = "net.md_5.specialsource.SpecialSource"
|
||||
args = [
|
||||
"--live",
|
||||
"-i",
|
||||
ssiJar.getName(),
|
||||
"-o",
|
||||
ssobfJar.getName(),
|
||||
"-m",
|
||||
m2s + "/org/spigotmc/minecraft-server/" + spigotJarVersion + "/minecraft-server-" + spigotJarVersion + "-maps-mojang.txt",
|
||||
"--reverse",
|
||||
]
|
||||
}
|
||||
|
||||
task specialSourceRemap(type: JavaExec)
|
||||
{
|
||||
group "remapping"
|
||||
dependsOn(specialSourceRemapObfuscate)
|
||||
workingDir = specialSourceFolder
|
||||
classpath = files(specialSourceJar,
|
||||
new File(m2s + "/org/spigotmc/spigot/" + spigotJarVersion + "/spigot-" + spigotJarVersion + "-remapped-obf.jar"))
|
||||
mainClass = "net.md_5.specialsource.SpecialSource"
|
||||
args = [
|
||||
"--live",
|
||||
"-i",
|
||||
ssobfJar.getName(),
|
||||
"-o",
|
||||
ssJar.getName(),
|
||||
"-m",
|
||||
m2s + "/org/spigotmc/minecraft-server/" + spigotJarVersion + "/minecraft-server-" + spigotJarVersion + "-maps-spigot.csrg"
|
||||
]
|
||||
}
|
||||
|
||||
tasks.compileJava.dependsOn(executeBuildTools)
|
||||
|
||||
compileJava {
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
|
||||
task setup()
|
||||
{
|
||||
group("iris")
|
||||
dependsOn(clean, executeBuildTools)
|
||||
}
|
||||
|
||||
task iris(type: Copy)
|
||||
{
|
||||
group "iris"
|
||||
from ssJar
|
||||
into buildDir
|
||||
rename { String fileName ->
|
||||
fileName.replace('Iris-' + version + '-rma.jar', "Iris-" + version + ".jar")
|
||||
}
|
||||
dependsOn(specialSourceRemap)
|
||||
}
|
||||
|
||||
def registerCustomOutputTask(name, path) {
|
||||
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
|
||||
return;
|
||||
}
|
||||
|
||||
tasks.register('build' + name, Copy) {
|
||||
group('development')
|
||||
outputs.upToDateWhen { false }
|
||||
dependsOn(iris)
|
||||
from(new File(buildDir, "Iris-" + version + ".jar"))
|
||||
into(file(path))
|
||||
rename { String fileName ->
|
||||
fileName.replace("Iris-" + version + ".jar", "Iris- "+ version +".jar")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def registerCustomOutputTaskUnix(name, path) {
|
||||
if (System.properties['os.name'].toLowerCase().contains('windows')) {
|
||||
return;
|
||||
}
|
||||
|
||||
tasks.register('build' + name, Copy) {
|
||||
group('development')
|
||||
outputs.upToDateWhen { false }
|
||||
dependsOn(iris)
|
||||
from(new File(buildDir, "Iris-" + version + ".jar"))
|
||||
into(file(path))
|
||||
rename { String fileName ->
|
||||
fileName.replace("Iris-" + version + ".jar", "Iris- "+ version +".jar")
|
||||
}
|
||||
}
|
||||
}
|
||||
22
gradle.properties
Normal file
22
gradle.properties
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Iris is a World Generator for Minecraft Bukkit Servers
|
||||
# Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
org.gradle.daemon=true
|
||||
org.gradle.parallel=true
|
||||
org.gradle.jvmargs=-Xmx3072m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
org.gradle.caching=true
|
||||
org.gradle.configureondemand=false
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
234
gradlew
vendored
Executable file
234
gradlew
vendored
Executable file
@@ -0,0 +1,234 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original 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.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=${0##*/}
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
89
gradlew.bat
vendored
Normal file
89
gradlew.bat
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
201
json/HTTP.java
201
json/HTTP.java
@@ -1,201 +0,0 @@
|
||||
package ninja.bytecode.shuriken.json;
|
||||
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Convert an HTTP header to a JSONObject and back.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class HTTP
|
||||
{
|
||||
|
||||
/** Carriage return/line feed. */
|
||||
public static final String CRLF = "\r\n";
|
||||
|
||||
/**
|
||||
* Convert an HTTP header string into a JSONObject. It can be a request
|
||||
* header or a response header. A request header will contain
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* Method: "POST" (for example),
|
||||
* "Request-URI": "/" (for example),
|
||||
* "HTTP-Version": "HTTP/1.1" (for example)
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* A response header will contain
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* "HTTP-Version": "HTTP/1.1" (for example),
|
||||
* "Status-Code": "200" (for example),
|
||||
* "Reason-Phrase": "OK" (for example)
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* In addition, the other parameters in the header will be captured, using
|
||||
* the HTTP field names as JSON names, so that
|
||||
*
|
||||
* <pre>
|
||||
* Date: Sun, 26 May 2002 18:06:04 GMT
|
||||
* Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s
|
||||
* Cache-Control: no-cache
|
||||
* </pre>
|
||||
*
|
||||
* become
|
||||
*
|
||||
* <pre>
|
||||
* {...
|
||||
* Date: "Sun, 26 May 2002 18:06:04 GMT",
|
||||
* Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s",
|
||||
* "Cache-Control": "no-cache",
|
||||
* ...}
|
||||
* </pre>
|
||||
*
|
||||
* It does no further checking or conversion. It does not parse dates. It
|
||||
* does not do '%' transforms on URLs.
|
||||
*
|
||||
* @param string
|
||||
* An HTTP header string.
|
||||
* @return A JSONObject containing the elements and attributes of the XML
|
||||
* string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string) throws JSONException
|
||||
{
|
||||
JSONObject jo = new JSONObject();
|
||||
HTTPTokener x = new HTTPTokener(string);
|
||||
String token;
|
||||
|
||||
token = x.nextToken();
|
||||
if(token.toUpperCase().startsWith("HTTP"))
|
||||
{
|
||||
|
||||
// Response
|
||||
|
||||
jo.put("HTTP-Version", token);
|
||||
jo.put("Status-Code", x.nextToken());
|
||||
jo.put("Reason-Phrase", x.nextTo('\0'));
|
||||
x.next();
|
||||
|
||||
} else
|
||||
{
|
||||
|
||||
// Request
|
||||
|
||||
jo.put("Method", token);
|
||||
jo.put("Request-URI", x.nextToken());
|
||||
jo.put("HTTP-Version", x.nextToken());
|
||||
}
|
||||
|
||||
// Fields
|
||||
|
||||
while(x.more())
|
||||
{
|
||||
String name = x.nextTo(':');
|
||||
x.next(':');
|
||||
jo.put(name, x.nextTo('\0'));
|
||||
x.next();
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into an HTTP header. A request header must contain
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* Method: "POST" (for example),
|
||||
* "Request-URI": "/" (for example),
|
||||
* "HTTP-Version": "HTTP/1.1" (for example)
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* A response header must contain
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* "HTTP-Version": "HTTP/1.1" (for example),
|
||||
* "Status-Code": "200" (for example),
|
||||
* "Reason-Phrase": "OK" (for example)
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* Any other members of the JSONObject will be output as HTTP fields. The
|
||||
* result will end with two CRLF pairs.
|
||||
*
|
||||
* @param jo
|
||||
* A JSONObject
|
||||
* @return An HTTP header string.
|
||||
* @throws JSONException
|
||||
* if the object does not contain enough information.
|
||||
*/
|
||||
public static String toString(JSONObject jo) throws JSONException
|
||||
{
|
||||
Iterator<String> keys = jo.keys();
|
||||
String string;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if(jo.has("Status-Code") && jo.has("Reason-Phrase"))
|
||||
{
|
||||
sb.append(jo.getString("HTTP-Version"));
|
||||
sb.append(' ');
|
||||
sb.append(jo.getString("Status-Code"));
|
||||
sb.append(' ');
|
||||
sb.append(jo.getString("Reason-Phrase"));
|
||||
} else if(jo.has("Method") && jo.has("Request-URI"))
|
||||
{
|
||||
sb.append(jo.getString("Method"));
|
||||
sb.append(' ');
|
||||
sb.append('"');
|
||||
sb.append(jo.getString("Request-URI"));
|
||||
sb.append('"');
|
||||
sb.append(' ');
|
||||
sb.append(jo.getString("HTTP-Version"));
|
||||
} else
|
||||
{
|
||||
throw new JSONException("Not enough material for an HTTP header.");
|
||||
}
|
||||
sb.append(CRLF);
|
||||
while(keys.hasNext())
|
||||
{
|
||||
string = keys.next();
|
||||
if(!"HTTP-Version".equals(string) && !"Status-Code".equals(string) && !"Reason-Phrase".equals(string) && !"Method".equals(string) && !"Request-URI".equals(string) && !jo.isNull(string))
|
||||
{
|
||||
sb.append(string);
|
||||
sb.append(": ");
|
||||
sb.append(jo.getString(string));
|
||||
sb.append(CRLF);
|
||||
}
|
||||
}
|
||||
sb.append(CRLF);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
package ninja.bytecode.shuriken.json;
|
||||
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The HTTPTokener extends the JSONTokener to provide additional methods for the
|
||||
* parsing of HTTP headers.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class HTTPTokener extends JSONTokener
|
||||
{
|
||||
|
||||
/**
|
||||
* Construct an HTTPTokener from a string.
|
||||
*
|
||||
* @param string
|
||||
* A source string.
|
||||
*/
|
||||
public HTTPTokener(String string)
|
||||
{
|
||||
super(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next token or string. This is used in parsing HTTP headers.
|
||||
*
|
||||
* @throws JSONException
|
||||
* @return A String.
|
||||
*/
|
||||
public String nextToken() throws JSONException
|
||||
{
|
||||
char c;
|
||||
char q;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
do
|
||||
{
|
||||
c = next();
|
||||
} while(Character.isWhitespace(c));
|
||||
if(c == '"' || c == '\'')
|
||||
{
|
||||
q = c;
|
||||
for(;;)
|
||||
{
|
||||
c = next();
|
||||
if(c < ' ')
|
||||
{
|
||||
throw syntaxError("Unterminated string.");
|
||||
}
|
||||
if(c == q)
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
for(;;)
|
||||
{
|
||||
if(c == 0 || Character.isWhitespace(c))
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
sb.append(c);
|
||||
c = next();
|
||||
}
|
||||
}
|
||||
}
|
||||
1252
json/JSONArray.java
1252
json/JSONArray.java
File diff suppressed because it is too large
Load Diff
@@ -1,50 +0,0 @@
|
||||
package ninja.bytecode.shuriken.json;
|
||||
|
||||
|
||||
/**
|
||||
* The JSONException is thrown by the JSON.org classes when things are amiss.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 0;
|
||||
private Throwable cause;
|
||||
|
||||
/**
|
||||
* Constructs a JSONException with an explanatory message.
|
||||
*
|
||||
* @param message
|
||||
* Detail about the reason for the exception.
|
||||
*/
|
||||
public JSONException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new JSONException with the specified cause.
|
||||
*
|
||||
* @param cause
|
||||
* The cause.
|
||||
*/
|
||||
public JSONException(Throwable cause)
|
||||
{
|
||||
super(cause.getMessage());
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cause of this exception or null if the cause is nonexistent
|
||||
* or unknown.
|
||||
*
|
||||
* @return the cause of this exception or null if the cause is nonexistent
|
||||
* or unknown.
|
||||
*/
|
||||
@Override
|
||||
public Throwable getCause()
|
||||
{
|
||||
return this.cause;
|
||||
}
|
||||
}
|
||||
555
json/JSONML.java
555
json/JSONML.java
@@ -1,555 +0,0 @@
|
||||
package ninja.bytecode.shuriken.json;
|
||||
|
||||
|
||||
/*
|
||||
Copyright (c) 2008 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* This provides static methods to convert an XML text into a JSONArray or
|
||||
* JSONObject, and to covert a JSONArray or JSONObject into an XML text using
|
||||
* the JsonML transform.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONML
|
||||
{
|
||||
|
||||
/**
|
||||
* Parse XML values and store them in a JSONArray.
|
||||
*
|
||||
* @param x
|
||||
* The XMLTokener containing the source string.
|
||||
* @param arrayForm
|
||||
* true if array form, false if object form.
|
||||
* @param ja
|
||||
* The JSONArray that is containing the current tag or null if we
|
||||
* are at the outermost level.
|
||||
* @return A JSONArray if the value is the outermost tag, otherwise null.
|
||||
* @throws JSONException
|
||||
*/
|
||||
private static Object parse(XMLTokener x, boolean arrayForm, JSONArray ja) throws JSONException
|
||||
{
|
||||
String attribute;
|
||||
char c;
|
||||
String closeTag = null;
|
||||
int i;
|
||||
JSONArray newja = null;
|
||||
JSONObject newjo = null;
|
||||
Object token;
|
||||
String tagName = null;
|
||||
|
||||
// Test for and skip past these forms:
|
||||
// <!-- ... -->
|
||||
// <![ ... ]]>
|
||||
// <! ... >
|
||||
// <? ... ?>
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(!x.more())
|
||||
{
|
||||
throw x.syntaxError("Bad XML");
|
||||
}
|
||||
token = x.nextContent();
|
||||
if(token == XML.LT)
|
||||
{
|
||||
token = x.nextToken();
|
||||
if(token instanceof Character)
|
||||
{
|
||||
if(token == XML.SLASH)
|
||||
{
|
||||
|
||||
// Close tag </
|
||||
|
||||
token = x.nextToken();
|
||||
if(!(token instanceof String))
|
||||
{
|
||||
throw new JSONException("Expected a closing name instead of '" + token + "'.");
|
||||
}
|
||||
if(x.nextToken() != XML.GT)
|
||||
{
|
||||
throw x.syntaxError("Misshaped close tag");
|
||||
}
|
||||
return token;
|
||||
} else if(token == XML.BANG)
|
||||
{
|
||||
|
||||
// <!
|
||||
|
||||
c = x.next();
|
||||
if(c == '-')
|
||||
{
|
||||
if(x.next() == '-')
|
||||
{
|
||||
x.skipPast("-->");
|
||||
} else
|
||||
{
|
||||
x.back();
|
||||
}
|
||||
} else if(c == '[')
|
||||
{
|
||||
token = x.nextToken();
|
||||
if(token.equals("CDATA") && x.next() == '[')
|
||||
{
|
||||
if(ja != null)
|
||||
{
|
||||
ja.put(x.nextCDATA());
|
||||
}
|
||||
} else
|
||||
{
|
||||
throw x.syntaxError("Expected 'CDATA['");
|
||||
}
|
||||
} else
|
||||
{
|
||||
i = 1;
|
||||
do
|
||||
{
|
||||
token = x.nextMeta();
|
||||
if(token == null)
|
||||
{
|
||||
throw x.syntaxError("Missing '>' after '<!'.");
|
||||
} else if(token == XML.LT)
|
||||
{
|
||||
i += 1;
|
||||
} else if(token == XML.GT)
|
||||
{
|
||||
i -= 1;
|
||||
}
|
||||
} while(i > 0);
|
||||
}
|
||||
} else if(token == XML.QUEST)
|
||||
{
|
||||
|
||||
// <?
|
||||
|
||||
x.skipPast("?>");
|
||||
} else
|
||||
{
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
|
||||
// Open tag <
|
||||
|
||||
} else
|
||||
{
|
||||
if(!(token instanceof String))
|
||||
{
|
||||
throw x.syntaxError("Bad tagName '" + token + "'.");
|
||||
}
|
||||
tagName = (String) token;
|
||||
newja = new JSONArray();
|
||||
newjo = new JSONObject();
|
||||
if(arrayForm)
|
||||
{
|
||||
newja.put(tagName);
|
||||
if(ja != null)
|
||||
{
|
||||
ja.put(newja);
|
||||
}
|
||||
} else
|
||||
{
|
||||
newjo.put("tagName", tagName);
|
||||
if(ja != null)
|
||||
{
|
||||
ja.put(newjo);
|
||||
}
|
||||
}
|
||||
token = null;
|
||||
for(;;)
|
||||
{
|
||||
if(token == null)
|
||||
{
|
||||
token = x.nextToken();
|
||||
}
|
||||
if(token == null)
|
||||
{
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
if(!(token instanceof String))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// attribute = value
|
||||
|
||||
attribute = (String) token;
|
||||
if(!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute)))
|
||||
{
|
||||
throw x.syntaxError("Reserved attribute.");
|
||||
}
|
||||
token = x.nextToken();
|
||||
if(token == XML.EQ)
|
||||
{
|
||||
token = x.nextToken();
|
||||
if(!(token instanceof String))
|
||||
{
|
||||
throw x.syntaxError("Missing value");
|
||||
}
|
||||
newjo.accumulate(attribute, XML.stringToValue((String) token));
|
||||
token = null;
|
||||
} else
|
||||
{
|
||||
newjo.accumulate(attribute, "");
|
||||
}
|
||||
}
|
||||
if(arrayForm && newjo.length() > 0)
|
||||
{
|
||||
newja.put(newjo);
|
||||
}
|
||||
|
||||
// Empty tag <.../>
|
||||
|
||||
if(token == XML.SLASH)
|
||||
{
|
||||
if(x.nextToken() != XML.GT)
|
||||
{
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
if(ja == null)
|
||||
{
|
||||
if(arrayForm)
|
||||
{
|
||||
return newja;
|
||||
} else
|
||||
{
|
||||
return newjo;
|
||||
}
|
||||
}
|
||||
|
||||
// Content, between <...> and </...>
|
||||
|
||||
} else
|
||||
{
|
||||
if(token != XML.GT)
|
||||
{
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
closeTag = (String) parse(x, arrayForm, newja);
|
||||
if(closeTag != null)
|
||||
{
|
||||
if(!closeTag.equals(tagName))
|
||||
{
|
||||
throw x.syntaxError("Mismatched '" + tagName + "' and '" + closeTag + "'");
|
||||
}
|
||||
tagName = null;
|
||||
if(!arrayForm && newja.length() > 0)
|
||||
{
|
||||
newjo.put("childNodes", newja);
|
||||
}
|
||||
if(ja == null)
|
||||
{
|
||||
if(arrayForm)
|
||||
{
|
||||
return newja;
|
||||
} else
|
||||
{
|
||||
return newjo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
if(ja != null)
|
||||
{
|
||||
ja.put(token instanceof String ? XML.stringToValue((String) token) : token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONArray using the JsonML transform. Each XML tag is represented as a
|
||||
* JSONArray in which the first element is the tag name. If the tag has
|
||||
* attributes, then the second element will be JSONObject containing the
|
||||
* name/value pairs. If the tag contains children, then strings and
|
||||
* JSONArrays will represent the child tags. Comments, prologs, DTDs, and
|
||||
* <code><[ [ ]]></code> are ignored.
|
||||
*
|
||||
* @param string
|
||||
* The source string.
|
||||
* @return A JSONArray containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(String string) throws JSONException
|
||||
{
|
||||
return toJSONArray(new XMLTokener(string));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONArray using the JsonML transform. Each XML tag is represented as a
|
||||
* JSONArray in which the first element is the tag name. If the tag has
|
||||
* attributes, then the second element will be JSONObject containing the
|
||||
* name/value pairs. If the tag contains children, then strings and
|
||||
* JSONArrays will represent the child content and tags. Comments, prologs,
|
||||
* DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
*
|
||||
* @param x
|
||||
* An XMLTokener.
|
||||
* @return A JSONArray containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(XMLTokener x) throws JSONException
|
||||
{
|
||||
return (JSONArray) parse(x, true, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as a
|
||||
* JSONObject with a "tagName" property. If the tag has attributes, then the
|
||||
* attributes will be in the JSONObject as properties. If the tag contains
|
||||
* children, the object will have a "childNodes" property which will be an
|
||||
* array of strings and JsonML JSONObjects.
|
||||
*
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
*
|
||||
* @param x
|
||||
* An XMLTokener of the XML source text.
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(XMLTokener x) throws JSONException
|
||||
{
|
||||
return (JSONObject) parse(x, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as a
|
||||
* JSONObject with a "tagName" property. If the tag has attributes, then the
|
||||
* attributes will be in the JSONObject as properties. If the tag contains
|
||||
* children, the object will have a "childNodes" property which will be an
|
||||
* array of strings and JsonML JSONObjects.
|
||||
*
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
*
|
||||
* @param string
|
||||
* The XML source text.
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string) throws JSONException
|
||||
{
|
||||
return toJSONObject(new XMLTokener(string));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the JSONML transformation, making an XML text from a JSONArray.
|
||||
*
|
||||
* @param ja
|
||||
* A JSONArray.
|
||||
* @return An XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONArray ja) throws JSONException
|
||||
{
|
||||
int i;
|
||||
JSONObject jo;
|
||||
String key;
|
||||
Iterator<String> keys;
|
||||
int length;
|
||||
Object object;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String tagName;
|
||||
String value;
|
||||
|
||||
// Emit <tagName
|
||||
|
||||
tagName = ja.getString(0);
|
||||
XML.noSpace(tagName);
|
||||
tagName = XML.escape(tagName);
|
||||
sb.append('<');
|
||||
sb.append(tagName);
|
||||
|
||||
object = ja.opt(1);
|
||||
if(object instanceof JSONObject)
|
||||
{
|
||||
i = 2;
|
||||
jo = (JSONObject) object;
|
||||
|
||||
// Emit the attributes
|
||||
|
||||
keys = jo.keys();
|
||||
while(keys.hasNext())
|
||||
{
|
||||
key = keys.next();
|
||||
XML.noSpace(key);
|
||||
value = jo.optString(key);
|
||||
if(value != null)
|
||||
{
|
||||
sb.append(' ');
|
||||
sb.append(XML.escape(key));
|
||||
sb.append('=');
|
||||
sb.append('"');
|
||||
sb.append(XML.escape(value));
|
||||
sb.append('"');
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
i = 1;
|
||||
}
|
||||
|
||||
// Emit content in body
|
||||
|
||||
length = ja.length();
|
||||
if(i >= length)
|
||||
{
|
||||
sb.append('/');
|
||||
sb.append('>');
|
||||
} else
|
||||
{
|
||||
sb.append('>');
|
||||
do
|
||||
{
|
||||
object = ja.get(i);
|
||||
i += 1;
|
||||
if(object != null)
|
||||
{
|
||||
if(object instanceof String)
|
||||
{
|
||||
sb.append(XML.escape(object.toString()));
|
||||
} else if(object instanceof JSONObject)
|
||||
{
|
||||
sb.append(toString((JSONObject) object));
|
||||
} else if(object instanceof JSONArray)
|
||||
{
|
||||
sb.append(toString((JSONArray) object));
|
||||
} else
|
||||
{
|
||||
sb.append(object.toString());
|
||||
}
|
||||
}
|
||||
} while(i < length);
|
||||
sb.append('<');
|
||||
sb.append('/');
|
||||
sb.append(tagName);
|
||||
sb.append('>');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the JSONML transformation, making an XML text from a JSONObject.
|
||||
* The JSONObject must contain a "tagName" property. If it has children,
|
||||
* then it must have a "childNodes" property containing an array of objects.
|
||||
* The other properties are attributes with string values.
|
||||
*
|
||||
* @param jo
|
||||
* A JSONObject.
|
||||
* @return An XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONObject jo) throws JSONException
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i;
|
||||
JSONArray ja;
|
||||
String key;
|
||||
Iterator<String> keys;
|
||||
int length;
|
||||
Object object;
|
||||
String tagName;
|
||||
String value;
|
||||
|
||||
// Emit <tagName
|
||||
|
||||
tagName = jo.optString("tagName");
|
||||
if(tagName == null)
|
||||
{
|
||||
return XML.escape(jo.toString());
|
||||
}
|
||||
XML.noSpace(tagName);
|
||||
tagName = XML.escape(tagName);
|
||||
sb.append('<');
|
||||
sb.append(tagName);
|
||||
|
||||
// Emit the attributes
|
||||
|
||||
keys = jo.keys();
|
||||
while(keys.hasNext())
|
||||
{
|
||||
key = keys.next();
|
||||
if(!"tagName".equals(key) && !"childNodes".equals(key))
|
||||
{
|
||||
XML.noSpace(key);
|
||||
value = jo.optString(key);
|
||||
if(value != null)
|
||||
{
|
||||
sb.append(' ');
|
||||
sb.append(XML.escape(key));
|
||||
sb.append('=');
|
||||
sb.append('"');
|
||||
sb.append(XML.escape(value));
|
||||
sb.append('"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Emit content in body
|
||||
|
||||
ja = jo.optJSONArray("childNodes");
|
||||
if(ja == null)
|
||||
{
|
||||
sb.append('/');
|
||||
sb.append('>');
|
||||
} else
|
||||
{
|
||||
sb.append('>');
|
||||
length = ja.length();
|
||||
for(i = 0; i < length; i += 1)
|
||||
{
|
||||
object = ja.get(i);
|
||||
if(object != null)
|
||||
{
|
||||
if(object instanceof String)
|
||||
{
|
||||
sb.append(XML.escape(object.toString()));
|
||||
} else if(object instanceof JSONObject)
|
||||
{
|
||||
sb.append(toString((JSONObject) object));
|
||||
} else if(object instanceof JSONArray)
|
||||
{
|
||||
sb.append(toString((JSONArray) object));
|
||||
} else
|
||||
{
|
||||
sb.append(object.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
sb.append('<');
|
||||
sb.append('/');
|
||||
sb.append(tagName);
|
||||
sb.append('>');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
2072
json/JSONObject.java
2072
json/JSONObject.java
File diff suppressed because it is too large
Load Diff
@@ -1,21 +0,0 @@
|
||||
package ninja.bytecode.shuriken.json;
|
||||
|
||||
|
||||
/**
|
||||
* The <code>JSONString</code> interface allows a <code>toJSONString()</code>
|
||||
* method so that a class can change the behavior of
|
||||
* <code>JSONObject.toString()</code>, <code>JSONArray.toString()</code>, and
|
||||
* <code>JSONWriter.value(</code>Object<code>)</code>. The
|
||||
* <code>toJSONString</code> method will be used instead of the default behavior
|
||||
* of using the Object's <code>toString()</code> method and quoting the result.
|
||||
*/
|
||||
public interface JSONString
|
||||
{
|
||||
/**
|
||||
* The <code>toJSONString</code> method allows a class to produce its own
|
||||
* JSON serialization.
|
||||
*
|
||||
* @return A strictly syntactically correct JSON text.
|
||||
*/
|
||||
public String toJSONString();
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package ninja.bytecode.shuriken.json;
|
||||
|
||||
|
||||
/*
|
||||
Copyright (c) 2006 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* JSONStringer provides a quick and convenient way of producing JSON text. The
|
||||
* texts produced strictly conform to JSON syntax rules. No whitespace is added,
|
||||
* so the results are ready for transmission or storage. Each instance of
|
||||
* JSONStringer can produce one JSON text.
|
||||
* <p>
|
||||
* A JSONStringer instance provides a <code>value</code> method for appending
|
||||
* values to the text, and a <code>key</code> method for adding keys before
|
||||
* values in objects. There are <code>array</code> and <code>endArray</code>
|
||||
* methods that make and bound array values, and <code>object</code> and
|
||||
* <code>endObject</code> methods which make and bound object values. All of
|
||||
* these methods return the JSONWriter instance, permitting cascade style. For
|
||||
* example,
|
||||
*
|
||||
* <pre>
|
||||
* myString = new JSONStringer().object().key("JSON").value("Hello, World!").endObject().toString();
|
||||
* </pre>
|
||||
*
|
||||
* which produces the string
|
||||
*
|
||||
* <pre>
|
||||
* {"JSON":"Hello, World!"}
|
||||
* </pre>
|
||||
* <p>
|
||||
* The first method called must be <code>array</code> or <code>object</code>.
|
||||
* There are no methods for adding commas or colons. JSONStringer adds them for
|
||||
* you. Objects and arrays can be nested up to 20 levels deep.
|
||||
* <p>
|
||||
* This can sometimes be easier than using a JSONObject to build a string.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2008-09-18
|
||||
*/
|
||||
public class JSONStringer extends JSONWriter
|
||||
{
|
||||
/**
|
||||
* Make a fresh JSONStringer. It can be used to build one JSON text.
|
||||
*/
|
||||
public JSONStringer()
|
||||
{
|
||||
super(new StringWriter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JSON text. This method is used to obtain the product of the
|
||||
* JSONStringer instance. It will return <code>null</code> if there was a
|
||||
* problem in the construction of the JSON text (such as the calls to
|
||||
* <code>array</code> were not properly balanced with calls to
|
||||
* <code>endArray</code>).
|
||||
*
|
||||
* @return The JSON text.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return this.mode == 'd' ? this.writer.toString() : null;
|
||||
}
|
||||
}
|
||||
@@ -1,504 +0,0 @@
|
||||
package ninja.bytecode.shuriken.json;
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A JSONTokener takes a source string and extracts characters and tokens from
|
||||
* it. It is used by the JSONObject and JSONArray constructors to parse JSON
|
||||
* source strings.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONTokener
|
||||
{
|
||||
|
||||
private long character;
|
||||
private boolean eof;
|
||||
private long index;
|
||||
private long line;
|
||||
private char previous;
|
||||
private Reader reader;
|
||||
private boolean usePrevious;
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from a Reader.
|
||||
*
|
||||
* @param reader
|
||||
* A reader.
|
||||
*/
|
||||
public JSONTokener(Reader reader)
|
||||
{
|
||||
this.reader = reader.markSupported() ? reader : new BufferedReader(reader);
|
||||
this.eof = false;
|
||||
this.usePrevious = false;
|
||||
this.previous = 0;
|
||||
this.index = 0;
|
||||
this.character = 1;
|
||||
this.line = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from an InputStream.
|
||||
*
|
||||
* @param inputStream
|
||||
* The source.
|
||||
*/
|
||||
public JSONTokener(InputStream inputStream) throws JSONException
|
||||
{
|
||||
this(new InputStreamReader(inputStream));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from a string.
|
||||
*
|
||||
* @param s
|
||||
* A source string.
|
||||
*/
|
||||
public JSONTokener(String s)
|
||||
{
|
||||
this(new StringReader(s));
|
||||
}
|
||||
|
||||
/**
|
||||
* Back up one character. This provides a sort of lookahead capability, so
|
||||
* that you can test for a digit or letter before attempting to parse the
|
||||
* next number or identifier.
|
||||
*/
|
||||
public void back() throws JSONException
|
||||
{
|
||||
if(this.usePrevious || this.index <= 0)
|
||||
{
|
||||
throw new JSONException("Stepping back two steps is not supported");
|
||||
}
|
||||
this.index -= 1;
|
||||
this.character -= 1;
|
||||
this.usePrevious = true;
|
||||
this.eof = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hex value of a character (base16).
|
||||
*
|
||||
* @param c
|
||||
* A character between '0' and '9' or between 'A' and 'F' or
|
||||
* between 'a' and 'f'.
|
||||
* @return An int between 0 and 15, or -1 if c was not a hex digit.
|
||||
*/
|
||||
public static int dehexchar(char c)
|
||||
{
|
||||
if(c >= '0' && c <= '9')
|
||||
{
|
||||
return c - '0';
|
||||
}
|
||||
if(c >= 'A' && c <= 'F')
|
||||
{
|
||||
return c - ('A' - 10);
|
||||
}
|
||||
if(c >= 'a' && c <= 'f')
|
||||
{
|
||||
return c - ('a' - 10);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public boolean end()
|
||||
{
|
||||
return this.eof && !this.usePrevious;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the source string still contains characters that next() can
|
||||
* consume.
|
||||
*
|
||||
* @return true if not yet at the end of the source.
|
||||
*/
|
||||
public boolean more() throws JSONException
|
||||
{
|
||||
this.next();
|
||||
if(this.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
this.back();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next character in the source string.
|
||||
*
|
||||
* @return The next character, or 0 if past the end of the source string.
|
||||
*/
|
||||
public char next() throws JSONException
|
||||
{
|
||||
int c;
|
||||
if(this.usePrevious)
|
||||
{
|
||||
this.usePrevious = false;
|
||||
c = this.previous;
|
||||
} else
|
||||
{
|
||||
try
|
||||
{
|
||||
c = this.reader.read();
|
||||
} catch(IOException exception)
|
||||
{
|
||||
throw new JSONException(exception);
|
||||
}
|
||||
|
||||
if(c <= 0)
|
||||
{ // End of stream
|
||||
this.eof = true;
|
||||
c = 0;
|
||||
}
|
||||
}
|
||||
this.index += 1;
|
||||
if(this.previous == '\r')
|
||||
{
|
||||
this.line += 1;
|
||||
this.character = c == '\n' ? 0 : 1;
|
||||
} else if(c == '\n')
|
||||
{
|
||||
this.line += 1;
|
||||
this.character = 0;
|
||||
} else
|
||||
{
|
||||
this.character += 1;
|
||||
}
|
||||
this.previous = (char) c;
|
||||
return this.previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume the next character, and check that it matches a specified
|
||||
* character.
|
||||
*
|
||||
* @param c
|
||||
* The character to match.
|
||||
* @return The character.
|
||||
* @throws JSONException
|
||||
* if the character does not match.
|
||||
*/
|
||||
public char next(char c) throws JSONException
|
||||
{
|
||||
char n = this.next();
|
||||
if(n != c)
|
||||
{
|
||||
throw this.syntaxError("Expected '" + c + "' and instead saw '" + n + "'");
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next n characters.
|
||||
*
|
||||
* @param n
|
||||
* The number of characters to take.
|
||||
* @return A string of n characters.
|
||||
* @throws JSONException
|
||||
* Substring bounds error if there are not n characters
|
||||
* remaining in the source string.
|
||||
*/
|
||||
public String next(int n) throws JSONException
|
||||
{
|
||||
if(n == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
char[] chars = new char[n];
|
||||
int pos = 0;
|
||||
|
||||
while(pos < n)
|
||||
{
|
||||
chars[pos] = this.next();
|
||||
if(this.end())
|
||||
{
|
||||
throw this.syntaxError("Substring bounds error");
|
||||
}
|
||||
pos += 1;
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next char in the string, skipping whitespace.
|
||||
*
|
||||
* @throws JSONException
|
||||
* @return A character, or 0 if there are no more characters.
|
||||
*/
|
||||
public char nextClean() throws JSONException
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
char c = this.next();
|
||||
if(c == 0 || c > ' ')
|
||||
{
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the characters up to the next close quote character. Backslash
|
||||
* processing is done. The formal JSON format does not allow strings in
|
||||
* single quotes, but an implementation is allowed to accept them.
|
||||
*
|
||||
* @param quote
|
||||
* The quoting character, either <code>"</code>
|
||||
* <small>(double quote)</small> or <code>'</code>
|
||||
* <small>(single quote)</small>.
|
||||
* @return A String.
|
||||
* @throws JSONException
|
||||
* Unterminated string.
|
||||
*/
|
||||
public String nextString(char quote) throws JSONException
|
||||
{
|
||||
char c;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(;;)
|
||||
{
|
||||
c = this.next();
|
||||
switch(c)
|
||||
{
|
||||
case 0:
|
||||
case '\n':
|
||||
case '\r':
|
||||
throw this.syntaxError("Unterminated string");
|
||||
case '\\':
|
||||
c = this.next();
|
||||
switch(c)
|
||||
{
|
||||
case 'b':
|
||||
sb.append('\b');
|
||||
break;
|
||||
case 't':
|
||||
sb.append('\t');
|
||||
break;
|
||||
case 'n':
|
||||
sb.append('\n');
|
||||
break;
|
||||
case 'f':
|
||||
sb.append('\f');
|
||||
break;
|
||||
case 'r':
|
||||
sb.append('\r');
|
||||
break;
|
||||
case 'u':
|
||||
sb.append((char) Integer.parseInt(this.next(4), 16));
|
||||
break;
|
||||
case '"':
|
||||
case '\'':
|
||||
case '\\':
|
||||
case '/':
|
||||
sb.append(c);
|
||||
break;
|
||||
default:
|
||||
throw this.syntaxError("Illegal escape.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if(c == quote)
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text up but not including the specified character or the end of
|
||||
* line, whichever comes first.
|
||||
*
|
||||
* @param delimiter
|
||||
* A delimiter character.
|
||||
* @return A string.
|
||||
*/
|
||||
public String nextTo(char delimiter) throws JSONException
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(;;)
|
||||
{
|
||||
char c = this.next();
|
||||
if(c == delimiter || c == 0 || c == '\n' || c == '\r')
|
||||
{
|
||||
if(c != 0)
|
||||
{
|
||||
this.back();
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text up but not including one of the specified delimiter
|
||||
* characters or the end of line, whichever comes first.
|
||||
*
|
||||
* @param delimiters
|
||||
* A set of delimiter characters.
|
||||
* @return A string, trimmed.
|
||||
*/
|
||||
public String nextTo(String delimiters) throws JSONException
|
||||
{
|
||||
char c;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(;;)
|
||||
{
|
||||
c = this.next();
|
||||
if(delimiters.indexOf(c) >= 0 || c == 0 || c == '\n' || c == '\r')
|
||||
{
|
||||
if(c != 0)
|
||||
{
|
||||
this.back();
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next value. The value can be a Boolean, Double, Integer,
|
||||
* JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
|
||||
*
|
||||
* @throws JSONException
|
||||
* If syntax error.
|
||||
*
|
||||
* @return An object.
|
||||
*/
|
||||
public Object nextValue() throws JSONException
|
||||
{
|
||||
char c = this.nextClean();
|
||||
String string;
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case '"':
|
||||
case '\'':
|
||||
return this.nextString(c);
|
||||
case '{':
|
||||
this.back();
|
||||
return new JSONObject(this);
|
||||
case '[':
|
||||
this.back();
|
||||
return new JSONArray(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle unquoted text. This could be the values true, false, or null,
|
||||
* or it can be a number. An implementation (such as this one) is
|
||||
* allowed to also accept non-standard forms.
|
||||
*
|
||||
* Accumulate characters until we reach the end of the text or a
|
||||
* formatting character.
|
||||
*/
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while(c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0)
|
||||
{
|
||||
sb.append(c);
|
||||
c = this.next();
|
||||
}
|
||||
this.back();
|
||||
|
||||
string = sb.toString().trim();
|
||||
if("".equals(string))
|
||||
{
|
||||
throw this.syntaxError("Missing value");
|
||||
}
|
||||
return JSONObject.stringToValue(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip characters until the next character is the requested character. If
|
||||
* the requested character is not found, no characters are skipped.
|
||||
*
|
||||
* @param to
|
||||
* A character to skip to.
|
||||
* @return The requested character, or zero if the requested character is
|
||||
* not found.
|
||||
*/
|
||||
public char skipTo(char to) throws JSONException
|
||||
{
|
||||
char c;
|
||||
try
|
||||
{
|
||||
long startIndex = this.index;
|
||||
long startCharacter = this.character;
|
||||
long startLine = this.line;
|
||||
this.reader.mark(1000000);
|
||||
do
|
||||
{
|
||||
c = this.next();
|
||||
if(c == 0)
|
||||
{
|
||||
this.reader.reset();
|
||||
this.index = startIndex;
|
||||
this.character = startCharacter;
|
||||
this.line = startLine;
|
||||
return c;
|
||||
}
|
||||
} while(c != to);
|
||||
} catch(IOException exception)
|
||||
{
|
||||
throw new JSONException(exception);
|
||||
}
|
||||
this.back();
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a JSONException to signal a syntax error.
|
||||
*
|
||||
* @param message
|
||||
* The error message.
|
||||
* @return A JSONException object, suitable for throwing
|
||||
*/
|
||||
public JSONException syntaxError(String message)
|
||||
{
|
||||
return new JSONException(message + this.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a printable string of this JSONTokener.
|
||||
*
|
||||
* @return " at {index} [character {character} line {line}]"
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return " at " + this.index + " [character " + this.character + " line " + this.line + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,388 +0,0 @@
|
||||
package ninja.bytecode.shuriken.json;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
/*
|
||||
Copyright (c) 2006 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JSONWriter provides a quick and convenient way of producing JSON text. The
|
||||
* texts produced strictly conform to JSON syntax rules. No whitespace is added,
|
||||
* so the results are ready for transmission or storage. Each instance of
|
||||
* JSONWriter can produce one JSON text.
|
||||
* <p>
|
||||
* A JSONWriter instance provides a <code>value</code> method for appending
|
||||
* values to the text, and a <code>key</code> method for adding keys before
|
||||
* values in objects. There are <code>array</code> and <code>endArray</code>
|
||||
* methods that make and bound array values, and <code>object</code> and
|
||||
* <code>endObject</code> methods which make and bound object values. All of
|
||||
* these methods return the JSONWriter instance, permitting a cascade style. For
|
||||
* example,
|
||||
*
|
||||
* <pre>
|
||||
* new JSONWriter(myWriter).object().key("JSON").value("Hello, World!").endObject();
|
||||
* </pre>
|
||||
*
|
||||
* which writes
|
||||
*
|
||||
* <pre>
|
||||
* {"JSON":"Hello, World!"}
|
||||
* </pre>
|
||||
* <p>
|
||||
* The first method called must be <code>array</code> or <code>object</code>.
|
||||
* There are no methods for adding commas or colons. JSONWriter adds them for
|
||||
* you. Objects and arrays can be nested up to 20 levels deep.
|
||||
* <p>
|
||||
* This can sometimes be easier than using a JSONObject to build a string.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2011-11-24
|
||||
*/
|
||||
public class JSONWriter
|
||||
{
|
||||
private static final int maxdepth = 200;
|
||||
|
||||
/**
|
||||
* The comma flag determines if a comma should be output before the next
|
||||
* value.
|
||||
*/
|
||||
private boolean comma;
|
||||
|
||||
/**
|
||||
* The current mode. Values: 'a' (array), 'd' (done), 'i' (initial), 'k'
|
||||
* (key), 'o' (object).
|
||||
*/
|
||||
protected char mode;
|
||||
|
||||
/**
|
||||
* The object/array stack.
|
||||
*/
|
||||
private final JSONObject stack[];
|
||||
|
||||
/**
|
||||
* The stack top index. A value of 0 indicates that the stack is empty.
|
||||
*/
|
||||
private int top;
|
||||
|
||||
/**
|
||||
* The writer that will receive the output.
|
||||
*/
|
||||
protected Writer writer;
|
||||
|
||||
/**
|
||||
* Make a fresh JSONWriter. It can be used to build one JSON text.
|
||||
*/
|
||||
public JSONWriter(Writer w)
|
||||
{
|
||||
this.comma = false;
|
||||
this.mode = 'i';
|
||||
this.stack = new JSONObject[maxdepth];
|
||||
this.top = 0;
|
||||
this.writer = w;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a value.
|
||||
*
|
||||
* @param string
|
||||
* A string value.
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
* If the value is out of sequence.
|
||||
*/
|
||||
private JSONWriter append(String string) throws JSONException
|
||||
{
|
||||
if(string == null)
|
||||
{
|
||||
throw new JSONException("Null pointer");
|
||||
}
|
||||
if(this.mode == 'o' || this.mode == 'a')
|
||||
{
|
||||
try
|
||||
{
|
||||
if(this.comma && this.mode == 'a')
|
||||
{
|
||||
this.writer.write(',');
|
||||
}
|
||||
this.writer.write(string);
|
||||
} catch(IOException e)
|
||||
{
|
||||
throw new JSONException(e);
|
||||
}
|
||||
if(this.mode == 'o')
|
||||
{
|
||||
this.mode = 'k';
|
||||
}
|
||||
this.comma = true;
|
||||
return this;
|
||||
}
|
||||
throw new JSONException("Value out of sequence.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin appending a new array. All values until the balancing
|
||||
* <code>endArray</code> will be appended to this array. The
|
||||
* <code>endArray</code> method must be called to mark the array's end.
|
||||
*
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
* If the nesting is too deep, or if the object is started in
|
||||
* the wrong place (for example as a key or after the end of the
|
||||
* outermost array or object).
|
||||
*/
|
||||
public JSONWriter array() throws JSONException
|
||||
{
|
||||
if(this.mode == 'i' || this.mode == 'o' || this.mode == 'a')
|
||||
{
|
||||
this.push(null);
|
||||
this.append("[");
|
||||
this.comma = false;
|
||||
return this;
|
||||
}
|
||||
throw new JSONException("Misplaced array.");
|
||||
}
|
||||
|
||||
/**
|
||||
* End something.
|
||||
*
|
||||
* @param mode
|
||||
* Mode
|
||||
* @param c
|
||||
* Closing character
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
* If unbalanced.
|
||||
*/
|
||||
private JSONWriter end(char mode, char c) throws JSONException
|
||||
{
|
||||
if(this.mode != mode)
|
||||
{
|
||||
throw new JSONException(mode == 'a' ? "Misplaced endArray." : "Misplaced endObject.");
|
||||
}
|
||||
this.pop(mode);
|
||||
try
|
||||
{
|
||||
this.writer.write(c);
|
||||
} catch(IOException e)
|
||||
{
|
||||
throw new JSONException(e);
|
||||
}
|
||||
this.comma = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* End an array. This method most be called to balance calls to
|
||||
* <code>array</code>.
|
||||
*
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
* If incorrectly nested.
|
||||
*/
|
||||
public JSONWriter endArray() throws JSONException
|
||||
{
|
||||
return this.end('a', ']');
|
||||
}
|
||||
|
||||
/**
|
||||
* End an object. This method most be called to balance calls to
|
||||
* <code>object</code>.
|
||||
*
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
* If incorrectly nested.
|
||||
*/
|
||||
public JSONWriter endObject() throws JSONException
|
||||
{
|
||||
return this.end('k', '}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a key. The key will be associated with the next value. In an
|
||||
* object, every value must be preceded by a key.
|
||||
*
|
||||
* @param string
|
||||
* A key string.
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
* If the key is out of place. For example, keys do not belong
|
||||
* in arrays or if the key is null.
|
||||
*/
|
||||
public JSONWriter key(String string) throws JSONException
|
||||
{
|
||||
if(string == null)
|
||||
{
|
||||
throw new JSONException("Null key.");
|
||||
}
|
||||
if(this.mode == 'k')
|
||||
{
|
||||
try
|
||||
{
|
||||
this.stack[this.top - 1].putOnce(string, Boolean.TRUE);
|
||||
if(this.comma)
|
||||
{
|
||||
this.writer.write(',');
|
||||
}
|
||||
this.writer.write(JSONObject.quote(string));
|
||||
this.writer.write(':');
|
||||
this.comma = false;
|
||||
this.mode = 'o';
|
||||
return this;
|
||||
} catch(IOException e)
|
||||
{
|
||||
throw new JSONException(e);
|
||||
}
|
||||
}
|
||||
throw new JSONException("Misplaced key.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin appending a new object. All keys and values until the balancing
|
||||
* <code>endObject</code> will be appended to this object. The
|
||||
* <code>endObject</code> method must be called to mark the object's end.
|
||||
*
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
* If the nesting is too deep, or if the object is started in
|
||||
* the wrong place (for example as a key or after the end of the
|
||||
* outermost array or object).
|
||||
*/
|
||||
public JSONWriter object() throws JSONException
|
||||
{
|
||||
if(this.mode == 'i')
|
||||
{
|
||||
this.mode = 'o';
|
||||
}
|
||||
if(this.mode == 'o' || this.mode == 'a')
|
||||
{
|
||||
this.append("{");
|
||||
this.push(new JSONObject());
|
||||
this.comma = false;
|
||||
return this;
|
||||
}
|
||||
throw new JSONException("Misplaced object.");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop an array or object scope.
|
||||
*
|
||||
* @param c
|
||||
* The scope to close.
|
||||
* @throws JSONException
|
||||
* If nesting is wrong.
|
||||
*/
|
||||
private void pop(char c) throws JSONException
|
||||
{
|
||||
if(this.top <= 0)
|
||||
{
|
||||
throw new JSONException("Nesting error.");
|
||||
}
|
||||
char m = this.stack[this.top - 1] == null ? 'a' : 'k';
|
||||
if(m != c)
|
||||
{
|
||||
throw new JSONException("Nesting error.");
|
||||
}
|
||||
this.top -= 1;
|
||||
this.mode = this.top == 0 ? 'd' : this.stack[this.top - 1] == null ? 'a' : 'k';
|
||||
}
|
||||
|
||||
/**
|
||||
* Push an array or object scope.
|
||||
*
|
||||
* @param jo
|
||||
* The scope to open.
|
||||
* @throws JSONException
|
||||
* If nesting is too deep.
|
||||
*/
|
||||
private void push(JSONObject jo) throws JSONException
|
||||
{
|
||||
if(this.top >= maxdepth)
|
||||
{
|
||||
throw new JSONException("Nesting too deep.");
|
||||
}
|
||||
this.stack[this.top] = jo;
|
||||
this.mode = jo == null ? 'a' : 'k';
|
||||
this.top += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append either the value <code>true</code> or the value <code>false</code>
|
||||
* .
|
||||
*
|
||||
* @param b
|
||||
* A boolean.
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
*/
|
||||
public JSONWriter value(boolean b) throws JSONException
|
||||
{
|
||||
return this.append(b ? "true" : "false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a double value.
|
||||
*
|
||||
* @param d
|
||||
* A double.
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
* If the number is not finite.
|
||||
*/
|
||||
public JSONWriter value(double d) throws JSONException
|
||||
{
|
||||
return this.value(new Double(d));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a long value.
|
||||
*
|
||||
* @param l
|
||||
* A long.
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
*/
|
||||
public JSONWriter value(long l) throws JSONException
|
||||
{
|
||||
return this.append(Long.toString(l));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an object value.
|
||||
*
|
||||
* @param object
|
||||
* The object to append. It can be null, or a Boolean, Number,
|
||||
* String, JSONObject, or JSONArray, or an object that implements
|
||||
* JSONString.
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
* If the value is out of sequence.
|
||||
*/
|
||||
public JSONWriter value(Object object) throws JSONException
|
||||
{
|
||||
return this.append(JSONObject.valueToString(object));
|
||||
}
|
||||
}
|
||||
584
json/XML.java
584
json/XML.java
@@ -1,584 +0,0 @@
|
||||
package ninja.bytecode.shuriken.json;
|
||||
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* This provides static methods to convert an XML text into a JSONObject, and to
|
||||
* covert a JSONObject into an XML text.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class XML
|
||||
{
|
||||
|
||||
/** The Character '&'. */
|
||||
public static final Character AMP = '&';
|
||||
|
||||
/** The Character '''. */
|
||||
public static final Character APOS = '\'';
|
||||
|
||||
/** The Character '!'. */
|
||||
public static final Character BANG = '!';
|
||||
|
||||
/** The Character '='. */
|
||||
public static final Character EQ = '=';
|
||||
|
||||
/** The Character '>'. */
|
||||
public static final Character GT = '>';
|
||||
|
||||
/** The Character '<'. */
|
||||
public static final Character LT = '<';
|
||||
|
||||
/** The Character '?'. */
|
||||
public static final Character QUEST = '?';
|
||||
|
||||
/** The Character '"'. */
|
||||
public static final Character QUOT = '"';
|
||||
|
||||
/** The Character '/'. */
|
||||
public static final Character SLASH = '/';
|
||||
|
||||
/**
|
||||
* Replace special characters with XML escapes:
|
||||
*
|
||||
* <pre>
|
||||
* & <small>(ampersand)</small> is replaced by &amp;
|
||||
* < <small>(less than)</small> is replaced by &lt;
|
||||
* > <small>(greater than)</small> is replaced by &gt;
|
||||
* " <small>(double quote)</small> is replaced by &quot;
|
||||
* </pre>
|
||||
*
|
||||
* @param string
|
||||
* The string to be escaped.
|
||||
* @return The escaped string.
|
||||
*/
|
||||
public static String escape(String string)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(string.length());
|
||||
for(int i = 0, length = string.length(); i < length; i++)
|
||||
{
|
||||
char c = string.charAt(i);
|
||||
switch(c)
|
||||
{
|
||||
case '&':
|
||||
sb.append("&");
|
||||
break;
|
||||
case '<':
|
||||
sb.append("<");
|
||||
break;
|
||||
case '>':
|
||||
sb.append(">");
|
||||
break;
|
||||
case '"':
|
||||
sb.append(""");
|
||||
break;
|
||||
case '\'':
|
||||
sb.append("'");
|
||||
break;
|
||||
default:
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an exception if the string contains whitespace. Whitespace is not
|
||||
* allowed in tagNames and attributes.
|
||||
*
|
||||
* @param string
|
||||
* A string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static void noSpace(String string) throws JSONException
|
||||
{
|
||||
int i, length = string.length();
|
||||
if(length == 0)
|
||||
{
|
||||
throw new JSONException("Empty string.");
|
||||
}
|
||||
for(i = 0; i < length; i += 1)
|
||||
{
|
||||
if(Character.isWhitespace(string.charAt(i)))
|
||||
{
|
||||
throw new JSONException("'" + string + "' contains a space character.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan the content following the named tag, attaching it to the context.
|
||||
*
|
||||
* @param x
|
||||
* The XMLTokener containing the source string.
|
||||
* @param context
|
||||
* The JSONObject that will include the new material.
|
||||
* @param name
|
||||
* The tag name.
|
||||
* @return true if the close tag is processed.
|
||||
* @throws JSONException
|
||||
*/
|
||||
private static boolean parse(XMLTokener x, JSONObject context, String name) throws JSONException
|
||||
{
|
||||
char c;
|
||||
int i;
|
||||
JSONObject jsonobject = null;
|
||||
String string;
|
||||
String tagName;
|
||||
Object token;
|
||||
|
||||
// Test for and skip past these forms:
|
||||
// <!-- ... -->
|
||||
// <! ... >
|
||||
// <![ ... ]]>
|
||||
// <? ... ?>
|
||||
// Report errors for these forms:
|
||||
// <>
|
||||
// <=
|
||||
// <<
|
||||
|
||||
token = x.nextToken();
|
||||
|
||||
// <!
|
||||
|
||||
if(token == BANG)
|
||||
{
|
||||
c = x.next();
|
||||
if(c == '-')
|
||||
{
|
||||
if(x.next() == '-')
|
||||
{
|
||||
x.skipPast("-->");
|
||||
return false;
|
||||
}
|
||||
x.back();
|
||||
} else if(c == '[')
|
||||
{
|
||||
token = x.nextToken();
|
||||
if("CDATA".equals(token))
|
||||
{
|
||||
if(x.next() == '[')
|
||||
{
|
||||
string = x.nextCDATA();
|
||||
if(string.length() > 0)
|
||||
{
|
||||
context.accumulate("content", string);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
throw x.syntaxError("Expected 'CDATA['");
|
||||
}
|
||||
i = 1;
|
||||
do
|
||||
{
|
||||
token = x.nextMeta();
|
||||
if(token == null)
|
||||
{
|
||||
throw x.syntaxError("Missing '>' after '<!'.");
|
||||
} else if(token == LT)
|
||||
{
|
||||
i += 1;
|
||||
} else if(token == GT)
|
||||
{
|
||||
i -= 1;
|
||||
}
|
||||
} while(i > 0);
|
||||
return false;
|
||||
} else if(token == QUEST)
|
||||
{
|
||||
|
||||
// <?
|
||||
|
||||
x.skipPast("?>");
|
||||
return false;
|
||||
} else if(token == SLASH)
|
||||
{
|
||||
|
||||
// Close tag </
|
||||
|
||||
token = x.nextToken();
|
||||
if(name == null)
|
||||
{
|
||||
throw x.syntaxError("Mismatched close tag " + token);
|
||||
}
|
||||
if(!token.equals(name))
|
||||
{
|
||||
throw x.syntaxError("Mismatched " + name + " and " + token);
|
||||
}
|
||||
if(x.nextToken() != GT)
|
||||
{
|
||||
throw x.syntaxError("Misshaped close tag");
|
||||
}
|
||||
return true;
|
||||
|
||||
} else if(token instanceof Character)
|
||||
{
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
|
||||
// Open tag <
|
||||
|
||||
} else
|
||||
{
|
||||
tagName = (String) token;
|
||||
token = null;
|
||||
jsonobject = new JSONObject();
|
||||
for(;;)
|
||||
{
|
||||
if(token == null)
|
||||
{
|
||||
token = x.nextToken();
|
||||
}
|
||||
|
||||
// attribute = value
|
||||
|
||||
if(token instanceof String)
|
||||
{
|
||||
string = (String) token;
|
||||
token = x.nextToken();
|
||||
if(token == EQ)
|
||||
{
|
||||
token = x.nextToken();
|
||||
if(!(token instanceof String))
|
||||
{
|
||||
throw x.syntaxError("Missing value");
|
||||
}
|
||||
jsonobject.accumulate(string, XML.stringToValue((String) token));
|
||||
token = null;
|
||||
} else
|
||||
{
|
||||
jsonobject.accumulate(string, "");
|
||||
}
|
||||
|
||||
// Empty tag <.../>
|
||||
|
||||
} else if(token == SLASH)
|
||||
{
|
||||
if(x.nextToken() != GT)
|
||||
{
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
if(jsonobject.length() > 0)
|
||||
{
|
||||
context.accumulate(tagName, jsonobject);
|
||||
} else
|
||||
{
|
||||
context.accumulate(tagName, "");
|
||||
}
|
||||
return false;
|
||||
|
||||
// Content, between <...> and </...>
|
||||
|
||||
} else if(token == GT)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
token = x.nextContent();
|
||||
if(token == null)
|
||||
{
|
||||
if(tagName != null)
|
||||
{
|
||||
throw x.syntaxError("Unclosed tag " + tagName);
|
||||
}
|
||||
return false;
|
||||
} else if(token instanceof String)
|
||||
{
|
||||
string = (String) token;
|
||||
if(string.length() > 0)
|
||||
{
|
||||
jsonobject.accumulate("content", XML.stringToValue(string));
|
||||
}
|
||||
|
||||
// Nested element
|
||||
|
||||
} else if(token == LT)
|
||||
{
|
||||
if(parse(x, jsonobject, tagName))
|
||||
{
|
||||
if(jsonobject.length() == 0)
|
||||
{
|
||||
context.accumulate(tagName, "");
|
||||
} else if(jsonobject.length() == 1 && jsonobject.opt("content") != null)
|
||||
{
|
||||
context.accumulate(tagName, jsonobject.opt("content"));
|
||||
} else
|
||||
{
|
||||
context.accumulate(tagName, jsonobject);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to convert a string into a number, boolean, or null. If the string
|
||||
* can't be converted, return the string. This is much less ambitious than
|
||||
* JSONObject.stringToValue, especially because it does not attempt to
|
||||
* convert plus forms, octal forms, hex forms, or E forms lacking decimal
|
||||
* points.
|
||||
*
|
||||
* @param string
|
||||
* A String.
|
||||
* @return A simple JSON value.
|
||||
*/
|
||||
public static Object stringToValue(String string)
|
||||
{
|
||||
if("true".equalsIgnoreCase(string))
|
||||
{
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
if("false".equalsIgnoreCase(string))
|
||||
{
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
if("null".equalsIgnoreCase(string))
|
||||
{
|
||||
return JSONObject.NULL;
|
||||
}
|
||||
|
||||
// If it might be a number, try converting it, first as a Long, and then
|
||||
// as a
|
||||
// Double. If that doesn't work, return the string.
|
||||
|
||||
try
|
||||
{
|
||||
char initial = string.charAt(0);
|
||||
if(initial == '-' || (initial >= '0' && initial <= '9'))
|
||||
{
|
||||
Long value = new Long(string);
|
||||
if(value.toString().equals(string))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
} catch(Exception ignore)
|
||||
{
|
||||
try
|
||||
{
|
||||
Double value = new Double(string);
|
||||
if(value.toString().equals(string))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
} catch(Exception ignoreAlso)
|
||||
{
|
||||
}
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject. Some information may be lost in this transformation because
|
||||
* JSON is a data format and XML is a document format. XML uses elements,
|
||||
* attributes, and content text, while JSON uses unordered collections of
|
||||
* name/value pairs and arrays of values. JSON does not does not like to
|
||||
* distinguish between elements and attributes. Sequences of similar
|
||||
* elements are represented as JSONArrays. Content text may be placed in a
|
||||
* "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
|
||||
* are ignored.
|
||||
*
|
||||
* @param string
|
||||
* The source string.
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string) throws JSONException
|
||||
{
|
||||
JSONObject jo = new JSONObject();
|
||||
XMLTokener x = new XMLTokener(string);
|
||||
while(x.more() && x.skipPast("<"))
|
||||
{
|
||||
parse(x, jo, null);
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into a well-formed, element-normal XML string.
|
||||
*
|
||||
* @param object
|
||||
* A JSONObject.
|
||||
* @return A string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(Object object) throws JSONException
|
||||
{
|
||||
return toString(object, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into a well-formed, element-normal XML string.
|
||||
*
|
||||
* @param object
|
||||
* A JSONObject.
|
||||
* @param tagName
|
||||
* The optional name of the enclosing tag.
|
||||
* @return A string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(Object object, String tagName) throws JSONException
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i;
|
||||
JSONArray ja;
|
||||
JSONObject jo;
|
||||
String key;
|
||||
Iterator<String> keys;
|
||||
int length;
|
||||
String string;
|
||||
Object value;
|
||||
if(object instanceof JSONObject)
|
||||
{
|
||||
|
||||
// Emit <tagName>
|
||||
|
||||
if(tagName != null)
|
||||
{
|
||||
sb.append('<');
|
||||
sb.append(tagName);
|
||||
sb.append('>');
|
||||
}
|
||||
|
||||
// Loop thru the keys.
|
||||
|
||||
jo = (JSONObject) object;
|
||||
keys = jo.keys();
|
||||
while(keys.hasNext())
|
||||
{
|
||||
key = keys.next();
|
||||
value = jo.opt(key);
|
||||
if(value == null)
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
string = value instanceof String ? (String) value : null;
|
||||
|
||||
// Emit content in body
|
||||
|
||||
if("content".equals(key))
|
||||
{
|
||||
if(value instanceof JSONArray)
|
||||
{
|
||||
ja = (JSONArray) value;
|
||||
length = ja.length();
|
||||
for(i = 0; i < length; i += 1)
|
||||
{
|
||||
if(i > 0)
|
||||
{
|
||||
sb.append('\n');
|
||||
}
|
||||
sb.append(escape(ja.get(i).toString()));
|
||||
}
|
||||
} else
|
||||
{
|
||||
sb.append(escape(value.toString()));
|
||||
}
|
||||
|
||||
// Emit an array of similar keys
|
||||
|
||||
} else if(value instanceof JSONArray)
|
||||
{
|
||||
ja = (JSONArray) value;
|
||||
length = ja.length();
|
||||
for(i = 0; i < length; i += 1)
|
||||
{
|
||||
value = ja.get(i);
|
||||
if(value instanceof JSONArray)
|
||||
{
|
||||
sb.append('<');
|
||||
sb.append(key);
|
||||
sb.append('>');
|
||||
sb.append(toString(value));
|
||||
sb.append("</");
|
||||
sb.append(key);
|
||||
sb.append('>');
|
||||
} else
|
||||
{
|
||||
sb.append(toString(value, key));
|
||||
}
|
||||
}
|
||||
} else if("".equals(value))
|
||||
{
|
||||
sb.append('<');
|
||||
sb.append(key);
|
||||
sb.append("/>");
|
||||
|
||||
// Emit a new tag <k>
|
||||
|
||||
} else
|
||||
{
|
||||
sb.append(toString(value, key));
|
||||
}
|
||||
}
|
||||
if(tagName != null)
|
||||
{
|
||||
|
||||
// Emit the </tagname> close tag
|
||||
|
||||
sb.append("</");
|
||||
sb.append(tagName);
|
||||
sb.append('>');
|
||||
}
|
||||
return sb.toString();
|
||||
|
||||
// XML does not have good support for arrays. If an array appears in
|
||||
// a place
|
||||
// where XML is lacking, synthesize an <array> element.
|
||||
|
||||
} else
|
||||
{
|
||||
if(object.getClass().isArray())
|
||||
{
|
||||
object = new JSONArray(object);
|
||||
}
|
||||
if(object instanceof JSONArray)
|
||||
{
|
||||
ja = (JSONArray) object;
|
||||
length = ja.length();
|
||||
for(i = 0; i < length; i += 1)
|
||||
{
|
||||
sb.append(toString(ja.opt(i), tagName == null ? "array" : tagName));
|
||||
}
|
||||
return sb.toString();
|
||||
} else
|
||||
{
|
||||
string = (object == null) ? "null" : escape(object.toString());
|
||||
return (tagName == null) ? "\"" + string + "\"" : (string.length() == 0) ? "<" + tagName + "/>" : "<" + tagName + ">" + string + "</" + tagName + ">";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,425 +0,0 @@
|
||||
package ninja.bytecode.shuriken.json;
|
||||
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The XMLTokener extends the JSONTokener to provide additional methods for the
|
||||
* parsing of XML texts.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class XMLTokener extends JSONTokener
|
||||
{
|
||||
|
||||
/**
|
||||
* The table of entity values. It initially contains Character values for
|
||||
* amp, apos, gt, lt, quot.
|
||||
*/
|
||||
public static final java.util.HashMap<String, Character> entity;
|
||||
|
||||
static
|
||||
{
|
||||
entity = new java.util.HashMap<String, Character>(8);
|
||||
entity.put("amp", XML.AMP);
|
||||
entity.put("apos", XML.APOS);
|
||||
entity.put("gt", XML.GT);
|
||||
entity.put("lt", XML.LT);
|
||||
entity.put("quot", XML.QUOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an XMLTokener from a string.
|
||||
*
|
||||
* @param s
|
||||
* A source string.
|
||||
*/
|
||||
public XMLTokener(String s)
|
||||
{
|
||||
super(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text in the CDATA block.
|
||||
*
|
||||
* @return The string up to the <code>]]></code>.
|
||||
* @throws JSONException
|
||||
* If the <code>]]></code> is not found.
|
||||
*/
|
||||
public String nextCDATA() throws JSONException
|
||||
{
|
||||
char c;
|
||||
int i;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(;;)
|
||||
{
|
||||
c = next();
|
||||
if(end())
|
||||
{
|
||||
throw syntaxError("Unclosed CDATA");
|
||||
}
|
||||
sb.append(c);
|
||||
i = sb.length() - 3;
|
||||
if(i >= 0 && sb.charAt(i) == ']' && sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>')
|
||||
{
|
||||
sb.setLength(i);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next XML outer token, trimming whitespace. There are two kinds of
|
||||
* tokens: the '<' character which begins a markup tag, and the content text
|
||||
* between markup tags.
|
||||
*
|
||||
* @return A string, or a '<' Character, or null if there is no more source
|
||||
* text.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public Object nextContent() throws JSONException
|
||||
{
|
||||
char c;
|
||||
StringBuilder sb;
|
||||
do
|
||||
{
|
||||
c = next();
|
||||
} while(Character.isWhitespace(c));
|
||||
if(c == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if(c == '<')
|
||||
{
|
||||
return XML.LT;
|
||||
}
|
||||
sb = new StringBuilder();
|
||||
for(;;)
|
||||
{
|
||||
if(c == '<' || c == 0)
|
||||
{
|
||||
back();
|
||||
return sb.toString().trim();
|
||||
}
|
||||
if(c == '&')
|
||||
{
|
||||
sb.append(nextEntity(c));
|
||||
} else
|
||||
{
|
||||
sb.append(c);
|
||||
}
|
||||
c = next();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the next entity. These entities are translated to Characters:
|
||||
* <code>& ' > < "</code>.
|
||||
*
|
||||
* @param ampersand
|
||||
* An ampersand character.
|
||||
* @return A Character or an entity String if the entity is not recognized.
|
||||
* @throws JSONException
|
||||
* If missing ';' in XML entity.
|
||||
*/
|
||||
public Object nextEntity(char ampersand) throws JSONException
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(;;)
|
||||
{
|
||||
char c = next();
|
||||
if(Character.isLetterOrDigit(c) || c == '#')
|
||||
{
|
||||
sb.append(Character.toLowerCase(c));
|
||||
} else if(c == ';')
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
throw syntaxError("Missing ';' in XML entity: &" + sb);
|
||||
}
|
||||
}
|
||||
String string = sb.toString();
|
||||
Object object = entity.get(string);
|
||||
return object != null ? object : ampersand + string + ";";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next XML meta token. This is used for skipping over
|
||||
* <!...> and <?...?> structures.
|
||||
*
|
||||
* @return Syntax characters (<code>< > / = ! ?</code>) are returned as
|
||||
* Character, and strings and names are returned as Boolean. We
|
||||
* don't care what the values actually are.
|
||||
* @throws JSONException
|
||||
* If a string is not properly closed or if the XML is badly
|
||||
* structured.
|
||||
*/
|
||||
public Object nextMeta() throws JSONException
|
||||
{
|
||||
char c;
|
||||
char q;
|
||||
do
|
||||
{
|
||||
c = next();
|
||||
} while(Character.isWhitespace(c));
|
||||
switch(c)
|
||||
{
|
||||
case 0:
|
||||
throw syntaxError("Misshaped meta tag");
|
||||
case '<':
|
||||
return XML.LT;
|
||||
case '>':
|
||||
return XML.GT;
|
||||
case '/':
|
||||
return XML.SLASH;
|
||||
case '=':
|
||||
return XML.EQ;
|
||||
case '!':
|
||||
return XML.BANG;
|
||||
case '?':
|
||||
return XML.QUEST;
|
||||
case '"':
|
||||
case '\'':
|
||||
q = c;
|
||||
for(;;)
|
||||
{
|
||||
c = next();
|
||||
if(c == 0)
|
||||
{
|
||||
throw syntaxError("Unterminated string");
|
||||
}
|
||||
if(c == q)
|
||||
{
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
default:
|
||||
for(;;)
|
||||
{
|
||||
c = next();
|
||||
if(Character.isWhitespace(c))
|
||||
{
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
switch(c)
|
||||
{
|
||||
case 0:
|
||||
case '<':
|
||||
case '>':
|
||||
case '/':
|
||||
case '=':
|
||||
case '!':
|
||||
case '?':
|
||||
case '"':
|
||||
case '\'':
|
||||
back();
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next XML Token. These tokens are found inside of angle brackets.
|
||||
* It may be one of these characters: <code>/ > = ! ?</code> or it may be a
|
||||
* string wrapped in single quotes or double quotes, or it may be a name.
|
||||
*
|
||||
* @return a String or a Character.
|
||||
* @throws JSONException
|
||||
* If the XML is not well formed.
|
||||
*/
|
||||
public Object nextToken() throws JSONException
|
||||
{
|
||||
char c;
|
||||
char q;
|
||||
StringBuilder sb;
|
||||
do
|
||||
{
|
||||
c = next();
|
||||
} while(Character.isWhitespace(c));
|
||||
switch(c)
|
||||
{
|
||||
case 0:
|
||||
throw syntaxError("Misshaped element");
|
||||
case '<':
|
||||
throw syntaxError("Misplaced '<'");
|
||||
case '>':
|
||||
return XML.GT;
|
||||
case '/':
|
||||
return XML.SLASH;
|
||||
case '=':
|
||||
return XML.EQ;
|
||||
case '!':
|
||||
return XML.BANG;
|
||||
case '?':
|
||||
return XML.QUEST;
|
||||
|
||||
// Quoted string
|
||||
|
||||
case '"':
|
||||
case '\'':
|
||||
q = c;
|
||||
sb = new StringBuilder();
|
||||
for(;;)
|
||||
{
|
||||
c = next();
|
||||
if(c == 0)
|
||||
{
|
||||
throw syntaxError("Unterminated string");
|
||||
}
|
||||
if(c == q)
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
if(c == '&')
|
||||
{
|
||||
sb.append(nextEntity(c));
|
||||
} else
|
||||
{
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
||||
// Name
|
||||
|
||||
sb = new StringBuilder();
|
||||
for(;;)
|
||||
{
|
||||
sb.append(c);
|
||||
c = next();
|
||||
if(Character.isWhitespace(c))
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
switch(c)
|
||||
{
|
||||
case 0:
|
||||
return sb.toString();
|
||||
case '>':
|
||||
case '/':
|
||||
case '=':
|
||||
case '!':
|
||||
case '?':
|
||||
case '[':
|
||||
case ']':
|
||||
back();
|
||||
return sb.toString();
|
||||
case '<':
|
||||
case '"':
|
||||
case '\'':
|
||||
throw syntaxError("Bad character in a name");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip characters until past the requested string. If it is not found, we
|
||||
* are left at the end of the source with a result of false.
|
||||
*
|
||||
* @param to
|
||||
* A string to skip past.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public boolean skipPast(String to) throws JSONException
|
||||
{
|
||||
boolean b;
|
||||
char c;
|
||||
int i;
|
||||
int j;
|
||||
int offset = 0;
|
||||
int length = to.length();
|
||||
char[] circle = new char[length];
|
||||
|
||||
/*
|
||||
* First fill the circle buffer with as many characters as are in the to
|
||||
* string. If we reach an early end, bail.
|
||||
*/
|
||||
|
||||
for(i = 0; i < length; i += 1)
|
||||
{
|
||||
c = next();
|
||||
if(c == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
circle[i] = c;
|
||||
}
|
||||
|
||||
/* We will loop, possibly for all of the remaining characters. */
|
||||
|
||||
for(;;)
|
||||
{
|
||||
j = offset;
|
||||
b = true;
|
||||
|
||||
/* Compare the circle buffer with the to string. */
|
||||
|
||||
for(i = 0; i < length; i += 1)
|
||||
{
|
||||
if(circle[j] != to.charAt(i))
|
||||
{
|
||||
b = false;
|
||||
break;
|
||||
}
|
||||
j += 1;
|
||||
if(j >= length)
|
||||
{
|
||||
j -= length;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we exit the loop with b intact, then victory is ours. */
|
||||
|
||||
if(b)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next character. If there isn't one, then defeat is ours.
|
||||
*/
|
||||
|
||||
c = next();
|
||||
if(c == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* Shove the character in the circle buffer and advance the circle
|
||||
* offset. The offset is mod n.
|
||||
*/
|
||||
circle[offset] = c;
|
||||
offset += 1;
|
||||
if(offset >= length)
|
||||
{
|
||||
offset -= length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,4 +5,6 @@
|
||||
"redstone IrisDimensions/redstone",
|
||||
"mars IrisDimensions/mars",
|
||||
"example IrisDimensions/example"
|
||||
"newhorizons IrisDimensions/newhorizons",
|
||||
"theend IrisDimensions/theend"
|
||||
]
|
||||
|
||||
2
lombok.config
Normal file
2
lombok.config
Normal file
@@ -0,0 +1,2 @@
|
||||
# This file is generated by the 'io.freefair.lombok' Gradle plugin
|
||||
config.stopBubbling = true
|
||||
21
out/production/resources/plugin.yml
Normal file
21
out/production/resources/plugin.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
name: ${name}
|
||||
version: ${version}
|
||||
main: ${main}
|
||||
load: STARTUP
|
||||
authors: [ cyberpwn, NextdoorPsycho ]
|
||||
website: volmit.com
|
||||
description: More than a Dimension!
|
||||
libraries:
|
||||
- org.zeroturnaround:zt-zip:1.14
|
||||
- com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2
|
||||
- org.ow2.asm:asm:9.2
|
||||
- com.google.code.gson:gson:2.8.7
|
||||
- it.unimi.dsi:fastutil:8.5.4
|
||||
- com.google.guava:guava:30.1.1-jre
|
||||
- bsf:bsf:2.4.0
|
||||
- rhino:js:1.7R2
|
||||
commands:
|
||||
iris:
|
||||
aliases: [ ir, irs ]
|
||||
api-version: ${apiversion}
|
||||
hotload-dependencies: false
|
||||
69
plains.json
69
plains.json
@@ -1,69 +0,0 @@
|
||||
{
|
||||
"children": [],
|
||||
"decorators": [],
|
||||
"objects": [],
|
||||
"name": "Plains",
|
||||
"layers": [
|
||||
{
|
||||
"minHeight": 1,
|
||||
"terrainZoom": 5,
|
||||
"maxHeight": 3,
|
||||
"palette": [
|
||||
"GRASS_BLOCK"
|
||||
],
|
||||
"dispersion": "SCATTER"
|
||||
},
|
||||
{
|
||||
"minHeight": 1,
|
||||
"terrainZoom": 5,
|
||||
"maxHeight": 1,
|
||||
"palette": [
|
||||
"DIRT"
|
||||
],
|
||||
"dispersion": "SCATTER"
|
||||
},
|
||||
{
|
||||
"minHeight": 1,
|
||||
"terrainZoom": 5,
|
||||
"maxHeight": 3,
|
||||
"palette": [
|
||||
"DIRT",
|
||||
"COARSE_DIRT"
|
||||
],
|
||||
"dispersion": "SCATTER"
|
||||
},
|
||||
{
|
||||
"minHeight": 6,
|
||||
"terrainZoom": 5,
|
||||
"maxHeight": 2341,
|
||||
"palette": [
|
||||
"STONE",
|
||||
"ANDESITE",
|
||||
"STONE"
|
||||
],
|
||||
"dispersion": "SCATTER"
|
||||
}
|
||||
],
|
||||
"childShrinkFactor": 1.55,
|
||||
"derivative": "THE_VOID",
|
||||
"auxiliaryGenerators": [
|
||||
{
|
||||
"offsetX": 0,
|
||||
"offsetZ": 0.01,
|
||||
"min": 1,
|
||||
"seed": 1336,
|
||||
"max": 5,
|
||||
"zoom": 3.065
|
||||
},
|
||||
{
|
||||
"offsetX": 0,
|
||||
"offsetZ": 0,
|
||||
"min": 1.01,
|
||||
"seed": 1339,
|
||||
"max": 2,
|
||||
"zoom": 1.6
|
||||
}
|
||||
],
|
||||
"highHeight": 3.66669,
|
||||
"lowHeight": 31.5
|
||||
}
|
||||
140
pom.xml
140
pom.xml
@@ -1,140 +0,0 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.volmit</groupId>
|
||||
<artifactId>Iris</artifactId>
|
||||
<version>1.3.3</version>
|
||||
<name>Iris</name>
|
||||
<properties>
|
||||
<skip.copy>false</skip.copy>
|
||||
<secretary.build>package</secretary.build>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
<includes>
|
||||
<include>**/*.xml</include>
|
||||
<include>**/*.yml</include>
|
||||
<include>**/*.txt</include>
|
||||
<include>**/*.properties</include>
|
||||
<include>**/*.json</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<compilerVersion>1.8</compilerVersion>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>volmit</id>
|
||||
<url>http://repo.volmit.com/repository/volmit/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.timeandspace</groupId>
|
||||
<artifactId>smoothie-map</artifactId>
|
||||
<version>2.0.2</version>
|
||||
</dependency>
|
||||
<!-- Spigot API -->
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.16.1-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Paper API -->
|
||||
<dependency>
|
||||
<groupId>io.papermc</groupId>
|
||||
<artifactId>paperlib</artifactId>
|
||||
<version>1.0.5</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- NMS -->
|
||||
<dependency>
|
||||
<groupId>org.bukkit.craftbukkit</groupId>
|
||||
<artifactId>1.16.3</artifactId>
|
||||
<version>1.16.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bukkit.craftbukkit</groupId>
|
||||
<artifactId>1.16.4</artifactId>
|
||||
<version>1.16.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Hooks -->
|
||||
<dependency>
|
||||
<groupId>com.bergerkiller.bukkit</groupId>
|
||||
<artifactId>BKCommonLib</artifactId>
|
||||
<version>1.16.4-v2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sk89q.worldedit</groupId>
|
||||
<artifactId>worldedit-bukkit</artifactId>
|
||||
<version>7.2.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.lumine.xikage</groupId>
|
||||
<artifactId>MythicMobs</artifactId>
|
||||
<version>4.9.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Utilities -->
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
<version>2.8.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.10</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.zeroturnaround</groupId>
|
||||
<artifactId>zt-zip</artifactId>
|
||||
<version>1.14</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
26
settings.gradle
Normal file
26
settings.gradle
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
pluginManagement {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
maven { url "https://dl.cloudsmith.io/public/arcane/archive/maven/" }
|
||||
}
|
||||
}
|
||||
rootProject.name = 'Iris'
|
||||
@@ -1,153 +0,0 @@
|
||||
package com.minelazz.epicworldgenerator.structures;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.object.IrisObject;
|
||||
import com.volmit.iris.util.B;
|
||||
import com.volmit.iris.util.DontObfuscate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.util.BlockVector;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.EnumSet;
|
||||
|
||||
@DontObfuscate
|
||||
public class StructureObject implements Serializable
|
||||
{
|
||||
@DontObfuscate
|
||||
public static final String MESSAGE0 = "This was created from .ewg serialization files";
|
||||
|
||||
@DontObfuscate
|
||||
public static final String MESSAGE1 = "This is not copied code, it is intended to ";
|
||||
|
||||
@DontObfuscate
|
||||
public static final String MESSAGE2 = "be used so that people can convert EWG files";
|
||||
|
||||
@DontObfuscate
|
||||
public static final String MESSAGE3 = "into .IOB files (iris objects)";
|
||||
|
||||
@DontObfuscate
|
||||
public static IrisObject convert(File so) throws IOException, ClassNotFoundException
|
||||
{
|
||||
FileInputStream fin = new FileInputStream(so);
|
||||
ObjectInputStream in = new ObjectInputStream(fin);
|
||||
StructureObject o = (StructureObject) in.readObject();
|
||||
in.close();
|
||||
int maxX = 0;
|
||||
int maxY = 0;
|
||||
int maxZ = 0;
|
||||
int minX = 0;
|
||||
int minY = 0;
|
||||
int minZ = 0;
|
||||
|
||||
for(SOBlock i : o.blocks)
|
||||
{
|
||||
maxX = maxX < i.x ? i.x : maxX;
|
||||
maxY = maxY < i.y ? i.y : maxY;
|
||||
maxZ = maxZ < i.z ? i.z : maxZ;
|
||||
minX = minX > i.x ? i.x : minX;
|
||||
minY = minY > i.y ? i.y : minY;
|
||||
minZ = minZ > i.z ? i.z : minZ;
|
||||
}
|
||||
|
||||
IrisObject iob = new IrisObject(maxX - minX, maxY - minY, maxZ - minZ);
|
||||
|
||||
for(SOBlock i : o.blocks)
|
||||
{
|
||||
BlockData bdx = null;
|
||||
|
||||
if(i.blockData == null)
|
||||
{
|
||||
BlockData f = map(i.id, i.data);
|
||||
bdx = f == null ? null : f;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
bdx = B.get(i.blockData);
|
||||
}
|
||||
|
||||
if(bdx != null)
|
||||
{
|
||||
iob.getBlocks().put(new BlockVector(i.x, -i.y, i.z), bdx);
|
||||
}
|
||||
}
|
||||
|
||||
return iob;
|
||||
}
|
||||
|
||||
@DontObfuscate
|
||||
@SuppressWarnings("deprecation")
|
||||
private static final BlockData map(int id, int dat)
|
||||
{
|
||||
for(Material i : EnumSet.allOf(Material.class))
|
||||
{
|
||||
if(!i.isLegacy())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(i.getId() == id)
|
||||
{
|
||||
return Bukkit.getUnsafe().fromLegacy(i, (byte) dat);
|
||||
}
|
||||
}
|
||||
|
||||
Iris.warn("Unknown Type " + id + ":" + dat);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@DontObfuscate
|
||||
private static final long serialVersionUID = -905274143366977303L;
|
||||
|
||||
@DontObfuscate
|
||||
public SOBlock[] blocks;
|
||||
@DontObfuscate
|
||||
public String name;
|
||||
|
||||
@DontObfuscate
|
||||
public final class SOBlock implements Serializable
|
||||
{
|
||||
@DontObfuscate
|
||||
private static final long serialVersionUID = 2610063934261982315L;
|
||||
|
||||
@DontObfuscate
|
||||
public final int x;
|
||||
|
||||
@DontObfuscate
|
||||
public final int y;
|
||||
|
||||
@DontObfuscate
|
||||
public final int z;
|
||||
|
||||
@DontObfuscate
|
||||
public final int id;
|
||||
|
||||
@DontObfuscate
|
||||
public final int data;
|
||||
|
||||
@DontObfuscate
|
||||
public String meta;
|
||||
|
||||
@DontObfuscate
|
||||
public String blockData;
|
||||
|
||||
@DontObfuscate
|
||||
final StructureObject ref;
|
||||
|
||||
@DontObfuscate
|
||||
public SOBlock(StructureObject structureObject, int x, int y, int z, String string)
|
||||
{
|
||||
this.ref = structureObject;
|
||||
meta = null;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
id = -1;
|
||||
data = 0;
|
||||
blockData = string;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,262 +0,0 @@
|
||||
package com.volmit.iris;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@Data
|
||||
public class IrisSettings
|
||||
{
|
||||
public static transient IrisSettings settings;
|
||||
private IrisSettingsCache cache = new IrisSettingsCache();
|
||||
private IrisSettingsConcurrency concurrency = new IrisSettingsConcurrency();
|
||||
private IrisSettingsParallax parallax = new IrisSettingsParallax();
|
||||
private IrisSettingsGeneral general = new IrisSettingsGeneral();
|
||||
private IrisSettingsGUI gui = new IrisSettingsGUI();
|
||||
private IrisSettingsGenerator generator = new IrisSettingsGenerator();
|
||||
private IrisSettingsStudio studio = new IrisSettingsStudio();
|
||||
|
||||
@DontObfuscate
|
||||
public int configurationVersion = 3;
|
||||
|
||||
public boolean isStudio() {
|
||||
return getStudio().isStudio();
|
||||
}
|
||||
|
||||
public boolean isUseServerLaunchedGuis() {
|
||||
return getGui().isUseServerLaunchedGuis();
|
||||
}
|
||||
|
||||
public long getParallaxRegionEvictionMS() {
|
||||
return getParallax().getParallaxRegionEvictionMS();
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsCache
|
||||
{
|
||||
@DontObfuscate
|
||||
public int streamingCacheSize = 8192;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsConcurrency
|
||||
{
|
||||
@DontObfuscate
|
||||
public int threadCount = -1;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsParallax
|
||||
{
|
||||
@DontObfuscate
|
||||
public int parallaxRegionEvictionMS = 15000;
|
||||
|
||||
@DontObfuscate
|
||||
public int parallaxChunkEvictionMS = 5000;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsGeneral
|
||||
{
|
||||
|
||||
@DontObfuscate
|
||||
public boolean commandSounds = true;
|
||||
|
||||
@DontObfuscate
|
||||
public boolean verbose = false;
|
||||
|
||||
@DontObfuscate
|
||||
public boolean ignoreWorldEdit = false;
|
||||
|
||||
@DontObfuscate
|
||||
public boolean disableNMS = false;
|
||||
|
||||
@DontObfuscate
|
||||
public boolean pluginMetrics = true;
|
||||
|
||||
@DontObfuscate
|
||||
public boolean splashLogoStartup = true;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsGUI
|
||||
{
|
||||
@DontObfuscate
|
||||
public boolean useServerLaunchedGuis = true;
|
||||
|
||||
@DontObfuscate
|
||||
public boolean maximumPregenGuiFPS = false;
|
||||
|
||||
@DontObfuscate
|
||||
public boolean localPregenGui = true;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsGenerator
|
||||
{
|
||||
@DontObfuscate
|
||||
public String defaultWorldType = "overworld";
|
||||
|
||||
@DontObfuscate
|
||||
public boolean mcaPregenerator = false;
|
||||
|
||||
@DontObfuscate
|
||||
public boolean systemEffects = true;
|
||||
|
||||
@DontObfuscate
|
||||
public boolean systemEntitySpawnOverrides = true;
|
||||
|
||||
@DontObfuscate
|
||||
public boolean systemEntityInitialSpawns = true;
|
||||
|
||||
@DontObfuscate
|
||||
public int maxBiomeChildDepth = 5;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsStudio
|
||||
{
|
||||
|
||||
@DontObfuscate
|
||||
public boolean studio = true;
|
||||
|
||||
@DontObfuscate
|
||||
public boolean openVSCode = true;
|
||||
}
|
||||
|
||||
public static IrisSettings get()
|
||||
{
|
||||
if(settings != null)
|
||||
{
|
||||
return settings;
|
||||
}
|
||||
|
||||
IrisSettings defaults = new IrisSettings();
|
||||
JSONObject def = new JSONObject(new Gson().toJson(defaults));
|
||||
if(settings == null)
|
||||
{
|
||||
settings = new IrisSettings();
|
||||
|
||||
File s = Iris.instance.getDataFile("settings.json");
|
||||
|
||||
if(!s.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||
}
|
||||
|
||||
catch(JSONException | IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
String ss = IO.readAll(s);
|
||||
settings = new Gson().fromJson(ss, IrisSettings.class);
|
||||
|
||||
J.a(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
JSONObject j = new JSONObject(ss);
|
||||
boolean u = false;
|
||||
for(String i : def.keySet())
|
||||
{
|
||||
if(!j.has(i))
|
||||
{
|
||||
u = true;
|
||||
j.put(i, def.get(i));
|
||||
Iris.warn("Adding new config key: " + i);
|
||||
}
|
||||
}
|
||||
|
||||
for(String i : new KSet<>(j.keySet()))
|
||||
{
|
||||
if(!def.has(i))
|
||||
{
|
||||
u = true;
|
||||
j.remove(i);
|
||||
Iris.warn("Removing unused config key: " + i);
|
||||
}
|
||||
}
|
||||
|
||||
if(u)
|
||||
{
|
||||
try
|
||||
{
|
||||
IO.writeAll(s, j.toString(4));
|
||||
Iris.info("Updated Configuration Files");
|
||||
}
|
||||
|
||||
catch(Throwable e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch(Throwable ee)
|
||||
{
|
||||
Iris.error("Configuration Error in settings.json! " + ee.getClass().getSimpleName() + ": " + ee.getMessage());
|
||||
Iris.warn("Attempting to fix configuration while retaining valid in-memory settings...");
|
||||
|
||||
try {
|
||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||
Iris.info("Configuration Fixed!");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Iris.error("ERROR! CONFIGURATION IMPOSSIBLE TO READ! Using an unmodifiable configuration from memory. Please delete the settings.json at some point to try to restore configurability!");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
catch(Throwable ee)
|
||||
{
|
||||
Iris.error("Configuration Error in settings.json! " + ee.getClass().getSimpleName() + ": " + ee.getMessage());
|
||||
Iris.warn("Attempting to fix configuration while retaining valid in-memory settings...");
|
||||
|
||||
try {
|
||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||
Iris.info("Configuration Fixed!");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Iris.error("ERROR! CONFIGURATION IMPOSSIBLE TO READ! Using an unmodifiable configuration from memory. Please delete the settings.json at some point to try to restore configurability!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!s.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||
}
|
||||
|
||||
catch(JSONException | IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
public static void invalidate()
|
||||
{
|
||||
synchronized(settings)
|
||||
{
|
||||
settings = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
186
src/main/java/com/volmit/iris/core/IrisSettings.java
Normal file
186
src/main/java/com/volmit/iris/core/IrisSettings.java
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONException;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@SuppressWarnings("SynchronizeOnNonFinalField")
|
||||
@Data
|
||||
public class IrisSettings {
|
||||
public static IrisSettings settings;
|
||||
private IrisSettingsGeneral general = new IrisSettingsGeneral();
|
||||
private IrisSettingsWorld world = new IrisSettingsWorld();
|
||||
private IrisSettingsGUI gui = new IrisSettingsGUI();
|
||||
private IrisSettingsAutoconfiguration autoConfiguration = new IrisSettingsAutoconfiguration();
|
||||
private IrisSettingsGenerator generator = new IrisSettingsGenerator();
|
||||
private IrisSettingsConcurrency concurrency = new IrisSettingsConcurrency();
|
||||
private IrisSettingsStudio studio = new IrisSettingsStudio();
|
||||
private IrisSettingsPerformance performance = new IrisSettingsPerformance();
|
||||
|
||||
public static int getThreadCount(int c) {
|
||||
return switch(c) {
|
||||
case -1, -2, -4 -> Runtime.getRuntime().availableProcessors() / -c;
|
||||
case 0, 1, 2 -> 1;
|
||||
default -> Math.max(c, 2);
|
||||
};
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsAutoconfiguration {
|
||||
public boolean configureSpigotTimeoutTime = true;
|
||||
public boolean configurePaperWatchdogDelay = true;
|
||||
public boolean autoRestartOnCustomBiomeInstall = true;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisAsyncTeleport {
|
||||
public boolean enabled = false;
|
||||
public int loadViewDistance = 2;
|
||||
public boolean urgent = false;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsWorld {
|
||||
public IrisAsyncTeleport asyncTeleport = new IrisAsyncTeleport();
|
||||
public boolean postLoadBlockUpdates = true;
|
||||
public boolean forcePersistEntities = true;
|
||||
public boolean anbientEntitySpawningSystem = true;
|
||||
public long asyncTickIntervalMS = 700;
|
||||
public double targetSpawnEntitiesPerChunk = 0.95;
|
||||
public boolean markerEntitySpawningSystem = true;
|
||||
public boolean effectSystem = true;
|
||||
public boolean worldEditWandCUI = true;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsConcurrency {
|
||||
public int parallelism = -1;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsPerformance {
|
||||
public boolean trimMantleInStudio = false;
|
||||
public int mantleKeepAlive = 30;
|
||||
public int cacheSize = 4_096;
|
||||
public int resourceLoaderCacheSize = 1_024;
|
||||
public int objectLoaderCacheSize = 4_096;
|
||||
public int scriptLoaderCacheSize = 512;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsGeneral {
|
||||
public boolean commandSounds = true;
|
||||
public boolean debug = false;
|
||||
public boolean disableNMS = false;
|
||||
public boolean pluginMetrics = true;
|
||||
public boolean splashLogoStartup = true;
|
||||
public boolean useConsoleCustomColors = true;
|
||||
public boolean useCustomColorsIngame = true;
|
||||
public String forceMainWorld = "";
|
||||
public int spinh = -20;
|
||||
public int spins = 7;
|
||||
public int spinb = 8;
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean canUseCustomColors(VolmitSender volmitSender) {
|
||||
return volmitSender.isPlayer() ? useCustomColorsIngame : useConsoleCustomColors;
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsGUI {
|
||||
public boolean useServerLaunchedGuis = true;
|
||||
public boolean maximumPregenGuiFPS = false;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsGenerator {
|
||||
public String defaultWorldType = "overworld";
|
||||
public int maxBiomeChildDepth = 4;
|
||||
public boolean preventLeafDecay = true;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsStudio {
|
||||
public boolean studio = true;
|
||||
public boolean openVSCode = true;
|
||||
public boolean disableTimeAndWeather = true;
|
||||
public boolean autoStartDefaultStudio = false;
|
||||
}
|
||||
|
||||
public static IrisSettings get() {
|
||||
if(settings != null) {
|
||||
return settings;
|
||||
}
|
||||
|
||||
settings = new IrisSettings();
|
||||
|
||||
File s = Iris.instance.getDataFile("settings.json");
|
||||
|
||||
if(!s.exists()) {
|
||||
try {
|
||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||
} catch(JSONException | IOException e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
String ss = IO.readAll(s);
|
||||
settings = new Gson().fromJson(ss, IrisSettings.class);
|
||||
try {
|
||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch(Throwable ee) {
|
||||
// Iris.reportError(ee); causes a self-reference & stackoverflow
|
||||
Iris.error("Configuration Error in settings.json! " + ee.getClass().getSimpleName() + ": " + ee.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
public static void invalidate() {
|
||||
synchronized(settings) {
|
||||
settings = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void forceSave() {
|
||||
File s = Iris.instance.getDataFile("settings.json");
|
||||
|
||||
try {
|
||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||
} catch(JSONException | IOException e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
243
src/main/java/com/volmit/iris/core/ServerConfigurator.java
Normal file
243
src/main/java/com/volmit/iris/core/ServerConfigurator.java
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.Queue;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ServerConfigurator {
|
||||
public static void configure() {
|
||||
IrisSettings.IrisSettingsAutoconfiguration s = IrisSettings.get().getAutoConfiguration();
|
||||
if(s.isConfigureSpigotTimeoutTime()) {
|
||||
J.attempt(ServerConfigurator::increaseKeepAliveSpigot);
|
||||
}
|
||||
|
||||
if(s.isConfigurePaperWatchdogDelay()) {
|
||||
J.attempt(ServerConfigurator::increasePaperWatchdog);
|
||||
}
|
||||
|
||||
installDataPacks(true);
|
||||
}
|
||||
|
||||
private static void increaseKeepAliveSpigot() throws IOException, InvalidConfigurationException {
|
||||
File spigotConfig = new File("config/spigot.yml");
|
||||
FileConfiguration f = new YamlConfiguration();
|
||||
f.load(spigotConfig);
|
||||
long tt = f.getLong("settings.timeout-time");
|
||||
|
||||
if(tt < TimeUnit.MINUTES.toSeconds(5)) {
|
||||
Iris.warn("Updating spigot.yml timeout-time: " + tt + " -> " + TimeUnit.MINUTES.toSeconds(5) + " (5 minutes)");
|
||||
Iris.warn("You can disable this change (autoconfigureServer) in Iris settings, then change back the value.");
|
||||
f.set("settings.timeout-time", TimeUnit.MINUTES.toSeconds(5));
|
||||
f.save(spigotConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private static void increasePaperWatchdog() throws IOException, InvalidConfigurationException {
|
||||
File spigotConfig = new File("config/paper-global.yml");
|
||||
FileConfiguration f = new YamlConfiguration();
|
||||
f.load(spigotConfig);
|
||||
long tt = f.getLong("watchdog.early-warning-delay");
|
||||
|
||||
if(tt < TimeUnit.MINUTES.toMillis(3)) {
|
||||
Iris.warn("Updating paper.yml watchdog early-warning-delay: " + tt + " -> " + TimeUnit.MINUTES.toMillis(3) + " (3 minutes)");
|
||||
Iris.warn("You can disable this change (autoconfigureServer) in Iris settings, then change back the value.");
|
||||
f.set("watchdog.early-warning-delay", TimeUnit.MINUTES.toMillis(3));
|
||||
f.save(spigotConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<File> getDatapacksFolder() {
|
||||
if(!IrisSettings.get().getGeneral().forceMainWorld.isEmpty()) {
|
||||
return new KList<File>().qadd(new File(IrisSettings.get().getGeneral().forceMainWorld + "/datapacks"));
|
||||
}
|
||||
KList<File> worlds = new KList<>();
|
||||
Bukkit.getServer().getWorlds().forEach(w -> worlds.add(new File(w.getWorldFolder(), "datapacks")));
|
||||
return worlds;
|
||||
}
|
||||
|
||||
|
||||
public static void installDataPacks(boolean fullInstall) {
|
||||
Iris.info("Checking Data Packs...");
|
||||
File packs = new File("plugins/Iris/packs");
|
||||
|
||||
if(packs.exists()) {
|
||||
for(File i : packs.listFiles()) {
|
||||
if(i.isDirectory()) {
|
||||
Iris.verbose("Checking Pack: " + i.getPath());
|
||||
IrisData data = IrisData.get(i);
|
||||
File dims = new File(i, "dimensions");
|
||||
|
||||
if(dims.exists()) {
|
||||
for(File j : dims.listFiles()) {
|
||||
if(j.getName().endsWith(".json")) {
|
||||
IrisDimension dim = data.getDimensionLoader().load(j.getName().split("\\Q.\\E")[0]);
|
||||
|
||||
if(dim == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Iris.verbose(" Checking Dimension " + dim.getLoadFile().getPath());
|
||||
for(File dpack : getDatapacksFolder()) {
|
||||
dim.installDataPack(() -> data, dpack);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Iris.info("Data Packs Setup!");
|
||||
|
||||
if(fullInstall)
|
||||
verifyDataPacksPost(IrisSettings.get().getAutoConfiguration().isAutoRestartOnCustomBiomeInstall());
|
||||
}
|
||||
|
||||
private static void verifyDataPacksPost(boolean allowRestarting) {
|
||||
File packs = new File("plugins/Iris/packs");
|
||||
|
||||
boolean bad = false;
|
||||
if(packs.exists()) {
|
||||
for(File i : packs.listFiles()) {
|
||||
if(i.isDirectory()) {
|
||||
Iris.verbose("Checking Pack: " + i.getPath());
|
||||
IrisData data = IrisData.get(i);
|
||||
File dims = new File(i, "dimensions");
|
||||
|
||||
if(dims.exists()) {
|
||||
for(File j : dims.listFiles()) {
|
||||
if(j.getName().endsWith(".json")) {
|
||||
IrisDimension dim = data.getDimensionLoader().load(j.getName().split("\\Q.\\E")[0]);
|
||||
|
||||
if(dim == null) {
|
||||
Iris.error("Failed to load " + j.getPath() + " ");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!verifyDataPackInstalled(dim)) {
|
||||
bad = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(bad) {
|
||||
if(allowRestarting) {
|
||||
restart();
|
||||
} else if(INMS.get().supportsDataPacks()) {
|
||||
Iris.error("============================================================================");
|
||||
Iris.error(C.ITALIC + "You need to restart your server to properly generate custom biomes.");
|
||||
Iris.error(C.ITALIC + "By continuing, Iris will use backup biomes in place of the custom biomes.");
|
||||
Iris.error("----------------------------------------------------------------------------");
|
||||
Iris.error(C.UNDERLINE + "IT IS HIGHLY RECOMMENDED YOU RESTART THE SERVER BEFORE GENERATING!");
|
||||
Iris.error("============================================================================");
|
||||
|
||||
for(Player i : Bukkit.getOnlinePlayers()) {
|
||||
if(i.isOp() || i.hasPermission("iris.all")) {
|
||||
VolmitSender sender = new VolmitSender(i, Iris.instance.getTag("WARNING"));
|
||||
sender.sendMessage("There are some Iris Packs that have custom biomes in them");
|
||||
sender.sendMessage("You need to restart your server to use these packs.");
|
||||
}
|
||||
}
|
||||
|
||||
J.sleep(3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void restart() {
|
||||
J.s(() -> {
|
||||
Iris.warn("New data pack entries have been installed in Iris! Restarting server!");
|
||||
Iris.warn("This will only happen when your pack changes (updates/first time setup)");
|
||||
Iris.warn("(You can disable this auto restart in iris settings)");
|
||||
J.s(() -> {
|
||||
Iris.warn("Looks like the restart command diddn't work. Stopping the server instead!");
|
||||
Bukkit.shutdown();
|
||||
}, 100);
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "restart");
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean verifyDataPackInstalled(IrisDimension dimension) {
|
||||
IrisData idm = IrisData.get(Iris.instance.getDataFolder("packs", dimension.getLoadKey()));
|
||||
KSet<String> keys = new KSet<>();
|
||||
boolean warn = false;
|
||||
|
||||
for(IrisBiome i : dimension.getAllBiomes(() -> idm)) {
|
||||
if(i.isCustom()) {
|
||||
for(IrisBiomeCustom j : i.getCustomDerivitives()) {
|
||||
keys.add(dimension.getLoadKey() + ":" + j.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!INMS.get().supportsDataPacks()) {
|
||||
if(!keys.isEmpty()) {
|
||||
Iris.warn("===================================================================================");
|
||||
Iris.warn("Pack " + dimension.getLoadKey() + " has " + keys.size() + " custom biome(s). ");
|
||||
Iris.warn("Your server version does not yet support datapacks for iris.");
|
||||
Iris.warn("The world will generate these biomes as backup biomes.");
|
||||
Iris.warn("====================================================================================");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
for(String i : keys) {
|
||||
Object o = INMS.get().getCustomBiomeBaseFor(i);
|
||||
|
||||
if(o == null) {
|
||||
Iris.warn("The Biome " + i + " is not registered on the server.");
|
||||
warn = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(warn) {
|
||||
Iris.error("The Pack " + dimension.getLoadKey() + " is INCAPABLE of generating custom biomes");
|
||||
Iris.error("If not done automatically, restart your server before generating with this pack!");
|
||||
}
|
||||
|
||||
return !warn;
|
||||
}
|
||||
}
|
||||
185
src/main/java/com/volmit/iris/core/commands/CommandEdit.java
Normal file
185
src/main/java/com/volmit/iris/core/commands/CommandEdit.java
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisCave;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPool;
|
||||
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
|
||||
import java.awt.Desktop;
|
||||
|
||||
|
||||
@Decree(name = "edit", origin = DecreeOrigin.PLAYER, studio = true, description = "Edit something")
|
||||
public class CommandEdit implements DecreeExecutor {
|
||||
|
||||
private boolean noStudio() {
|
||||
if(!sender().isPlayer()) {
|
||||
sender().sendMessage(C.RED + "Players only!");
|
||||
return true;
|
||||
}
|
||||
if(!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||
sender().sendMessage(C.RED + "No studio world is open!");
|
||||
return true;
|
||||
}
|
||||
if(!engine().isStudio()) {
|
||||
sender().sendMessage(C.RED + "You must be in a studio world!");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Decree(description = "Edit the biome you specified", aliases = {"b"}, origin = DecreeOrigin.PLAYER)
|
||||
public void biome(@Param(contextual = false, description = "The biome to edit") IrisBiome biome) {
|
||||
if(noStudio()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if(biome == null || biome.getLoadFile() == null) {
|
||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||
return;
|
||||
}
|
||||
Desktop.getDesktop().open(biome.getLoadFile());
|
||||
sender().sendMessage(C.GREEN + "Opening " + biome.getTypeName() + " " + biome.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Edit the region you specified", aliases = {"r"}, origin = DecreeOrigin.PLAYER)
|
||||
public void region(@Param(contextual = false, description = "The region to edit") IrisRegion region) {
|
||||
if(noStudio()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if(region == null || region.getLoadFile() == null) {
|
||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||
return;
|
||||
}
|
||||
Desktop.getDesktop().open(region.getLoadFile());
|
||||
sender().sendMessage(C.GREEN + "Opening " + region.getTypeName() + " " + region.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Edit the dimension you specified", aliases = {"d"}, origin = DecreeOrigin.PLAYER)
|
||||
public void dimension(@Param(contextual = false, description = "The dimension to edit") IrisDimension dimension) {
|
||||
if(noStudio()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if(dimension == null || dimension.getLoadFile() == null) {
|
||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||
return;
|
||||
}
|
||||
Desktop.getDesktop().open(dimension.getLoadFile());
|
||||
sender().sendMessage(C.GREEN + "Opening " + dimension.getTypeName() + " " + dimension.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Edit the cave file you specified", aliases = {"c"}, origin = DecreeOrigin.PLAYER)
|
||||
public void cave(@Param(contextual = false, description = "The cave to edit") IrisCave cave) {
|
||||
if(noStudio()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if(cave == null || cave.getLoadFile() == null) {
|
||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||
return;
|
||||
}
|
||||
Desktop.getDesktop().open(cave.getLoadFile());
|
||||
sender().sendMessage(C.GREEN + "Opening " + cave.getTypeName() + " " + cave.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Edit the structure file you specified", aliases = {"jigsawstructure", "structure"}, origin = DecreeOrigin.PLAYER)
|
||||
public void jigsaw(@Param(contextual = false, description = "The jigsaw structure to edit") IrisJigsawStructure jigsaw) {
|
||||
if(noStudio()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if(jigsaw == null || jigsaw.getLoadFile() == null) {
|
||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||
return;
|
||||
}
|
||||
Desktop.getDesktop().open(jigsaw.getLoadFile());
|
||||
sender().sendMessage(C.GREEN + "Opening " + jigsaw.getTypeName() + " " + jigsaw.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Edit the pool file you specified", aliases = {"jigsawpool", "pool"}, origin = DecreeOrigin.PLAYER)
|
||||
public void jigsawPool(@Param(contextual = false, description = "The jigsaw pool to edit") IrisJigsawPool pool) {
|
||||
if(noStudio()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if(pool == null || pool.getLoadFile() == null) {
|
||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||
return;
|
||||
}
|
||||
Desktop.getDesktop().open(pool.getLoadFile());
|
||||
sender().sendMessage(C.GREEN + "Opening " + pool.getTypeName() + " " + pool.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Edit the jigsaw piece file you specified", aliases = {"jigsawpiece", "piece"}, origin = DecreeOrigin.PLAYER)
|
||||
public void jigsawPiece(@Param(contextual = false, description = "The jigsaw piece to edit") IrisJigsawPiece piece) {
|
||||
if(noStudio()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if(piece == null || piece.getLoadFile() == null) {
|
||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||
return;
|
||||
}
|
||||
Desktop.getDesktop().open(piece.getLoadFile());
|
||||
sender().sendMessage(C.GREEN + "Opening " + piece.getTypeName() + " " + piece.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
93
src/main/java/com/volmit/iris/core/commands/CommandFind.java
Normal file
93
src/main/java/com/volmit/iris/core/commands/CommandFind.java
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
|
||||
import com.volmit.iris.util.format.C;
|
||||
|
||||
@Decree(name = "find", origin = DecreeOrigin.PLAYER, description = "Iris Find commands", aliases = "goto")
|
||||
public class CommandFind implements DecreeExecutor {
|
||||
@Decree(description = "Find a biome")
|
||||
public void biome(
|
||||
@Param(description = "The biome to look for")
|
||||
IrisBiome biome
|
||||
) {
|
||||
Engine e = engine();
|
||||
|
||||
if(e == null) {
|
||||
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
||||
return;
|
||||
}
|
||||
|
||||
e.gotoBiome(biome, player());
|
||||
}
|
||||
|
||||
@Decree(description = "Find a region")
|
||||
public void region(
|
||||
@Param(description = "The region to look for")
|
||||
IrisRegion region
|
||||
) {
|
||||
Engine e = engine();
|
||||
|
||||
if(e == null) {
|
||||
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
||||
return;
|
||||
}
|
||||
|
||||
e.gotoRegion(region, player());
|
||||
}
|
||||
|
||||
@Decree(description = "Find a structure")
|
||||
public void structure(
|
||||
@Param(description = "The structure to look for")
|
||||
IrisJigsawStructure structure
|
||||
) {
|
||||
Engine e = engine();
|
||||
|
||||
if(e == null) {
|
||||
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
||||
return;
|
||||
}
|
||||
|
||||
e.gotoJigsaw(structure, player());
|
||||
}
|
||||
|
||||
@Decree(description = "Find an object")
|
||||
public void object(
|
||||
@Param(description = "The object to look for", customHandler = ObjectHandler.class)
|
||||
String object
|
||||
) {
|
||||
Engine e = engine();
|
||||
|
||||
if(e == null) {
|
||||
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
||||
return;
|
||||
}
|
||||
|
||||
e.gotoObject(object, player());
|
||||
}
|
||||
}
|
||||
343
src/main/java/com/volmit/iris/core/commands/CommandIris.java
Normal file
343
src/main/java/com/volmit/iris/core/commands/CommandIris.java
Normal file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.decree.DecreeContext;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.jobs.QueueJob;
|
||||
import com.volmit.iris.util.stream.utility.ProfiledStream;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
@Decree(name = "iris", aliases = {"ir", "irs"}, description = "Basic Command")
|
||||
public class CommandIris implements DecreeExecutor {
|
||||
private CommandStudio studio;
|
||||
private CommandPregen pregen;
|
||||
private CommandSettings settings;
|
||||
private CommandObject object;
|
||||
private CommandJigsaw jigsaw;
|
||||
private CommandWhat what;
|
||||
private CommandEdit edit;
|
||||
private CommandFind find;
|
||||
|
||||
@Decree(description = "Create a new world", aliases = {"+", "c"})
|
||||
public void create(
|
||||
@Param(aliases = "world-name", description = "The name of the world to create")
|
||||
String name,
|
||||
@Param(aliases = "dimension", description = "The dimension type to create the world with", defaultValue = "default")
|
||||
IrisDimension type,
|
||||
@Param(description = "The seed to generate the world with", defaultValue = "1337")
|
||||
long seed
|
||||
) {
|
||||
if(name.equals("iris")) {
|
||||
sender().sendMessage(C.RED + "You cannot use the world name \"iris\" for creating worlds as Iris uses this directory for studio worlds.");
|
||||
sender().sendMessage(C.RED + "May we suggest the name \"IrisWorld\" instead?");
|
||||
return;
|
||||
}
|
||||
|
||||
if(new File(name).exists()) {
|
||||
sender().sendMessage(C.RED + "That folder already exists!");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
IrisToolbelt.createWorld()
|
||||
.dimension(type.getLoadKey())
|
||||
.name(name)
|
||||
.seed(seed)
|
||||
.sender(sender())
|
||||
.studio(false)
|
||||
.create();
|
||||
} catch(Throwable e) {
|
||||
sender().sendMessage(C.RED + "Exception raised during creation. See the console for more details.");
|
||||
Iris.error("Exception raised during world creation: " + e.getMessage());
|
||||
Iris.reportError(e);
|
||||
return;
|
||||
}
|
||||
|
||||
sender().sendMessage(C.GREEN + "Successfully created your world!");
|
||||
}
|
||||
|
||||
@Decree(description = "Remove an Iris world", aliases = {"del", "rm"}, sync = true)
|
||||
public void remove(
|
||||
@Param(description = "The world to remove")
|
||||
World world,
|
||||
@Param(description = "Whether to also remove the folder (if set to false, just does not load the world)", defaultValue = "true")
|
||||
boolean delete
|
||||
) {
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", Bukkit.getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
|
||||
return;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "Removing world: " + world.getName());
|
||||
try {
|
||||
if (IrisToolbelt.removeWorld(world)) {
|
||||
sender().sendMessage(C.GREEN + "Successfully removed " + world.getName() + " from bukkit.yml");
|
||||
} else {
|
||||
sender().sendMessage(C.YELLOW + "Looks like the world was already removed from bukkit.yml");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
sender().sendMessage(C.RED + "Failed to save bukkit.yml because of " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
IrisToolbelt.evacuate(world, "Deleting world");
|
||||
Bukkit.unloadWorld(world, false);
|
||||
if (delete && world.getWorldFolder().delete()) {
|
||||
sender().sendMessage(C.GREEN + "Successfully removed world folder");
|
||||
} else {
|
||||
sender().sendMessage(C.RED + "Failed to remove world folder");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Print version information")
|
||||
public void version() {
|
||||
sender().sendMessage(C.GREEN + "Iris v" + Iris.instance.getDescription().getVersion() + " by Volmit Software");
|
||||
}
|
||||
|
||||
@Decree(description = "Print world height information", origin = DecreeOrigin.PLAYER)
|
||||
public void height() {
|
||||
sender().sendMessage(C.GREEN + "" + sender().player().getWorld().getMinHeight() + " to " + sender().player().getWorld().getMaxHeight());
|
||||
sender().sendMessage(C.GREEN + "Total Height: " + (sender().player().getWorld().getMaxHeight() - sender().player().getWorld().getMinHeight()));
|
||||
}
|
||||
|
||||
@Decree(description = "QOL command to open a overworld studio world.", sync = true)
|
||||
public void so() {
|
||||
sender().sendMessage(C.GREEN + "Opening studio for the \"Overworld\" pack (seed: 1337)");
|
||||
Iris.service(StudioSVC.class).open(sender(), 1337, "overworld");
|
||||
}
|
||||
|
||||
@Decree(description = "Set aura spins")
|
||||
public void aura(
|
||||
@Param(description = "The h color value", defaultValue = "-20")
|
||||
int h,
|
||||
@Param(description = "The s color value", defaultValue = "7")
|
||||
int s,
|
||||
@Param(description = "The b color value", defaultValue = "8")
|
||||
int b
|
||||
) {
|
||||
IrisSettings.get().getGeneral().setSpinh(h);
|
||||
IrisSettings.get().getGeneral().setSpins(s);
|
||||
IrisSettings.get().getGeneral().setSpinb(b);
|
||||
IrisSettings.get().forceSave();
|
||||
sender().sendMessage("<rainbow>Aura Spins updated to " + h + " " + s + " " + b);
|
||||
}
|
||||
|
||||
@Decree(description = "Bitwise calculations")
|
||||
public void bitwise(
|
||||
@Param(description = "The first value to run calculations on")
|
||||
int value1,
|
||||
@Param(description = "The operator: | & ^ ≺≺ ≻≻ %")
|
||||
String operator,
|
||||
@Param(description = "The second value to run calculations on")
|
||||
int value2
|
||||
) {
|
||||
Integer v = null;
|
||||
switch(operator) {
|
||||
case "|" -> v = value1 | value2;
|
||||
case "&" -> v = value1 & value2;
|
||||
case "^" -> v = value1 ^ value2;
|
||||
case "%" -> v = value1 % value2;
|
||||
case ">>" -> v = value1 >> value2;
|
||||
case "<<" -> v = value1 << value2;
|
||||
}
|
||||
if(v == null) {
|
||||
sender().sendMessage(C.RED + "The operator you entered: (" + operator + ") is invalid!");
|
||||
return;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "" + value1 + " " + C.GREEN + operator.replaceAll("<", "≺").replaceAll(">", "≻").replaceAll("%", "%") + " " + C.GREEN + value2 + C.GREEN + " returns " + C.GREEN + v);
|
||||
}
|
||||
|
||||
@Decree(description = "Toggle debug")
|
||||
public void debug(
|
||||
@Param(name = "on", description = "Whether or not debug should be on", defaultValue = "other")
|
||||
Boolean on
|
||||
) {
|
||||
boolean to = on == null ? !IrisSettings.get().getGeneral().isDebug() : on;
|
||||
IrisSettings.get().getGeneral().setDebug(to);
|
||||
IrisSettings.get().forceSave();
|
||||
sender().sendMessage(C.GREEN + "Set debug to: " + to);
|
||||
}
|
||||
|
||||
@Decree(description = "Download a project.", aliases = "dl")
|
||||
public void download(
|
||||
@Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project")
|
||||
String pack,
|
||||
@Param(name = "branch", description = "The branch to download from", defaultValue = "main")
|
||||
String branch,
|
||||
@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
||||
boolean trim,
|
||||
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
||||
boolean overwrite
|
||||
) {
|
||||
sender().sendMessage(C.GREEN + "Downloading pack: " + pack + "/" + branch + (trim ? " trimmed" : "") + (overwrite ? " overwriting" : ""));
|
||||
if(pack.equals("overworld")) {
|
||||
String url = "https://github.com/IrisDimensions/overworld/releases/download/" + Iris.OVERWORLD_TAG + "/overworld.zip";
|
||||
Iris.service(StudioSVC.class).downloadRelease(sender(), url, trim, overwrite);
|
||||
} else {
|
||||
Iris.service(StudioSVC.class).downloadSearch(sender(), "IrisDimensions/" + pack + "/" + branch, trim, overwrite);
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Get metrics for your world", aliases = "measure", origin = DecreeOrigin.PLAYER)
|
||||
public void metrics() {
|
||||
if(!IrisToolbelt.isIrisWorld(world())) {
|
||||
sender().sendMessage(C.RED + "You must be in an Iris world");
|
||||
return;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "Sending metrics...");
|
||||
engine().printMetrics(sender());
|
||||
}
|
||||
|
||||
@Decree(description = "Reload configuration file (this is also done automatically)")
|
||||
public void reload() {
|
||||
IrisSettings.invalidate();
|
||||
IrisSettings.get();
|
||||
sender().sendMessage(C.GREEN + "Hotloaded settings");
|
||||
}
|
||||
|
||||
@Decree(name = "regen", description = "Regenerate nearby chunks.", aliases = "rg", sync = true, origin = DecreeOrigin.PLAYER)
|
||||
public void regen(
|
||||
@Param(name = "radius", description = "The radius of nearby cunks", defaultValue = "5")
|
||||
int radius
|
||||
) {
|
||||
if(IrisToolbelt.isIrisWorld(player().getWorld())) {
|
||||
VolmitSender sender = sender();
|
||||
J.a(() -> {
|
||||
DecreeContext.touch(sender);
|
||||
PlatformChunkGenerator plat = IrisToolbelt.access(player().getWorld());
|
||||
Engine engine = plat.getEngine();
|
||||
try {
|
||||
Chunk cx = player().getLocation().getChunk();
|
||||
KList<Runnable> js = new KList<>();
|
||||
BurstExecutor b = MultiBurst.burst.burst();
|
||||
b.setMulticore(false);
|
||||
int rad = engine.getMantle().getRealRadius();
|
||||
for(int i = -(radius + rad); i <= radius + rad; i++) {
|
||||
for(int j = -(radius + rad); j <= radius + rad; j++) {
|
||||
engine.getMantle().getMantle().deleteChunk(i + cx.getX(), j + cx.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = -radius; i <= radius; i++) {
|
||||
for(int j = -radius; j <= radius; j++) {
|
||||
int finalJ = j;
|
||||
int finalI = i;
|
||||
b.queue(() -> plat.injectChunkReplacement(player().getWorld(), finalI + cx.getX(), finalJ + cx.getZ(), (f) -> {
|
||||
synchronized(js) {
|
||||
js.add(f);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
b.complete();
|
||||
sender().sendMessage(C.GREEN + "Regenerating " + Form.f(js.size()) + " Sections");
|
||||
QueueJob<Runnable> r = new QueueJob<>() {
|
||||
final KList<Future<?>> futures = new KList<>();
|
||||
|
||||
@Override
|
||||
public void execute(Runnable runnable) {
|
||||
futures.add(J.sfut(runnable));
|
||||
|
||||
if(futures.size() > 64) {
|
||||
while(futures.isNotEmpty()) {
|
||||
try {
|
||||
futures.remove(0).get();
|
||||
} catch(InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Regenerating";
|
||||
}
|
||||
};
|
||||
r.queue(js);
|
||||
r.execute(sender());
|
||||
} catch(Throwable e) {
|
||||
sender().sendMessage("Unable to parse view-distance");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
sender().sendMessage(C.RED + "You must be in an Iris World to use regen!");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Update the pack of a world (UNSAFE!)", name = "^world", aliases = "update-world")
|
||||
public void updateWorld(
|
||||
@Param(description = "The world to update", contextual = true)
|
||||
World world,
|
||||
@Param(description = "The pack to install into the world", contextual = true, aliases = "dimension")
|
||||
IrisDimension pack,
|
||||
@Param(description = "Make sure to make a backup & read the warnings first!", defaultValue = "false", aliases = "c")
|
||||
boolean confirm,
|
||||
@Param(description = "Should Iris download the pack again for you", defaultValue = "false", name = "fresh-download", aliases = {"fresh", "new"})
|
||||
boolean freshDownload
|
||||
) {
|
||||
if(!confirm) {
|
||||
sender().sendMessage(new String[] {
|
||||
C.RED + "You should always make a backup before using this",
|
||||
C.YELLOW + "Issues caused by this can be, but are not limited to:",
|
||||
C.YELLOW + " - Broken chunks (cut-offs) between old and new chunks (before & after the update)",
|
||||
C.YELLOW + " - Regenerated chunks that do not fit in with the old chunks",
|
||||
C.YELLOW + " - Structures not spawning again when regenerating",
|
||||
C.YELLOW + " - Caves not lining up",
|
||||
C.YELLOW + " - Terrain layers not lining up",
|
||||
C.RED + "Now that you are aware of the risks, and have made a back-up:",
|
||||
C.RED + "/iris ^world <world> <pack> confirm=true"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
File folder = world.getWorldFolder();
|
||||
folder.mkdirs();
|
||||
|
||||
if(freshDownload) {
|
||||
Iris.service(StudioSVC.class).downloadSearch(sender(), pack.getLoadKey(), false, true);
|
||||
}
|
||||
|
||||
Iris.service(StudioSVC.class).installIntoWorld(sender(), pack.getLoadKey(), folder);
|
||||
}
|
||||
}
|
||||
112
src/main/java/com/volmit/iris/core/commands/CommandJigsaw.java
Normal file
112
src/main/java/com/volmit/iris/core/commands/CommandJigsaw.java
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.edit.JigsawEditor;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.engine.jigsaw.PlannedStructure;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
||||
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
||||
import com.volmit.iris.engine.object.IrisObject;
|
||||
import com.volmit.iris.engine.object.IrisPosition;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@Decree(name = "jigsaw", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris jigsaw commands")
|
||||
public class CommandJigsaw implements DecreeExecutor {
|
||||
@Decree(description = "Edit a jigsaw piece")
|
||||
public void edit(
|
||||
@Param(description = "The jigsaw piece to edit")
|
||||
IrisJigsawPiece piece
|
||||
) {
|
||||
File dest = piece.getLoadFile();
|
||||
new JigsawEditor(player(), piece, IrisData.loadAnyObject(piece.getObject()), dest);
|
||||
}
|
||||
|
||||
@Decree(description = "Place a jigsaw structure")
|
||||
public void place(
|
||||
@Param(description = "The jigsaw structure to place")
|
||||
IrisJigsawStructure structure
|
||||
) {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation()), new RNG());
|
||||
sender().sendMessage(C.GREEN + "Generated " + ps.getPieces().size() + " pieces in " + Form.duration(p.getMilliseconds(), 2));
|
||||
ps.place(world());
|
||||
}
|
||||
|
||||
@Decree(description = "Create a jigsaw piece")
|
||||
public void create(
|
||||
@Param(description = "The name of the jigsaw piece")
|
||||
String piece,
|
||||
@Param(description = "The project to add the jigsaw piece to")
|
||||
String project,
|
||||
@Param(description = "The object to use for this piece", customHandler = ObjectHandler.class)
|
||||
String object
|
||||
) {
|
||||
IrisObject o = IrisData.loadAnyObject(object);
|
||||
|
||||
if(object == null) {
|
||||
sender().sendMessage(C.RED + "Failed to find existing object");
|
||||
return;
|
||||
}
|
||||
|
||||
File dest = Iris.instance.getDataFile("packs", project, "jigsaw-pieces", piece + ".json");
|
||||
new JigsawEditor(player(), null, o, dest);
|
||||
sender().sendMessage(C.GRAY + "* Right Click blocks to make them connectors");
|
||||
sender().sendMessage(C.GRAY + "* Right Click connectors to orient them");
|
||||
sender().sendMessage(C.GRAY + "* Shift + Right Click connectors to remove them");
|
||||
sender().sendMessage(C.GREEN + "Remember to use /iris jigsaw save");
|
||||
}
|
||||
|
||||
@Decree(description = "Exit the current jigsaw editor")
|
||||
public void exit() {
|
||||
JigsawEditor editor = JigsawEditor.editors.get(player());
|
||||
|
||||
if(editor == null) {
|
||||
sender().sendMessage(C.GOLD + "You don't have any pieces open to exit!");
|
||||
return;
|
||||
}
|
||||
|
||||
editor.exit();
|
||||
sender().sendMessage(C.GREEN + "Exited Jigsaw Editor");
|
||||
}
|
||||
|
||||
@Decree(description = "Save & Exit the current jigsaw editor")
|
||||
public void save() {
|
||||
JigsawEditor editor = JigsawEditor.editors.get(player());
|
||||
|
||||
if(editor == null) {
|
||||
sender().sendMessage(C.GOLD + "You don't have any pieces open to save!");
|
||||
return;
|
||||
}
|
||||
|
||||
editor.close();
|
||||
sender().sendMessage(C.GREEN + "Saved & Exited Jigsaw Editor");
|
||||
}
|
||||
}
|
||||
530
src/main/java/com/volmit/iris/core/commands/CommandObject.java
Normal file
530
src/main/java/com/volmit/iris/core/commands/CommandObject.java
Normal file
@@ -0,0 +1,530 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.link.WorldEditLink;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.service.ObjectSVC;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.service.WandSVC;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IObjectPlacer;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisObject;
|
||||
import com.volmit.iris.engine.object.IrisObjectPlacement;
|
||||
import com.volmit.iris.engine.object.IrisObjectPlacementScaleInterpolator;
|
||||
import com.volmit.iris.engine.object.IrisObjectRotation;
|
||||
import com.volmit.iris.engine.object.TileData;
|
||||
import com.volmit.iris.util.data.Cuboid;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.math.Direction;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.scheduling.Queue;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.TileState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Decree(name = "object", aliases = "o", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris object manipulation")
|
||||
public class CommandObject implements DecreeExecutor {
|
||||
|
||||
private static final Set<Material> skipBlocks = Set.of(Material.GRASS, Material.SNOW, Material.VINE, Material.TORCH, Material.DEAD_BUSH,
|
||||
Material.POPPY, Material.DANDELION);
|
||||
|
||||
public static IObjectPlacer createPlacer(World world, Map<Block, BlockData> futureBlockChanges) {
|
||||
|
||||
return new IObjectPlacer() {
|
||||
@Override
|
||||
public int getHighest(int x, int z, IrisData data) {
|
||||
return world.getHighestBlockYAt(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHighest(int x, int z, IrisData data, boolean ignoreFluid) {
|
||||
return world.getHighestBlockYAt(x, z, ignoreFluid ? HeightMap.OCEAN_FLOOR : HeightMap.MOTION_BLOCKING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int x, int y, int z, BlockData d) {
|
||||
Block block = world.getBlockAt(x, y, z);
|
||||
|
||||
//Prevent blocks being set in or bellow bedrock
|
||||
if(y <= world.getMinHeight() || block.getType() == Material.BEDROCK) return;
|
||||
|
||||
futureBlockChanges.put(block, block.getBlockData());
|
||||
|
||||
block.setBlockData(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData get(int x, int y, int z) {
|
||||
return world.getBlockAt(x, y, z).getBlockData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPreventingDecay() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCarved(int x, int y, int z) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolid(int x, int y, int z) {
|
||||
return world.getBlockAt(x, y, z).getType().isSolid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnderwater(int x, int z) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFluidHeight() {
|
||||
return 63;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugSmartBore() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
|
||||
BlockState state = world.getBlockAt(xx, yy, zz).getState();
|
||||
tile.toBukkitTry(state);
|
||||
state.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Engine getEngine() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Decree(description = "Check the composition of an object")
|
||||
public void analyze(
|
||||
@Param(description = "The object to analyze", customHandler = ObjectHandler.class)
|
||||
String object
|
||||
) {
|
||||
IrisObject o = IrisData.loadAnyObject(object);
|
||||
sender().sendMessage("Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD() + "");
|
||||
sender().sendMessage("Blocks Used: " + NumberFormat.getIntegerInstance().format(o.getBlocks().size()));
|
||||
|
||||
Queue<BlockData> queue = o.getBlocks().enqueueValues();
|
||||
Map<Material, Set<BlockData>> unsorted = new HashMap<>();
|
||||
Map<BlockData, Integer> amounts = new HashMap<>();
|
||||
Map<Material, Integer> materials = new HashMap<>();
|
||||
while(queue.hasNext()) {
|
||||
BlockData block = queue.next();
|
||||
|
||||
//unsorted.put(block.getMaterial(), block);
|
||||
|
||||
if(!amounts.containsKey(block)) {
|
||||
amounts.put(block, 1);
|
||||
|
||||
|
||||
} else
|
||||
amounts.put(block, amounts.get(block) + 1);
|
||||
|
||||
if(!materials.containsKey(block.getMaterial())) {
|
||||
materials.put(block.getMaterial(), 1);
|
||||
unsorted.put(block.getMaterial(), new HashSet<>());
|
||||
unsorted.get(block.getMaterial()).add(block);
|
||||
} else {
|
||||
materials.put(block.getMaterial(), materials.get(block.getMaterial()) + 1);
|
||||
unsorted.get(block.getMaterial()).add(block);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
List<Material> sortedMatsList = amounts.keySet().stream().map(BlockData::getMaterial)
|
||||
.sorted().collect(Collectors.toList());
|
||||
Set<Material> sortedMats = new TreeSet<>(Comparator.comparingInt(materials::get).reversed());
|
||||
sortedMats.addAll(sortedMatsList);
|
||||
sender().sendMessage("== Blocks in object ==");
|
||||
|
||||
int n = 0;
|
||||
for(Material mat : sortedMats) {
|
||||
int amount = materials.get(mat);
|
||||
List<BlockData> set = new ArrayList<>(unsorted.get(mat));
|
||||
set.sort(Comparator.comparingInt(amounts::get).reversed());
|
||||
BlockData data = set.get(0);
|
||||
int dataAmount = amounts.get(data);
|
||||
|
||||
String string = " - " + mat.toString() + "*" + amount;
|
||||
if(data.getAsString(true).contains("[")) {
|
||||
string = string + " --> [" + data.getAsString(true).split("\\[")[1]
|
||||
.replaceAll("true", ChatColor.GREEN + "true" + ChatColor.GRAY)
|
||||
.replaceAll("false", ChatColor.RED + "false" + ChatColor.GRAY) + "*" + dataAmount;
|
||||
}
|
||||
|
||||
sender().sendMessage(string);
|
||||
|
||||
n++;
|
||||
|
||||
if(n >= 10) {
|
||||
sender().sendMessage(" + " + (sortedMats.size() - n) + " other block types");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Get a powder that reveals objects", studio = true, aliases = "d")
|
||||
public void dust() {
|
||||
player().getInventory().addItem(WandSVC.createDust());
|
||||
sender().playSound(Sound.AMBIENT_SOUL_SAND_VALLEY_ADDITIONS, 1f, 1.5f);
|
||||
}
|
||||
|
||||
@Decree(description = "Contract a selection based on your looking direction", aliases = "-")
|
||||
public void contract(
|
||||
@Param(description = "The amount to inset by", defaultValue = "1")
|
||||
int amount
|
||||
) {
|
||||
if(!WandSVC.isHoldingWand(player())) {
|
||||
sender().sendMessage("Hold your wand.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Location[] b = WandSVC.getCuboid(player());
|
||||
Location a1 = b[0].clone();
|
||||
Location a2 = b[1].clone();
|
||||
Cuboid cursor = new Cuboid(a1, a2);
|
||||
Direction d = Direction.closest(player().getLocation().getDirection()).reverse();
|
||||
assert d != null;
|
||||
cursor = cursor.expand(d, -amount);
|
||||
b[0] = cursor.getLowerNE();
|
||||
b[1] = cursor.getUpperSW();
|
||||
player().getInventory().setItemInMainHand(WandSVC.createWand(b[0], b[1]));
|
||||
player().updateInventory();
|
||||
sender().playSound(Sound.ENTITY_ITEM_FRAME_ROTATE_ITEM, 1f, 0.55f);
|
||||
}
|
||||
|
||||
@Decree(description = "Set point 1 to look", aliases = "p1")
|
||||
public void position1(
|
||||
@Param(description = "Whether to use your current position, or where you look", defaultValue = "true")
|
||||
boolean here
|
||||
) {
|
||||
if(!WandSVC.isHoldingWand(player())) {
|
||||
sender().sendMessage("Ready your Wand.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(WandSVC.isHoldingWand(player())) {
|
||||
Location[] g = WandSVC.getCuboid(player());
|
||||
|
||||
if(!here) {
|
||||
// TODO: WARNING HEIGHT
|
||||
g[1] = player().getTargetBlock(null, 256).getLocation().clone();
|
||||
} else {
|
||||
g[1] = player().getLocation().getBlock().getLocation().clone().add(0, -1, 0);
|
||||
}
|
||||
player().setItemInHand(WandSVC.createWand(g[0], g[1]));
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Set point 2 to look", aliases = "p2")
|
||||
public void position2(
|
||||
@Param(description = "Whether to use your current position, or where you look", defaultValue = "true")
|
||||
boolean here
|
||||
) {
|
||||
if(!WandSVC.isHoldingWand(player())) {
|
||||
sender().sendMessage("Ready your Wand.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(WandSVC.isHoldingIrisWand(player())) {
|
||||
Location[] g = WandSVC.getCuboid(player());
|
||||
|
||||
if(!here) {
|
||||
// TODO: WARNING HEIGHT
|
||||
g[0] = player().getTargetBlock(null, 256).getLocation().clone();
|
||||
} else {
|
||||
g[0] = player().getLocation().getBlock().getLocation().clone().add(0, -1, 0);
|
||||
}
|
||||
player().setItemInHand(WandSVC.createWand(g[0], g[1]));
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Paste an object", sync = true)
|
||||
public void paste(
|
||||
@Param(description = "The object to paste", customHandler = ObjectHandler.class)
|
||||
String object,
|
||||
@Param(description = "Whether or not to edit the object (need to hold wand)", defaultValue = "false")
|
||||
boolean edit,
|
||||
@Param(description = "The amount of degrees to rotate by", defaultValue = "0")
|
||||
int rotate,
|
||||
@Param(description = "The factor by which to scale the object placement", defaultValue = "1")
|
||||
double scale
|
||||
// ,
|
||||
// @Param(description = "The scale interpolator to use", defaultValue = "none")
|
||||
// IrisObjectPlacementScaleInterpolator interpolator
|
||||
) {
|
||||
IrisObject o = IrisData.loadAnyObject(object);
|
||||
double maxScale = Double.max(10 - o.getBlocks().size() / 10000d, 1);
|
||||
if(scale > maxScale) {
|
||||
sender().sendMessage(C.YELLOW + "Indicated scale exceeds maximum. Downscaled to maximum: " + maxScale);
|
||||
scale = maxScale;
|
||||
}
|
||||
|
||||
sender().playSound(Sound.BLOCK_ENCHANTMENT_TABLE_USE, 1f, 1.5f);
|
||||
|
||||
IrisObjectPlacement placement = new IrisObjectPlacement();
|
||||
placement.setRotation(IrisObjectRotation.of(0, rotate, 0));
|
||||
|
||||
ItemStack wand = player().getInventory().getItemInMainHand();
|
||||
Location block = player().getTargetBlock(skipBlocks, 256).getLocation().clone().add(0, 1, 0);
|
||||
|
||||
Map<Block, BlockData> futureChanges = new HashMap<>();
|
||||
|
||||
if(scale != 1)
|
||||
{
|
||||
o = o.scaled(scale, IrisObjectPlacementScaleInterpolator.TRICUBIC);
|
||||
}
|
||||
|
||||
o.place(block.getBlockX(), block.getBlockY() + (int) o.getCenter().getY(), block.getBlockZ(), createPlacer(block.getWorld(), futureChanges), placement, new RNG(), null);
|
||||
|
||||
Iris.service(ObjectSVC.class).addChanges(futureChanges);
|
||||
|
||||
if(edit) {
|
||||
ItemStack newWand = WandSVC.createWand(block.clone().subtract(o.getCenter()).add(o.getW() - 1,
|
||||
o.getH() + o.getCenter().clone().getY() - 1, o.getD() - 1), block.clone().subtract(o.getCenter().clone().setY(0)));
|
||||
if(WandSVC.isWand(wand)) {
|
||||
wand = newWand;
|
||||
player().getInventory().setItemInMainHand(wand);
|
||||
sender().sendMessage("Updated wand for " + "objects/" + o.getLoadKey() + ".iob ");
|
||||
} else {
|
||||
int slot = WandSVC.findWand(player().getInventory());
|
||||
if(slot == -1) {
|
||||
player().getInventory().addItem(newWand);
|
||||
sender().sendMessage("Given new wand for " + "objects/" + o.getLoadKey() + ".iob ");
|
||||
} else {
|
||||
player().getInventory().setItem(slot, newWand);
|
||||
sender().sendMessage("Updated wand for " + "objects/" + o.getLoadKey() + ".iob ");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sender().sendMessage("Placed " + object);
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Save an object")
|
||||
public void save(
|
||||
@Param(description = "The dimension to store the object in", contextual = true)
|
||||
IrisDimension dimension,
|
||||
@Param(description = "The file to store it in, can use / for subfolders")
|
||||
String name,
|
||||
@Param(description = "Overwrite existing object files", defaultValue = "false", aliases = "force")
|
||||
boolean overwrite
|
||||
) {
|
||||
IrisObject o = WandSVC.createSchematic(player());
|
||||
|
||||
if(o == null) {
|
||||
sender().sendMessage(C.YELLOW + "You need to hold your wand!");
|
||||
return;
|
||||
}
|
||||
|
||||
File file = Iris.service(StudioSVC.class).getWorkspaceFile(dimension.getLoadKey(), "objects", name + ".iob");
|
||||
|
||||
if(file.exists() && !overwrite) {
|
||||
sender().sendMessage(C.RED + "File already exists. Set overwrite=true to overwrite it.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
o.write(file);
|
||||
} catch(IOException e) {
|
||||
sender().sendMessage(C.RED + "Failed to save object because of an IOException: " + e.getMessage());
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
sender().playSound(Sound.BLOCK_ENCHANTMENT_TABLE_USE, 1f, 1.5f);
|
||||
sender().sendMessage(C.GREEN + "Successfully object to saved: " + dimension.getLoadKey() + "/objects/" + name);
|
||||
}
|
||||
|
||||
@Decree(description = "Shift a selection in your looking direction", aliases = "-")
|
||||
public void shift(
|
||||
@Param(description = "The amount to shift by", defaultValue = "1")
|
||||
int amount
|
||||
) {
|
||||
if(!WandSVC.isHoldingWand(player())) {
|
||||
sender().sendMessage("Hold your wand.");
|
||||
return;
|
||||
}
|
||||
|
||||
Location[] b = WandSVC.getCuboid(player());
|
||||
Location a1 = b[0].clone();
|
||||
Location a2 = b[1].clone();
|
||||
Direction d = Direction.closest(player().getLocation().getDirection()).reverse();
|
||||
a1.add(d.toVector().multiply(amount));
|
||||
a2.add(d.toVector().multiply(amount));
|
||||
Cuboid cursor = new Cuboid(a1, a2);
|
||||
b[0] = cursor.getLowerNE();
|
||||
b[1] = cursor.getUpperSW();
|
||||
player().getInventory().setItemInMainHand(WandSVC.createWand(b[0], b[1]));
|
||||
player().updateInventory();
|
||||
sender().playSound(Sound.ENTITY_ITEM_FRAME_ROTATE_ITEM, 1f, 0.55f);
|
||||
}
|
||||
|
||||
@Decree(description = "Undo a number of pastes", aliases = "-")
|
||||
public void undo(
|
||||
@Param(description = "The amount of pastes to undo", defaultValue = "1")
|
||||
int amount
|
||||
) {
|
||||
ObjectSVC service = Iris.service(ObjectSVC.class);
|
||||
int actualReverts = Math.min(service.getUndos().size(), amount);
|
||||
service.revertChanges(actualReverts);
|
||||
sender().sendMessage("Reverted " + actualReverts + " pastes!");
|
||||
}
|
||||
|
||||
@Decree(description = "Gets an object wand and grabs the current WorldEdit selection.", aliases = "we", origin = DecreeOrigin.PLAYER, studio = true)
|
||||
public void we() {
|
||||
if(!Bukkit.getPluginManager().isPluginEnabled("WorldEdit")) {
|
||||
sender().sendMessage(C.RED + "You can't get a WorldEdit selection without WorldEdit, you know.");
|
||||
return;
|
||||
}
|
||||
|
||||
Cuboid locs = WorldEditLink.getSelection(sender().player());
|
||||
|
||||
if(locs == null)
|
||||
{
|
||||
sender().sendMessage(C.RED + "You don't have a WorldEdit selection in this world.");
|
||||
return;
|
||||
}
|
||||
|
||||
sender().player().getInventory().addItem(WandSVC.createWand(locs.getLowerNE(), locs.getUpperSW()));
|
||||
sender().sendMessage(C.GREEN + "A fresh wand with your current WorldEdit selection on it!");
|
||||
}
|
||||
|
||||
@Decree(description = "Get an object wand", sync = true)
|
||||
public void wand() {
|
||||
player().getInventory().addItem(WandSVC.createWand());
|
||||
sender().playSound(Sound.ITEM_ARMOR_EQUIP_NETHERITE, 1f, 1.5f);
|
||||
sender().sendMessage(C.GREEN + "Poof! Good luck building!");
|
||||
}
|
||||
|
||||
@Decree(name = "x&y", description = "Autoselect up, down & out", sync = true)
|
||||
public void xay() {
|
||||
if(!WandSVC.isHoldingWand(player())) {
|
||||
sender().sendMessage(C.YELLOW + "Hold your wand!");
|
||||
return;
|
||||
}
|
||||
|
||||
Location[] b = WandSVC.getCuboid(player());
|
||||
Location a1 = b[0].clone();
|
||||
Location a2 = b[1].clone();
|
||||
Location a1x = b[0].clone();
|
||||
Location a2x = b[1].clone();
|
||||
Cuboid cursor = new Cuboid(a1, a2);
|
||||
Cuboid cursorx = new Cuboid(a1, a2);
|
||||
|
||||
while(!cursor.containsOnly(Material.AIR)) {
|
||||
a1.add(new org.bukkit.util.Vector(0, 1, 0));
|
||||
a2.add(new org.bukkit.util.Vector(0, 1, 0));
|
||||
cursor = new Cuboid(a1, a2);
|
||||
}
|
||||
|
||||
a1.add(new org.bukkit.util.Vector(0, -1, 0));
|
||||
a2.add(new org.bukkit.util.Vector(0, -1, 0));
|
||||
|
||||
while(!cursorx.containsOnly(Material.AIR)) {
|
||||
a1x.add(new org.bukkit.util.Vector(0, -1, 0));
|
||||
a2x.add(new org.bukkit.util.Vector(0, -1, 0));
|
||||
cursorx = new Cuboid(a1x, a2x);
|
||||
}
|
||||
|
||||
a1x.add(new org.bukkit.util.Vector(0, 1, 0));
|
||||
a2x.add(new Vector(0, 1, 0));
|
||||
b[0] = a1;
|
||||
b[1] = a2x;
|
||||
cursor = new Cuboid(b[0], b[1]);
|
||||
cursor = cursor.contract(Cuboid.CuboidDirection.North);
|
||||
cursor = cursor.contract(Cuboid.CuboidDirection.South);
|
||||
cursor = cursor.contract(Cuboid.CuboidDirection.East);
|
||||
cursor = cursor.contract(Cuboid.CuboidDirection.West);
|
||||
b[0] = cursor.getLowerNE();
|
||||
b[1] = cursor.getUpperSW();
|
||||
player().getInventory().setItemInMainHand(WandSVC.createWand(b[0], b[1]));
|
||||
player().updateInventory();
|
||||
sender().playSound(Sound.ENTITY_ITEM_FRAME_ROTATE_ITEM, 1f, 0.55f);
|
||||
sender().sendMessage(C.GREEN + "Auto-select complete!");
|
||||
}
|
||||
|
||||
@Decree(name = "x+y", description = "Autoselect up & out", sync = true)
|
||||
public void xpy() {
|
||||
if(!WandSVC.isHoldingWand(player())) {
|
||||
sender().sendMessage(C.YELLOW + "Hold your wand!");
|
||||
return;
|
||||
}
|
||||
|
||||
Location[] b = WandSVC.getCuboid(player());
|
||||
b[0].add(new Vector(0, 1, 0));
|
||||
b[1].add(new Vector(0, 1, 0));
|
||||
Location a1 = b[0].clone();
|
||||
Location a2 = b[1].clone();
|
||||
Cuboid cursor = new Cuboid(a1, a2);
|
||||
|
||||
while(!cursor.containsOnly(Material.AIR)) {
|
||||
a1.add(new Vector(0, 1, 0));
|
||||
a2.add(new Vector(0, 1, 0));
|
||||
cursor = new Cuboid(a1, a2);
|
||||
}
|
||||
|
||||
a1.add(new Vector(0, -1, 0));
|
||||
a2.add(new Vector(0, -1, 0));
|
||||
b[0] = a1;
|
||||
a2 = b[1];
|
||||
cursor = new Cuboid(a1, a2);
|
||||
cursor = cursor.contract(Cuboid.CuboidDirection.North);
|
||||
cursor = cursor.contract(Cuboid.CuboidDirection.South);
|
||||
cursor = cursor.contract(Cuboid.CuboidDirection.East);
|
||||
cursor = cursor.contract(Cuboid.CuboidDirection.West);
|
||||
b[0] = cursor.getLowerNE();
|
||||
b[1] = cursor.getUpperSW();
|
||||
player().getInventory().setItemInMainHand(WandSVC.createWand(b[0], b[1]));
|
||||
player().updateInventory();
|
||||
sender().playSound(Sound.ENTITY_ITEM_FRAME_ROTATE_ITEM, 1f, 0.55f);
|
||||
sender().sendMessage(C.GREEN + "Auto-select complete!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.gui.PregeneratorJob;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
@Decree(name = "pregen", aliases = "pregenerate", description = "Pregenerate your Iris worlds!")
|
||||
public class CommandPregen implements DecreeExecutor {
|
||||
@Decree(description = "Pregenerate a world")
|
||||
public void start(
|
||||
@Param(description = "The radius of the pregen in blocks", aliases = "size")
|
||||
int radius,
|
||||
@Param(description = "The world to pregen", contextual = true)
|
||||
World world,
|
||||
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
|
||||
Vector center
|
||||
) {
|
||||
try {
|
||||
if(sender().isPlayer() && access() == null) {
|
||||
sender().sendMessage(C.RED + "The engine access for this world is null!");
|
||||
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
|
||||
}
|
||||
radius = Math.max(radius, 1024);
|
||||
int w = (radius >> 9 + 1) * 2;
|
||||
IrisToolbelt.pregenerate(PregenTask
|
||||
.builder()
|
||||
.center(new Position2(center))
|
||||
.width(w)
|
||||
.height(w)
|
||||
.build(), world);
|
||||
String msg = C.GREEN + "Pregen started in " + C.GOLD + world.getName() + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
|
||||
sender().sendMessage(msg);
|
||||
Iris.info(msg);
|
||||
} catch(Throwable e) {
|
||||
sender().sendMessage(C.RED + "Epic fail. See console.");
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Stop the active pregeneration task", aliases = "x")
|
||||
public void stop() {
|
||||
if(PregeneratorJob.shutdownInstance()) {
|
||||
sender().sendMessage(C.GREEN + "Stopped pregeneration task");
|
||||
} else {
|
||||
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
|
||||
public void pause() {
|
||||
if(PregeneratorJob.pauseResume()) {
|
||||
sender().sendMessage(C.GREEN + "Paused/unpaused pregeneration task, now: " + (PregeneratorJob.isPaused() ? "Paused" : "Running") + ".");
|
||||
} else {
|
||||
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to pause/unpause.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
|
||||
public class CommandSettings implements DecreeExecutor {
|
||||
|
||||
}
|
||||
900
src/main/java/com/volmit/iris/core/commands/CommandStudio.java
Normal file
900
src/main/java/com/volmit/iris/core/commands/CommandStudio.java
Normal file
@@ -0,0 +1,900 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.gui.NoiseExplorerGUI;
|
||||
import com.volmit.iris.core.gui.VisionGUI;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.project.IrisProject;
|
||||
import com.volmit.iris.core.service.ConversionSVC;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.InventorySlotType;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisBiomePaletteLayer;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisEntity;
|
||||
import com.volmit.iris.engine.object.IrisGenerator;
|
||||
import com.volmit.iris.engine.object.IrisInterpolator;
|
||||
import com.volmit.iris.engine.object.IrisLootTable;
|
||||
import com.volmit.iris.engine.object.IrisNoiseGenerator;
|
||||
import com.volmit.iris.engine.object.IrisObject;
|
||||
import com.volmit.iris.engine.object.IrisObjectPlacement;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
import com.volmit.iris.engine.object.IrisScript;
|
||||
import com.volmit.iris.engine.object.NoiseStyle;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.function.Function2;
|
||||
import com.volmit.iris.util.function.NoiseProvider;
|
||||
import com.volmit.iris.util.interpolation.InterpolationMethod;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONArray;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import com.volmit.iris.util.noise.CNG;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.O;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import com.volmit.iris.util.scheduling.jobs.Job;
|
||||
import com.volmit.iris.util.scheduling.jobs.JobCollection;
|
||||
import com.volmit.iris.util.scheduling.jobs.QueueJob;
|
||||
import com.volmit.iris.util.scheduling.jobs.SingleJob;
|
||||
import io.papermc.lib.PaperLib;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.FluidCollisionMode;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.util.BlockVector;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Decree(name = "studio", aliases = {"std", "s"}, description = "Studio Commands", studio = true)
|
||||
public class CommandStudio implements DecreeExecutor {
|
||||
public static String hrf(Duration duration) {
|
||||
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
|
||||
}
|
||||
|
||||
private CommandFind find;
|
||||
private CommandEdit edit;
|
||||
|
||||
|
||||
@Decree(description = "Download a project.", aliases = "dl")
|
||||
public void download(
|
||||
@Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project")
|
||||
String pack,
|
||||
@Param(name = "branch", description = "The branch to download from", defaultValue = "master")
|
||||
String branch,
|
||||
@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
||||
boolean trim,
|
||||
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
||||
boolean overwrite
|
||||
) {
|
||||
new CommandIris().download(pack, branch, trim, overwrite);
|
||||
}
|
||||
|
||||
@Decree(description = "Open a new studio world", aliases = "o", sync = true)
|
||||
public void open(
|
||||
@Param(defaultValue = "default", description = "The dimension to open a studio for", aliases = "dim")
|
||||
IrisDimension dimension,
|
||||
@Param(defaultValue = "1337", description = "The seed to generate the studio with", aliases = "s")
|
||||
long seed) {
|
||||
sender().sendMessage(C.GREEN + "Opening studio for the \"" + dimension.getName() + "\" pack (seed: " + seed + ")");
|
||||
Iris.service(StudioSVC.class).open(sender(), seed, dimension.getLoadKey());
|
||||
}
|
||||
|
||||
@Decree(description = "Open VSCode for a dimension", aliases = {"vsc", "edit"})
|
||||
public void vscode(
|
||||
@Param(defaultValue = "default", description = "The dimension to open VSCode for", aliases = "dim")
|
||||
IrisDimension dimension
|
||||
) {
|
||||
sender().sendMessage(C.GREEN + "Opening VSCode for the \"" + dimension.getName() + "\" pack");
|
||||
Iris.service(StudioSVC.class).openVSCode(sender(), dimension.getLoadKey());
|
||||
}
|
||||
|
||||
@Decree(description = "Close an open studio project", aliases = {"x", "c"}, sync = true)
|
||||
public void close() {
|
||||
if(!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||
sender().sendMessage(C.RED + "No open studio projects.");
|
||||
return;
|
||||
}
|
||||
|
||||
Iris.service(StudioSVC.class).close();
|
||||
sender().sendMessage(C.GREEN + "Project Closed.");
|
||||
}
|
||||
|
||||
@Decree(description = "Create a new studio project", aliases = "+", sync = true)
|
||||
public void create(
|
||||
@Param(description = "The name of this new Iris Project.")
|
||||
String name,
|
||||
@Param(description = "Copy the contents of an existing project in your packs folder and use it as a template in this new project.", contextual = true)
|
||||
IrisDimension template) {
|
||||
if(template != null) {
|
||||
Iris.service(StudioSVC.class).create(sender(), name, template.getLoadKey());
|
||||
} else {
|
||||
Iris.service(StudioSVC.class).create(sender(), name);
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Clean an Iris Project, optionally beautifying JSON & fixing block ids with missing keys. Also rebuilds the vscode schemas. ")
|
||||
public void clean(
|
||||
@Param(description = "The project to update", contextual = true)
|
||||
IrisDimension project,
|
||||
|
||||
@Param(defaultValue = "true", description = "Filters all valid JSON files with a beautifier (indentation: 4)")
|
||||
boolean beautify,
|
||||
|
||||
@Param(name = "fix-ids", defaultValue = "true", description = "Fixes any block ids used such as \"dirt\" will be converted to \"minecraft:dirt\"")
|
||||
boolean fixIds,
|
||||
|
||||
@Param(name = "rewrite-objects", defaultValue = "false", description = "Imports all objects and re-writes them cleaning up positions & block data in the process.")
|
||||
boolean rewriteObjects
|
||||
) {
|
||||
KList<Job> jobs = new KList<>();
|
||||
KList<File> files = new KList<File>();
|
||||
files(Iris.instance.getDataFolder("packs", project.getLoadKey()), files);
|
||||
MultiBurst burst = MultiBurst.burst;
|
||||
|
||||
jobs.add(new SingleJob("Updating Workspace", () -> {
|
||||
if(!new IrisProject(Iris.service(StudioSVC.class).getWorkspaceFolder(project.getLoadKey())).updateWorkspace()) {
|
||||
sender().sendMessage(C.GOLD + "Invalid project: " + project.getLoadKey() + ". Try deleting the code-workspace file and try again.");
|
||||
}
|
||||
J.sleep(250);
|
||||
}));
|
||||
|
||||
sender().sendMessage("Files: " + files.size());
|
||||
|
||||
if(fixIds) {
|
||||
QueueJob<File> r = new QueueJob<>() {
|
||||
@Override
|
||||
public void execute(File f) {
|
||||
try {
|
||||
JSONObject p = new JSONObject(IO.readAll(f));
|
||||
fixBlocks(p);
|
||||
J.sleep(1);
|
||||
IO.writeAll(f, p.toString(4));
|
||||
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Fixing IDs";
|
||||
}
|
||||
};
|
||||
|
||||
r.queue(files);
|
||||
jobs.add(r);
|
||||
}
|
||||
|
||||
if(beautify) {
|
||||
QueueJob<File> r = new QueueJob<>() {
|
||||
@Override
|
||||
public void execute(File f) {
|
||||
try {
|
||||
JSONObject p = new JSONObject(IO.readAll(f));
|
||||
IO.writeAll(f, p.toString(4));
|
||||
J.sleep(1);
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Beautify";
|
||||
}
|
||||
};
|
||||
|
||||
r.queue(files);
|
||||
jobs.add(r);
|
||||
}
|
||||
|
||||
if(rewriteObjects) {
|
||||
QueueJob<Runnable> q = new QueueJob<>() {
|
||||
@Override
|
||||
public void execute(Runnable runnable) {
|
||||
runnable.run();
|
||||
J.sleep(50);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Rewriting Objects";
|
||||
}
|
||||
};
|
||||
|
||||
IrisData data = IrisData.get(Iris.service(StudioSVC.class).getWorkspaceFolder(project.getLoadKey()));
|
||||
for(String f : data.getObjectLoader().getPossibleKeys()) {
|
||||
Future<?> gg = burst.complete(() -> {
|
||||
File ff = data.getObjectLoader().findFile(f);
|
||||
IrisObject oo = new IrisObject(0, 0, 0);
|
||||
try {
|
||||
oo.read(ff);
|
||||
} catch(Throwable e) {
|
||||
Iris.error("FAILER TO READ: " + f);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
oo.write(ff);
|
||||
} catch(IOException e) {
|
||||
Iris.error("FAILURE TO WRITE: " + oo.getLoadFile());
|
||||
}
|
||||
});
|
||||
|
||||
q.queue(() -> {
|
||||
try {
|
||||
gg.get();
|
||||
} catch(InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
jobs.add(q);
|
||||
}
|
||||
|
||||
new JobCollection("Cleaning", jobs).execute(sender());
|
||||
}
|
||||
|
||||
@Decree(description = "Get the version of a pack")
|
||||
public void version(
|
||||
@Param(defaultValue = "default", description = "The dimension get the version of", aliases = "dim", contextual = true)
|
||||
IrisDimension dimension
|
||||
) {
|
||||
sender().sendMessage(C.GREEN + "The \"" + dimension.getName() + "\" pack has version: " + dimension.getVersion());
|
||||
}
|
||||
|
||||
@Decree(description = "Convert objects in the \"convert\" folder")
|
||||
public void convert() {
|
||||
Iris.service(ConversionSVC.class).check(sender());
|
||||
}
|
||||
|
||||
|
||||
@Decree(description = "Execute a script", aliases = "run", origin = DecreeOrigin.PLAYER)
|
||||
public void execute(
|
||||
@Param(description = "The script to run")
|
||||
IrisScript script
|
||||
) {
|
||||
engine().getExecution().execute(script.getLoadKey());
|
||||
}
|
||||
|
||||
@Decree(description = "Open the noise explorer (External GUI)", aliases = {"nmap", "n"})
|
||||
public void noise() {
|
||||
if(noGUI()) return;
|
||||
sender().sendMessage(C.GREEN + "Opening Noise Explorer!");
|
||||
NoiseExplorerGUI.launch();
|
||||
}
|
||||
|
||||
@Decree(description = "Charges all spawners in the area", aliases = "zzt", origin = DecreeOrigin.PLAYER)
|
||||
public void charge() {
|
||||
if(!IrisToolbelt.isIrisWorld(world())) {
|
||||
sender().sendMessage(C.RED + "You must be in an Iris world to charge spawners!");
|
||||
return;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "Charging spawners!");
|
||||
engine().getWorldManager().chargeEnergy();
|
||||
}
|
||||
|
||||
@Decree(description = "Preview noise gens (External GUI)", aliases = {"generator", "gen"})
|
||||
public void explore(
|
||||
@Param(description = "The generator to explore", contextual = true)
|
||||
IrisGenerator generator,
|
||||
@Param(description = "The seed to generate with", defaultValue = "12345")
|
||||
long seed
|
||||
) {
|
||||
if(noGUI()) return;
|
||||
sender().sendMessage(C.GREEN + "Opening Noise Explorer!");
|
||||
|
||||
Supplier<Function2<Double, Double, Double>> l = () -> {
|
||||
|
||||
if(generator == null) {
|
||||
return (x, z) -> 0D;
|
||||
}
|
||||
|
||||
return (x, z) -> generator.getHeight(x, z, new RNG(seed).nextParallelRNG(3245).lmax());
|
||||
};
|
||||
NoiseExplorerGUI.launch(l, "Custom Generator");
|
||||
}
|
||||
|
||||
@Decree(description = "Hotload a studio", aliases = {"reload", "h"})
|
||||
public void hotload() {
|
||||
if(!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||
sender().sendMessage(C.RED + "No studio world open!");
|
||||
return;
|
||||
}
|
||||
Iris.service(StudioSVC.class).getActiveProject().getActiveProvider().getEngine().hotload();
|
||||
sender().sendMessage(C.GREEN + "Hotloaded");
|
||||
}
|
||||
|
||||
@Decree(description = "Show loot if a chest were right here", origin = DecreeOrigin.PLAYER, sync = true)
|
||||
public void loot(
|
||||
@Param(description = "Fast insertion of items in virtual inventory (may cause performance drop)", defaultValue = "false")
|
||||
boolean fast,
|
||||
@Param(description = "Whether or not to append to the inventory currently open (if false, clears opened inventory)", defaultValue = "true")
|
||||
boolean add
|
||||
) {
|
||||
if(noStudio()) return;
|
||||
|
||||
KList<IrisLootTable> tables = engine().getLootTables(RNG.r, player().getLocation().getBlock());
|
||||
Inventory inv = Bukkit.createInventory(null, 27 * 2);
|
||||
|
||||
try {
|
||||
engine().addItems(true, inv, RNG.r, tables, InventorySlotType.STORAGE, player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cannot add items to virtual inventory because of: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
O<Integer> ta = new O<>();
|
||||
ta.set(-1);
|
||||
|
||||
ta.set(Bukkit.getScheduler().scheduleSyncRepeatingTask(Iris.instance, () ->
|
||||
{
|
||||
if(!player().getOpenInventory().getType().equals(InventoryType.CHEST)) {
|
||||
Bukkit.getScheduler().cancelTask(ta.get());
|
||||
sender().sendMessage(C.GREEN + "Opened inventory!");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!add) {
|
||||
inv.clear();
|
||||
}
|
||||
|
||||
engine().addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
|
||||
}, 0, fast ? 5 : 35));
|
||||
|
||||
sender().sendMessage(C.GREEN + "Opening inventory now!");
|
||||
player().openInventory(inv);
|
||||
}
|
||||
|
||||
@Decree(description = "Render a world map (External GUI)", aliases = "render")
|
||||
public void map(
|
||||
@Param(name = "world", description = "The world to open the generator for", contextual = true)
|
||||
World world
|
||||
) {
|
||||
if(noGUI()) return;
|
||||
|
||||
if(!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage(C.RED + "You need to be in or specify an Iris-generated world!");
|
||||
return;
|
||||
}
|
||||
|
||||
VisionGUI.launch(IrisToolbelt.access(world).getEngine(), 0);
|
||||
sender().sendMessage(C.GREEN + "Opening map!");
|
||||
}
|
||||
|
||||
@Decree(description = "Package a dimension into a compressed format", aliases = "package")
|
||||
public void pkg(
|
||||
@Param(name = "dimension", description = "The dimension pack to compress", contextual = true, defaultValue = "default")
|
||||
IrisDimension dimension,
|
||||
@Param(name = "obfuscate", description = "Whether or not to obfuscate the pack", defaultValue = "false")
|
||||
boolean obfuscate,
|
||||
@Param(name = "minify", description = "Whether or not to minify the pack", defaultValue = "true")
|
||||
boolean minify
|
||||
) {
|
||||
Iris.service(StudioSVC.class).compilePackage(sender(), dimension.getLoadKey(), obfuscate, minify);
|
||||
}
|
||||
|
||||
@Decree(description = "Profiles the performance of a dimension", origin = DecreeOrigin.PLAYER)
|
||||
public void profile(
|
||||
@Param(description = "The dimension to profile", contextual = true, defaultValue = "default")
|
||||
IrisDimension dimension
|
||||
) {
|
||||
File pack = dimension.getLoadFile().getParentFile().getParentFile();
|
||||
File report = Iris.instance.getDataFile("profile.txt");
|
||||
IrisProject project = new IrisProject(pack);
|
||||
IrisData data = IrisData.get(pack);
|
||||
|
||||
KList<String> fileText = new KList<>();
|
||||
|
||||
KMap<NoiseStyle, Double> styleTimings = new KMap<>();
|
||||
KMap<InterpolationMethod, Double> interpolatorTimings = new KMap<>();
|
||||
KMap<String, Double> generatorTimings = new KMap<>();
|
||||
KMap<String, Double> biomeTimings = new KMap<>();
|
||||
KMap<String, Double> regionTimings = new KMap<>();
|
||||
|
||||
sender().sendMessage("Calculating Performance Metrics for Noise generators");
|
||||
|
||||
for(NoiseStyle i : NoiseStyle.values()) {
|
||||
CNG c = i.create(new RNG(i.hashCode()));
|
||||
|
||||
for(int j = 0; j < 3000; j++) {
|
||||
c.noise(j, j + 1000, j * j);
|
||||
c.noise(j, -j);
|
||||
}
|
||||
|
||||
PrecisionStopwatch px = PrecisionStopwatch.start();
|
||||
|
||||
for(int j = 0; j < 100000; j++) {
|
||||
c.noise(j, j + 1000, j * j);
|
||||
c.noise(j, -j);
|
||||
}
|
||||
|
||||
styleTimings.put(i, px.getMilliseconds());
|
||||
}
|
||||
|
||||
fileText.add("Noise Style Performance Impacts: ");
|
||||
|
||||
for(NoiseStyle i : styleTimings.sortKNumber()) {
|
||||
fileText.add(i.name() + ": " + styleTimings.get(i));
|
||||
}
|
||||
|
||||
fileText.add("");
|
||||
|
||||
sender().sendMessage("Calculating Interpolator Timings...");
|
||||
|
||||
for(InterpolationMethod i : InterpolationMethod.values()) {
|
||||
IrisInterpolator in = new IrisInterpolator();
|
||||
in.setFunction(i);
|
||||
in.setHorizontalScale(8);
|
||||
|
||||
NoiseProvider np = (x, z) -> Math.random();
|
||||
|
||||
for(int j = 0; j < 3000; j++) {
|
||||
in.interpolate(j, -j, np);
|
||||
}
|
||||
|
||||
PrecisionStopwatch px = PrecisionStopwatch.start();
|
||||
|
||||
for(int j = 0; j < 100000; j++) {
|
||||
in.interpolate(j + 10000, -j - 100000, np);
|
||||
}
|
||||
|
||||
interpolatorTimings.put(i, px.getMilliseconds());
|
||||
}
|
||||
|
||||
fileText.add("Noise Interpolator Performance Impacts: ");
|
||||
|
||||
for(InterpolationMethod i : interpolatorTimings.sortKNumber()) {
|
||||
fileText.add(i.name() + ": " + interpolatorTimings.get(i));
|
||||
}
|
||||
|
||||
fileText.add("");
|
||||
|
||||
sender().sendMessage("Processing Generator Scores: ");
|
||||
|
||||
KMap<String, KList<String>> btx = new KMap<>();
|
||||
|
||||
for(String i : data.getGeneratorLoader().getPossibleKeys()) {
|
||||
KList<String> vv = new KList<>();
|
||||
IrisGenerator g = data.getGeneratorLoader().load(i);
|
||||
KList<IrisNoiseGenerator> composites = g.getAllComposites();
|
||||
double score = 0;
|
||||
int m = 0;
|
||||
for(IrisNoiseGenerator j : composites) {
|
||||
m++;
|
||||
score += styleTimings.get(j.getStyle().getStyle());
|
||||
vv.add("Composite Noise Style " + m + " " + j.getStyle().getStyle().name() + ": " + styleTimings.get(j.getStyle().getStyle()));
|
||||
}
|
||||
|
||||
score += interpolatorTimings.get(g.getInterpolator().getFunction());
|
||||
vv.add("Interpolator " + g.getInterpolator().getFunction().name() + ": " + interpolatorTimings.get(g.getInterpolator().getFunction()));
|
||||
generatorTimings.put(i, score);
|
||||
btx.put(i, vv);
|
||||
}
|
||||
|
||||
fileText.add("Project Generator Performance Impacts: ");
|
||||
|
||||
for(String i : generatorTimings.sortKNumber()) {
|
||||
fileText.add(i + ": " + generatorTimings.get(i));
|
||||
|
||||
btx.get(i).forEach((ii) -> fileText.add(" " + ii));
|
||||
}
|
||||
|
||||
fileText.add("");
|
||||
|
||||
KMap<String, KList<String>> bt = new KMap<>();
|
||||
|
||||
for(String i : data.getBiomeLoader().getPossibleKeys()) {
|
||||
KList<String> vv = new KList<>();
|
||||
IrisBiome b = data.getBiomeLoader().load(i);
|
||||
double score = 0;
|
||||
|
||||
int m = 0;
|
||||
for(IrisBiomePaletteLayer j : b.getLayers()) {
|
||||
m++;
|
||||
score += styleTimings.get(j.getStyle().getStyle());
|
||||
vv.add("Palette Layer " + m + ": " + styleTimings.get(j.getStyle().getStyle()));
|
||||
}
|
||||
|
||||
score += styleTimings.get(b.getBiomeStyle().getStyle());
|
||||
vv.add("Biome Style: " + styleTimings.get(b.getBiomeStyle().getStyle()));
|
||||
score += styleTimings.get(b.getChildStyle().getStyle());
|
||||
vv.add("Child Style: " + styleTimings.get(b.getChildStyle().getStyle()));
|
||||
biomeTimings.put(i, score);
|
||||
bt.put(i, vv);
|
||||
}
|
||||
|
||||
fileText.add("Project Biome Performance Impacts: ");
|
||||
|
||||
for(String i : biomeTimings.sortKNumber()) {
|
||||
fileText.add(i + ": " + biomeTimings.get(i));
|
||||
|
||||
bt.get(i).forEach((ff) -> fileText.add(" " + ff));
|
||||
}
|
||||
|
||||
fileText.add("");
|
||||
|
||||
for(String i : data.getRegionLoader().getPossibleKeys()) {
|
||||
IrisRegion b = data.getRegionLoader().load(i);
|
||||
double score = 0;
|
||||
|
||||
score += styleTimings.get(b.getLakeStyle().getStyle());
|
||||
score += styleTimings.get(b.getRiverStyle().getStyle());
|
||||
regionTimings.put(i, score);
|
||||
}
|
||||
|
||||
fileText.add("Project Region Performance Impacts: ");
|
||||
|
||||
for(String i : regionTimings.sortKNumber()) {
|
||||
fileText.add(i + ": " + regionTimings.get(i));
|
||||
}
|
||||
|
||||
fileText.add("");
|
||||
|
||||
double m = 0;
|
||||
for(double i : biomeTimings.v()) {
|
||||
m += i;
|
||||
}
|
||||
m /= biomeTimings.size();
|
||||
double mm = 0;
|
||||
for(double i : generatorTimings.v()) {
|
||||
mm += i;
|
||||
}
|
||||
mm /= generatorTimings.size();
|
||||
m += mm;
|
||||
double mmm = 0;
|
||||
for(double i : regionTimings.v()) {
|
||||
mmm += i;
|
||||
}
|
||||
mmm /= regionTimings.size();
|
||||
m += mmm;
|
||||
|
||||
fileText.add("Average Score: " + m);
|
||||
sender().sendMessage("Score: " + Form.duration(m, 0));
|
||||
|
||||
try {
|
||||
IO.writeAll(report, fileText.toString("\n"));
|
||||
} catch(IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
sender().sendMessage(C.GREEN + "Done! " + report.getPath());
|
||||
}
|
||||
|
||||
@Decree(description = "Summon an Iris Entity", origin = DecreeOrigin.PLAYER)
|
||||
public void summon(
|
||||
@Param(description = "The Iris Entity to spawn")
|
||||
IrisEntity entity,
|
||||
@Param(description = "The location at which to spawn the entity", defaultValue = "self")
|
||||
Vector location
|
||||
) {
|
||||
if(!sender().isPlayer()) {
|
||||
sender().sendMessage(C.RED + "Players only (this is a config error. Ask support to add DecreeOrigin.PLAYER to the command you tried to run)");
|
||||
return;
|
||||
}
|
||||
|
||||
sender().sendMessage(C.GREEN + "Spawning entity");
|
||||
entity.spawn(engine(), new Location(world(), location.getX(), location.getY(), location.getZ()));
|
||||
}
|
||||
|
||||
@Decree(description = "Teleport to the active studio world", aliases = "stp", origin = DecreeOrigin.PLAYER, sync = true)
|
||||
public void tpstudio() {
|
||||
if(!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||
sender().sendMessage(C.RED + "No studio world is open!");
|
||||
return;
|
||||
}
|
||||
|
||||
if(IrisToolbelt.isIrisWorld(world()) && engine().isStudio()) {
|
||||
sender().sendMessage(C.RED + "You are already in a studio world!");
|
||||
return;
|
||||
}
|
||||
|
||||
sender().sendMessage(C.GREEN + "Sending you to the studio world!");
|
||||
player().teleport(Iris.service(StudioSVC.class).getActiveProject().getActiveProvider().getTarget().getWorld().spawnLocation());
|
||||
player().setGameMode(GameMode.SPECTATOR);
|
||||
}
|
||||
|
||||
@Decree(description = "Update your dimension projects VSCode workspace")
|
||||
public void update(
|
||||
@Param(description = "The dimension to update the workspace of", contextual = true, defaultValue = "default")
|
||||
IrisDimension dimension
|
||||
) {
|
||||
sender().sendMessage(C.GOLD + "Updating Code Workspace for " + dimension.getName() + "...");
|
||||
if(new IrisProject(dimension.getLoader().getDataFolder()).updateWorkspace()) {
|
||||
sender().sendMessage(C.GREEN + "Updated Code Workspace for " + dimension.getName());
|
||||
} else {
|
||||
sender().sendMessage(C.RED + "Invalid project: " + dimension.getName() + ". Try deleting the code-workspace file and try again.");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(aliases = "find-objects", description = "Get information about nearby structures")
|
||||
public void objects() {
|
||||
if(!IrisToolbelt.isIrisWorld(player().getWorld())) {
|
||||
sender().sendMessage(C.RED + "You must be in an Iris world");
|
||||
return;
|
||||
}
|
||||
|
||||
World world = player().getWorld();
|
||||
|
||||
if(!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage("You must be in an iris world.");
|
||||
return;
|
||||
}
|
||||
KList<Chunk> chunks = new KList<>();
|
||||
int bx = player().getLocation().getChunk().getX();
|
||||
int bz = player().getLocation().getChunk().getZ();
|
||||
|
||||
try {
|
||||
Location l = player().getTargetBlockExact(48, FluidCollisionMode.NEVER).getLocation();
|
||||
|
||||
int cx = l.getChunk().getX();
|
||||
int cz = l.getChunk().getZ();
|
||||
new Spiraler(3, 3, (x, z) -> chunks.addIfMissing(world.getChunkAt(x + cx, z + cz))).drain();
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
new Spiraler(3, 3, (x, z) -> chunks.addIfMissing(world.getChunkAt(x + bx, z + bz))).drain();
|
||||
sender().sendMessage("Capturing IGenData from " + chunks.size() + " nearby chunks.");
|
||||
try {
|
||||
File ff = Iris.instance.getDataFile("reports/" + M.ms() + ".txt");
|
||||
PrintWriter pw = new PrintWriter(ff);
|
||||
pw.println("=== Iris Chunk Report ===");
|
||||
pw.println("== General Info ==");
|
||||
pw.println("Iris Version: " + Iris.instance.getDescription().getVersion());
|
||||
pw.println("Bukkit Version: " + Bukkit.getBukkitVersion());
|
||||
pw.println("MC Version: " + Bukkit.getVersion());
|
||||
pw.println("PaperSpigot: " + (PaperLib.isPaper() ? "Yup!" : "Nope!"));
|
||||
pw.println("Report Captured At: " + new Date());
|
||||
pw.println("Chunks: (" + chunks.size() + "): ");
|
||||
|
||||
for(Chunk i : chunks) {
|
||||
pw.println("- [" + i.getX() + ", " + i.getZ() + "]");
|
||||
}
|
||||
|
||||
int regions = 0;
|
||||
long size = 0;
|
||||
String age = "No idea...";
|
||||
|
||||
try {
|
||||
for(File i : Objects.requireNonNull(new File(world.getWorldFolder(), "region").listFiles())) {
|
||||
if(i.isFile()) {
|
||||
size += i.length();
|
||||
}
|
||||
}
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
try {
|
||||
FileTime creationTime = (FileTime) Files.getAttribute(world.getWorldFolder().toPath(), "creationTime");
|
||||
age = hrf(Duration.of(M.ms() - creationTime.toMillis(), ChronoUnit.MILLIS));
|
||||
} catch(IOException e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
KList<String> biomes = new KList<>();
|
||||
KList<String> caveBiomes = new KList<>();
|
||||
KMap<String, KMap<String, KList<String>>> objects = new KMap<>();
|
||||
|
||||
for(Chunk i : chunks) {
|
||||
for(int j = 0; j < 16; j += 3) {
|
||||
|
||||
for(int k = 0; k < 16; k += 3) {
|
||||
|
||||
assert engine() != null;
|
||||
IrisBiome bb = engine().getSurfaceBiome((i.getX() * 16) + j, (i.getZ() * 16) + k);
|
||||
IrisBiome bxf = engine().getCaveBiome((i.getX() * 16) + j, (i.getZ() * 16) + k);
|
||||
biomes.addIfMissing(bb.getName() + " [" + Form.capitalize(bb.getInferredType().name().toLowerCase()) + "] " + " (" + bb.getLoadFile().getName() + ")");
|
||||
caveBiomes.addIfMissing(bxf.getName() + " (" + bxf.getLoadFile().getName() + ")");
|
||||
exportObjects(bb, pw, engine(), objects);
|
||||
exportObjects(bxf, pw, engine(), objects);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
regions = Objects.requireNonNull(new File(world.getWorldFolder().getPath() + "/region").list()).length;
|
||||
|
||||
pw.println();
|
||||
pw.println("== World Info ==");
|
||||
pw.println("World Name: " + world.getName());
|
||||
pw.println("Age: " + age);
|
||||
pw.println("Folder: " + world.getWorldFolder().getPath());
|
||||
pw.println("Regions: " + Form.f(regions));
|
||||
pw.println("Chunks: max. " + Form.f(regions * 32 * 32));
|
||||
pw.println("World Size: min. " + Form.fileSize(size));
|
||||
pw.println();
|
||||
pw.println("== Biome Info ==");
|
||||
pw.println("Found " + biomes.size() + " Biome(s): ");
|
||||
|
||||
for(String i : biomes) {
|
||||
pw.println("- " + i);
|
||||
}
|
||||
pw.println();
|
||||
|
||||
pw.println("== Object Info ==");
|
||||
|
||||
for(String i : objects.k()) {
|
||||
pw.println("- " + i);
|
||||
|
||||
for(String j : objects.get(i).k()) {
|
||||
pw.println(" @ " + j);
|
||||
|
||||
for(String k : objects.get(i).get(j)) {
|
||||
pw.println(" * " + k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pw.println();
|
||||
pw.close();
|
||||
|
||||
sender().sendMessage("Reported to: " + ff.getPath());
|
||||
} catch(FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void exportObjects(IrisBiome bb, PrintWriter pw, Engine g, KMap<String, KMap<String, KList<String>>> objects) {
|
||||
String n1 = bb.getName() + " [" + Form.capitalize(bb.getInferredType().name().toLowerCase()) + "] " + " (" + bb.getLoadFile().getName() + ")";
|
||||
int m = 0;
|
||||
KSet<String> stop = new KSet<>();
|
||||
for(IrisObjectPlacement f : bb.getObjects()) {
|
||||
m++;
|
||||
String n2 = "Placement #" + m + " (" + f.getPlace().size() + " possible objects)";
|
||||
|
||||
for(String i : f.getPlace()) {
|
||||
String nn3 = i + ": [ERROR] Failed to find object!";
|
||||
|
||||
try {
|
||||
if(stop.contains(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
File ff = g.getData().getObjectLoader().findFile(i);
|
||||
BlockVector sz = IrisObject.sampleSize(ff);
|
||||
nn3 = i + ": size=[" + sz.getBlockX() + "," + sz.getBlockY() + "," + sz.getBlockZ() + "] location=[" + ff.getPath() + "]";
|
||||
stop.add(i);
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
String n3 = nn3;
|
||||
objects.computeIfAbsent(n1, (k1) -> new KMap<>())
|
||||
.computeIfAbsent(n2, (k) -> new KList<>()).addIfMissing(n3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if server GUIs are not enabled
|
||||
*/
|
||||
private boolean noGUI() {
|
||||
if(!IrisSettings.get().getGui().isUseServerLaunchedGuis()) {
|
||||
sender().sendMessage(C.RED + "You must have server launched GUIs enabled in the settings!");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if no studio is open or the player is not in one
|
||||
*/
|
||||
private boolean noStudio() {
|
||||
if(!sender().isPlayer()) {
|
||||
sender().sendMessage(C.RED + "Players only!");
|
||||
return true;
|
||||
}
|
||||
if(!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||
sender().sendMessage(C.RED + "No studio world is open!");
|
||||
return true;
|
||||
}
|
||||
if(!engine().isStudio()) {
|
||||
sender().sendMessage(C.RED + "You must be in a studio world!");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public void files(File clean, KList<File> files) {
|
||||
if(clean.isDirectory()) {
|
||||
for(File i : clean.listFiles()) {
|
||||
files(i, files);
|
||||
}
|
||||
} else if(clean.getName().endsWith(".json")) {
|
||||
try {
|
||||
files.add(clean);
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.error("Failed to beautify " + clean.getAbsolutePath() + " You may have errors in your json!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fixBlocks(JSONObject obj) {
|
||||
for(String i : obj.keySet()) {
|
||||
Object o = obj.get(i);
|
||||
|
||||
if(i.equals("block") && o instanceof String && !o.toString().trim().isEmpty() && !o.toString().contains(":")) {
|
||||
obj.put(i, "minecraft:" + o);
|
||||
}
|
||||
|
||||
if(o instanceof JSONObject) {
|
||||
fixBlocks((JSONObject) o);
|
||||
} else if(o instanceof JSONArray) {
|
||||
fixBlocks((JSONArray) o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fixBlocks(JSONArray obj) {
|
||||
for(int i = 0; i < obj.length(); i++) {
|
||||
Object o = obj.get(i);
|
||||
|
||||
if(o instanceof JSONObject) {
|
||||
fixBlocks((JSONObject) o);
|
||||
} else if(o instanceof JSONArray) {
|
||||
fixBlocks((JSONArray) o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
153
src/main/java/com/volmit/iris/core/commands/CommandWhat.java
Normal file
153
src/main/java/com/volmit/iris/core/commands/CommandWhat.java
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.edit.BlockSignal;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.matter.MatterMarker;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.FluidCollisionMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@Decree(name = "what", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris What?")
|
||||
public class CommandWhat implements DecreeExecutor {
|
||||
@Decree(description = "What is in my hand?", origin = DecreeOrigin.PLAYER)
|
||||
public void hand() {
|
||||
try {
|
||||
BlockData bd = player().getInventory().getItemInMainHand().getType().createBlockData();
|
||||
if(!bd.getMaterial().equals(Material.AIR)) {
|
||||
sender().sendMessage("Material: " + C.GREEN + bd.getMaterial().name());
|
||||
sender().sendMessage("Full: " + C.WHITE + bd.getAsString(true));
|
||||
} else {
|
||||
sender().sendMessage("Please hold a block/item");
|
||||
}
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Material bd = player().getInventory().getItemInMainHand().getType();
|
||||
if(!bd.equals(Material.AIR)) {
|
||||
sender().sendMessage("Material: " + C.GREEN + bd.name());
|
||||
} else {
|
||||
sender().sendMessage("Please hold a block/item");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "What biome am i in?", origin = DecreeOrigin.PLAYER)
|
||||
public void biome() {
|
||||
try {
|
||||
IrisBiome b = engine().getBiome(player().getLocation().getBlockX(), player().getLocation().getBlockY() - player().getWorld().getMinHeight(), player().getLocation().getBlockZ());
|
||||
sender().sendMessage("IBiome: " + b.getLoadKey() + " (" + b.getDerivative().name() + ")");
|
||||
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage("Non-Iris Biome: " + player().getLocation().getBlock().getBiome().name());
|
||||
|
||||
if(player().getLocation().getBlock().getBiome().equals(Biome.CUSTOM)) {
|
||||
try {
|
||||
sender().sendMessage("Data Pack Biome: " + INMS.get().getTrueBiomeBaseKey(player().getLocation()) + " (ID: " + INMS.get().getTrueBiomeBaseId(INMS.get().getTrueBiomeBase(player().getLocation())) + ")");
|
||||
} catch(Throwable ee) {
|
||||
Iris.reportError(ee);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "What block am i looking at?", origin = DecreeOrigin.PLAYER)
|
||||
public void block() {
|
||||
BlockData bd;
|
||||
try {
|
||||
bd = player().getTargetBlockExact(128, FluidCollisionMode.NEVER).getBlockData();
|
||||
} catch(NullPointerException e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage("Please look at any block, not at the sky");
|
||||
bd = null;
|
||||
}
|
||||
|
||||
if(bd != null) {
|
||||
sender().sendMessage("Material: " + C.GREEN + bd.getMaterial().name());
|
||||
sender().sendMessage("Full: " + C.WHITE + bd.getAsString(true));
|
||||
|
||||
if(B.isStorage(bd)) {
|
||||
sender().sendMessage(C.YELLOW + "* Storage Block (Loot Capable)");
|
||||
}
|
||||
|
||||
if(B.isLit(bd)) {
|
||||
sender().sendMessage(C.YELLOW + "* Lit Block (Light Capable)");
|
||||
}
|
||||
|
||||
if(B.isFoliage(bd)) {
|
||||
sender().sendMessage(C.YELLOW + "* Foliage Block");
|
||||
}
|
||||
|
||||
if(B.isDecorant(bd)) {
|
||||
sender().sendMessage(C.YELLOW + "* Decorant Block");
|
||||
}
|
||||
|
||||
if(B.isFluid(bd)) {
|
||||
sender().sendMessage(C.YELLOW + "* Fluid Block");
|
||||
}
|
||||
|
||||
if(B.isFoliagePlantable(bd)) {
|
||||
sender().sendMessage(C.YELLOW + "* Plantable Foliage Block");
|
||||
}
|
||||
|
||||
if(B.isSolid(bd)) {
|
||||
sender().sendMessage(C.YELLOW + "* Solid Block");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Show markers in chunk", origin = DecreeOrigin.PLAYER)
|
||||
public void markers(@Param(description = "Marker name such as cave_floor or cave_ceiling") String marker) {
|
||||
Chunk c = player().getLocation().getChunk();
|
||||
|
||||
if(IrisToolbelt.isIrisWorld(c.getWorld())) {
|
||||
int m = 1;
|
||||
AtomicInteger v = new AtomicInteger(0);
|
||||
|
||||
for(int xxx = c.getX() - 4; xxx <= c.getX() + 4; xxx++) {
|
||||
for(int zzz = c.getZ() - 4; zzz <= c.getZ() + 4; zzz++) {
|
||||
IrisToolbelt.access(c.getWorld()).getEngine().getMantle().findMarkers(xxx, zzz, new MatterMarker(marker))
|
||||
.convert((i) -> i.toLocation(c.getWorld())).forEach((i) -> {
|
||||
J.s(() -> BlockSignal.of(i.getBlock(), 100));
|
||||
v.incrementAndGet();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
sender().sendMessage("Found " + v.get() + " Nearby Markers (" + marker + ")");
|
||||
} else {
|
||||
sender().sendMessage("Iris worlds only.");
|
||||
}
|
||||
}
|
||||
}
|
||||
43
src/main/java/com/volmit/iris/core/edit/BlockEditor.java
Normal file
43
src/main/java/com/volmit/iris/core/edit/BlockEditor.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.edit;
|
||||
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.io.Closeable;
|
||||
|
||||
public interface BlockEditor extends Closeable {
|
||||
long last();
|
||||
|
||||
void set(int x, int y, int z, BlockData d);
|
||||
|
||||
BlockData get(int x, int y, int z);
|
||||
|
||||
void setBiome(int x, int z, Biome b);
|
||||
|
||||
void setBiome(int x, int y, int z, Biome b);
|
||||
|
||||
@Override
|
||||
void close();
|
||||
|
||||
Biome getBiome(int x, int y, int z);
|
||||
|
||||
Biome getBiome(int x, int z);
|
||||
}
|
||||
@@ -1,8 +1,26 @@
|
||||
package com.volmit.iris.manager.edit;
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import com.volmit.iris.util.J;
|
||||
import com.volmit.iris.scaffold.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.SR;
|
||||
package com.volmit.iris.core.edit;
|
||||
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.SR;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -10,19 +28,45 @@ import org.bukkit.entity.FallingBlock;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@SuppressWarnings("InstantiationOfUtilityClass")
|
||||
public class BlockSignal {
|
||||
public static void of(Block block, int ticks)
|
||||
{
|
||||
public static final AtomicInteger active = new AtomicInteger(0);
|
||||
|
||||
public BlockSignal(Block block, int ticks) {
|
||||
active.incrementAndGet();
|
||||
Location tg = block.getLocation().clone().add(0.5, 0, 0.5);
|
||||
FallingBlock e = block.getWorld().spawnFallingBlock(tg, block.getBlockData());
|
||||
e.setGravity(false);
|
||||
e.setInvulnerable(true);
|
||||
e.setGlowing(true);
|
||||
e.setDropItem(false);
|
||||
e.setHurtEntities(false);
|
||||
e.setSilent(true);
|
||||
e.setTicksLived(1);
|
||||
e.setVelocity(new Vector(0, 0, 0));
|
||||
J.s(() -> {
|
||||
e.remove();
|
||||
active.decrementAndGet();
|
||||
BlockData type = block.getBlockData();
|
||||
MultiBurst.burst.lazy(() -> {
|
||||
for(Player i : block.getWorld().getPlayers()) {
|
||||
i.sendBlockChange(block.getLocation(), block.getBlockData());
|
||||
}
|
||||
});
|
||||
}, ticks);
|
||||
}
|
||||
|
||||
public static void of(Block block, int ticks) {
|
||||
new BlockSignal(block, ticks);
|
||||
}
|
||||
|
||||
public static void of(Block block)
|
||||
{
|
||||
public static void of(Block block) {
|
||||
of(block, 100);
|
||||
}
|
||||
|
||||
public static Runnable forever(Block block)
|
||||
{
|
||||
public static Runnable forever(Block block) {
|
||||
Location tg = block.getLocation().clone().add(0.5, 0, 0.5).clone();
|
||||
FallingBlock e = block.getWorld().spawnFallingBlock(tg.clone(), block.getBlockData());
|
||||
e.setGravity(false);
|
||||
@@ -38,8 +82,7 @@ public class BlockSignal {
|
||||
new SR(20) {
|
||||
@Override
|
||||
public void run() {
|
||||
if(e.isDead())
|
||||
{
|
||||
if(e.isDead()) {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
@@ -55,37 +98,10 @@ public class BlockSignal {
|
||||
BlockData type = block.getBlockData();
|
||||
|
||||
MultiBurst.burst.lazy(() -> {
|
||||
for(Player i : block.getWorld().getPlayers())
|
||||
{
|
||||
for(Player i : block.getWorld().getPlayers()) {
|
||||
i.sendBlockChange(block.getLocation(), block.getBlockData());
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
public BlockSignal(Block block, int ticks)
|
||||
{
|
||||
Location tg = block.getLocation().clone().add(0.5, 0, 0.5).clone();
|
||||
FallingBlock e = block.getWorld().spawnFallingBlock(tg.clone(), block.getBlockData());
|
||||
e.setGravity(false);
|
||||
e.setInvulnerable(true);
|
||||
e.setGlowing(true);
|
||||
e.teleport(tg.clone());
|
||||
e.setDropItem(false);
|
||||
e.setHurtEntities(false);
|
||||
e.setSilent(true);
|
||||
e.setTicksLived(1);
|
||||
e.setVelocity(new Vector(0, 0, 0));
|
||||
J.s(() -> {
|
||||
e.remove();
|
||||
BlockData type = block.getBlockData();
|
||||
|
||||
MultiBurst.burst.lazy(() -> {
|
||||
for(Player i : block.getWorld().getPlayers())
|
||||
{
|
||||
i.sendBlockChange(block.getLocation(), block.getBlockData());
|
||||
}
|
||||
});
|
||||
}, ticks);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.edit;
|
||||
|
||||
import com.volmit.iris.util.math.M;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
@SuppressWarnings("ClassCanBeRecord")
|
||||
public class BukkitBlockEditor implements BlockEditor {
|
||||
private final World world;
|
||||
|
||||
public BukkitBlockEditor(World world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int x, int y, int z, BlockData d) {
|
||||
world.getBlockAt(x, y, z).setBlockData(d, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData get(int x, int y, int z) {
|
||||
return world.getBlockAt(x, y, z).getBlockData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public long last() {
|
||||
return M.ms();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void setBiome(int x, int z, Biome b) {
|
||||
world.setBiome(x, z, b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int y, int z, Biome b) {
|
||||
world.setBiome(x, y, z, b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Biome getBiome(int x, int y, int z) {
|
||||
return world.getBiome(x, y, z);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public Biome getBiome(int x, int z) {
|
||||
return world.getBiome(x, z);
|
||||
}
|
||||
}
|
||||
127
src/main/java/com/volmit/iris/core/edit/DustRevealer.java
Normal file
127
src/main/java/com/volmit/iris/core/edit/DustRevealer.java
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.edit;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.math.BlockPosition;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
@SuppressWarnings("ALL")
|
||||
@Data
|
||||
public class DustRevealer {
|
||||
private final Engine engine;
|
||||
private final World world;
|
||||
private final BlockPosition block;
|
||||
private final String key;
|
||||
private final KList<BlockPosition> hits;
|
||||
|
||||
public DustRevealer(Engine engine, World world, BlockPosition block, String key, KList<BlockPosition> hits) {
|
||||
this.engine = engine;
|
||||
this.world = world;
|
||||
this.block = block;
|
||||
this.key = key;
|
||||
this.hits = hits;
|
||||
|
||||
J.s(() -> {
|
||||
new BlockSignal(world.getBlockAt(block.getX(), block.getY(), block.getZ()), 10);
|
||||
if(M.r(0.25)) {
|
||||
world.playSound(block.toBlock(world).getLocation(), Sound.BLOCK_AMETHYST_BLOCK_CHIME, 1f, RNG.r.f(0.2f, 2f));
|
||||
}
|
||||
J.a(() -> {
|
||||
while(BlockSignal.active.get() > 128) {
|
||||
J.sleep(5);
|
||||
}
|
||||
|
||||
try {
|
||||
is(new BlockPosition(block.getX() + 1, block.getY(), block.getZ()));
|
||||
is(new BlockPosition(block.getX() - 1, block.getY(), block.getZ()));
|
||||
is(new BlockPosition(block.getX(), block.getY() + 1, block.getZ()));
|
||||
is(new BlockPosition(block.getX(), block.getY() - 1, block.getZ()));
|
||||
is(new BlockPosition(block.getX(), block.getY(), block.getZ() + 1));
|
||||
is(new BlockPosition(block.getX(), block.getY(), block.getZ() - 1));
|
||||
is(new BlockPosition(block.getX() + 1, block.getY(), block.getZ() + 1));
|
||||
is(new BlockPosition(block.getX() + 1, block.getY(), block.getZ() - 1));
|
||||
is(new BlockPosition(block.getX() - 1, block.getY(), block.getZ() + 1));
|
||||
is(new BlockPosition(block.getX() - 1, block.getY(), block.getZ() - 1));
|
||||
is(new BlockPosition(block.getX() + 1, block.getY() + 1, block.getZ()));
|
||||
is(new BlockPosition(block.getX() + 1, block.getY() - 1, block.getZ()));
|
||||
is(new BlockPosition(block.getX() - 1, block.getY() + 1, block.getZ()));
|
||||
is(new BlockPosition(block.getX() - 1, block.getY() - 1, block.getZ()));
|
||||
is(new BlockPosition(block.getX(), block.getY() + 1, block.getZ() - 1));
|
||||
is(new BlockPosition(block.getX(), block.getY() + 1, block.getZ() + 1));
|
||||
is(new BlockPosition(block.getX(), block.getY() - 1, block.getZ() - 1));
|
||||
is(new BlockPosition(block.getX(), block.getY() - 1, block.getZ() + 1));
|
||||
is(new BlockPosition(block.getX() - 1, block.getY() + 1, block.getZ() - 1));
|
||||
is(new BlockPosition(block.getX() - 1, block.getY() + 1, block.getZ() + 1));
|
||||
is(new BlockPosition(block.getX() - 1, block.getY() - 1, block.getZ() - 1));
|
||||
is(new BlockPosition(block.getX() - 1, block.getY() - 1, block.getZ() + 1));
|
||||
is(new BlockPosition(block.getX() + 1, block.getY() + 1, block.getZ() - 1));
|
||||
is(new BlockPosition(block.getX() + 1, block.getY() + 1, block.getZ() + 1));
|
||||
is(new BlockPosition(block.getX() + 1, block.getY() - 1, block.getZ() - 1));
|
||||
is(new BlockPosition(block.getX() + 1, block.getY() - 1, block.getZ() + 1));
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}, RNG.r.i(2, 8));
|
||||
}
|
||||
|
||||
public static void spawn(Block block, VolmitSender sender) {
|
||||
World world = block.getWorld();
|
||||
Engine access = IrisToolbelt.access(world).getEngine();
|
||||
|
||||
if(access != null) {
|
||||
String a = access.getObjectPlacementKey(block.getX(), block.getY() - block.getWorld().getMinHeight(), block.getZ());
|
||||
if(a != null) {
|
||||
world.playSound(block.getLocation(), Sound.ITEM_LODESTONE_COMPASS_LOCK, 1f, 0.1f);
|
||||
|
||||
sender.sendMessage("Found object " + a);
|
||||
J.a(() -> {
|
||||
new DustRevealer(access, world, new BlockPosition(block.getX(), block.getY(), block.getZ()), a, new KList<>());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean is(BlockPosition a) {
|
||||
int betterY = a.getY() - world.getMinHeight();
|
||||
if(isValidTry(a) && engine.getObjectPlacementKey(a.getX(), betterY, a.getZ()) != null && engine.getObjectPlacementKey(a.getX(), betterY, a.getZ()).equals(key)) {
|
||||
hits.add(a);
|
||||
new DustRevealer(engine, world, a, key, hits);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isValidTry(BlockPosition b) {
|
||||
return !hits.contains(b);
|
||||
}
|
||||
}
|
||||
264
src/main/java/com/volmit/iris/core/edit/JigsawEditor.java
Normal file
264
src/main/java/com/volmit/iris/core/edit/JigsawEditor.java
Normal file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.edit;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.service.WandSVC;
|
||||
import com.volmit.iris.engine.object.IrisDirection;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPieceConnector;
|
||||
import com.volmit.iris.engine.object.IrisObject;
|
||||
import com.volmit.iris.engine.object.IrisPosition;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.Cuboid;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class JigsawEditor implements Listener {
|
||||
public static final KMap<Player, JigsawEditor> editors = new KMap<>();
|
||||
private final Player player;
|
||||
private final IrisObject object;
|
||||
private final File targetSaveLocation;
|
||||
private final IrisJigsawPiece piece;
|
||||
private final Location origin;
|
||||
private final Cuboid cuboid;
|
||||
private final int ticker;
|
||||
private final KMap<IrisPosition, Runnable> falling = new KMap<>();
|
||||
private final ChronoLatch cl = new ChronoLatch(100);
|
||||
private Location target;
|
||||
|
||||
public JigsawEditor(Player player, IrisJigsawPiece piece, IrisObject object, File saveLocation) {
|
||||
if(editors.containsKey(player)) {
|
||||
editors.get(player).close();
|
||||
}
|
||||
|
||||
editors.put(player, this);
|
||||
if(object == null)
|
||||
{
|
||||
throw new RuntimeException("Object is null! " + piece.getObject());
|
||||
}
|
||||
this.object = object;
|
||||
this.player = player;
|
||||
origin = player.getLocation().clone().add(0, 7, 0);
|
||||
target = origin;
|
||||
this.targetSaveLocation = saveLocation;
|
||||
this.piece = piece == null ? new IrisJigsawPiece() : piece;
|
||||
this.piece.setObject(object.getLoadKey());
|
||||
cuboid = new Cuboid(origin.clone(), origin.clone().add(object.getW() - 1, object.getH() - 1, object.getD() - 1));
|
||||
ticker = J.sr(this::onTick, 0);
|
||||
J.s(() -> object.placeCenterY(origin));
|
||||
Iris.instance.registerListener(this);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(PlayerMoveEvent e) {
|
||||
if(e.getPlayer().equals(player)) {
|
||||
try {
|
||||
target = player.getTargetBlockExact(7).getLocation();
|
||||
} catch(Throwable ex) {
|
||||
Iris.reportError(ex);
|
||||
target = player.getLocation();
|
||||
return;
|
||||
}
|
||||
|
||||
if(cuboid.contains(target)) {
|
||||
for(IrisPosition i : falling.k()) {
|
||||
Location at = toLocation(i);
|
||||
|
||||
if(at.equals(target)) {
|
||||
falling.remove(i).run();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Location toLocation(IrisPosition i) {
|
||||
return origin.clone()
|
||||
.add(new Vector(i.getX(), i.getY(), i.getZ()))
|
||||
.add(object.getCenter())
|
||||
.getBlock()
|
||||
.getLocation();
|
||||
}
|
||||
|
||||
public IrisPosition toPosition(Location l) {
|
||||
return new IrisPosition(l.clone().getBlock().getLocation()
|
||||
.subtract(origin.clone())
|
||||
.subtract(object.getCenter())
|
||||
.add(1, 1, 1)
|
||||
.toVector());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(PlayerInteractEvent e) {
|
||||
if(e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) {
|
||||
if(e.getClickedBlock() != null && cuboid.contains(e.getClickedBlock().getLocation()) && e.getPlayer().equals(player)) {
|
||||
IrisPosition pos = toPosition(e.getClickedBlock().getLocation());
|
||||
IrisJigsawPieceConnector connector = null;
|
||||
for(IrisJigsawPieceConnector i : piece.getConnectors()) {
|
||||
if(i.getPosition().equals(pos)) {
|
||||
connector = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!player.isSneaking() && connector == null) {
|
||||
connector = new IrisJigsawPieceConnector();
|
||||
connector.setDirection(IrisDirection.getDirection(e.getBlockFace()));
|
||||
connector.setPosition(pos);
|
||||
piece.getConnectors().add(connector);
|
||||
player.playSound(e.getClickedBlock().getLocation(), Sound.ENTITY_ITEM_FRAME_ADD_ITEM, 1f, 1f);
|
||||
} else if(player.isSneaking() && connector != null) {
|
||||
piece.getConnectors().remove(connector);
|
||||
player.playSound(e.getClickedBlock().getLocation(), Sound.ENTITY_ITEM_FRAME_REMOVE_ITEM, 1f, 1f);
|
||||
} else if(connector != null && !player.isSneaking()) {
|
||||
connector.setDirection(IrisDirection.getDirection(e.getBlockFace()));
|
||||
player.playSound(e.getClickedBlock().getLocation(), Sound.ENTITY_ITEM_FRAME_ROTATE_ITEM, 1f, 1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeKey(JSONObject o, String... path)
|
||||
{
|
||||
if(path.length == 1)
|
||||
{
|
||||
o.remove(path[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> s = new java.util.ArrayList<>(List.of(path));
|
||||
s.remove(0);
|
||||
removeKey(o.getJSONObject(path[0]), s.toArray(new String[0]));
|
||||
}
|
||||
|
||||
private List<JSONObject> getObjectsInArray(JSONObject a, String key)
|
||||
{
|
||||
KList<JSONObject> o = new KList<>();
|
||||
|
||||
for(int i = 0; i < a.getJSONArray(key).length(); i++)
|
||||
{
|
||||
o.add(a.getJSONArray(key).getJSONObject(i));
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
exit();
|
||||
try {
|
||||
JSONObject j = new JSONObject(new Gson().toJson(piece));
|
||||
// Remove sub-key
|
||||
removeKey(j, "placementOptions", "translateCenter"); // should work
|
||||
J.attempt(() -> j.getJSONObject("placementOptions").remove("translateCenter")); // otherwise
|
||||
|
||||
// remove root key
|
||||
removeKey(j, "placementOptions"); // should work
|
||||
j.remove("placementOptions"); // otherwise
|
||||
|
||||
// Remove key in all objects in array
|
||||
for(JSONObject i : getObjectsInArray(j, "connectors"))
|
||||
{
|
||||
removeKey(i, "rotateConnector");
|
||||
}
|
||||
|
||||
IO.writeAll(targetSaveLocation, j.toString(4));
|
||||
} catch(IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void exit() {
|
||||
J.car(ticker);
|
||||
Iris.instance.unregisterListener(this);
|
||||
try {
|
||||
J.sfut(() -> {
|
||||
object.unplaceCenterY(origin);
|
||||
falling.v().forEach(Runnable::run);
|
||||
}).get();
|
||||
} catch(InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
editors.remove(player);
|
||||
}
|
||||
|
||||
public void onTick() {
|
||||
if(cl.flip()) {
|
||||
Iris.service(WandSVC.class).draw(cuboid, player);
|
||||
|
||||
f:
|
||||
for(IrisPosition i : falling.k()) {
|
||||
for(IrisJigsawPieceConnector j : piece.getConnectors()) {
|
||||
if(j.getPosition().equals(i)) {
|
||||
continue f;
|
||||
}
|
||||
}
|
||||
|
||||
falling.remove(i).run();
|
||||
}
|
||||
|
||||
for(IrisJigsawPieceConnector i : piece.getConnectors()) {
|
||||
IrisPosition pos = i.getPosition();
|
||||
Location at = toLocation(pos);
|
||||
|
||||
Vector dir = i.getDirection().toVector().clone();
|
||||
|
||||
|
||||
for(int ix = 0; ix < RNG.r.i(1, 3); ix++) {
|
||||
at.getWorld().spawnParticle(Particle.SOUL_FIRE_FLAME, at.clone().getBlock().getLocation().add(0.25, 0.25, 0.25).add(RNG.r.d(0.5), RNG.r.d(0.5), RNG.r.d(0.5)), 0, dir.getX(), dir.getY(), dir.getZ(), 0.092 + RNG.r.d(-0.03, 0.08));
|
||||
}
|
||||
|
||||
if(at.getBlock().getLocation().equals(target)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!falling.containsKey(pos)) {
|
||||
if(at.getBlock().getType().isAir()) {
|
||||
at.getBlock().setType(Material.STONE);
|
||||
}
|
||||
|
||||
falling.put(pos, BlockSignal.forever(at.getBlock()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.events;
|
||||
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class IrisEngineEvent extends Event {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private Engine engine;
|
||||
|
||||
public IrisEngineEvent() {
|
||||
super(true);
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.events;
|
||||
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
public class IrisEngineHotloadEvent extends IrisEngineEvent {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
public IrisEngineHotloadEvent(Engine engine) {
|
||||
super(engine);
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
350
src/main/java/com/volmit/iris/core/gui/NoiseExplorerGUI.java
Normal file
350
src/main/java/com/volmit/iris/core/gui/NoiseExplorerGUI.java
Normal file
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.gui;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.events.IrisEngineHotloadEvent;
|
||||
import com.volmit.iris.engine.object.NoiseStyle;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.function.Function2;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.math.RollingSequence;
|
||||
import com.volmit.iris.util.noise.CNG;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLayeredPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JViewport;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, Listener {
|
||||
|
||||
private static final long serialVersionUID = 2094606939770332040L;
|
||||
|
||||
static JComboBox<String> combo;
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
static boolean hd = false;
|
||||
static double ascale = 10;
|
||||
static double oxp = 0;
|
||||
static double ozp = 0;
|
||||
static double mxx = 0;
|
||||
static double mzz = 0;
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
static boolean down = false;
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
RollingSequence r = new RollingSequence(20);
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
boolean colorMode = true;
|
||||
double scale = 1;
|
||||
CNG cng = NoiseStyle.STATIC.create(new RNG(RNG.r.nextLong()));
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
MultiBurst gx = MultiBurst.burst;
|
||||
ReentrantLock l = new ReentrantLock();
|
||||
BufferedImage img;
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
Function2<Double, Double, Double> generator;
|
||||
Supplier<Function2<Double, Double, Double>> loader;
|
||||
double ox = 0; //Offset X
|
||||
double oz = 0; //Offset Y
|
||||
double mx = 0;
|
||||
double mz = 0;
|
||||
double lx = Double.MAX_VALUE; //MouseX
|
||||
double lz = Double.MAX_VALUE; //MouseY
|
||||
double t;
|
||||
double tz;
|
||||
|
||||
public NoiseExplorerGUI() {
|
||||
Iris.instance.registerListener(this);
|
||||
addMouseWheelListener(this);
|
||||
addMouseMotionListener(new MouseMotionListener() {
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
Point cp = e.getPoint();
|
||||
|
||||
lx = (cp.getX());
|
||||
lz = (cp.getY());
|
||||
mx = lx;
|
||||
mz = lz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
Point cp = e.getPoint();
|
||||
ox += (lx - cp.getX()) * scale;
|
||||
oz += (lz - cp.getY()) * scale;
|
||||
lx = cp.getX();
|
||||
lz = cp.getY();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void createAndShowGUI(Supplier<Function2<Double, Double, Double>> loader, String genName) {
|
||||
JFrame frame = new JFrame("Noise Explorer: " + genName);
|
||||
NoiseExplorerGUI nv = new NoiseExplorerGUI();
|
||||
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||
JLayeredPane pane = new JLayeredPane();
|
||||
nv.setSize(new Dimension(1440, 820));
|
||||
pane.add(nv, 1, 0);
|
||||
nv.loader = loader;
|
||||
nv.generator = loader.get();
|
||||
frame.add(pane);
|
||||
File file = Iris.getCached("Iris Icon", "https://raw.githubusercontent.com/VolmitSoftware/Iris/master/icon.png");
|
||||
|
||||
if(file != null) {
|
||||
try {
|
||||
frame.setIconImage(ImageIO.read(file));
|
||||
} catch(IOException e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
frame.setSize(1440, 820);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private static void createAndShowGUI() {
|
||||
JFrame frame = new JFrame("Noise Explorer");
|
||||
NoiseExplorerGUI nv = new NoiseExplorerGUI();
|
||||
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||
KList<String> li = new KList<>(NoiseStyle.values()).toStringList().sort();
|
||||
combo = new JComboBox<>(li.toArray(new String[0]));
|
||||
combo.setSelectedItem("STATIC");
|
||||
combo.setFocusable(false);
|
||||
combo.addActionListener(e -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
String b = (String) (((JComboBox<String>) e.getSource()).getSelectedItem());
|
||||
NoiseStyle s = NoiseStyle.valueOf(b);
|
||||
nv.cng = s.create(RNG.r.nextParallelRNG(RNG.r.imax()));
|
||||
});
|
||||
|
||||
combo.setSize(500, 30);
|
||||
JLayeredPane pane = new JLayeredPane();
|
||||
nv.setSize(new Dimension(1440, 820));
|
||||
pane.add(nv, 1, 0);
|
||||
pane.add(combo, 2, 0);
|
||||
frame.add(pane);
|
||||
File file = Iris.getCached("Iris Icon", "https://raw.githubusercontent.com/VolmitSoftware/Iris/master/icon.png");
|
||||
|
||||
if(file != null) {
|
||||
try {
|
||||
frame.setIconImage(ImageIO.read(file));
|
||||
} catch(IOException e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
frame.setSize(1440, 820);
|
||||
frame.setVisible(true);
|
||||
frame.addWindowListener(new java.awt.event.WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
|
||||
Iris.instance.unregisterListener(nv);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void launch(Supplier<Function2<Double, Double, Double>> gen, String genName) {
|
||||
EventQueue.invokeLater(() -> createAndShowGUI(gen, genName));
|
||||
}
|
||||
|
||||
public static void launch() {
|
||||
EventQueue.invokeLater(NoiseExplorerGUI::createAndShowGUI);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(IrisEngineHotloadEvent e) {
|
||||
if(generator != null)
|
||||
generator = loader.get();
|
||||
}
|
||||
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
|
||||
int notches = e.getWheelRotation();
|
||||
if(e.isControlDown()) {
|
||||
t = t + ((0.0025 * t) * notches);
|
||||
return;
|
||||
}
|
||||
|
||||
scale = scale + ((0.044 * scale) * notches);
|
||||
scale = Math.max(scale, 0.00001);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
if(scale < ascale) {
|
||||
ascale -= Math.abs(scale - ascale) * 0.16;
|
||||
}
|
||||
|
||||
if(scale > ascale) {
|
||||
ascale += Math.abs(ascale - scale) * 0.16;
|
||||
}
|
||||
|
||||
if(t < tz) {
|
||||
tz -= Math.abs(t - tz) * 0.29;
|
||||
}
|
||||
|
||||
if(t > tz) {
|
||||
tz += Math.abs(tz - t) * 0.29;
|
||||
}
|
||||
|
||||
if(ox < oxp) {
|
||||
oxp -= Math.abs(ox - oxp) * 0.16;
|
||||
}
|
||||
|
||||
if(ox > oxp) {
|
||||
oxp += Math.abs(oxp - ox) * 0.16;
|
||||
}
|
||||
|
||||
if(oz < ozp) {
|
||||
ozp -= Math.abs(oz - ozp) * 0.16;
|
||||
}
|
||||
|
||||
if(oz > ozp) {
|
||||
ozp += Math.abs(ozp - oz) * 0.16;
|
||||
}
|
||||
|
||||
if(mx < mxx) {
|
||||
mxx -= Math.abs(mx - mxx) * 0.16;
|
||||
}
|
||||
|
||||
if(mx > mxx) {
|
||||
mxx += Math.abs(mxx - mx) * 0.16;
|
||||
}
|
||||
|
||||
if(mz < mzz) {
|
||||
mzz -= Math.abs(mz - mzz) * 0.16;
|
||||
}
|
||||
|
||||
if(mz > mzz) {
|
||||
mzz += Math.abs(mzz - mz) * 0.16;
|
||||
}
|
||||
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
int accuracy = hd ? 1 : M.clip((r.getAverage() / 12D), 2D, 128D).intValue();
|
||||
accuracy = down ? accuracy * 4 : accuracy;
|
||||
int v = 1000;
|
||||
|
||||
if(g instanceof Graphics2D gg) {
|
||||
|
||||
if(getParent().getWidth() != w || getParent().getHeight() != h) {
|
||||
w = getParent().getWidth();
|
||||
h = getParent().getHeight();
|
||||
img = null;
|
||||
}
|
||||
|
||||
if(img == null) {
|
||||
img = new BufferedImage(w / accuracy, h / accuracy, BufferedImage.TYPE_INT_RGB);
|
||||
}
|
||||
|
||||
BurstExecutor e = gx.burst(w);
|
||||
|
||||
for(int x = 0; x < w / accuracy; x++) {
|
||||
int xx = x;
|
||||
|
||||
int finalAccuracy = accuracy;
|
||||
e.queue(() -> {
|
||||
for(int z = 0; z < h / finalAccuracy; z++) {
|
||||
double n = generator != null ? generator.apply(((xx * finalAccuracy) * ascale) + oxp, ((z * finalAccuracy) * ascale) + ozp) : cng.noise(((xx * finalAccuracy) * ascale) + oxp, ((z * finalAccuracy) * ascale) + ozp);
|
||||
n = n > 1 ? 1 : n < 0 ? 0 : n;
|
||||
|
||||
try {
|
||||
Color color = colorMode ? Color.getHSBColor((float) (n), 1f - (float) (n * n * n * n * n * n), 1f - (float) n) : Color.getHSBColor(0f, 0f, (float) n);
|
||||
int rgb = color.getRGB();
|
||||
img.setRGB(xx, z, rgb);
|
||||
} catch(Throwable xxx) {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
e.complete();
|
||||
gg.drawImage(img, 0, 0, getParent().getWidth() * accuracy, getParent().getHeight() * accuracy, (img, infoflags, x, y, width, height) -> true);
|
||||
}
|
||||
|
||||
p.end();
|
||||
|
||||
t += 1D;
|
||||
r.put(p.getMilliseconds());
|
||||
|
||||
if(!isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!getParent().isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!getParent().getParent().isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EventQueue.invokeLater(() ->
|
||||
{
|
||||
J.sleep((long) Math.max(0, 32 - r.getAverage()));
|
||||
repaint();
|
||||
});
|
||||
}
|
||||
|
||||
static class HandScrollListener extends MouseAdapter {
|
||||
private static final Point pp = new Point();
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
JViewport vport = (JViewport) e.getSource();
|
||||
JComponent label = (JComponent) vport.getView();
|
||||
Point cp = e.getPoint();
|
||||
Point vp = vport.getViewPosition();
|
||||
vp.translate(pp.x - cp.x, pp.y - cp.y);
|
||||
label.scrollRectToVisible(new Rectangle(vp, vport.getSize()));
|
||||
|
||||
pp.setLocation(cp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
pp.setLocation(e.getPoint());
|
||||
}
|
||||
}
|
||||
}
|
||||
440
src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java
Normal file
440
src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java
Normal file
@@ -0,0 +1,440 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.gui;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.pregenerator.IrisPregenerator;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.format.MemoryMonitor;
|
||||
import com.volmit.iris.util.function.Consumer2;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class PregeneratorJob implements PregenListener {
|
||||
private static final Color COLOR_EXISTS = parseColor("#4d7d5b");
|
||||
private static final Color COLOR_BLACK = parseColor("#4d7d5b");
|
||||
private static final Color COLOR_MANTLE = parseColor("#3c2773");
|
||||
private static final Color COLOR_GENERATING = parseColor("#66967f");
|
||||
private static final Color COLOR_NETWORK = parseColor("#a863c2");
|
||||
private static final Color COLOR_NETWORK_GENERATING = parseColor("#836b8c");
|
||||
private static final Color COLOR_GENERATED = parseColor("#65c295");
|
||||
private static final Color COLOR_CLEANED = parseColor("#34eb93");
|
||||
public static PregeneratorJob instance;
|
||||
private final MemoryMonitor monitor;
|
||||
private final PregenTask task;
|
||||
private final boolean saving;
|
||||
private final KList<Consumer<Double>> onProgress = new KList<>();
|
||||
private final KList<Runnable> whenDone = new KList<>();
|
||||
private final IrisPregenerator pregenerator;
|
||||
private final Position2 min;
|
||||
private final Position2 max;
|
||||
private JFrame frame;
|
||||
private PregenRenderer renderer;
|
||||
private int rgc = 0;
|
||||
private final ChronoLatch cl = new ChronoLatch(TimeUnit.MINUTES.toMillis(1));
|
||||
private String[] info;
|
||||
private final Engine engine;
|
||||
|
||||
public PregeneratorJob(PregenTask task, PregeneratorMethod method, Engine engine) {
|
||||
this.engine = engine;
|
||||
instance = this;
|
||||
monitor = new MemoryMonitor(50);
|
||||
saving = false;
|
||||
info = new String[] {"Initializing..."};
|
||||
this.task = task;
|
||||
this.pregenerator = new IrisPregenerator(task, method, this);
|
||||
max = new Position2(0, 0);
|
||||
min = new Position2(0, 0);
|
||||
task.iterateRegions((xx, zz) -> {
|
||||
min.setX(Math.min(xx << 5, min.getX()));
|
||||
min.setZ(Math.min(zz << 5, min.getZ()));
|
||||
max.setX(Math.max((xx << 5) + 31, max.getX()));
|
||||
max.setZ(Math.max((zz << 5) + 31, max.getZ()));
|
||||
});
|
||||
|
||||
if(IrisSettings.get().getGui().isUseServerLaunchedGuis()) {
|
||||
open();
|
||||
}
|
||||
|
||||
J.a(this.pregenerator::start, 20);
|
||||
}
|
||||
|
||||
public Mantle getMantle() {
|
||||
return pregenerator.getMantle();
|
||||
}
|
||||
|
||||
public static boolean shutdownInstance() {
|
||||
if(instance == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
J.a(() -> instance.pregenerator.close());
|
||||
return true;
|
||||
}
|
||||
|
||||
public static PregeneratorJob getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static boolean pauseResume() {
|
||||
if(instance == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(isPaused()) {
|
||||
instance.pregenerator.resume();
|
||||
} else {
|
||||
instance.pregenerator.pause();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isPaused() {
|
||||
if(instance == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return instance.paused();
|
||||
}
|
||||
|
||||
private static Color parseColor(String c) {
|
||||
String v = (c.startsWith("#") ? c : "#" + c).trim();
|
||||
try {
|
||||
return Color.decode(v);
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.error("Error Parsing 'color', (" + c + ")");
|
||||
}
|
||||
|
||||
return Color.RED;
|
||||
}
|
||||
|
||||
public PregeneratorJob onProgress(Consumer<Double> c) {
|
||||
onProgress.add(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PregeneratorJob whenDone(Runnable r) {
|
||||
whenDone.add(r);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void drawRegion(int x, int z, Color color) {
|
||||
J.a(() -> {
|
||||
PregenTask.iterateRegion(x, z, (xx, zz) -> {
|
||||
draw(xx, zz, color);
|
||||
J.sleep(3);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public void draw(int x, int z, Color color) {
|
||||
try {
|
||||
if(renderer != null && frame != null && frame.isVisible()) {
|
||||
renderer.func.accept(new Position2(x, z), color);
|
||||
}
|
||||
} catch(Throwable ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
J.a(() -> {
|
||||
pregenerator.close();
|
||||
close();
|
||||
instance = null;
|
||||
});
|
||||
}
|
||||
|
||||
public void close() {
|
||||
J.a(() -> {
|
||||
try {
|
||||
monitor.close();
|
||||
J.sleep(3000);
|
||||
frame.setVisible(false);
|
||||
} catch(Throwable e) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void open() {
|
||||
J.a(() -> {
|
||||
try {
|
||||
frame = new JFrame("Pregen View");
|
||||
renderer = new PregenRenderer();
|
||||
frame.addKeyListener(renderer);
|
||||
renderer.l = new ReentrantLock();
|
||||
renderer.frame = frame;
|
||||
renderer.job = this;
|
||||
renderer.func = (c, b) ->
|
||||
{
|
||||
renderer.l.lock();
|
||||
renderer.order.add(() -> renderer.draw(c, b, renderer.bg));
|
||||
renderer.l.unlock();
|
||||
};
|
||||
frame.add(renderer);
|
||||
frame.setSize(1000, 1000);
|
||||
frame.setVisible(true);
|
||||
} catch(Throwable e) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method) {
|
||||
info = new String[] {
|
||||
(paused() ? "PAUSED" : (saving ? "Saving... " : "Generating")) + " " + Form.f(generated) + " of " + Form.f(totalChunks) + " (" + Form.pc(percent, 0) + " Complete)",
|
||||
"Speed: " + Form.f(chunksPerSecond, 0) + " Chunks/s, " + Form.f(regionsPerMinute, 1) + " Regions/m, " + Form.f(chunksPerMinute, 0) + " Chunks/m",
|
||||
Form.duration(eta, 2) + " Remaining " + " (" + Form.duration(elapsed, 2) + " Elapsed)",
|
||||
"Generation Method: " + method,
|
||||
"Memory: " + Form.memSize(monitor.getUsedBytes(), 2) + " (" + Form.pc(monitor.getUsagePercent(), 0) + ") Pressure: " + Form.memSize(monitor.getPressure(), 0) + "/s",
|
||||
|
||||
};
|
||||
|
||||
for(Consumer<Double> i : onProgress) {
|
||||
i.accept(percent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkGenerating(int x, int z) {
|
||||
if(engine != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
draw(x, z, COLOR_GENERATING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkGenerated(int x, int z) {
|
||||
if(engine != null) {
|
||||
draw(x, z, engine.draw((x << 4) + 8, (z << 4) + 8));
|
||||
return;
|
||||
}
|
||||
|
||||
draw(x, z, COLOR_GENERATED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionGenerated(int x, int z) {
|
||||
shouldGc();
|
||||
rgc++;
|
||||
}
|
||||
|
||||
private void shouldGc() {
|
||||
if(cl.flip() && rgc > 16) {
|
||||
System.gc();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionGenerating(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkCleaned(int x, int z) {
|
||||
//draw(x, z, COLOR_CLEANED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionSkipped(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkStarted(int x, int z) {
|
||||
drawRegion(x, z, COLOR_NETWORK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkFailed(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkReclaim(int revert) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkGeneratedChunk(int x, int z) {
|
||||
draw(x, z, COLOR_NETWORK_GENERATING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkDownloaded(int x, int z) {
|
||||
drawRegion(x, z, COLOR_NETWORK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
close();
|
||||
instance = null;
|
||||
whenDone.forEach(Runnable::run);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaving() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkExistsInRegionGen(int x, int z) {
|
||||
if(engine != null) {
|
||||
draw(x, z, engine.draw((x << 4) + 8, (z << 4) + 8));
|
||||
return;
|
||||
}
|
||||
|
||||
draw(x, z, COLOR_EXISTS);
|
||||
}
|
||||
|
||||
private Position2 getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
private Position2 getMin() {
|
||||
return min;
|
||||
}
|
||||
|
||||
private boolean paused() {
|
||||
return pregenerator.paused();
|
||||
}
|
||||
|
||||
private String[] getProgress() {
|
||||
return info;
|
||||
}
|
||||
|
||||
public static class PregenRenderer extends JPanel implements KeyListener {
|
||||
private static final long serialVersionUID = 2094606939770332040L;
|
||||
private final KList<Runnable> order = new KList<>();
|
||||
private final int res = 512;
|
||||
private final BufferedImage image = new BufferedImage(res, res, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D bg;
|
||||
private PregeneratorJob job;
|
||||
private ReentrantLock l;
|
||||
private Consumer2<Position2, Color> func;
|
||||
private JFrame frame;
|
||||
|
||||
public PregenRenderer() {
|
||||
|
||||
}
|
||||
|
||||
public void paint(int x, int z, Color c) {
|
||||
func.accept(new Position2(x, z), c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics gx) {
|
||||
Graphics2D g = (Graphics2D) gx;
|
||||
bg = (Graphics2D) image.getGraphics();
|
||||
l.lock();
|
||||
|
||||
while(order.isNotEmpty()) {
|
||||
try {
|
||||
order.pop().run();
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
l.unlock();
|
||||
g.drawImage(image, 0, 0, getParent().getWidth(), getParent().getHeight(), (img, infoflags, x, y, width, height) -> true);
|
||||
g.setColor(Color.WHITE);
|
||||
g.setFont(new Font("Hevetica", Font.BOLD, 13));
|
||||
String[] prog = job.getProgress();
|
||||
int h = g.getFontMetrics().getHeight() + 5;
|
||||
int hh = 20;
|
||||
|
||||
if(job.paused()) {
|
||||
g.drawString("PAUSED", 20, hh += h);
|
||||
|
||||
g.drawString("Press P to Resume", 20, hh += h);
|
||||
} else {
|
||||
for(String i : prog) {
|
||||
g.drawString(i, 20, hh += h);
|
||||
}
|
||||
|
||||
g.drawString("Press P to Pause", 20, hh += h);
|
||||
}
|
||||
|
||||
J.sleep(IrisSettings.get().getGui().isMaximumPregenGuiFPS() ? 4 : 250);
|
||||
repaint();
|
||||
}
|
||||
|
||||
private void draw(Position2 p, Color c, Graphics2D bg) {
|
||||
double pw = M.lerpInverse(job.getMin().getX(), job.getMax().getX(), p.getX());
|
||||
double ph = M.lerpInverse(job.getMin().getZ(), job.getMax().getZ(), p.getZ());
|
||||
double pwa = M.lerpInverse(job.getMin().getX(), job.getMax().getX(), p.getX() + 1);
|
||||
double pha = M.lerpInverse(job.getMin().getZ(), job.getMax().getZ(), p.getZ() + 1);
|
||||
int x = (int) M.lerp(0, res, pw);
|
||||
int z = (int) M.lerp(0, res, ph);
|
||||
int xa = (int) M.lerp(0, res, pwa);
|
||||
int za = (int) M.lerp(0, res, pha);
|
||||
bg.setColor(c);
|
||||
bg.fillRect(x, z, xa - x, za - z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
if(e.getKeyCode() == KeyEvent.VK_P) {
|
||||
PregeneratorJob.pauseResume();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
frame.setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
845
src/main/java/com/volmit/iris/core/gui/VisionGUI.java
Normal file
845
src/main/java/com/volmit/iris/core/gui/VisionGUI.java
Normal file
@@ -0,0 +1,845 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.gui;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.gui.components.IrisRenderer;
|
||||
import com.volmit.iris.core.gui.components.RenderType;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.IrisComplex;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
import com.volmit.iris.engine.object.IrisWorld;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.math.BlockPosition;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RollingSequence;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.O;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.event.MouseInputListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener, MouseMotionListener, MouseInputListener {
|
||||
private static final long serialVersionUID = 2094606939770332040L;
|
||||
private final KList<LivingEntity> lastEntities = new KList<>();
|
||||
private final KMap<String, Long> notifications = new KMap<>();
|
||||
private final ChronoLatch centities = new ChronoLatch(1000);
|
||||
private final RollingSequence rs = new RollingSequence(512);
|
||||
private final O<Integer> m = new O<>();
|
||||
private final KMap<BlockPosition, BufferedImage> positions = new KMap<>();
|
||||
private final KMap<BlockPosition, BufferedImage> fastpositions = new KMap<>();
|
||||
private final KSet<BlockPosition> working = new KSet<>();
|
||||
private final KSet<BlockPosition> workingfast = new KSet<>();
|
||||
double tfps = 240D;
|
||||
int ltc = 3;
|
||||
private RenderType currentType = RenderType.BIOME;
|
||||
private boolean help = true;
|
||||
private boolean helpIgnored = false;
|
||||
private boolean shift = false;
|
||||
private Player player = null;
|
||||
private boolean debug = false;
|
||||
private boolean control = false;
|
||||
private boolean eco = false;
|
||||
private boolean lowtile = false;
|
||||
private boolean follow = false;
|
||||
private boolean alt = false;
|
||||
private IrisRenderer renderer;
|
||||
private IrisWorld world;
|
||||
private double velocity = 0;
|
||||
private int lowq = 12;
|
||||
private double scale = 128;
|
||||
private double mscale = 4D;
|
||||
private int w = 0;
|
||||
private int h = 0;
|
||||
private double lx = 0;
|
||||
private double lz = 0;
|
||||
private double ox = 0;
|
||||
private double oz = 0;
|
||||
private double hx = 0;
|
||||
private double hz = 0;
|
||||
private double oxp = 0;
|
||||
private double ozp = 0;
|
||||
private Engine engine;
|
||||
private int tid = 0;
|
||||
private final ExecutorService e = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), r -> {
|
||||
tid++;
|
||||
Thread t = new Thread(r);
|
||||
t.setName("Iris HD Renderer " + tid);
|
||||
t.setPriority(Thread.MIN_PRIORITY);
|
||||
t.setUncaughtExceptionHandler((et, e) ->
|
||||
{
|
||||
Iris.info("Exception encountered in " + et.getName());
|
||||
e.printStackTrace();
|
||||
});
|
||||
|
||||
return t;
|
||||
});
|
||||
|
||||
private final ExecutorService eh = Executors.newFixedThreadPool(ltc, r -> {
|
||||
tid++;
|
||||
Thread t = new Thread(r);
|
||||
t.setName("Iris Renderer " + tid);
|
||||
t.setPriority(Thread.NORM_PRIORITY);
|
||||
t.setUncaughtExceptionHandler((et, e) ->
|
||||
{
|
||||
Iris.info("Exception encountered in " + et.getName());
|
||||
e.printStackTrace();
|
||||
});
|
||||
|
||||
return t;
|
||||
});
|
||||
private BufferedImage texture;
|
||||
|
||||
public VisionGUI(JFrame frame) {
|
||||
m.set(8);
|
||||
rs.put(1);
|
||||
addMouseWheelListener(this);
|
||||
addMouseMotionListener(this);
|
||||
addMouseListener(this);
|
||||
frame.addKeyListener(this);
|
||||
J.a(() -> {
|
||||
J.sleep(10000);
|
||||
|
||||
if(!helpIgnored && help) {
|
||||
help = false;
|
||||
}
|
||||
});
|
||||
frame.addWindowListener(new java.awt.event.WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
|
||||
e.shutdown();
|
||||
eh.shutdown();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void createAndShowGUI(Engine r, int s, IrisWorld world) {
|
||||
JFrame frame = new JFrame("Vision");
|
||||
VisionGUI nv = new VisionGUI(frame);
|
||||
nv.world = world;
|
||||
nv.engine = r;
|
||||
nv.renderer = new IrisRenderer(r);
|
||||
frame.add(nv);
|
||||
frame.setSize(1440, 820);
|
||||
frame.setVisible(true);
|
||||
File file = Iris.getCached("Iris Icon", "https://raw.githubusercontent.com/VolmitSoftware/Iris/master/icon.png");
|
||||
|
||||
if(file != null) {
|
||||
try {
|
||||
nv.texture = ImageIO.read(file);
|
||||
frame.setIconImage(ImageIO.read(file));
|
||||
} catch(IOException e) {
|
||||
Iris.reportError(e);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void launch(Engine g, int i) {
|
||||
J.a(() ->
|
||||
createAndShowGUI(g, i, g.getWorld()));
|
||||
}
|
||||
|
||||
public boolean updateEngine() {
|
||||
if(engine.isClosed()) {
|
||||
if(world.hasRealWorld()) {
|
||||
try {
|
||||
engine = IrisToolbelt.access(world.realWorld()).getEngine();
|
||||
return !engine.isClosed();
|
||||
} catch(Throwable e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
Point cp = e.getPoint();
|
||||
lx = (cp.getX());
|
||||
lz = (cp.getY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
Point cp = e.getPoint();
|
||||
ox += (lx - cp.getX()) * scale;
|
||||
oz += (lz - cp.getY()) * scale;
|
||||
lx = cp.getX();
|
||||
lz = cp.getY();
|
||||
}
|
||||
|
||||
public int getColor(double wx, double wz) {
|
||||
BiFunction<Double, Double, Integer> colorFunction = (d, dx) -> Color.black.getRGB();
|
||||
|
||||
switch(currentType) {
|
||||
case BIOME, DECORATOR_LOAD, OBJECT_LOAD, LAYER_LOAD -> colorFunction = (x, z) -> engine.getComplex().getTrueBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
||||
case BIOME_LAND -> colorFunction = (x, z) -> engine.getComplex().getLandBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
||||
case BIOME_SEA -> colorFunction = (x, z) -> engine.getComplex().getSeaBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
||||
case REGION -> colorFunction = (x, z) -> engine.getComplex().getRegionStream().get(x, z).getColor(engine.getComplex(), currentType).getRGB();
|
||||
case CAVE_LAND -> colorFunction = (x, z) -> engine.getComplex().getCaveBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
||||
case HEIGHT -> colorFunction = (x, z) -> Color.getHSBColor(engine.getComplex().getHeightStream().get(x, z).floatValue(), 100, 100).getRGB();
|
||||
}
|
||||
|
||||
return colorFunction.apply(wx, wz);
|
||||
}
|
||||
|
||||
public void notify(String s) {
|
||||
notifications.put(s, M.ms() + 2500);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if(e.getKeyCode() == KeyEvent.VK_SHIFT) {
|
||||
shift = true;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_CONTROL) {
|
||||
control = true;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_SEMICOLON) {
|
||||
debug = true;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_SLASH) {
|
||||
help = true;
|
||||
helpIgnored = true;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_ALT) {
|
||||
alt = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
if(e.getKeyCode() == KeyEvent.VK_SEMICOLON) {
|
||||
debug = false;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_SHIFT) {
|
||||
shift = false;
|
||||
}
|
||||
|
||||
if(e.getKeyCode() == KeyEvent.VK_CONTROL) {
|
||||
control = false;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_SLASH) {
|
||||
help = false;
|
||||
helpIgnored = true;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_ALT) {
|
||||
alt = false;
|
||||
}
|
||||
|
||||
// Pushes
|
||||
if(e.getKeyCode() == KeyEvent.VK_F) {
|
||||
follow = !follow;
|
||||
|
||||
if(player != null && follow) {
|
||||
notify("Following " + player.getName() + ". Press F to disable");
|
||||
} else if(follow) {
|
||||
notify("Can't follow, no one is in the world");
|
||||
follow = false;
|
||||
} else {
|
||||
notify("Follow Off");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(e.getKeyCode() == KeyEvent.VK_R) {
|
||||
dump();
|
||||
notify("Refreshing Chunks");
|
||||
return;
|
||||
}
|
||||
|
||||
if(e.getKeyCode() == KeyEvent.VK_P) {
|
||||
lowtile = !lowtile;
|
||||
dump();
|
||||
notify("Rendering " + (lowtile ? "Low" : "High") + " Quality Tiles");
|
||||
return;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_E) {
|
||||
eco = !eco;
|
||||
dump();
|
||||
notify("Using " + (eco ? "60" : "Uncapped") + " FPS Limit");
|
||||
return;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_EQUALS) {
|
||||
mscale = mscale + ((0.044 * mscale) * -3);
|
||||
mscale = Math.max(mscale, 0.00001);
|
||||
dump();
|
||||
return;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_MINUS) {
|
||||
mscale = mscale + ((0.044 * mscale) * 3);
|
||||
mscale = Math.max(mscale, 0.00001);
|
||||
dump();
|
||||
return;
|
||||
}
|
||||
|
||||
if(e.getKeyCode() == KeyEvent.VK_BACK_SLASH) {
|
||||
mscale = 1D;
|
||||
dump();
|
||||
notify("Zoom Reset");
|
||||
return;
|
||||
}
|
||||
|
||||
int currentMode = currentType.ordinal();
|
||||
|
||||
for(RenderType i : RenderType.values()) {
|
||||
if(e.getKeyChar() == String.valueOf(i.ordinal() + 1).charAt(0)) {
|
||||
if(i.ordinal() != currentMode) {
|
||||
currentType = i;
|
||||
dump();
|
||||
notify("Rendering " + Form.capitalizeWords(currentType.name().toLowerCase().replaceAll("\\Q_\\E", " ")));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(e.getKeyCode() == KeyEvent.VK_M) {
|
||||
currentType = RenderType.values()[(currentMode + 1) % RenderType.values().length];
|
||||
notify("Rendering " + Form.capitalizeWords(currentType.name().toLowerCase().replaceAll("\\Q_\\E", " ")));
|
||||
dump();
|
||||
}
|
||||
}
|
||||
|
||||
private void dump() {
|
||||
positions.clear();
|
||||
fastpositions.clear();
|
||||
}
|
||||
|
||||
public BufferedImage getTile(KSet<BlockPosition> fg, int div, int x, int z, O<Integer> m) {
|
||||
BlockPosition key = new BlockPosition((int) mscale, Math.floorDiv(x, div), Math.floorDiv(z, div));
|
||||
fg.add(key);
|
||||
|
||||
if(positions.containsKey(key)) {
|
||||
return positions.get(key);
|
||||
}
|
||||
|
||||
if(fastpositions.containsKey(key)) {
|
||||
if(!working.contains(key) && working.size() < 9) {
|
||||
m.set(m.get() - 1);
|
||||
|
||||
if(m.get() >= 0 && velocity < 50) {
|
||||
working.add(key);
|
||||
double mk = mscale;
|
||||
double mkd = scale;
|
||||
e.submit(() ->
|
||||
{
|
||||
PrecisionStopwatch ps = PrecisionStopwatch.start();
|
||||
BufferedImage b = renderer.render(x * mscale, z * mscale, div * mscale, div / (lowtile ? 3 : 1), currentType);
|
||||
rs.put(ps.getMilliseconds());
|
||||
working.remove(key);
|
||||
|
||||
if(mk == mscale && mkd == scale) {
|
||||
positions.put(key, b);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return fastpositions.get(key);
|
||||
}
|
||||
|
||||
if(workingfast.contains(key) || workingfast.size() > Runtime.getRuntime().availableProcessors()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
workingfast.add(key);
|
||||
double mk = mscale;
|
||||
double mkd = scale;
|
||||
eh.submit(() ->
|
||||
{
|
||||
PrecisionStopwatch ps = PrecisionStopwatch.start();
|
||||
BufferedImage b = renderer.render(x * mscale, z * mscale, div * mscale, div / lowq, currentType);
|
||||
rs.put(ps.getMilliseconds());
|
||||
workingfast.remove(key);
|
||||
|
||||
if(mk == mscale && mkd == scale) {
|
||||
fastpositions.put(key, b);
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
private double getWorldX(double screenX) {
|
||||
//return (mscale * screenX) + ((oxp / scale) * mscale);
|
||||
return (mscale * screenX) + ((oxp / scale));
|
||||
}
|
||||
|
||||
private double getWorldZ(double screenZ) {
|
||||
return (mscale * screenZ) + ((ozp / scale) * mscale);
|
||||
}
|
||||
|
||||
private double getScreenX(double x) {
|
||||
return (x / mscale) - ((oxp / scale));
|
||||
}
|
||||
|
||||
private double getScreenZ(double z) {
|
||||
return (z / mscale) - ((ozp / scale));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics gx) {
|
||||
|
||||
if(engine.isClosed()) {
|
||||
EventQueue.invokeLater(() -> {
|
||||
try
|
||||
{
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
catch(Throwable e)
|
||||
{
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(updateEngine()) {
|
||||
dump();
|
||||
}
|
||||
|
||||
if(ox < oxp) {
|
||||
velocity = Math.abs(ox - oxp) * 0.36;
|
||||
oxp -= velocity;
|
||||
}
|
||||
|
||||
if(ox > oxp) {
|
||||
velocity = Math.abs(oxp - ox) * 0.36;
|
||||
oxp += velocity;
|
||||
}
|
||||
|
||||
if(oz < ozp) {
|
||||
velocity = Math.abs(oz - ozp) * 0.36;
|
||||
ozp -= velocity;
|
||||
}
|
||||
|
||||
if(oz > ozp) {
|
||||
velocity = Math.abs(ozp - oz) * 0.36;
|
||||
ozp += velocity;
|
||||
}
|
||||
|
||||
if(lx < hx) {
|
||||
hx -= Math.abs(lx - hx) * 0.36;
|
||||
}
|
||||
|
||||
if(lx > hx) {
|
||||
hx += Math.abs(hx - lx) * 0.36;
|
||||
}
|
||||
|
||||
if(lz < hz) {
|
||||
hz -= Math.abs(lz - hz) * 0.36;
|
||||
}
|
||||
|
||||
if(lz > hz) {
|
||||
hz += Math.abs(hz - lz) * 0.36;
|
||||
}
|
||||
|
||||
if(centities.flip()) {
|
||||
J.s(() -> {
|
||||
synchronized(lastEntities) {
|
||||
lastEntities.clear();
|
||||
lastEntities.addAll(world.getEntitiesByClass(LivingEntity.class));
|
||||
}
|
||||
});
|
||||
}
|
||||
lowq = Math.max(Math.min((int) M.lerp(8, 28, velocity / 1000D), 28), 8);
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
Graphics2D g = (Graphics2D) gx;
|
||||
w = getWidth();
|
||||
h = getHeight();
|
||||
double vscale = scale;
|
||||
scale = w / 12D;
|
||||
|
||||
if(scale != vscale) {
|
||||
positions.clear();
|
||||
}
|
||||
|
||||
KSet<BlockPosition> gg = new KSet<>();
|
||||
int iscale = (int) scale;
|
||||
g.setColor(Color.white);
|
||||
g.clearRect(0, 0, w, h);
|
||||
int posX = (int) oxp;
|
||||
int posZ = (int) ozp;
|
||||
m.set(3);
|
||||
|
||||
for(int r = 0; r < Math.max(w, h); r += iscale) {
|
||||
for(int i = -iscale; i < w + iscale; i += iscale) {
|
||||
for(int j = -iscale; j < h + iscale; j += iscale) {
|
||||
int a = i - (w / 2);
|
||||
int b = j - (h / 2);
|
||||
if(a * a + b * b <= r * r) {
|
||||
BufferedImage t = getTile(gg, iscale, Math.floorDiv((posX / iscale) + i, iscale) * iscale, Math.floorDiv((posZ / iscale) + j, iscale) * iscale, m);
|
||||
|
||||
if(t != null) {
|
||||
g.drawImage(t, i - ((posX / iscale) % (iscale)), j - ((posZ / iscale) % (iscale)), iscale, iscale, (img, infoflags, x, y, width, height) -> true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p.end();
|
||||
|
||||
for(BlockPosition i : positions.k()) {
|
||||
if(!gg.contains(i)) {
|
||||
positions.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
hanleFollow();
|
||||
renderOverlays(g);
|
||||
|
||||
if(!isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!getParent().isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!getParent().getParent().isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
J.a(() ->
|
||||
{
|
||||
J.sleep(eco ? 15 : 1);
|
||||
repaint();
|
||||
});
|
||||
}
|
||||
|
||||
private void hanleFollow() {
|
||||
if(follow && player != null) {
|
||||
animateTo(player.getLocation().getX(), player.getLocation().getZ());
|
||||
}
|
||||
}
|
||||
|
||||
private void renderOverlays(Graphics2D g) {
|
||||
renderPlayer(g);
|
||||
|
||||
if(help) {
|
||||
renderOverlayHelp(g);
|
||||
} else if(debug) {
|
||||
renderOverlayDebug(g);
|
||||
}
|
||||
|
||||
renderOverlayLegend(g);
|
||||
|
||||
renderHoverOverlay(g, shift);
|
||||
if(!notifications.isEmpty()) {
|
||||
renderNotification(g);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderOverlayLegend(Graphics2D g) {
|
||||
KList<String> l = new KList<>();
|
||||
l.add("Zoom: " + Form.pc(mscale, 0));
|
||||
l.add("Blocks: " + Form.f((int) mscale * w) + " by " + Form.f((int) mscale * h));
|
||||
l.add("BPP: " + Form.f(mscale, 1));
|
||||
l.add("Render Mode: " + Form.capitalizeWords(currentType.name().toLowerCase().replaceAll("\\Q_\\E", " ")));
|
||||
|
||||
drawCardBR(g, l);
|
||||
}
|
||||
|
||||
private void renderNotification(Graphics2D g) {
|
||||
drawCardCB(g, notifications.k());
|
||||
|
||||
for(String i : notifications.k()) {
|
||||
if(M.ms() > notifications.get(i)) {
|
||||
notifications.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderPlayer(Graphics2D g) {
|
||||
Player b = null;
|
||||
|
||||
for(Player i : world.getPlayers()) {
|
||||
b = i;
|
||||
renderPosition(g, i.getLocation().getX(), i.getLocation().getZ());
|
||||
}
|
||||
|
||||
synchronized(lastEntities) {
|
||||
double dist = Double.MAX_VALUE;
|
||||
LivingEntity h = null;
|
||||
|
||||
for(LivingEntity i : lastEntities) {
|
||||
if(i instanceof Player) {
|
||||
continue;
|
||||
}
|
||||
|
||||
renderMobPosition(g, i, i.getLocation().getX(), i.getLocation().getZ());
|
||||
if(shift) {
|
||||
double d = i.getLocation().distanceSquared(new Location(i.getWorld(), getWorldX(hx), i.getLocation().getY(), getWorldZ(hz)));
|
||||
|
||||
if(d < dist) {
|
||||
dist = d;
|
||||
h = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(h != null && shift) {
|
||||
g.setColor(Color.red);
|
||||
g.fillRoundRect((int) getScreenX(h.getLocation().getX()) - 10, (int) getScreenZ(h.getLocation().getZ()) - 10, 20, 20, 20, 20);
|
||||
KList<String> k = new KList<>();
|
||||
k.add(Form.capitalizeWords(h.getType().name().toLowerCase(Locale.ROOT).replaceAll("\\Q_\\E", " ")) + h.getEntityId());
|
||||
|
||||
k.add("Pos: " + h.getLocation().getBlockX() + ", " + h.getLocation().getBlockY() + ", " + h.getLocation().getBlockZ());
|
||||
k.add("UUID: " + h.getUniqueId());
|
||||
k.add("HP: " + h.getHealth() + " / " + h.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
|
||||
|
||||
drawCardTR(g, k);
|
||||
}
|
||||
}
|
||||
|
||||
player = b;
|
||||
}
|
||||
|
||||
private void animateTo(double wx, double wz) {
|
||||
double cx = getWorldX(getWidth() / 2);
|
||||
double cz = getWorldZ(getHeight() / 2);
|
||||
ox += (wx - cx);
|
||||
oz += (wz - cz);
|
||||
}
|
||||
|
||||
private void renderPosition(Graphics2D g, double x, double z) {
|
||||
if(texture != null) {
|
||||
g.drawImage(texture, (int) getScreenX(x), (int) getScreenZ(z), 66, 66, (img, infoflags, xx, xy, width, height) -> true);
|
||||
} else {
|
||||
g.setColor(Color.darkGray);
|
||||
g.fillRoundRect((int) getScreenX(x) - 15, (int) getScreenZ(z) - 15, 30, 30, 15, 15);
|
||||
g.setColor(Color.cyan.darker().darker());
|
||||
g.fillRoundRect((int) getScreenX(x) - 10, (int) getScreenZ(z) - 10, 20, 20, 10, 10);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderMobPosition(Graphics2D g, LivingEntity e, double x, double z) {
|
||||
g.setColor(Color.red.darker().darker());
|
||||
g.fillRoundRect((int) getScreenX(x) - 2, (int) getScreenZ(z) - 2, 4, 4, 4, 4);
|
||||
}
|
||||
|
||||
private void renderHoverOverlay(Graphics2D g, boolean detailed) {
|
||||
IrisBiome biome = engine.getComplex().getTrueBiomeStream().get(getWorldX(hx), getWorldZ(hz));
|
||||
IrisRegion region = engine.getComplex().getRegionStream().get(getWorldX(hx), getWorldZ(hz));
|
||||
KList<String> l = new KList<>();
|
||||
l.add("Biome: " + biome.getName());
|
||||
l.add("Region: " + region.getName() + "(" + region.getLoadKey() + ")");
|
||||
l.add("Block " + (int) getWorldX(hx) + ", " + (int) getWorldZ(hz));
|
||||
if(detailed) {
|
||||
l.add("Chunk " + ((int) getWorldX(hx) >> 4) + ", " + ((int) getWorldZ(hz) >> 4));
|
||||
l.add("Region " + (((int) getWorldX(hx) >> 4) >> 5) + ", " + (((int) getWorldZ(hz) >> 4) >> 5));
|
||||
l.add("Key: " + biome.getLoadKey());
|
||||
l.add("File: " + biome.getLoadFile());
|
||||
}
|
||||
|
||||
drawCardAt((float) hx, (float) hz, 0, 0, g, l);
|
||||
}
|
||||
|
||||
private void renderOverlayDebug(Graphics2D g) {
|
||||
KList<String> l = new KList<>();
|
||||
l.add("Velocity: " + (int) velocity);
|
||||
l.add("Center Pos: " + Form.f((int) getWorldX(getWidth() / 2)) + ", " + Form.f((int) getWorldZ(getHeight() / 2)));
|
||||
drawCardBL(g, l);
|
||||
}
|
||||
|
||||
private void renderOverlayHelp(Graphics2D g) {
|
||||
KList<String> l = new KList<>();
|
||||
l.add("/ to show this help screen");
|
||||
l.add("R to repaint the screen");
|
||||
l.add("F to follow first player");
|
||||
l.add("+/- to Change Zoom");
|
||||
l.add("\\ to reset zoom to 1");
|
||||
l.add("M to cycle render modes");
|
||||
l.add("P to toggle Tile Quality Mode");
|
||||
l.add("E to toggle Eco FPS Mode");
|
||||
|
||||
int ff = 0;
|
||||
for(RenderType i : RenderType.values()) {
|
||||
ff++;
|
||||
l.add(ff + " to view " + Form.capitalizeWords(i.name().toLowerCase().replaceAll("\\Q_\\E", " ")));
|
||||
}
|
||||
|
||||
l.add("Shift for additional biome details (at cursor)");
|
||||
l.add("CTRL + Click to teleport to location");
|
||||
l.add("ALT + Click to open biome in VSCode");
|
||||
drawCardTL(g, l);
|
||||
}
|
||||
|
||||
private void drawCardTL(Graphics2D g, KList<String> text) {
|
||||
drawCardAt(0, 0, 0, 0, g, text);
|
||||
}
|
||||
|
||||
private void drawCardBR(Graphics2D g, KList<String> text) {
|
||||
drawCardAt(getWidth(), getHeight(), 1, 1, g, text);
|
||||
}
|
||||
|
||||
private void drawCardBL(Graphics2D g, KList<String> text) {
|
||||
drawCardAt(0, getHeight(), 0, 1, g, text);
|
||||
}
|
||||
|
||||
private void drawCardTR(Graphics2D g, KList<String> text) {
|
||||
drawCardAt(getWidth(), 0, 1, 0, g, text);
|
||||
}
|
||||
|
||||
private void open() {
|
||||
IrisComplex complex = engine.getComplex();
|
||||
File r = null;
|
||||
switch(currentType) {
|
||||
case BIOME, LAYER_LOAD, DECORATOR_LOAD, OBJECT_LOAD, HEIGHT -> r = complex.getTrueBiomeStream().get(getWorldX(hx), getWorldZ(hz)).openInVSCode();
|
||||
case BIOME_LAND -> r = complex.getLandBiomeStream().get(getWorldX(hx), getWorldZ(hz)).openInVSCode();
|
||||
case BIOME_SEA -> r = complex.getSeaBiomeStream().get(getWorldX(hx), getWorldZ(hz)).openInVSCode();
|
||||
case REGION -> r = complex.getRegionStream().get(getWorldX(hx), getWorldZ(hz)).openInVSCode();
|
||||
case CAVE_LAND -> r = complex.getCaveBiomeStream().get(getWorldX(hx), getWorldZ(hz)).openInVSCode();
|
||||
}
|
||||
|
||||
notify("Opening " + r.getPath() + " in VSCode");
|
||||
}
|
||||
|
||||
private void teleport() {
|
||||
J.s(() -> {
|
||||
if(player != null) {
|
||||
int xx = (int) getWorldX(hx);
|
||||
int zz = (int) getWorldZ(hz);
|
||||
int h = engine.getComplex().getRoundedHeighteightStream().get(xx, zz);
|
||||
player.teleport(new Location(player.getWorld(), xx, h, zz));
|
||||
notify("Teleporting to " + xx + ", " + h + ", " + zz);
|
||||
} else {
|
||||
notify("No player in world, can't teleport.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void drawCardCB(Graphics2D g, KList<String> text) {
|
||||
drawCardAt(getWidth() / 2, getHeight(), 0.5, 1, g, text);
|
||||
}
|
||||
|
||||
private void drawCardCT(Graphics2D g, KList<String> text) {
|
||||
drawCardAt(getWidth() / 2, 0, 0.5, 0, g, text);
|
||||
}
|
||||
|
||||
private void drawCardAt(float x, float y, double pushX, double pushZ, Graphics2D g, KList<String> text) {
|
||||
g.setFont(new Font("Hevetica", Font.BOLD, 16));
|
||||
int h = 0;
|
||||
int w = 0;
|
||||
|
||||
for(String i : text) {
|
||||
h += g.getFontMetrics().getHeight();
|
||||
w = Math.max(w, g.getFontMetrics().stringWidth(i));
|
||||
}
|
||||
|
||||
w += 28;
|
||||
h += 14;
|
||||
|
||||
int cw = (int) ((w + 26) * pushX);
|
||||
int ch = (int) ((h + 26) * pushZ);
|
||||
|
||||
g.setColor(Color.darkGray);
|
||||
g.fillRect((int) x + 7 + 2 - cw, (int) y + 12 + 2 - ch, w + 7, h); // Shadow
|
||||
g.setColor(Color.gray);
|
||||
g.fillRect((int) x + 7 + 1 - cw, (int) y + 12 + 1 - ch, w + 7, h); // Shadow
|
||||
g.setColor(Color.white);
|
||||
g.fillRect((int) x + 7 - cw, (int) y + 12 - ch, w + 7, h);
|
||||
|
||||
g.setColor(Color.black);
|
||||
int m = 0;
|
||||
for(String i : text) {
|
||||
g.drawString(i, x + 14 - cw, y + 14 - ch + (++m * g.getFontMetrics().getHeight()));
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
int notches = e.getWheelRotation();
|
||||
if(e.isControlDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Iris.info("Blocks/Pixel: " + (mscale) + ", Blocks Wide: " + (w * mscale));
|
||||
positions.clear();
|
||||
fastpositions.clear();
|
||||
mscale = mscale + ((0.25 * mscale) * notches);
|
||||
mscale = Math.max(mscale, 0.00001);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if(control) {
|
||||
teleport();
|
||||
} else if(alt) {
|
||||
open();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.gui.components;
|
||||
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.interpolation.IrisInterpolation;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@SuppressWarnings("ClassCanBeRecord")
|
||||
public class IrisRenderer {
|
||||
private final Engine renderer;
|
||||
|
||||
public IrisRenderer(Engine renderer) {
|
||||
this.renderer = renderer;
|
||||
}
|
||||
|
||||
public BufferedImage render(double sx, double sz, double size, int resolution, RenderType currentType) {
|
||||
BufferedImage image = new BufferedImage(resolution, resolution, BufferedImage.TYPE_INT_RGB);
|
||||
BiFunction<Double, Double, Integer> colorFunction = (d, dx) -> Color.black.getRGB();
|
||||
|
||||
switch(currentType) {
|
||||
case BIOME, DECORATOR_LOAD, OBJECT_LOAD, LAYER_LOAD -> colorFunction = (x, z) -> renderer.getComplex().getTrueBiomeStream().get(x, z).getColor(renderer, currentType).getRGB();
|
||||
case BIOME_LAND -> colorFunction = (x, z) -> renderer.getComplex().getLandBiomeStream().get(x, z).getColor(renderer, currentType).getRGB();
|
||||
case BIOME_SEA -> colorFunction = (x, z) -> renderer.getComplex().getSeaBiomeStream().get(x, z).getColor(renderer, currentType).getRGB();
|
||||
case REGION -> colorFunction = (x, z) -> renderer.getComplex().getRegionStream().get(x, z).getColor(renderer.getComplex(), currentType).getRGB();
|
||||
case CAVE_LAND -> colorFunction = (x, z) -> renderer.getComplex().getCaveBiomeStream().get(x, z).getColor(renderer, currentType).getRGB();
|
||||
case HEIGHT -> colorFunction = (x, z) -> Color.getHSBColor(renderer.getComplex().getHeightStream().get(x, z).floatValue(), 100, 100).getRGB();
|
||||
}
|
||||
|
||||
double x, z;
|
||||
int i, j;
|
||||
for(i = 0; i < resolution; i++) {
|
||||
x = IrisInterpolation.lerp(sx, sx + size, (double) i / (double) (resolution));
|
||||
|
||||
for(j = 0; j < resolution; j++) {
|
||||
z = IrisInterpolation.lerp(sz, sz + size, (double) j / (double) (resolution));
|
||||
image.setRGB(i, j, colorFunction.apply(x, z));
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.gui.components;
|
||||
|
||||
public enum RenderType {
|
||||
BIOME, BIOME_LAND, BIOME_SEA, REGION, CAVE_LAND, HEIGHT, OBJECT_LOAD, DECORATOR_LOAD, LAYER_LOAD
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.gui.components;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Renderer {
|
||||
Color draw(double x, double z);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.gui.components;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
public class TileRender {
|
||||
private BufferedImage image;
|
||||
private int quality;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.MissingResourceException;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public abstract class ExternalDataProvider {
|
||||
|
||||
@Getter
|
||||
private final String pluginId;
|
||||
|
||||
public Plugin getPlugin() {
|
||||
return Bukkit.getPluginManager().getPlugin(pluginId);
|
||||
}
|
||||
|
||||
public boolean isPresent() {
|
||||
return getPlugin() != null;
|
||||
}
|
||||
|
||||
public abstract void init();
|
||||
|
||||
public abstract BlockData getBlockData(NamespacedKey blockId) throws MissingResourceException;
|
||||
|
||||
public abstract ItemStack getItemStack(NamespacedKey itemId) throws MissingResourceException;
|
||||
|
||||
public abstract NamespacedKey[] getBlockTypes();
|
||||
|
||||
public abstract boolean isValidProvider(NamespacedKey namespace);
|
||||
}
|
||||
115
src/main/java/com/volmit/iris/core/link/IrisPapiExpansion.java
Normal file
115
src/main/java/com/volmit/iris/core/link/IrisPapiExpansion.java
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
// See/update https://app.gitbook.com/@volmitsoftware/s/iris/compatability/papi/
|
||||
public class IrisPapiExpansion extends PlaceholderExpansion {
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return "iris";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthor() {
|
||||
return "Volmit Software";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return Iris.instance.getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean persist() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onRequest(OfflinePlayer player, String p) {
|
||||
Location l = null;
|
||||
PlatformChunkGenerator a = null;
|
||||
|
||||
if(player.isOnline()) {
|
||||
l = player.getPlayer().getLocation();
|
||||
a = IrisToolbelt.access(l.getWorld());
|
||||
}
|
||||
|
||||
if(p.equalsIgnoreCase("biome_name")) {
|
||||
if(a != null) {
|
||||
return getBiome(a, l).getName();
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("biome_id")) {
|
||||
if(a != null) {
|
||||
return getBiome(a, l).getLoadKey();
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("biome_file")) {
|
||||
if(a != null) {
|
||||
return getBiome(a, l).getLoadFile().getPath();
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("region_name")) {
|
||||
if(a != null) {
|
||||
return a.getEngine().getRegion(l).getName();
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("region_id")) {
|
||||
if(a != null) {
|
||||
return a.getEngine().getRegion(l).getLoadKey();
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("region_file")) {
|
||||
if(a != null) {
|
||||
return a.getEngine().getRegion(l).getLoadFile().getPath();
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("terrain_slope")) {
|
||||
if(a != null) {
|
||||
return (a.getEngine())
|
||||
.getComplex().getSlopeStream()
|
||||
.get(l.getX(), l.getZ()) + "";
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("terrain_height")) {
|
||||
if(a != null) {
|
||||
return Math.round(a.getEngine().getHeight(l.getBlockX(), l.getBlockZ())) + "";
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("world_mode")) {
|
||||
if(a != null) {
|
||||
return a.isStudio() ? "Studio" : "Production";
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("world_seed")) {
|
||||
if(a != null) {
|
||||
return a.getEngine().getSeedManager().getSeed() + "";
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("world_speed")) {
|
||||
if(a != null) {
|
||||
return a.getEngine().getGeneratedPerSecond() + "/s";
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private IrisBiome getBiome(PlatformChunkGenerator a, Location l) {
|
||||
return a.getEngine().getBiome(l.getBlockX(), l.getBlockY() - l.getWorld().getMinHeight(), l.getBlockZ());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import dev.lone.itemsadder.api.CustomBlock;
|
||||
import dev.lone.itemsadder.api.CustomStack;
|
||||
import dev.lone.itemsadder.api.ItemsAdder;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.MissingResourceException;
|
||||
|
||||
public class ItemAdderDataProvider extends ExternalDataProvider {
|
||||
|
||||
public ItemAdderDataProvider() {
|
||||
super("ItemsAdder");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() { }
|
||||
|
||||
@Override
|
||||
public BlockData getBlockData(NamespacedKey blockId) throws MissingResourceException {
|
||||
return CustomBlock.getBaseBlockData(blockId.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(NamespacedKey itemId) throws MissingResourceException {
|
||||
CustomStack stack = CustomStack.getInstance(itemId.toString());
|
||||
if(stack == null)
|
||||
throw new MissingResourceException("Failed to find ItemData!", itemId.getNamespace(), itemId.getKey());
|
||||
return stack.getItemStack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamespacedKey[] getBlockTypes() {
|
||||
KList<NamespacedKey> keys = new KList<>();
|
||||
for(String s : ItemsAdder.getNamespacedBlocksNamesInConfig())
|
||||
keys.add(NamespacedKey.fromString(s));
|
||||
return keys.toArray(new NamespacedKey[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(NamespacedKey blockId) {
|
||||
for(NamespacedKey k : getBlockTypes())
|
||||
if(k.equals(blockId)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
143
src/main/java/com/volmit/iris/core/link/MultiverseCoreLink.java
Normal file
143
src/main/java/com/volmit/iris/core/link/MultiverseCoreLink.java
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldType;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
public class MultiverseCoreLink {
|
||||
private final KMap<String, String> worldNameTypes = new KMap<>();
|
||||
|
||||
public MultiverseCoreLink() {
|
||||
|
||||
}
|
||||
|
||||
public boolean addWorld(String worldName, IrisDimension dim, String seed) {
|
||||
if(!isSupported()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
Plugin p = getMultiverse();
|
||||
Object mvWorldManager = p.getClass().getDeclaredMethod("getMVWorldManager").invoke(p);
|
||||
Method m = mvWorldManager.getClass().getDeclaredMethod("addWorld",
|
||||
|
||||
String.class, World.Environment.class, String.class, WorldType.class, Boolean.class, String.class, boolean.class);
|
||||
boolean b = (boolean) m.invoke(mvWorldManager, worldName, dim.getEnvironment(), seed, WorldType.NORMAL, false, "Iris", false);
|
||||
saveConfig();
|
||||
return b;
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, ?> getList() {
|
||||
try {
|
||||
Plugin p = getMultiverse();
|
||||
Object mvWorldManager = p.getClass().getDeclaredMethod("getMVWorldManager").invoke(p);
|
||||
Field f = mvWorldManager.getClass().getDeclaredField("worldsFromTheConfig");
|
||||
f.setAccessible(true);
|
||||
return (Map<String, ?>) f.get(mvWorldManager);
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void removeFromConfig(World world) {
|
||||
if(!isSupported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
getList().remove(world.getName());
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
public void removeFromConfig(String world) {
|
||||
if(!isSupported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
getList().remove(world);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
public void saveConfig() {
|
||||
try {
|
||||
Plugin p = getMultiverse();
|
||||
Object mvWorldManager = p.getClass().getDeclaredMethod("getMVWorldManager").invoke(p);
|
||||
mvWorldManager.getClass().getDeclaredMethod("saveWorldsConfig").invoke(mvWorldManager);
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void assignWorldType(String worldName, String type) {
|
||||
worldNameTypes.put(worldName, type);
|
||||
}
|
||||
|
||||
public String getWorldNameType(String worldName, String defaultType) {
|
||||
try {
|
||||
String t = worldNameTypes.get(worldName);
|
||||
return t == null ? defaultType : t;
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
return defaultType;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSupported() {
|
||||
return getMultiverse() != null;
|
||||
}
|
||||
|
||||
public Plugin getMultiverse() {
|
||||
|
||||
return Bukkit.getPluginManager().getPlugin("Multiverse-Core");
|
||||
}
|
||||
|
||||
public String envName(World.Environment environment) {
|
||||
if(environment == null) {
|
||||
return "normal";
|
||||
}
|
||||
|
||||
return switch(environment) {
|
||||
case NORMAL -> "normal";
|
||||
case NETHER -> "nether";
|
||||
case THE_END -> "end";
|
||||
default -> environment.toString().toLowerCase();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
115
src/main/java/com/volmit/iris/core/link/MythicMobsLink.java
Normal file
115
src/main/java/com/volmit/iris/core/link/MythicMobsLink.java
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class MythicMobsLink {
|
||||
|
||||
private Collection<String> mobs;
|
||||
private BiFunction<String, Location, Entity> spawnMobFunction;
|
||||
|
||||
public MythicMobsLink() {
|
||||
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return getPlugin() != null;
|
||||
}
|
||||
|
||||
public Plugin getPlugin() {
|
||||
return Bukkit.getPluginManager().getPlugin("MythicMobs");
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn a mythic mob at this location
|
||||
*
|
||||
* @param mob
|
||||
* The mob
|
||||
* @param location
|
||||
* The location
|
||||
* @return The mob, or null if it can't be spawned
|
||||
*/
|
||||
public @Nullable
|
||||
Entity spawnMob(String mob, Location location) {
|
||||
if(!isEnabled()) return null;
|
||||
|
||||
if(spawnMobFunction != null) {
|
||||
return spawnMobFunction.apply(mob, location);
|
||||
}
|
||||
|
||||
try {
|
||||
Class<?> mythicMobClass = Class.forName("io.lumine.mythic.bukkit.MythicBukkit");
|
||||
Method getInst = mythicMobClass.getDeclaredMethod("inst");
|
||||
Object inst = getInst.invoke(null);
|
||||
Method getAPIHelper = mythicMobClass.getDeclaredMethod("getAPIHelper");
|
||||
Object apiHelper = getAPIHelper.invoke(inst);
|
||||
Method spawnMobMethod = apiHelper.getClass().getDeclaredMethod("spawnMythicMob", String.class, Location.class);
|
||||
|
||||
spawnMobFunction = (str, loc) -> {
|
||||
try {
|
||||
return (Entity) spawnMobMethod.invoke(apiHelper, str, loc);
|
||||
} catch(InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return spawnMobFunction.apply(mob, location);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Collection<String> getMythicMobTypes() {
|
||||
if(mobs != null) {
|
||||
return mobs;
|
||||
}
|
||||
|
||||
if(isEnabled()) {
|
||||
|
||||
try {
|
||||
Class<?> mythicMobClass = Class.forName("io.lumine.xikage.mythicmobs.MythicMobs");
|
||||
Method getInst = mythicMobClass.getDeclaredMethod("inst");
|
||||
Object inst = getInst.invoke(null);
|
||||
Method getMobManager = mythicMobClass.getDeclaredMethod("getMobManager");
|
||||
Object mobManager = getMobManager.invoke(inst);
|
||||
Method getMobNames = mobManager.getClass().getDeclaredMethod("getMobNames");
|
||||
mobs = (Collection<String>) getMobNames.invoke(mobManager);
|
||||
return mobs;
|
||||
} catch(ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
112
src/main/java/com/volmit/iris/core/link/OraxenDataProvider.java
Normal file
112
src/main/java/com/volmit/iris/core/link/OraxenDataProvider.java
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import io.th0rgal.oraxen.items.ItemBuilder;
|
||||
import io.th0rgal.oraxen.items.OraxenItems;
|
||||
import io.th0rgal.oraxen.mechanics.MechanicFactory;
|
||||
import io.th0rgal.oraxen.mechanics.MechanicsManager;
|
||||
import io.th0rgal.oraxen.mechanics.provided.gameplay.block.BlockMechanic;
|
||||
import io.th0rgal.oraxen.mechanics.provided.gameplay.block.BlockMechanicFactory;
|
||||
import io.th0rgal.oraxen.mechanics.provided.gameplay.noteblock.NoteBlockMechanicFactory;
|
||||
import io.th0rgal.oraxen.utils.Utils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.MultipleFacing;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Optional;
|
||||
|
||||
public class OraxenDataProvider extends ExternalDataProvider {
|
||||
|
||||
private static final String FIELD_FACTORIES_MAP = "FACTORIES_BY_MECHANIC_ID";
|
||||
|
||||
private Map<String, MechanicFactory> factories;
|
||||
|
||||
public OraxenDataProvider() { super("Oraxen"); }
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
try {
|
||||
Field f = MechanicsManager.class.getDeclaredField(FIELD_FACTORIES_MAP);
|
||||
f.setAccessible(true);
|
||||
factories = (Map<String, MechanicFactory>) f.get(null);
|
||||
} catch(NoSuchFieldException | IllegalAccessException e) {
|
||||
Iris.error("Failed to set up Oraxen Link:");
|
||||
Iris.error("\t" + e.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData getBlockData(NamespacedKey blockId) throws MissingResourceException {
|
||||
MechanicFactory f = getFactory(blockId);
|
||||
if(f instanceof NoteBlockMechanicFactory)
|
||||
return ((NoteBlockMechanicFactory)f).createNoteBlockData(blockId.getKey());
|
||||
else if(f instanceof BlockMechanicFactory) {
|
||||
MultipleFacing newBlockData = (MultipleFacing) Bukkit.createBlockData(Material.MUSHROOM_STEM);
|
||||
Utils.setBlockFacing(newBlockData, ((BlockMechanic)f.getMechanic(blockId.getKey())).getCustomVariation());
|
||||
return newBlockData;
|
||||
} else
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.getNamespace(), blockId.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(NamespacedKey itemId) throws MissingResourceException {
|
||||
Optional<ItemBuilder> opt = OraxenItems.getOptionalItemById(itemId.getKey());
|
||||
return opt.orElseThrow(() -> new MissingResourceException("Failed to find ItemData!", itemId.getNamespace(), itemId.getKey())).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamespacedKey[] getBlockTypes() {
|
||||
KList<NamespacedKey> names = new KList<>();
|
||||
for(String name : OraxenItems.getItemNames()) {
|
||||
try {
|
||||
NamespacedKey key = new NamespacedKey("oraxen", name);
|
||||
if(getBlockData(key) != null)
|
||||
names.add(key);
|
||||
} catch(MissingResourceException ignored) { }
|
||||
}
|
||||
|
||||
return names.toArray(new NamespacedKey[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPresent() {
|
||||
return super.isPresent() && factories != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(NamespacedKey key) {
|
||||
return key.getNamespace().equalsIgnoreCase("oraxen");
|
||||
}
|
||||
|
||||
private MechanicFactory getFactory(NamespacedKey key) throws MissingResourceException {
|
||||
return factories.values().stream()
|
||||
.filter(i -> i.getItems().contains(key.getKey()))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new MissingResourceException("Failed to find BlockData!", key.getNamespace(), key.getKey()));
|
||||
}
|
||||
}
|
||||
37
src/main/java/com/volmit/iris/core/link/WorldEditLink.java
Normal file
37
src/main/java/com/volmit/iris/core/link/WorldEditLink.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.util.data.Cuboid;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class WorldEditLink {
|
||||
public static Cuboid getSelection(Player p)
|
||||
{
|
||||
try
|
||||
{
|
||||
Object instance = Class.forName("com.sk89q.worldedit.WorldEdit").getDeclaredMethod("getInstance").invoke(null);
|
||||
Object sessionManager = instance.getClass().getDeclaredMethod("getSessionManager").invoke(instance);
|
||||
Object player = Class.forName("com.sk89q.worldedit.bukkit.BukkitAdapter").getDeclaredMethod("adapt", Player.class).invoke(null, p);
|
||||
Object localSession = sessionManager.getClass().getDeclaredMethod("getIfPresent", Class.forName("com.sk89q.worldedit.session.SessionOwner")).invoke(sessionManager, player);
|
||||
Object world = Class.forName("com.sk89q.worldedit.bukkit.BukkitAdapter").getDeclaredMethod("adapt", World.class).invoke(null, p.getWorld());
|
||||
Object region = localSession.getClass().getDeclaredMethod("getSelection", world.getClass()).invoke(localSession, world);
|
||||
Object min = region.getClass().getDeclaredMethod("getMinimumPoint").invoke(region);
|
||||
Object max = region.getClass().getDeclaredMethod("getMaximumPoint").invoke(region);
|
||||
return new Cuboid(p.getWorld(),
|
||||
(int)min.getClass().getDeclaredMethod("getX").invoke(min),
|
||||
(int)min.getClass().getDeclaredMethod("getY").invoke(min),
|
||||
(int)min.getClass().getDeclaredMethod("getZ").invoke(min),
|
||||
(int)min.getClass().getDeclaredMethod("getX").invoke(max),
|
||||
(int)min.getClass().getDeclaredMethod("getY").invoke(max),
|
||||
(int)min.getClass().getDeclaredMethod("getZ").invoke(max)
|
||||
);
|
||||
}
|
||||
|
||||
catch(Throwable e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.loader;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.engine.object.IrisImage;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.data.KCache;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
|
||||
public class ImageResourceLoader extends ResourceLoader<IrisImage> {
|
||||
public ImageResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
||||
super(root, idm, folderName, resourceTypeName, IrisImage.class);
|
||||
loadCache = new KCache<>(this::loadRaw, IrisSettings.get().getPerformance().getObjectLoaderCacheSize());
|
||||
}
|
||||
|
||||
public boolean supportsSchemas() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
return loadCache.getSize();
|
||||
}
|
||||
|
||||
public long getTotalStorage() {
|
||||
return getSize();
|
||||
}
|
||||
|
||||
protected IrisImage loadFile(File j, String name) {
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
BufferedImage bu = ImageIO.read(j);
|
||||
IrisImage img = new IrisImage(bu);
|
||||
img.setLoadFile(j);
|
||||
img.setLoader(manager);
|
||||
img.setLoadKey(name);
|
||||
logLoad(j, img);
|
||||
tlt.addAndGet(p.getMilliseconds());
|
||||
return img;
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getPossibleKeys() {
|
||||
if(possibleKeys != null) {
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
||||
KSet<String> m = new KSet<>();
|
||||
|
||||
for(File i : getFolders()) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".png")) {
|
||||
m.add(j.getName().replaceAll("\\Q.png\\E", ""));
|
||||
} else if(j.isDirectory()) {
|
||||
for(File k : j.listFiles()) {
|
||||
if(k.isFile() && k.getName().endsWith(".png")) {
|
||||
m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.png\\E", ""));
|
||||
} else if(k.isDirectory()) {
|
||||
for(File l : k.listFiles()) {
|
||||
if(l.isFile() && l.getName().endsWith(".png")) {
|
||||
m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.png\\E", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KList<String> v = new KList<>(m);
|
||||
possibleKeys = v.toArray(new String[0]);
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
public File findFile(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".png") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".png");
|
||||
|
||||
if(file.exists()) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IrisImage load(String name) {
|
||||
return load(name, true);
|
||||
}
|
||||
|
||||
private IrisImage loadRaw(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".png") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return loadFile(j, name);
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".png");
|
||||
|
||||
if(file.exists()) {
|
||||
return loadFile(file, name);
|
||||
}
|
||||
}
|
||||
|
||||
Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IrisImage load(String name, boolean warn) {
|
||||
return loadCache.get(name);
|
||||
}
|
||||
}
|
||||
470
src/main/java/com/volmit/iris/core/loader/IrisData.java
Normal file
470
src/main/java/com/volmit/iris/core/loader/IrisData.java
Normal file
@@ -0,0 +1,470 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.loader;
|
||||
|
||||
import com.google.gson.ExclusionStrategy;
|
||||
import com.google.gson.FieldAttributes;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.TypeAdapterFactory;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.data.cache.AtomicCache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.engine.object.annotations.Snippet;
|
||||
import com.volmit.iris.engine.object.matter.IrisMatterObject;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.context.IrisContext;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Data
|
||||
public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
private static final KMap<File, IrisData> dataLoaders = new KMap<>();
|
||||
private final File dataFolder;
|
||||
private final int id;
|
||||
private boolean closed = false;
|
||||
private ResourceLoader<IrisBiome> biomeLoader;
|
||||
private ResourceLoader<IrisLootTable> lootLoader;
|
||||
private ResourceLoader<IrisRegion> regionLoader;
|
||||
private ResourceLoader<IrisDimension> dimensionLoader;
|
||||
private ResourceLoader<IrisGenerator> generatorLoader;
|
||||
private ResourceLoader<IrisJigsawPiece> jigsawPieceLoader;
|
||||
private ResourceLoader<IrisJigsawPool> jigsawPoolLoader;
|
||||
private ResourceLoader<IrisJigsawStructure> jigsawStructureLoader;
|
||||
private ResourceLoader<IrisEntity> entityLoader;
|
||||
private ResourceLoader<IrisMarker> markerLoader;
|
||||
private ResourceLoader<IrisSpawner> spawnerLoader;
|
||||
private ResourceLoader<IrisMod> modLoader;
|
||||
private ResourceLoader<IrisBlockData> blockLoader;
|
||||
private ResourceLoader<IrisExpression> expressionLoader;
|
||||
private ResourceLoader<IrisObject> objectLoader;
|
||||
private ResourceLoader<IrisMatterObject> matterLoader;
|
||||
private ResourceLoader<IrisImage> imageLoader;
|
||||
private ResourceLoader<IrisScript> scriptLoader;
|
||||
private ResourceLoader<IrisCave> caveLoader;
|
||||
private ResourceLoader<IrisRavine> ravineLoader;
|
||||
private ResourceLoader<IrisMatterObject> matterObjectLoader;
|
||||
private KMap<String, KList<String>> possibleSnippets;
|
||||
private Gson gson;
|
||||
private Gson snippetLoader;
|
||||
private GsonBuilder builder;
|
||||
private KMap<Class<? extends IrisRegistrant>, ResourceLoader<? extends IrisRegistrant>> loaders = new KMap<>();
|
||||
private Engine engine;
|
||||
|
||||
private IrisData(File dataFolder) {
|
||||
this.engine = null;
|
||||
this.dataFolder = dataFolder;
|
||||
this.id = RNG.r.imax();
|
||||
hotloaded();
|
||||
}
|
||||
|
||||
public static IrisData get(File dataFolder) {
|
||||
return dataLoaders.computeIfAbsent(dataFolder, IrisData::new);
|
||||
}
|
||||
|
||||
public static void dereference() {
|
||||
dataLoaders.v().forEach(IrisData::cleanupEngine);
|
||||
}
|
||||
|
||||
public static int cacheSize() {
|
||||
int m = 0;
|
||||
for(IrisData i : dataLoaders.values()) {
|
||||
for(ResourceLoader<?> j : i.getLoaders().values()) {
|
||||
m += j.getLoadCache().getSize();
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
private static void printData(ResourceLoader<?> rl) {
|
||||
Iris.warn(" " + rl.getResourceTypeName() + " @ /" + rl.getFolderName() + ": Cache=" + rl.getLoadCache().getSize() + " Folders=" + rl.getFolders().size());
|
||||
}
|
||||
|
||||
public static IrisObject loadAnyObject(String key) {
|
||||
return loadAny(key, (dm) -> dm.getObjectLoader().load(key, false));
|
||||
}
|
||||
public static IrisMatterObject loadAnyMatter(String key) {
|
||||
return loadAny(key, (dm) -> dm.getMatterLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisBiome loadAnyBiome(String key) {
|
||||
return loadAny(key, (dm) -> dm.getBiomeLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisExpression loadAnyExpression(String key) {
|
||||
return loadAny(key, (dm) -> dm.getExpressionLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisMod loadAnyMod(String key) {
|
||||
return loadAny(key, (dm) -> dm.getModLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisJigsawPiece loadAnyJigsawPiece(String key) {
|
||||
return loadAny(key, (dm) -> dm.getJigsawPieceLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisJigsawPool loadAnyJigsawPool(String key) {
|
||||
return loadAny(key, (dm) -> dm.getJigsawPoolLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisEntity loadAnyEntity(String key) {
|
||||
return loadAny(key, (dm) -> dm.getEntityLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisLootTable loadAnyLootTable(String key) {
|
||||
return loadAny(key, (dm) -> dm.getLootLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisBlockData loadAnyBlock(String key) {
|
||||
return loadAny(key, (dm) -> dm.getBlockLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisSpawner loadAnySpaner(String key) {
|
||||
return loadAny(key, (dm) -> dm.getSpawnerLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisScript loadAnyScript(String key) {
|
||||
return loadAny(key, (dm) -> dm.getScriptLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisRavine loadAnyRavine(String key) {
|
||||
return loadAny(key, (dm) -> dm.getRavineLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisRegion loadAnyRegion(String key) {
|
||||
return loadAny(key, (dm) -> dm.getRegionLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisMarker loadAnyMarker(String key) {
|
||||
return loadAny(key, (dm) -> dm.getMarkerLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisCave loadAnyCave(String key) {
|
||||
return loadAny(key, (dm) -> dm.getCaveLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisImage loadAnyImage(String key) {
|
||||
return loadAny(key, (dm) -> dm.getImageLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisDimension loadAnyDimension(String key) {
|
||||
return loadAny(key, (dm) -> dm.getDimensionLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisJigsawStructure loadAnyJigsawStructure(String key) {
|
||||
return loadAny(key, (dm) -> dm.getJigsawStructureLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisGenerator loadAnyGenerator(String key) {
|
||||
return loadAny(key, (dm) -> dm.getGeneratorLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static <T extends IrisRegistrant> T loadAny(String key, Function<IrisData, T> v) {
|
||||
try {
|
||||
for(File i : Objects.requireNonNull(Iris.instance.getDataFolder("packs").listFiles())) {
|
||||
if(i.isDirectory()) {
|
||||
IrisData dm = get(i);
|
||||
T t = v.apply(dm);
|
||||
|
||||
if(t != null) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ResourceLoader<?> getTypedLoaderFor(File f) {
|
||||
String[] k = f.getPath().split("\\Q" + File.separator + "\\E");
|
||||
|
||||
for(String i : k) {
|
||||
for(ResourceLoader<?> j : loaders.values()) {
|
||||
if(j.getFolderName().equals(i)) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void cleanupEngine() {
|
||||
if(engine != null && engine.isClosed()) {
|
||||
engine = null;
|
||||
Iris.debug("Dereferenced Data<Engine> " + getId() + " " + getDataFolder());
|
||||
}
|
||||
}
|
||||
|
||||
public void preprocessObject(IrisRegistrant t) {
|
||||
try {
|
||||
IrisContext ctx = IrisContext.get();
|
||||
Engine engine = this.engine;
|
||||
|
||||
if(engine == null && ctx != null && ctx.getEngine() != null) {
|
||||
engine = ctx.getEngine();
|
||||
}
|
||||
|
||||
if(engine == null && t.getPreprocessors().isNotEmpty()) {
|
||||
Iris.error("Failed to preprocess object " + t.getLoadKey() + " because there is no engine context here. (See stack below)");
|
||||
try {
|
||||
throw new RuntimeException();
|
||||
} catch(Throwable ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if(engine != null && t.getPreprocessors().isNotEmpty()) {
|
||||
synchronized(this) {
|
||||
engine.getExecution().getAPI().setPreprocessorObject(t);
|
||||
|
||||
for(String i : t.getPreprocessors()) {
|
||||
engine.getExecution().execute(i);
|
||||
Iris.debug("Loader<" + C.GREEN + t.getTypeName() + C.LIGHT_PURPLE + "> iprocess " + C.YELLOW + t.getLoadKey() + C.LIGHT_PURPLE + " in <rainbow>" + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Throwable e) {
|
||||
Iris.error("Failed to preprocess object!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
closed = true;
|
||||
dump();
|
||||
}
|
||||
|
||||
public IrisData copy() {
|
||||
return IrisData.get(dataFolder);
|
||||
}
|
||||
|
||||
private <T extends IrisRegistrant> ResourceLoader<T> registerLoader(Class<T> registrant) {
|
||||
try {
|
||||
IrisRegistrant rr = registrant.getConstructor().newInstance();
|
||||
ResourceLoader<T> r = null;
|
||||
if(registrant.equals(IrisObject.class)) {
|
||||
r = (ResourceLoader<T>) new ObjectResourceLoader(dataFolder, this, rr.getFolderName(),
|
||||
rr.getTypeName());
|
||||
} else if(registrant.equals(IrisMatterObject.class)) {
|
||||
r = (ResourceLoader<T>) new MatterObjectResourceLoader(dataFolder, this, rr.getFolderName(),
|
||||
rr.getTypeName());
|
||||
} else if(registrant.equals(IrisScript.class)) {
|
||||
r = (ResourceLoader<T>) new ScriptResourceLoader(dataFolder, this, rr.getFolderName(),
|
||||
rr.getTypeName());
|
||||
} else if(registrant.equals(IrisImage.class)) {
|
||||
r = (ResourceLoader<T>) new ImageResourceLoader(dataFolder, this, rr.getFolderName(),
|
||||
rr.getTypeName());
|
||||
} else {
|
||||
J.attempt(() -> registrant.getConstructor().newInstance().registerTypeAdapters(builder));
|
||||
r = new ResourceLoader<>(dataFolder, this, rr.getFolderName(), rr.getTypeName(), registrant);
|
||||
}
|
||||
|
||||
loaders.put(registrant, r);
|
||||
|
||||
return r;
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
Iris.error("Failed to create loader! " + registrant.getCanonicalName());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public synchronized void hotloaded() {
|
||||
possibleSnippets = new KMap<>();
|
||||
builder = new GsonBuilder()
|
||||
.addDeserializationExclusionStrategy(this)
|
||||
.addSerializationExclusionStrategy(this)
|
||||
.setLenient()
|
||||
.registerTypeAdapterFactory(this)
|
||||
.setPrettyPrinting();
|
||||
loaders.clear();
|
||||
File packs = dataFolder;
|
||||
packs.mkdirs();
|
||||
this.lootLoader = registerLoader(IrisLootTable.class);
|
||||
this.spawnerLoader = registerLoader(IrisSpawner.class);
|
||||
this.entityLoader = registerLoader(IrisEntity.class);
|
||||
this.regionLoader = registerLoader(IrisRegion.class);
|
||||
this.biomeLoader = registerLoader(IrisBiome.class);
|
||||
this.modLoader = registerLoader(IrisMod.class);
|
||||
this.dimensionLoader = registerLoader(IrisDimension.class);
|
||||
this.jigsawPoolLoader = registerLoader(IrisJigsawPool.class);
|
||||
this.jigsawStructureLoader = registerLoader(IrisJigsawStructure.class);
|
||||
this.jigsawPieceLoader = registerLoader(IrisJigsawPiece.class);
|
||||
this.generatorLoader = registerLoader(IrisGenerator.class);
|
||||
this.caveLoader = registerLoader(IrisCave.class);
|
||||
this.markerLoader = registerLoader(IrisMarker.class);
|
||||
this.ravineLoader = registerLoader(IrisRavine.class);
|
||||
this.blockLoader = registerLoader(IrisBlockData.class);
|
||||
this.expressionLoader = registerLoader(IrisExpression.class);
|
||||
this.objectLoader = registerLoader(IrisObject.class);
|
||||
this.imageLoader = registerLoader(IrisImage.class);
|
||||
this.scriptLoader = registerLoader(IrisScript.class);
|
||||
this.matterObjectLoader = registerLoader(IrisMatterObject.class);
|
||||
gson = builder.create();
|
||||
}
|
||||
|
||||
public void dump() {
|
||||
for(ResourceLoader<?> i : loaders.values()) {
|
||||
i.clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
public void clearLists() {
|
||||
for(ResourceLoader<?> i : loaders.values()) {
|
||||
i.clearList();
|
||||
}
|
||||
}
|
||||
|
||||
public String toLoadKey(File f) {
|
||||
if(f.getPath().startsWith(getDataFolder().getPath())) {
|
||||
String[] full = f.getPath().split("\\Q" + File.separator + "\\E");
|
||||
String[] df = getDataFolder().getPath().split("\\Q" + File.separator + "\\E");
|
||||
StringBuilder g = new StringBuilder();
|
||||
boolean m = true;
|
||||
for(int i = 0; i < full.length; i++) {
|
||||
if(i >= df.length) {
|
||||
if(m) {
|
||||
m = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
g.append("/").append(full[i]);
|
||||
}
|
||||
}
|
||||
|
||||
String ff = g.substring(1).split("\\Q.\\E")[0];
|
||||
return ff;
|
||||
} else {
|
||||
Iris.error("Forign file from loader " + f.getPath() + " (loader realm: " + getDataFolder().getPath() + ")");
|
||||
}
|
||||
|
||||
Iris.error("Failed to load " + f.getPath() + " (loader realm: " + getDataFolder().getPath() + ")");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldSkipField(FieldAttributes f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldSkipClass(Class<?> c) {
|
||||
if(c.equals(AtomicCache.class)) {
|
||||
return true;
|
||||
} else return c.equals(ChronoLatch.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
||||
if(!typeToken.getRawType().isAnnotationPresent(Snippet.class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String snippetType = typeToken.getRawType().getDeclaredAnnotation(Snippet.class).value();
|
||||
|
||||
return new TypeAdapter<>() {
|
||||
@Override
|
||||
public void write(JsonWriter jsonWriter, T t) throws IOException {
|
||||
gson.getDelegateAdapter(IrisData.this, typeToken).write(jsonWriter, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T read(JsonReader reader) throws IOException {
|
||||
TypeAdapter<T> adapter = gson.getDelegateAdapter(IrisData.this, typeToken);
|
||||
|
||||
if(reader.peek().equals(JsonToken.STRING)) {
|
||||
String r = reader.nextString();
|
||||
|
||||
if(r.startsWith("snippet/" + snippetType + "/")) {
|
||||
File f = new File(getDataFolder(), r + ".json");
|
||||
|
||||
if(f.exists()) {
|
||||
try {
|
||||
JsonReader snippetReader = new JsonReader(new FileReader(f));
|
||||
return adapter.read(snippetReader);
|
||||
} catch(Throwable e) {
|
||||
Iris.error("Couldn't read snippet " + r + " in " + reader.getPath() + " (" + e.getMessage() + ")");
|
||||
}
|
||||
} else {
|
||||
Iris.error("Couldn't find snippet " + r + " in " + reader.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return adapter.read(reader);
|
||||
} catch(Throwable e) {
|
||||
Iris.error("Failed to read " + typeToken.getRawType().getCanonicalName() + "... faking objects a little to load the file at least.");
|
||||
try {
|
||||
return (T) typeToken.getRawType().getConstructor().newInstance();
|
||||
} catch(Throwable ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public KList<String> getPossibleSnippets(String f) {
|
||||
return possibleSnippets.computeIfAbsent(f, (k) -> {
|
||||
KList<String> l = new KList<>();
|
||||
|
||||
File snippetFolder = new File(getDataFolder(), "snippet/" + f);
|
||||
|
||||
if(snippetFolder.exists() && snippetFolder.isDirectory()) {
|
||||
for(File i : snippetFolder.listFiles()) {
|
||||
l.add("snippet/" + f + "/" + i.getName().split("\\Q.\\E")[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return l;
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.loader;
|
||||
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.object.IrisScript;
|
||||
import com.volmit.iris.engine.object.annotations.ArrayType;
|
||||
import com.volmit.iris.engine.object.annotations.Desc;
|
||||
import com.volmit.iris.engine.object.annotations.RegistryListResource;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import lombok.Data;
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.io.File;
|
||||
|
||||
@Data
|
||||
public abstract class IrisRegistrant {
|
||||
@Desc("Preprocess this object in-memory when it's loaded, run scripts using the variable 'Iris.getPreprocessorObject()' and modify properties about this object before it's used.")
|
||||
@RegistryListResource(IrisScript.class)
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
private KList<String> preprocessors = new KList<>();
|
||||
|
||||
private transient IrisData loader;
|
||||
|
||||
private transient String loadKey;
|
||||
|
||||
private transient File loadFile;
|
||||
|
||||
public abstract String getFolderName();
|
||||
|
||||
public abstract String getTypeName();
|
||||
|
||||
public void registerTypeAdapters(GsonBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
public File openInVSCode() {
|
||||
try {
|
||||
Desktop.getDesktop().open(getLoadFile());
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
return getLoadFile();
|
||||
}
|
||||
|
||||
public abstract void scanForErrors(JSONObject p, VolmitSender sender);
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.loader;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.engine.object.matter.IrisMatterObject;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.data.KCache;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class MatterObjectResourceLoader extends ResourceLoader<IrisMatterObject> {
|
||||
public MatterObjectResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
||||
super(root, idm, folderName, resourceTypeName, IrisMatterObject.class);
|
||||
loadCache = new KCache<>(this::loadRaw, IrisSettings.get().getPerformance().getObjectLoaderCacheSize());
|
||||
}
|
||||
|
||||
public boolean supportsSchemas() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
return loadCache.getSize();
|
||||
}
|
||||
|
||||
public long getTotalStorage() {
|
||||
return getSize();
|
||||
}
|
||||
|
||||
protected IrisMatterObject loadFile(File j, String name) {
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
IrisMatterObject t = IrisMatterObject.from(j);
|
||||
t.setLoadKey(name);
|
||||
t.setLoader(manager);
|
||||
t.setLoadFile(j);
|
||||
logLoad(j, t);
|
||||
tlt.addAndGet(p.getMilliseconds());
|
||||
return t;
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getPossibleKeys() {
|
||||
if(possibleKeys != null) {
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
||||
KSet<String> m = new KSet<>();
|
||||
|
||||
for(File i : getFolders()) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".mat")) {
|
||||
m.add(j.getName().replaceAll("\\Q.mat\\E", ""));
|
||||
} else if(j.isDirectory()) {
|
||||
for(File k : j.listFiles()) {
|
||||
if(k.isFile() && k.getName().endsWith(".mat")) {
|
||||
m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.mat\\E", ""));
|
||||
} else if(k.isDirectory()) {
|
||||
for(File l : k.listFiles()) {
|
||||
if(l.isFile() && l.getName().endsWith(".mat")) {
|
||||
m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.mat\\E", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KList<String> v = new KList<>(m);
|
||||
possibleKeys = v.toArray(new String[0]);
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
public File findFile(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".mat") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".mat");
|
||||
|
||||
if(file.exists()) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IrisMatterObject load(String name) {
|
||||
return load(name, true);
|
||||
}
|
||||
|
||||
private IrisMatterObject loadRaw(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".mat") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return loadFile(j, name);
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".mat");
|
||||
|
||||
if(file.exists()) {
|
||||
return loadFile(file, name);
|
||||
}
|
||||
}
|
||||
|
||||
Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IrisMatterObject load(String name, boolean warn) {
|
||||
return loadCache.get(name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.loader;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.engine.object.IrisObject;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.data.KCache;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
||||
public ObjectResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
||||
super(root, idm, folderName, resourceTypeName, IrisObject.class);
|
||||
loadCache = new KCache<>(this::loadRaw, IrisSettings.get().getPerformance().getObjectLoaderCacheSize());
|
||||
}
|
||||
|
||||
public boolean supportsSchemas() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
return loadCache.getSize();
|
||||
}
|
||||
|
||||
public long getTotalStorage() {
|
||||
return getSize();
|
||||
}
|
||||
|
||||
protected IrisObject loadFile(File j, String name) {
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
IrisObject t = new IrisObject(0, 0, 0);
|
||||
t.read(j);
|
||||
t.setLoadKey(name);
|
||||
t.setLoader(manager);
|
||||
t.setLoadFile(j);
|
||||
logLoad(j, t);
|
||||
tlt.addAndGet(p.getMilliseconds());
|
||||
return t;
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getPossibleKeys() {
|
||||
if(possibleKeys != null) {
|
||||
return possibleKeys;
|
||||
}
|
||||
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
||||
KSet<String> m = new KSet<>();
|
||||
for(File i : getFolders()) {
|
||||
m.addAll(getFiles(i, ".iob", true));
|
||||
}
|
||||
possibleKeys = m.toArray(new String[0]);
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
private KList<String> getFiles(File dir, String ext, boolean skipDirName) {
|
||||
KList<String> paths = new KList<>();
|
||||
String name = skipDirName ? "" : dir.getName() + "/";
|
||||
for(File f : dir.listFiles()) {
|
||||
if(f.isFile() && f.getName().endsWith(ext)) {
|
||||
paths.add(name + f.getName().replaceAll("\\Q" + ext + "\\E", ""));
|
||||
} else if(f.isDirectory()) {
|
||||
getFiles(f, ext, false).forEach(e -> paths.add(name + e));
|
||||
}
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
public File findFile(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".iob") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".iob");
|
||||
|
||||
if(file.exists()) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IrisObject load(String name) {
|
||||
return load(name, true);
|
||||
}
|
||||
|
||||
private IrisObject loadRaw(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".iob") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return loadFile(j, name);
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".iob");
|
||||
|
||||
if(file.exists()) {
|
||||
return loadFile(file, name);
|
||||
}
|
||||
}
|
||||
|
||||
Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IrisObject load(String name, boolean warn) {
|
||||
return loadCache.get(name);
|
||||
}
|
||||
}
|
||||
400
src/main/java/com/volmit/iris/core/loader/ResourceLoader.java
Normal file
400
src/main/java/com/volmit/iris/core/loader/ResourceLoader.java
Normal file
@@ -0,0 +1,400 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.loader;
|
||||
|
||||
import com.google.common.util.concurrent.AtomicDouble;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.project.SchemaBuilder;
|
||||
import com.volmit.iris.core.service.PreservationSVC;
|
||||
import com.volmit.iris.engine.framework.MeteredCache;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.data.KCache;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONArray;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Data
|
||||
public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
public static final AtomicDouble tlt = new AtomicDouble(0);
|
||||
private static final int CACHE_SIZE = 100000;
|
||||
protected File root;
|
||||
protected String folderName;
|
||||
protected String resourceTypeName;
|
||||
protected KCache<String, T> loadCache;
|
||||
protected final AtomicReference<KList<File>> folderCache;
|
||||
protected Class<? extends T> objectClass;
|
||||
protected String cname;
|
||||
protected String[] possibleKeys = null;
|
||||
protected IrisData manager;
|
||||
protected AtomicInteger loads;
|
||||
protected ChronoLatch sec;
|
||||
|
||||
public ResourceLoader(File root, IrisData manager, String folderName, String resourceTypeName, Class<? extends T> objectClass) {
|
||||
this.manager = manager;
|
||||
folderCache = new AtomicReference<>();
|
||||
sec = new ChronoLatch(5000);
|
||||
loads = new AtomicInteger();
|
||||
this.objectClass = objectClass;
|
||||
cname = objectClass.getCanonicalName();
|
||||
this.resourceTypeName = resourceTypeName;
|
||||
this.root = root;
|
||||
this.folderName = folderName;
|
||||
loadCache = new KCache<>(this::loadRaw, IrisSettings.get().getPerformance().getResourceLoaderCacheSize());
|
||||
Iris.debug("Loader<" + C.GREEN + resourceTypeName + C.LIGHT_PURPLE + "> created in " + C.RED + "IDM/" + manager.getId() + C.LIGHT_PURPLE + " on " + C.GRAY + manager.getDataFolder().getPath());
|
||||
Iris.service(PreservationSVC.class).registerCache(this);
|
||||
}
|
||||
|
||||
public JSONObject buildSchema() {
|
||||
Iris.debug("Building Schema " + objectClass.getSimpleName() + " " + root.getPath());
|
||||
JSONObject o = new JSONObject();
|
||||
KList<String> fm = new KList<>();
|
||||
|
||||
for(int g = 1; g < 8; g++) {
|
||||
fm.add("/" + folderName + Form.repeat("/*", g) + ".json");
|
||||
}
|
||||
|
||||
o.put("fileMatch", new JSONArray(fm.toArray()));
|
||||
o.put("url", "./.iris/schema/" + getFolderName() + "-schema.json");
|
||||
File a = new File(getManager().getDataFolder(), ".iris/schema/" + getFolderName() + "-schema.json");
|
||||
J.attemptAsync(() -> IO.writeAll(a, new SchemaBuilder(objectClass, manager).construct().toString(4)));
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
public File findFile(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".json");
|
||||
|
||||
if(file.exists()) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void logLoad(File path, T t) {
|
||||
loads.getAndIncrement();
|
||||
|
||||
if(loads.get() == 1) {
|
||||
sec.flip();
|
||||
}
|
||||
|
||||
if(sec.flip()) {
|
||||
J.a(() -> {
|
||||
Iris.verbose("Loaded " + C.WHITE + loads.get() + " " + resourceTypeName + (loads.get() == 1 ? "" : "s") + C.GRAY + " (" + Form.f(getLoadCache().getSize()) + " " + resourceTypeName + (loadCache.getSize() == 1 ? "" : "s") + " Loaded)");
|
||||
loads.set(0);
|
||||
});
|
||||
}
|
||||
|
||||
Iris.debug("Loader<" + C.GREEN + resourceTypeName + C.LIGHT_PURPLE + "> iload " + C.YELLOW + t.getLoadKey() + C.LIGHT_PURPLE + " in " + C.GRAY + t.getLoadFile().getPath() + C.LIGHT_PURPLE + " TLT: " + C.RED + Form.duration(tlt.get(), 2));
|
||||
}
|
||||
|
||||
public void failLoad(File path, Throwable e) {
|
||||
J.a(() -> Iris.warn("Couldn't Load " + resourceTypeName + " file: " + path.getPath() + ": " + e.getMessage()));
|
||||
}
|
||||
|
||||
private KList<File> matchAllFiles(File root, Predicate<File> f) {
|
||||
KList<File> fx = new KList<>();
|
||||
matchFiles(root, fx, f);
|
||||
return fx;
|
||||
}
|
||||
|
||||
private void matchFiles(File at, KList<File> files, Predicate<File> f) {
|
||||
if(at.isDirectory()) {
|
||||
for(File i : at.listFiles()) {
|
||||
matchFiles(i, files, f);
|
||||
}
|
||||
} else {
|
||||
if(f.test(at)) {
|
||||
files.add(at);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getPossibleKeys() {
|
||||
if(possibleKeys != null) {
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
KSet<String> m = new KSet<>();
|
||||
KList<File> files = getFolders();
|
||||
|
||||
if(files == null) {
|
||||
possibleKeys = new String[0];
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
for(File i : files) {
|
||||
for(File j : matchAllFiles(i, (f) -> f.getName().endsWith(".json"))) {
|
||||
m.add(i.toURI().relativize(j.toURI()).getPath().replaceAll("\\Q.json\\E", ""));
|
||||
}
|
||||
}
|
||||
|
||||
KList<String> v = new KList<>(m);
|
||||
possibleKeys = v.toArray(new String[0]);
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
public long count() {
|
||||
return loadCache.getSize();
|
||||
}
|
||||
|
||||
protected T loadFile(File j, String name) {
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
T t = getManager().getGson()
|
||||
.fromJson(preprocess(new JSONObject(IO.readAll(j))).toString(0), objectClass);
|
||||
t.setLoadKey(name);
|
||||
t.setLoadFile(j);
|
||||
t.setLoader(manager);
|
||||
getManager().preprocessObject(t);
|
||||
logLoad(j, t);
|
||||
tlt.addAndGet(p.getMilliseconds());
|
||||
return t;
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
failLoad(j, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected JSONObject preprocess(JSONObject j) {
|
||||
return j;
|
||||
}
|
||||
|
||||
public Stream<T> streamAll(Stream<String> s) {
|
||||
return s.map(this::load);
|
||||
}
|
||||
|
||||
public KList<T> loadAll(KList<String> s) {
|
||||
KList<T> m = new KList<>();
|
||||
|
||||
for(String i : s) {
|
||||
T t = load(i);
|
||||
|
||||
if(t != null) {
|
||||
m.add(t);
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
public KList<T> loadAll(KList<String> s, Consumer<T> postLoad) {
|
||||
KList<T> m = new KList<>();
|
||||
|
||||
for(String i : s) {
|
||||
T t = load(i);
|
||||
|
||||
if(t != null) {
|
||||
m.add(t);
|
||||
postLoad.accept(t);
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
public KList<T> loadAll(String[] s) {
|
||||
KList<T> m = new KList<>();
|
||||
|
||||
for(String i : s) {
|
||||
T t = load(i);
|
||||
|
||||
if(t != null) {
|
||||
m.add(t);
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
public T load(String name) {
|
||||
return load(name, true);
|
||||
}
|
||||
|
||||
private T loadRaw(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
//noinspection ConstantConditions
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return loadFile(j, name);
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".json");
|
||||
|
||||
if(file.exists()) {
|
||||
return loadFile(file, name);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public T load(String name, boolean warn) {
|
||||
if(name == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(name.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return loadCache.get(name);
|
||||
}
|
||||
|
||||
public KList<File> getFolders() {
|
||||
|
||||
|
||||
synchronized(folderCache) {
|
||||
if(folderCache.get() == null) {
|
||||
KList<File> fc = new KList<>();
|
||||
|
||||
for(File i : root.listFiles()) {
|
||||
if(i.isDirectory()) {
|
||||
if(i.getName().equals(folderName)) {
|
||||
fc.add(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
folderCache.set(fc);
|
||||
}
|
||||
}
|
||||
|
||||
return folderCache.get();
|
||||
}
|
||||
|
||||
public KList<File> getFolders(String rc) {
|
||||
KList<File> folders = getFolders().copy();
|
||||
|
||||
if(rc.contains(":")) {
|
||||
for(File i : folders.copy()) {
|
||||
if(!rc.startsWith(i.getName() + ":")) {
|
||||
folders.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return folders;
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
possibleKeys = null;
|
||||
loadCache.invalidate();
|
||||
folderCache.set(null);
|
||||
}
|
||||
|
||||
public File fileFor(T b) {
|
||||
for(File i : getFolders()) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(b.getLoadKey())) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, b.getLoadKey() + ".json");
|
||||
|
||||
if(file.exists()) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isLoaded(String next) {
|
||||
return loadCache.contains(next);
|
||||
}
|
||||
|
||||
public void clearList() {
|
||||
folderCache.set(null);
|
||||
possibleKeys = null;
|
||||
}
|
||||
|
||||
public KList<String> getPossibleKeys(String arg) {
|
||||
KList<String> f = new KList<>();
|
||||
|
||||
for(String i : getPossibleKeys()) {
|
||||
if(i.equalsIgnoreCase(arg) || i.toLowerCase(Locale.ROOT).startsWith(arg.toLowerCase(Locale.ROOT)) || i.toLowerCase(Locale.ROOT).contains(arg.toLowerCase(Locale.ROOT)) || arg.toLowerCase(Locale.ROOT).contains(i.toLowerCase(Locale.ROOT))) {
|
||||
f.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
public boolean supportsSchemas() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void clean() {
|
||||
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
return loadCache.getSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KCache<?, ?> getRawCache() {
|
||||
return loadCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaxSize() {
|
||||
return loadCache.getMaxSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return getManager().isClosed();
|
||||
}
|
||||
|
||||
public long getTotalStorage() {
|
||||
return getSize();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.loader;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.engine.object.IrisScript;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.data.KCache;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
||||
public ScriptResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
||||
super(root, idm, folderName, resourceTypeName, IrisScript.class);
|
||||
loadCache = new KCache<>(this::loadRaw, IrisSettings.get().getPerformance().getScriptLoaderCacheSize());
|
||||
}
|
||||
|
||||
public boolean supportsSchemas() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
return loadCache.getSize();
|
||||
}
|
||||
|
||||
protected IrisScript loadFile(File j, String name) {
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
IrisScript t = new IrisScript(IO.readAll(j));
|
||||
t.setLoadKey(name);
|
||||
t.setLoader(manager);
|
||||
t.setLoadFile(j);
|
||||
logLoad(j, t);
|
||||
tlt.addAndGet(p.getMilliseconds());
|
||||
return t;
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getPossibleKeys() {
|
||||
if(possibleKeys != null) {
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
||||
KSet<String> m = new KSet<>();
|
||||
|
||||
for(File i : getFolders()) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".js")) {
|
||||
m.add(j.getName().replaceAll("\\Q.js\\E", ""));
|
||||
} else if(j.isDirectory()) {
|
||||
for(File k : j.listFiles()) {
|
||||
if(k.isFile() && k.getName().endsWith(".js")) {
|
||||
m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.js\\E", ""));
|
||||
} else if(k.isDirectory()) {
|
||||
for(File l : k.listFiles()) {
|
||||
if(l.isFile() && l.getName().endsWith(".js")) {
|
||||
m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.js\\E", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KList<String> v = new KList<>(m);
|
||||
possibleKeys = v.toArray(new String[0]);
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
public File findFile(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".js");
|
||||
|
||||
if(file.exists()) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private IrisScript loadRaw(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return loadFile(j, name);
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".js");
|
||||
|
||||
if(file.exists()) {
|
||||
return loadFile(file, name);
|
||||
}
|
||||
}
|
||||
|
||||
Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IrisScript load(String name, boolean warn) {
|
||||
return loadCache.get(name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface BiomeBaseInjector {
|
||||
default void setBiome(int x, int z, Object biomeBase) {
|
||||
setBiome(x, 0, z, biomeBase);
|
||||
}
|
||||
|
||||
void setBiome(int x, int y, int z, Object biomeBase);
|
||||
}
|
||||
77
src/main/java/com/volmit/iris/core/nms/INMS.java
Normal file
77
src/main/java/com/volmit/iris/core/nms/INMS.java
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.nms.v19_2.NMSBinding19_2;
|
||||
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class INMS {
|
||||
//@builder
|
||||
private static final KMap<String, Class<? extends INMSBinding>> bindings = new KMap<String, Class<? extends INMSBinding>>()
|
||||
.qput("v1_19_R1", NMSBinding19_2.class);
|
||||
//@done
|
||||
private static final INMSBinding binding = bind();
|
||||
|
||||
public static INMSBinding get() {
|
||||
return binding;
|
||||
}
|
||||
|
||||
public static String getNMSTag() {
|
||||
if(IrisSettings.get().getGeneral().isDisableNMS()) {
|
||||
return "BUKKIT";
|
||||
}
|
||||
|
||||
try {
|
||||
return Bukkit.getServer().getClass().getCanonicalName().split("\\Q.\\E")[3];
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.error("Failed to determine server nms version!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return "BUKKIT";
|
||||
}
|
||||
|
||||
private static INMSBinding bind() {
|
||||
String code = getNMSTag();
|
||||
Iris.info("Locating NMS Binding for " + code);
|
||||
|
||||
if(bindings.containsKey(code)) {
|
||||
try {
|
||||
INMSBinding b = bindings.get(code).getConstructor().newInstance();
|
||||
Iris.info("Craftbukkit " + code + " <-> " + b.getClass().getSimpleName() + " Successfully Bound");
|
||||
|
||||
return b;
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
Iris.info("Craftbukkit " + code + " <-> " + NMSBinding1X.class.getSimpleName() + " Successfully Bound");
|
||||
Iris.warn("Note: Some features of Iris may not work the same since you are on an unsupported version of Minecraft.");
|
||||
Iris.warn("Note: If this is a new version, expect an update soon.");
|
||||
|
||||
return new NMSBinding1X();
|
||||
}
|
||||
}
|
||||
86
src/main/java/com/volmit/iris/core/nms/INMSBinding.java
Normal file
86
src/main/java/com/volmit/iris/core/nms/INMSBinding.java
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms;
|
||||
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
public interface INMSBinding {
|
||||
boolean hasTile(Location l);
|
||||
|
||||
CompoundTag serializeTile(Location location);
|
||||
|
||||
void deserializeTile(CompoundTag s, Location newPosition);
|
||||
|
||||
CompoundTag serializeEntity(Entity location);
|
||||
|
||||
Entity deserializeEntity(CompoundTag s, Location newPosition);
|
||||
|
||||
boolean supportsCustomHeight();
|
||||
|
||||
Object getBiomeBaseFromId(int id);
|
||||
|
||||
int getMinHeight(World world);
|
||||
|
||||
boolean supportsCustomBiomes();
|
||||
|
||||
int getTrueBiomeBaseId(Object biomeBase);
|
||||
|
||||
Object getTrueBiomeBase(Location location);
|
||||
|
||||
String getTrueBiomeBaseKey(Location location);
|
||||
|
||||
Object getCustomBiomeBaseFor(String mckey);
|
||||
Object getCustomBiomeBaseHolderFor(String mckey);
|
||||
|
||||
String getKeyForBiomeBase(Object biomeBase);
|
||||
|
||||
Object getBiomeBase(World world, Biome biome);
|
||||
|
||||
Object getBiomeBase(Object registry, Biome biome);
|
||||
|
||||
boolean isBukkit();
|
||||
|
||||
int getBiomeId(Biome biome);
|
||||
|
||||
MCABiomeContainer newBiomeContainer(int min, int max, int[] data);
|
||||
|
||||
MCABiomeContainer newBiomeContainer(int min, int max);
|
||||
|
||||
default World createWorld(WorldCreator c) {
|
||||
return c.createWorld();
|
||||
}
|
||||
|
||||
int countCustomBiomes();
|
||||
|
||||
void forceBiomeInto(int x, int y, int z, Object somethingVeryDirty, ChunkGenerator.BiomeGrid chunk);
|
||||
|
||||
default boolean supportsDataPacks() {
|
||||
return false;
|
||||
}
|
||||
|
||||
MCAPaletteAccess createPalette();
|
||||
}
|
||||
159
src/main/java/com/volmit/iris/core/nms/NMSVersion.java
Normal file
159
src/main/java/com/volmit/iris/core/nms/NMSVersion.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public enum NMSVersion {
|
||||
R1_19_1,
|
||||
R1_18_2,
|
||||
R1_18,
|
||||
R1_17,
|
||||
R1_16,
|
||||
R1_15,
|
||||
R1_14,
|
||||
R1_13,
|
||||
R1_13_1,
|
||||
R1_12,
|
||||
R1_11,
|
||||
R1_10,
|
||||
R1_9_4,
|
||||
R1_9_2,
|
||||
R1_8;
|
||||
|
||||
public static NMSVersion getMinimum() {
|
||||
return values()[values().length - 1];
|
||||
}
|
||||
|
||||
public static NMSVersion getMaximum() {
|
||||
return values()[0];
|
||||
}
|
||||
|
||||
public static NMSVersion current() {
|
||||
if(tryVersion("1_8_R3")) {
|
||||
return R1_8;
|
||||
}
|
||||
|
||||
if(tryVersion("1_9_R1")) {
|
||||
return R1_9_2;
|
||||
}
|
||||
|
||||
if(tryVersion("1_9_R2")) {
|
||||
return R1_9_4;
|
||||
}
|
||||
|
||||
if(tryVersion("1_10_R1")) {
|
||||
return R1_10;
|
||||
}
|
||||
|
||||
if(tryVersion("1_11_R1")) {
|
||||
return R1_11;
|
||||
}
|
||||
|
||||
if(tryVersion("1_12_R1")) {
|
||||
return R1_12;
|
||||
}
|
||||
|
||||
if(tryVersion("1_13_R1")) {
|
||||
return R1_13;
|
||||
}
|
||||
|
||||
if(tryVersion("1_13_R2")) {
|
||||
return R1_13_1;
|
||||
}
|
||||
|
||||
if(tryVersion("1_14_R1")) {
|
||||
return R1_14;
|
||||
}
|
||||
|
||||
if(tryVersion("1_15_R1")) {
|
||||
return R1_15;
|
||||
}
|
||||
|
||||
if(tryVersion("1_16_R1")) {
|
||||
return R1_16;
|
||||
}
|
||||
|
||||
if(tryVersion("1_17_R1")) {
|
||||
return R1_17;
|
||||
}
|
||||
|
||||
if(tryVersion("1_18_R1")) {
|
||||
return R1_18;
|
||||
}
|
||||
if(tryVersion("1_18_R2")) {
|
||||
return R1_18_2;
|
||||
}
|
||||
if(tryVersion("1_19_R1")) {
|
||||
return R1_19_1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean tryVersion(String v) {
|
||||
try {
|
||||
Class.forName("org.bukkit.craftbukkit.v" + v + ".CraftWorld");
|
||||
return true;
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<NMSVersion> getAboveInclusive() {
|
||||
List<NMSVersion> n = new ArrayList<>();
|
||||
|
||||
for(NMSVersion i : values()) {
|
||||
if(i.ordinal() >= ordinal()) {
|
||||
n.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
public List<NMSVersion> betweenInclusive(NMSVersion other) {
|
||||
List<NMSVersion> n = new ArrayList<>();
|
||||
|
||||
for(NMSVersion i : values()) {
|
||||
if(i.ordinal() <= Math.max(other.ordinal(), ordinal()) && i.ordinal() >= Math.min(ordinal(), other.ordinal())) {
|
||||
n.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
public List<NMSVersion> getBelowInclusive() {
|
||||
List<NMSVersion> n = new ArrayList<>();
|
||||
|
||||
for(NMSVersion i : values()) {
|
||||
if(i.ordinal() <= ordinal()) {
|
||||
n.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
}
|
||||
443
src/main/java/com/volmit/iris/core/nms/v19_2/NMSBinding19_2.java
Normal file
443
src/main/java/com/volmit/iris/core/nms/v19_2/NMSBinding19_2.java
Normal file
@@ -0,0 +1,443 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms.v19_2;
|
||||
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMSBinding;
|
||||
import com.volmit.iris.engine.data.cache.AtomicCache;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.nbt.io.NBTUtil;
|
||||
import com.volmit.iris.util.nbt.mca.NBTWorld;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCAChunkBiomeContainer;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCAGlobalPalette;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCAIdMap;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCAIdMapper;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCAPalette;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCAPalettedContainer;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCAWrappedPalettedContainer;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import net.minecraft.core.*;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
|
||||
import org.bukkit.craftbukkit.v1_19_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class NMSBinding19_2 implements INMSBinding {
|
||||
|
||||
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
|
||||
private final BlockData AIR = Material.AIR.createBlockData();
|
||||
private final AtomicCache<MCAIdMap<net.minecraft.world.level.biome.Biome>> biomeMapCache = new AtomicCache<>();
|
||||
private final AtomicCache<MCAIdMapper<BlockState>> registryCache = new AtomicCache<>();
|
||||
private final AtomicCache<MCAPalette<BlockState>> globalCache = new AtomicCache<>();
|
||||
private final AtomicCache<RegistryAccess> registryAccess = new AtomicCache<>();
|
||||
private final AtomicCache<Method> byIdRef = new AtomicCache<>();
|
||||
private Field biomeStorageCache = null;
|
||||
|
||||
@Override
|
||||
public boolean hasTile(Location l) {
|
||||
return ((CraftWorld) l.getWorld()).getHandle().getBlockEntity(new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ()), false) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeTile(Location location) {
|
||||
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), true);
|
||||
|
||||
if(e == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
net.minecraft.nbt.CompoundTag tag = e.saveWithFullMetadata();
|
||||
return convert(tag);
|
||||
}
|
||||
|
||||
private CompoundTag convert(net.minecraft.nbt.CompoundTag tag) {
|
||||
try {
|
||||
ByteArrayOutputStream boas = new ByteArrayOutputStream();
|
||||
DataOutputStream dos = new DataOutputStream(boas);
|
||||
tag.write(dos);
|
||||
dos.close();
|
||||
return (CompoundTag) NBTUtil.read(new ByteArrayInputStream(boas.toByteArray()), false).getTag();
|
||||
} catch(Throwable ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private net.minecraft.nbt.CompoundTag convert(CompoundTag tag) {
|
||||
try {
|
||||
ByteArrayOutputStream boas = new ByteArrayOutputStream();
|
||||
NBTUtil.write(tag, boas, false);
|
||||
DataInputStream din = new DataInputStream(new ByteArrayInputStream(boas.toByteArray()));
|
||||
net.minecraft.nbt.CompoundTag c = NbtIo.read(din);
|
||||
din.close();
|
||||
return c;
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeTile(CompoundTag c, Location pos) {
|
||||
((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeEntity(Entity location) {
|
||||
return null;// TODO:
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity deserializeEntity(CompoundTag s, Location newPosition) {
|
||||
return null;// TODO:
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCustomHeight() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private RegistryAccess registry() {
|
||||
return registryAccess.aquire(() -> (RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer()));
|
||||
}
|
||||
|
||||
private Registry<net.minecraft.world.level.biome.Biome> getCustomBiomeRegistry() {
|
||||
|
||||
return registry().registry(Registry.BIOME_REGISTRY).orElse(null);
|
||||
}
|
||||
|
||||
private Registry<Block> getBlockRegistry() {
|
||||
return registry().registry(Registry.BLOCK_REGISTRY).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBiomeBaseFromId(int id) {
|
||||
try {
|
||||
return byIdRef.aquire(() -> {
|
||||
for(Method i : IdMap.class.getDeclaredMethods()) {
|
||||
if(i.getParameterCount() == 1 && i.getParameterTypes()[0].equals(int.class)) {
|
||||
Iris.info("[NMS] Found byId method in " + IdMap.class.getSimpleName() + "." + i.getName() + "(int) => " + Biome.class.getSimpleName());
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
Iris.error("Cannot find byId method!");
|
||||
return null;
|
||||
}).invoke(getCustomBiomeRegistry(), id);
|
||||
} catch(IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinHeight(World world) {
|
||||
return world.getMinHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCustomBiomes() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTrueBiomeBaseId(Object biomeBase) {
|
||||
return getCustomBiomeRegistry().getId((net.minecraft.world.level.biome.Biome) biomeBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTrueBiomeBase(Location location) {
|
||||
return ((CraftWorld) location.getWorld()).getHandle().getBiome(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTrueBiomeBaseKey(Location location) {
|
||||
return getKeyForBiomeBase(getTrueBiomeBase(location));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCustomBiomeBaseFor(String mckey) {
|
||||
return getCustomBiomeRegistry().get(new ResourceLocation(mckey));
|
||||
}
|
||||
@Override
|
||||
public Object getCustomBiomeBaseHolderFor(String mckey) {
|
||||
return getCustomBiomeRegistry().getHolder(getTrueBiomeBaseId(getCustomBiomeRegistry().get(new ResourceLocation(mckey)))).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKeyForBiomeBase(Object biomeBase) {
|
||||
return getCustomBiomeRegistry().getKey((net.minecraft.world.level.biome.Biome) biomeBase).getPath(); // something, not something:something
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBiomeBase(World world, Biome biome) {
|
||||
return getBiomeBase(((CraftWorld) world).getHandle().registryAccess().registry(Registry.BIOME_REGISTRY).orElse(null), biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBiomeBase(Object registry, Biome biome) {
|
||||
Object v = baseBiomeCache.get(biome);
|
||||
|
||||
if(v != null) {
|
||||
return v;
|
||||
}
|
||||
//noinspection unchecked
|
||||
v = org.bukkit.craftbukkit.v1_19_R1.block.CraftBlock.biomeToBiomeBase((Registry<net.minecraft.world.level.biome.Biome>) registry, biome);
|
||||
if(v == null) {
|
||||
// Ok so there is this new biome name called "CUSTOM" in Paper's new releases.
|
||||
// But, this does NOT exist within CraftBukkit which makes it return an error.
|
||||
// So, we will just return the ID that the plains biome returns instead.
|
||||
//noinspection unchecked
|
||||
return org.bukkit.craftbukkit.v1_19_R1.block.CraftBlock.biomeToBiomeBase((Registry<net.minecraft.world.level.biome.Biome>) registry, Biome.PLAINS);
|
||||
}
|
||||
baseBiomeCache.put(biome, v);
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBukkit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBiomeId(Biome biome) {
|
||||
for(World i : Bukkit.getWorlds()) {
|
||||
if(i.getEnvironment().equals(World.Environment.NORMAL)) {
|
||||
Registry<net.minecraft.world.level.biome.Biome> registry = ((CraftWorld) i).getHandle().registryAccess().registry(Registry.BIOME_REGISTRY).orElse(null);
|
||||
return registry.getId((net.minecraft.world.level.biome.Biome) getBiomeBase(registry, biome));
|
||||
}
|
||||
}
|
||||
|
||||
return biome.ordinal();
|
||||
}
|
||||
|
||||
private MCAIdMap<net.minecraft.world.level.biome.Biome> getBiomeMapping() {
|
||||
return biomeMapCache.aquire(() -> new MCAIdMap<>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<net.minecraft.world.level.biome.Biome> iterator() {
|
||||
return getCustomBiomeRegistry().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(net.minecraft.world.level.biome.Biome paramT) {
|
||||
return getCustomBiomeRegistry().getId(paramT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.minecraft.world.level.biome.Biome byId(int paramInt) {
|
||||
return (net.minecraft.world.level.biome.Biome) getBiomeBaseFromId(paramInt);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private MCABiomeContainer getBiomeContainerInterface(MCAIdMap<net.minecraft.world.level.biome.Biome> biomeMapping, MCAChunkBiomeContainer<net.minecraft.world.level.biome.Biome> base) {
|
||||
return new MCABiomeContainer() {
|
||||
@Override
|
||||
public int[] getData() {
|
||||
return base.writeBiomes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int y, int z, int id) {
|
||||
base.setBiome(x, y, z, biomeMapping.byId(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBiome(int x, int y, int z) {
|
||||
return biomeMapping.getId(base.getBiome(x, y, z));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public MCABiomeContainer newBiomeContainer(int min, int max) {
|
||||
MCAChunkBiomeContainer<net.minecraft.world.level.biome.Biome> base = new MCAChunkBiomeContainer<>(getBiomeMapping(), min, max);
|
||||
return getBiomeContainerInterface(getBiomeMapping(), base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MCABiomeContainer newBiomeContainer(int min, int max, int[] data) {
|
||||
MCAChunkBiomeContainer<net.minecraft.world.level.biome.Biome> base = new MCAChunkBiomeContainer<>(getBiomeMapping(), min, max, data);
|
||||
return getBiomeContainerInterface(getBiomeMapping(), base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countCustomBiomes() {
|
||||
AtomicInteger a = new AtomicInteger(0);
|
||||
|
||||
getCustomBiomeRegistry().keySet().forEach((i) -> {
|
||||
if(i.getNamespace().equals("minecraft")) {
|
||||
return;
|
||||
}
|
||||
|
||||
a.incrementAndGet();
|
||||
Iris.debug("Custom Biome: " + i);
|
||||
});
|
||||
|
||||
return a.get();
|
||||
}
|
||||
|
||||
public boolean supportsDataPacks() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceBiomeInto(int x, int y, int z, Object somethingVeryDirty, ChunkGenerator.BiomeGrid chunk) {
|
||||
try {
|
||||
ChunkAccess s = (ChunkAccess) getFieldForBiomeStorage(chunk).get(chunk);
|
||||
Holder<net.minecraft.world.level.biome.Biome> biome = (Holder<net.minecraft.world.level.biome.Biome>) somethingVeryDirty;
|
||||
s.setBiome(x, y, z, biome);
|
||||
} catch(IllegalAccessException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private Field getFieldForBiomeStorage(Object storage) {
|
||||
Field f = biomeStorageCache;
|
||||
|
||||
if(f != null) {
|
||||
return f;
|
||||
}
|
||||
try {
|
||||
|
||||
f = storage.getClass().getDeclaredField("biome");
|
||||
f.setAccessible(true);
|
||||
return f;
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
Iris.error(storage.getClass().getCanonicalName());
|
||||
}
|
||||
|
||||
biomeStorageCache = f;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MCAPaletteAccess createPalette() {
|
||||
MCAIdMapper<BlockState> registry = registryCache.aquireNasty(() -> {
|
||||
Field cf = net.minecraft.core.IdMapper.class.getDeclaredField("tToId");
|
||||
Field df = net.minecraft.core.IdMapper.class.getDeclaredField("idToT");
|
||||
Field bf = net.minecraft.core.IdMapper.class.getDeclaredField("nextId");
|
||||
cf.setAccessible(true);
|
||||
df.setAccessible(true);
|
||||
bf.setAccessible(true);
|
||||
net.minecraft.core.IdMapper<BlockState> blockData = Block.BLOCK_STATE_REGISTRY;
|
||||
int b = bf.getInt(blockData);
|
||||
Object2IntMap<BlockState> c = (Object2IntMap<BlockState>) cf.get(blockData);
|
||||
List<BlockState> d = (List<BlockState>) df.get(blockData);
|
||||
return new MCAIdMapper<BlockState>(c, d, b);
|
||||
});
|
||||
MCAPalette<BlockState> global = globalCache.aquireNasty(() -> new MCAGlobalPalette<>(registry, ((CraftBlockData) AIR).getState()));
|
||||
MCAPalettedContainer<BlockState> container = new MCAPalettedContainer<>(global, registry,
|
||||
i -> ((CraftBlockData) NBTWorld.getBlockData(i)).getState(),
|
||||
i -> NBTWorld.getCompound(CraftBlockData.fromData(i)),
|
||||
((CraftBlockData) AIR).getState());
|
||||
return new MCAWrappedPalettedContainer<>(container,
|
||||
i -> NBTWorld.getCompound(CraftBlockData.fromData(i)),
|
||||
i -> ((CraftBlockData) NBTWorld.getBlockData(i)).getState());
|
||||
}
|
||||
|
||||
private static Object getFor(Class<?> type, Object source) {
|
||||
Object o = fieldFor(type, source);
|
||||
|
||||
if(o != null) {
|
||||
return o;
|
||||
}
|
||||
|
||||
return invokeFor(type, source);
|
||||
}
|
||||
|
||||
private static Object invokeFor(Class<?> returns, Object in) {
|
||||
for(Method i : in.getClass().getMethods()) {
|
||||
if(i.getReturnType().equals(returns)) {
|
||||
i.setAccessible(true);
|
||||
try {
|
||||
Iris.debug("[NMS] Found " + returns.getSimpleName() + " in " + in.getClass().getSimpleName() + "." + i.getName() + "()");
|
||||
return i.invoke(in);
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Object fieldFor(Class<?> returns, Object in) {
|
||||
return fieldForClass(returns, in.getClass(), in);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T fieldForClass(Class<T> returnType, Class<?> sourceType, Object in) {
|
||||
for(Field i : sourceType.getDeclaredFields()) {
|
||||
if(i.getType().equals(returnType)) {
|
||||
i.setAccessible(true);
|
||||
try {
|
||||
Iris.debug("[NMS] Found " + returnType.getSimpleName() + " in " + sourceType.getSimpleName() + "." + i.getName());
|
||||
return (T) i.get(in);
|
||||
} catch(IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<?> getClassType(Class<?> type, int ordinal) {
|
||||
return type.getDeclaredClasses()[ordinal];
|
||||
}
|
||||
}
|
||||
173
src/main/java/com/volmit/iris/core/nms/v1X/NMSBinding1X.java
Normal file
173
src/main/java/com/volmit/iris/core/nms/v1X/NMSBinding1X.java
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms.v1X;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMSBinding;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
public class NMSBinding1X implements INMSBinding {
|
||||
private static final boolean supportsCustomHeight = testCustomHeight();
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private static boolean testCustomHeight() {
|
||||
try {
|
||||
if(World.class.getDeclaredMethod("getMaxHeight") != null && World.class.getDeclaredMethod("getMinHeight") != null)
|
||||
;
|
||||
{
|
||||
return true;
|
||||
}
|
||||
} catch(Throwable ignored) {
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTile(Location l) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeTile(Location location) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeTile(CompoundTag s, Location newPosition) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeEntity(Entity location) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity deserializeEntity(CompoundTag s, Location newPosition) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCustomHeight() {
|
||||
return supportsCustomHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBiomeBaseFromId(int id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinHeight(World world) {
|
||||
return supportsCustomHeight ? world.getMinHeight() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCustomBiomes() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTrueBiomeBaseId(Object biomeBase) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTrueBiomeBase(Location location) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTrueBiomeBaseKey(Location location) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCustomBiomeBaseFor(String mckey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCustomBiomeBaseHolderFor(String mckey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKeyForBiomeBase(Object biomeBase) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object getBiomeBase(World world, Biome biome) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBiomeBase(Object registry, Biome biome) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBukkit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBiomeId(Biome biome) {
|
||||
return biome.ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MCABiomeContainer newBiomeContainer(int min, int max) {
|
||||
Iris.error("Cannot use the custom biome data! Iris is incapable of using MCA generation on this version of minecraft!");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MCABiomeContainer newBiomeContainer(int min, int max, int[] v) {
|
||||
Iris.error("Cannot use the custom biome data! Iris is incapable of using MCA generation on this version of minecraft!");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countCustomBiomes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceBiomeInto(int x, int y, int z, Object somethingVeryDirty, ChunkGenerator.BiomeGrid chunk) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public MCAPaletteAccess createPalette() {
|
||||
Iris.error("Cannot use the global data palette! Iris is incapable of using MCA generation on this version of minecraft!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
400
src/main/java/com/volmit/iris/core/pack/IrisPack.java
Normal file
400
src/main/java/com/volmit/iris/core/pack/IrisPack.java
Normal file
@@ -0,0 +1,400 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pack;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.loader.ResourceLoader;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisWorld;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.exceptions.IrisException;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONArray;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import lombok.Data;
|
||||
import org.bukkit.World;
|
||||
import org.zeroturnaround.zip.commons.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* Represents an Iris pack that exists
|
||||
*/
|
||||
@Data
|
||||
public class IrisPack {
|
||||
private final File folder;
|
||||
private final IrisData data;
|
||||
|
||||
/**
|
||||
* Create an iris pack backed by a data folder
|
||||
* the data folder is assumed to be in the Iris/packs/NAME folder
|
||||
*
|
||||
* @param name
|
||||
* the name
|
||||
*/
|
||||
public IrisPack(String name) {
|
||||
this(packsPack(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an iris pack backed by a data folder
|
||||
*
|
||||
* @param folder
|
||||
* the folder of the pack. Must be a directory
|
||||
*/
|
||||
public IrisPack(File folder) {
|
||||
this.folder = folder;
|
||||
|
||||
if(!folder.exists()) {
|
||||
throw new RuntimeException("Cannot open Pack " + folder.getPath() + " (directory doesnt exist)");
|
||||
}
|
||||
|
||||
if(!folder.isDirectory()) {
|
||||
throw new RuntimeException("Cannot open Pack " + folder.getPath() + " (not a directory)");
|
||||
}
|
||||
|
||||
this.data = IrisData.get(folder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new pack from the input url
|
||||
*
|
||||
* @param sender
|
||||
* the sender
|
||||
* @param url
|
||||
* the url, or name, or really anything see IrisPackRepository.from(String)
|
||||
* @return the iris pack
|
||||
* @throws IrisException
|
||||
* fails
|
||||
*/
|
||||
public static Future<IrisPack> from(VolmitSender sender, String url) throws IrisException {
|
||||
IrisPackRepository repo = IrisPackRepository.from(url);
|
||||
if(repo == null) {
|
||||
throw new IrisException("Null Repo");
|
||||
}
|
||||
|
||||
try {
|
||||
return from(sender, repo);
|
||||
} catch(MalformedURLException e) {
|
||||
throw new IrisException("Malformed URL " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a pack from a repo
|
||||
*
|
||||
* @param sender
|
||||
* the sender
|
||||
* @param repo
|
||||
* the repo
|
||||
* @return the pack
|
||||
* @throws MalformedURLException
|
||||
* shit happens
|
||||
*/
|
||||
public static Future<IrisPack> from(VolmitSender sender, IrisPackRepository repo) throws MalformedURLException {
|
||||
CompletableFuture<IrisPack> pack = new CompletableFuture<>();
|
||||
repo.install(sender, () -> {
|
||||
pack.complete(new IrisPack(repo.getRepo()));
|
||||
});
|
||||
return pack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a blank pack with a given name
|
||||
*
|
||||
* @param name
|
||||
* the name of the pack
|
||||
* @return the pack
|
||||
* @throws IrisException
|
||||
* if the pack already exists or another error
|
||||
*/
|
||||
public static IrisPack blank(String name) throws IrisException {
|
||||
File f = packsPack(name);
|
||||
|
||||
if(f.exists()) {
|
||||
throw new IrisException("Already exists");
|
||||
}
|
||||
|
||||
File fd = new File(f, "dimensions/" + name + ".json");
|
||||
fd.getParentFile().mkdirs();
|
||||
try {
|
||||
IO.writeAll(fd, "{\n" +
|
||||
" \"name\": \"" + Form.capitalize(name) + "\",\n" +
|
||||
" \"version\": 1\n" +
|
||||
"}\n");
|
||||
} catch(IOException e) {
|
||||
throw new IrisException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
IrisPack pack = new IrisPack(f);
|
||||
pack.updateWorkspace();
|
||||
return pack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a packs pack folder for a name. Such that overworld would resolve as Iris/packs/overworld
|
||||
*
|
||||
* @param name
|
||||
* the name
|
||||
* @return the file path
|
||||
*/
|
||||
public static File packsPack(String name) {
|
||||
return Iris.instance.getDataFolderNoCreate(StudioSVC.WORKSPACE_NAME, name);
|
||||
}
|
||||
|
||||
private static KList<File> collectFiles(File f, String fileExtension) {
|
||||
KList<File> l = new KList<>();
|
||||
|
||||
if(f.isDirectory()) {
|
||||
for(File i : f.listFiles()) {
|
||||
l.addAll(collectFiles(i, fileExtension));
|
||||
}
|
||||
} else if(f.getName().endsWith("." + fileExtension)) {
|
||||
l.add(f);
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete this pack. This invalidates this pack and you should
|
||||
* probably no longer use this instance after deleting this pack
|
||||
*/
|
||||
public void delete() {
|
||||
IO.delete(folder);
|
||||
folder.delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of this pack
|
||||
*
|
||||
* @return the pack name
|
||||
*/
|
||||
public String getName() {
|
||||
return folder.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file path of the workspace file
|
||||
*
|
||||
* @return the workspace file path
|
||||
*/
|
||||
public File getWorkspaceFile() {
|
||||
return new File(getFolder(), getName() + ".code-workspace");
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the workspace file
|
||||
*
|
||||
* @return true if it was updated
|
||||
*/
|
||||
public boolean updateWorkspace() {
|
||||
getFolder().mkdirs();
|
||||
File ws = getWorkspaceFile();
|
||||
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
Iris.debug("Building Workspace: " + ws.getPath());
|
||||
JSONObject j = generateWorkspaceConfig();
|
||||
IO.writeAll(ws, j.toString(4));
|
||||
p.end();
|
||||
Iris.debug("Building Workspace: " + ws.getPath() + " took " + Form.duration(p.getMilliseconds(), 2));
|
||||
return true;
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.warn("Pack invalid: " + ws.getAbsolutePath() + " Re-creating. You may loose some vs-code workspace settings! But not your actual project!");
|
||||
ws.delete();
|
||||
try {
|
||||
IO.writeAll(ws, generateWorkspaceConfig());
|
||||
} catch(IOException e1) {
|
||||
Iris.reportError(e1);
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install this pack into a world
|
||||
*
|
||||
* @param world
|
||||
* the world to install into (world/iris/pack)
|
||||
* @return the installed pack
|
||||
*/
|
||||
public IrisPack install(World world) throws IrisException {
|
||||
return install(new File(world.getWorldFolder(), "iris/pack"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Install this pack into a world
|
||||
*
|
||||
* @param world
|
||||
* the world to install into (world/iris/pack)
|
||||
* @return the installed pack
|
||||
*/
|
||||
public IrisPack install(IrisWorld world) throws IrisException {
|
||||
return install(new File(world.worldFolder(), "iris/pack"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Install this pack into a world
|
||||
*
|
||||
* @param folder
|
||||
* the folder to install this pack into
|
||||
* @return the installed pack
|
||||
*/
|
||||
public IrisPack install(File folder) throws IrisException {
|
||||
if(folder.exists()) {
|
||||
throw new IrisException("Cannot install new pack because the folder " + folder.getName() + " already exists!");
|
||||
}
|
||||
|
||||
folder.mkdirs();
|
||||
|
||||
try {
|
||||
FileUtils.copyDirectory(getFolder(), folder);
|
||||
} catch(IOException e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
return new IrisPack(folder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new pack using this pack as a template. The new pack will be renamed & have a renamed dimension
|
||||
* to match it.
|
||||
*
|
||||
* @param newName
|
||||
* the new pack name
|
||||
* @return the new IrisPack
|
||||
*/
|
||||
public IrisPack install(String newName) throws IrisException {
|
||||
File newPack = packsPack(newName);
|
||||
|
||||
if(newPack.exists()) {
|
||||
throw new IrisException("Cannot install new pack because the folder " + newName + " already exists!");
|
||||
}
|
||||
|
||||
try {
|
||||
FileUtils.copyDirectory(getFolder(), newPack);
|
||||
} catch(IOException e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
IrisData data = IrisData.get(newPack);
|
||||
IrisDimension dim = data.getDimensionLoader().load(getDimensionKey());
|
||||
data.dump();
|
||||
File from = dim.getLoadFile();
|
||||
File to = new File(from.getParentFile(), newName + ".json");
|
||||
try {
|
||||
FileUtils.moveFile(from, to);
|
||||
new File(newPack, getWorkspaceFile().getName()).delete();
|
||||
} catch(Throwable e) {
|
||||
throw new IrisException(e);
|
||||
}
|
||||
|
||||
IrisPack pack = new IrisPack(newPack);
|
||||
pack.updateWorkspace();
|
||||
|
||||
return pack;
|
||||
}
|
||||
|
||||
/**
|
||||
* The dimension's assumed loadkey
|
||||
*
|
||||
* @return getName()
|
||||
*/
|
||||
public String getDimensionKey() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the main dimension object
|
||||
*
|
||||
* @return the dimension (folder name as dim key)
|
||||
*/
|
||||
public IrisDimension getDimension() {
|
||||
return getData().getDimensionLoader().load(getDimensionKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all files in this pack with the given extension
|
||||
*
|
||||
* @param fileExtension
|
||||
* the extension
|
||||
* @return the list of files
|
||||
*/
|
||||
public KList<File> collectFiles(String fileExtension) {
|
||||
return collectFiles(getFolder(), fileExtension);
|
||||
}
|
||||
|
||||
private JSONObject generateWorkspaceConfig() {
|
||||
JSONObject ws = new JSONObject();
|
||||
JSONArray folders = new JSONArray();
|
||||
JSONObject folder = new JSONObject();
|
||||
folder.put("path", ".");
|
||||
folders.put(folder);
|
||||
ws.put("folders", folders);
|
||||
JSONObject settings = new JSONObject();
|
||||
settings.put("workbench.colorTheme", "Monokai");
|
||||
settings.put("workbench.preferredDarkColorTheme", "Solarized Dark");
|
||||
settings.put("workbench.tips.enabled", false);
|
||||
settings.put("workbench.tree.indent", 24);
|
||||
settings.put("files.autoSave", "onFocusChange");
|
||||
JSONObject jc = new JSONObject();
|
||||
jc.put("editor.autoIndent", "brackets");
|
||||
jc.put("editor.acceptSuggestionOnEnter", "smart");
|
||||
jc.put("editor.cursorSmoothCaretAnimation", true);
|
||||
jc.put("editor.dragAndDrop", false);
|
||||
jc.put("files.trimTrailingWhitespace", true);
|
||||
jc.put("diffEditor.ignoreTrimWhitespace", true);
|
||||
jc.put("files.trimFinalNewlines", true);
|
||||
jc.put("editor.suggest.showKeywords", false);
|
||||
jc.put("editor.suggest.showSnippets", false);
|
||||
jc.put("editor.suggest.showWords", false);
|
||||
JSONObject st = new JSONObject();
|
||||
st.put("strings", true);
|
||||
jc.put("editor.quickSuggestions", st);
|
||||
jc.put("editor.suggest.insertMode", "replace");
|
||||
settings.put("[json]", jc);
|
||||
settings.put("json.maxItemsComputed", 30000);
|
||||
JSONArray schemas = new JSONArray();
|
||||
IrisData dm = IrisData.get(getFolder());
|
||||
|
||||
for(ResourceLoader<?> r : dm.getLoaders().v()) {
|
||||
if(r.supportsSchemas()) {
|
||||
schemas.put(r.buildSchema());
|
||||
}
|
||||
}
|
||||
|
||||
settings.put("json.schemas", schemas);
|
||||
ws.put("settings", settings);
|
||||
|
||||
return ws;
|
||||
}
|
||||
}
|
||||
132
src/main/java/com/volmit/iris/core/pack/IrisPackRepository.java
Normal file
132
src/main/java/com/volmit/iris/core/pack/IrisPackRepository.java
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pack;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.jobs.DownloadJob;
|
||||
import com.volmit.iris.util.scheduling.jobs.JobCollection;
|
||||
import com.volmit.iris.util.scheduling.jobs.SingleJob;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
import org.zeroturnaround.zip.commons.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.UUID;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class IrisPackRepository {
|
||||
@Builder.Default
|
||||
private String user = "IrisDimensions";
|
||||
|
||||
@Builder.Default
|
||||
private String repo = "overworld";
|
||||
|
||||
@Builder.Default
|
||||
private String branch = "master";
|
||||
|
||||
@Builder.Default
|
||||
private String tag = "";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static IrisPackRepository from(String g) {
|
||||
// https://github.com/IrisDimensions/overworld
|
||||
if(g.startsWith("https://github.com/")) {
|
||||
String sub = g.split("\\Qgithub.com/\\E")[1];
|
||||
IrisPackRepository r = IrisPackRepository.builder()
|
||||
.user(sub.split("\\Q/\\E")[0])
|
||||
.repo(sub.split("\\Q/\\E")[1]).build();
|
||||
|
||||
if(g.contains("/tree/")) {
|
||||
r.setBranch(g.split("/tree/")[1]);
|
||||
}
|
||||
|
||||
return r;
|
||||
} else if(g.contains("/")) {
|
||||
String[] f = g.split("\\Q/\\E");
|
||||
|
||||
if(f.length == 1) {
|
||||
return from(g);
|
||||
} else if(f.length == 2) {
|
||||
return IrisPackRepository.builder()
|
||||
.user(f[0])
|
||||
.repo(f[1])
|
||||
.build();
|
||||
} else if(f.length >= 3) {
|
||||
IrisPackRepository r = IrisPackRepository.builder()
|
||||
.user(f[0])
|
||||
.repo(f[1])
|
||||
.build();
|
||||
|
||||
if(f[2].startsWith("#")) {
|
||||
r.setTag(f[2].substring(1));
|
||||
} else {
|
||||
r.setBranch(f[2]);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
return IrisPackRepository.builder()
|
||||
.user("IrisDimensions")
|
||||
.repo(g)
|
||||
.branch(g.equals("overworld") ? "stable" : "master")
|
||||
.build();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toURL() {
|
||||
if(!tag.trim().isEmpty()) {
|
||||
return "https://codeload.github.com/" + user + "/" + repo + "/zip/refs/tags/" + tag;
|
||||
}
|
||||
|
||||
return "https://codeload.github.com/" + user + "/" + repo + "/zip/refs/heads/" + branch;
|
||||
}
|
||||
|
||||
public void install(VolmitSender sender, Runnable whenComplete) throws MalformedURLException {
|
||||
File pack = Iris.instance.getDataFolderNoCreate(StudioSVC.WORKSPACE_NAME, getRepo());
|
||||
|
||||
if(!pack.exists()) {
|
||||
File dl = new File(Iris.getTemp(), "dltk-" + UUID.randomUUID() + ".zip");
|
||||
File work = new File(Iris.getTemp(), "extk-" + UUID.randomUUID());
|
||||
new JobCollection(Form.capitalize(getRepo()),
|
||||
new DownloadJob(toURL(), pack),
|
||||
new SingleJob("Extracting", () -> ZipUtil.unpack(dl, work)),
|
||||
new SingleJob("Installing", () -> {
|
||||
try {
|
||||
FileUtils.copyDirectory(work.listFiles()[0], pack);
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
})).execute(sender, whenComplete);
|
||||
} else {
|
||||
sender.sendMessage("Pack already exists!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RollingSequence;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.Looper;
|
||||
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class IrisPregenerator {
|
||||
private final PregenTask task;
|
||||
private final PregeneratorMethod generator;
|
||||
private final PregenListener listener;
|
||||
private final Looper ticker;
|
||||
private final AtomicBoolean paused;
|
||||
private final AtomicBoolean shutdown;
|
||||
private final RollingSequence chunksPerSecond;
|
||||
private final RollingSequence chunksPerMinute;
|
||||
private final RollingSequence regionsPerMinute;
|
||||
private final AtomicInteger generated;
|
||||
private final AtomicInteger generatedLast;
|
||||
private final AtomicInteger generatedLastMinute;
|
||||
private final AtomicInteger totalChunks;
|
||||
private final AtomicLong startTime;
|
||||
private final ChronoLatch minuteLatch;
|
||||
private final AtomicReference<String> currentGeneratorMethod;
|
||||
private final KSet<Position2> generatedRegions;
|
||||
private final KSet<Position2> retry;
|
||||
private final KSet<Position2> net;
|
||||
private final ChronoLatch cl;
|
||||
private final Semaphore limiter;
|
||||
|
||||
public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) {
|
||||
this.listener = listenify(listener);
|
||||
cl = new ChronoLatch(5000);
|
||||
limiter = new Semaphore(Runtime.getRuntime().availableProcessors());
|
||||
generatedRegions = new KSet<>();
|
||||
this.shutdown = new AtomicBoolean(false);
|
||||
this.paused = new AtomicBoolean(false);
|
||||
this.task = task;
|
||||
this.generator = generator;
|
||||
retry = new KSet<>();
|
||||
net = new KSet<>();
|
||||
currentGeneratorMethod = new AtomicReference<>("Void");
|
||||
minuteLatch = new ChronoLatch(60000, false);
|
||||
chunksPerSecond = new RollingSequence(10);
|
||||
chunksPerMinute = new RollingSequence(10);
|
||||
regionsPerMinute = new RollingSequence(10);
|
||||
generated = new AtomicInteger(0);
|
||||
generatedLast = new AtomicInteger(0);
|
||||
generatedLastMinute = new AtomicInteger(0);
|
||||
totalChunks = new AtomicInteger(0);
|
||||
task.iterateRegions((_a, _b) -> totalChunks.addAndGet(1024));
|
||||
startTime = new AtomicLong(M.ms());
|
||||
ticker = new Looper() {
|
||||
@Override
|
||||
protected long loop() {
|
||||
long eta = computeETA();
|
||||
int secondGenerated = generated.get() - generatedLast.get();
|
||||
generatedLast.set(generated.get());
|
||||
chunksPerSecond.put(secondGenerated);
|
||||
|
||||
if(minuteLatch.flip()) {
|
||||
int minuteGenerated = generated.get() - generatedLastMinute.get();
|
||||
generatedLastMinute.set(generated.get());
|
||||
chunksPerMinute.put(minuteGenerated);
|
||||
regionsPerMinute.put((double) minuteGenerated / 1024D);
|
||||
}
|
||||
|
||||
listener.onTick(chunksPerSecond.getAverage(), chunksPerMinute.getAverage(),
|
||||
regionsPerMinute.getAverage(),
|
||||
(double) generated.get() / (double) totalChunks.get(),
|
||||
generated.get(), totalChunks.get(),
|
||||
totalChunks.get() - generated.get(),
|
||||
eta, M.ms() - startTime.get(), currentGeneratorMethod.get());
|
||||
|
||||
if(cl.flip()) {
|
||||
Iris.info("Pregen: " + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (" + Form.pc((double) generated.get() / (double) totalChunks.get(), 0) + ") " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2));
|
||||
}
|
||||
|
||||
return 1000;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private long computeETA() {
|
||||
return (long) ((totalChunks.get() - generated.get()) *
|
||||
((double) (M.ms() - startTime.get()) / (double) generated.get()));
|
||||
}
|
||||
|
||||
public void close() {
|
||||
shutdown.set(true);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
init();
|
||||
ticker.start();
|
||||
checkRegions();
|
||||
task.iterateRegions((x, z) -> visitRegion(x, z, true));
|
||||
task.iterateRegions((x, z) -> visitRegion(x, z, false));
|
||||
shutdown();
|
||||
}
|
||||
|
||||
private void checkRegions() {
|
||||
task.iterateRegions(this::checkRegion);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
generator.init();
|
||||
generator.save();
|
||||
}
|
||||
|
||||
private void shutdown() {
|
||||
listener.onSaving();
|
||||
generator.close();
|
||||
ticker.interrupt();
|
||||
listener.onClose();
|
||||
getMantle().trim(0);
|
||||
}
|
||||
|
||||
private void visitRegion(int x, int z, boolean regions) {
|
||||
while(paused.get() && !shutdown.get()) {
|
||||
J.sleep(50);
|
||||
}
|
||||
|
||||
if(shutdown.get()) {
|
||||
listener.onRegionSkipped(x, z);
|
||||
return;
|
||||
}
|
||||
|
||||
Position2 pos = new Position2(x, z);
|
||||
|
||||
if(generatedRegions.contains(pos)) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentGeneratorMethod.set(generator.getMethod(x, z));
|
||||
boolean hit = false;
|
||||
if(generator.supportsRegions(x, z, listener) && regions) {
|
||||
hit = true;
|
||||
try {
|
||||
limiter.acquire();
|
||||
listener.onRegionGenerating(x, z);
|
||||
generator.generateRegion(x, z, listener);
|
||||
limiter.release();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else if(!regions) {
|
||||
hit = true;
|
||||
listener.onRegionGenerating(x, z);
|
||||
PregenTask.iterateRegion(x, z, (xx, zz) -> {
|
||||
try {
|
||||
limiter.acquire();
|
||||
generator.generateChunk(xx, zz, listener);
|
||||
limiter.release();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(hit) {
|
||||
listener.onRegionGenerated(x, z);
|
||||
listener.onSaving();
|
||||
generator.save();
|
||||
generatedRegions.add(pos);
|
||||
checkRegions();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRegion(int x, int z) {
|
||||
if(generatedRegions.contains(new Position2(x, z))) {
|
||||
return;
|
||||
}
|
||||
|
||||
generator.supportsRegions(x, z, listener);
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
paused.set(true);
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
paused.set(false);
|
||||
}
|
||||
|
||||
private PregenListener listenify(PregenListener listener) {
|
||||
return new PregenListener() {
|
||||
@Override
|
||||
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method) {
|
||||
listener.onTick(chunksPerSecond, chunksPerMinute, regionsPerMinute, percent, generated, totalChunks, chunksRemaining, eta, elapsed, method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkGenerating(int x, int z) {
|
||||
listener.onChunkGenerating(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkGenerated(int x, int z) {
|
||||
listener.onChunkGenerated(x, z);
|
||||
generated.addAndGet(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionGenerated(int x, int z) {
|
||||
listener.onRegionGenerated(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionGenerating(int x, int z) {
|
||||
listener.onRegionGenerating(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkCleaned(int x, int z) {
|
||||
listener.onChunkCleaned(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionSkipped(int x, int z) {
|
||||
listener.onRegionSkipped(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkStarted(int x, int z) {
|
||||
net.add(new Position2(x, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkFailed(int x, int z) {
|
||||
retry.add(new Position2(x, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkReclaim(int revert) {
|
||||
generated.addAndGet(-revert);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkGeneratedChunk(int x, int z) {
|
||||
generated.addAndGet(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkDownloaded(int x, int z) {
|
||||
net.remove(new Position2(x, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
listener.onClose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaving() {
|
||||
listener.onSaving();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkExistsInRegionGen(int x, int z) {
|
||||
listener.onChunkExistsInRegionGen(x, z);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public boolean paused() {
|
||||
return paused.get();
|
||||
}
|
||||
|
||||
public Mantle getMantle() {
|
||||
return generator.getMantle();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class LazyPregenerator extends Thread implements Listener
|
||||
{
|
||||
private final LazyPregenJob job;
|
||||
private final File destination;
|
||||
private final int maxPosition;
|
||||
private final World world;
|
||||
private final long rate;
|
||||
private final ChronoLatch latch;
|
||||
|
||||
public LazyPregenerator(LazyPregenJob job, File destination)
|
||||
{
|
||||
this.job = job;
|
||||
this.destination = destination;
|
||||
this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {}).count();
|
||||
this.world = Bukkit.getWorld(job.getWorld());
|
||||
this.rate = Math.round((1D / (job.chunksPerMinute / 60D)) * 1000D);
|
||||
this.latch = new ChronoLatch(60000);
|
||||
}
|
||||
|
||||
public LazyPregenerator(File file) throws IOException {
|
||||
this(new Gson().fromJson(IO.readAll(file), LazyPregenJob.class), file);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(WorldUnloadEvent e)
|
||||
{
|
||||
if(e.getWorld().equals(world)) {
|
||||
interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
while(!interrupted()) {
|
||||
J.sleep(rate);
|
||||
tick();
|
||||
}
|
||||
|
||||
try {
|
||||
saveNow();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if(latch.flip())
|
||||
{
|
||||
save();
|
||||
Iris.info("LazyGen: " + world.getName() + " RTT: " + Form.duration((Math.pow((job.radiusBlocks / 16D), 2) / job.chunksPerMinute) * 60 * 1000, 2));
|
||||
}
|
||||
|
||||
if(job.getPosition() >= maxPosition)
|
||||
{
|
||||
if(job.isHealing())
|
||||
{
|
||||
int pos = (job.getHealingPosition() + 1) % maxPosition;
|
||||
job.setHealingPosition(pos);
|
||||
tickRegenerate(getChunk(pos));
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Iris.verbose("Completed Lazy Gen!");
|
||||
interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
int pos = job.getPosition() + 1;
|
||||
job.setPosition(pos);
|
||||
tickGenerate(getChunk(pos));
|
||||
}
|
||||
}
|
||||
|
||||
private void tickGenerate(Position2 chunk) {
|
||||
if(PaperLib.isPaper()) {
|
||||
PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true).thenAccept((i) -> Iris.verbose("Generated Async " + chunk));
|
||||
}
|
||||
else {
|
||||
J.s(() -> world.getChunkAt(chunk.getX(), chunk.getZ()));
|
||||
Iris.verbose("Generated " + chunk);
|
||||
}
|
||||
}
|
||||
|
||||
private void tickRegenerate(Position2 chunk) {
|
||||
J.s(() -> world.regenerateChunk(chunk.getX(), chunk.getZ()));
|
||||
Iris.verbose("Regenerated " + chunk);
|
||||
}
|
||||
|
||||
public Position2 getChunk(int position)
|
||||
{
|
||||
int p = -1;
|
||||
AtomicInteger xx = new AtomicInteger();
|
||||
AtomicInteger zz = new AtomicInteger();
|
||||
Spiraler s = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
|
||||
xx.set(x);
|
||||
zz.set(z);
|
||||
});
|
||||
|
||||
while(s.hasNext() && p++ < position) {
|
||||
s.next();
|
||||
}
|
||||
|
||||
return new Position2(xx.get(), zz.get());
|
||||
}
|
||||
|
||||
public void save()
|
||||
{
|
||||
J.a(() -> {
|
||||
try {
|
||||
saveNow();
|
||||
}
|
||||
|
||||
catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void saveNow() throws IOException {
|
||||
IO.writeAll(this.destination, new Gson().toJson(job));
|
||||
}
|
||||
|
||||
public static void loadLazyGenerators()
|
||||
{
|
||||
for(World i : Bukkit.getWorlds())
|
||||
{
|
||||
File lazygen = new File(i.getWorldFolder(), "lazygen.json");
|
||||
|
||||
if(lazygen.exists()) {
|
||||
try {
|
||||
LazyPregenerator p = new LazyPregenerator(lazygen);
|
||||
p.start();
|
||||
Iris.info("Started Lazy Pregenerator: " + p.job);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public static class LazyPregenJob
|
||||
{
|
||||
private String world;
|
||||
@Builder.Default private int healingPosition = 0;
|
||||
@Builder.Default private boolean healing = false;
|
||||
@Builder.Default private int chunksPerMinute = 32; // 48 hours is roughly 5000 radius
|
||||
@Builder.Default private int radiusBlocks = 5000;
|
||||
@Builder.Default private int position = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
public interface PregenListener {
|
||||
void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method);
|
||||
|
||||
void onChunkGenerating(int x, int z);
|
||||
|
||||
void onChunkGenerated(int x, int z);
|
||||
|
||||
void onRegionGenerated(int x, int z);
|
||||
|
||||
void onRegionGenerating(int x, int z);
|
||||
|
||||
void onChunkCleaned(int x, int z);
|
||||
|
||||
void onRegionSkipped(int x, int z);
|
||||
|
||||
void onNetworkStarted(int x, int z);
|
||||
|
||||
void onNetworkFailed(int x, int z);
|
||||
|
||||
void onNetworkReclaim(int revert);
|
||||
|
||||
void onNetworkGeneratedChunk(int x, int z);
|
||||
|
||||
void onNetworkDownloaded(int x, int z);
|
||||
|
||||
void onClose();
|
||||
|
||||
void onSaving();
|
||||
|
||||
void onChunkExistsInRegionGen(int x, int z);
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.Spiraled;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
public class PregenTask {
|
||||
private static final Position2 ZERO = new Position2(0, 0);
|
||||
private static final KList<Position2> ORDER_CENTER = computeChunkOrder();
|
||||
private static final KMap<Position2, KList<Position2>> ORDERS = new KMap<>();
|
||||
|
||||
@Builder.Default
|
||||
private Position2 center = new Position2(0, 0);
|
||||
@Builder.Default
|
||||
private int width = 1;
|
||||
@Builder.Default
|
||||
private int height = 1;
|
||||
|
||||
public static void iterateRegion(int xr, int zr, Spiraled s, Position2 pull) {
|
||||
for(Position2 i : ORDERS.computeIfAbsent(pull, PregenTask::computeOrder)) {
|
||||
s.on(i.getX() + (xr << 5), i.getZ() + (zr << 5));
|
||||
}
|
||||
}
|
||||
|
||||
public static void iterateRegion(int xr, int zr, Spiraled s) {
|
||||
iterateRegion(xr, zr, s, new Position2(0, 0));
|
||||
}
|
||||
|
||||
private static KList<Position2> computeOrder(Position2 pull) {
|
||||
KList<Position2> p = new KList<>();
|
||||
new Spiraler(33, 33, (x, z) -> {
|
||||
int xx = (x + 15);
|
||||
int zz = (z + 15);
|
||||
if(xx < 0 || xx > 31 || zz < 0 || zz > 31) {
|
||||
return;
|
||||
}
|
||||
|
||||
p.add(new Position2(xx, zz));
|
||||
}).drain();
|
||||
p.sort(Comparator.comparing((i) -> i.distance(pull)));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
private static KList<Position2> computeChunkOrder() {
|
||||
Position2 center = new Position2(15, 15);
|
||||
KList<Position2> p = new KList<>();
|
||||
new Spiraler(33, 33, (x, z) -> {
|
||||
int xx = x + 15;
|
||||
int zz = z + 15;
|
||||
if(xx < 0 || xx > 31 || zz < 0 || zz > 31) {
|
||||
return;
|
||||
}
|
||||
|
||||
p.add(new Position2(xx, zz));
|
||||
}).drain();
|
||||
p.sort(Comparator.comparing((i) -> i.distance(center)));
|
||||
return p;
|
||||
}
|
||||
|
||||
public void iterateRegions(Spiraled s) {
|
||||
new Spiraler(getWidth() * 2, getHeight() * 2, s)
|
||||
.setOffset(center.getX(), center.getZ()).drain();
|
||||
}
|
||||
|
||||
public void iterateAllChunks(Spiraled s) {
|
||||
new Spiraler(getWidth() * 2, getHeight() * 2, (x, z) -> iterateRegion(x, z, s))
|
||||
.setOffset(center.getX(), center.getZ()).drain();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
|
||||
/**
|
||||
* Represents something that is capable of generating in chunks or regions, or both
|
||||
*/
|
||||
public interface PregeneratorMethod {
|
||||
/**
|
||||
* This is called before any generate methods are called. Setup your generator here
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* This is called after the pregenerator is done. Save your work and stop threads
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* This is called every X amount of chunks or regions. Save work,
|
||||
* but no need to save all of it. At the end, close() will still be called.
|
||||
*/
|
||||
void save();
|
||||
|
||||
/**
|
||||
* Return true if regions can be generated
|
||||
*
|
||||
* @param x
|
||||
* the x region
|
||||
* @param z
|
||||
* the z region
|
||||
* @return true if they can be
|
||||
*/
|
||||
boolean supportsRegions(int x, int z, PregenListener listener);
|
||||
|
||||
/**
|
||||
* Return the name of the method being used
|
||||
*
|
||||
* @param x
|
||||
* the x region
|
||||
* @param z
|
||||
* the z region
|
||||
* @return the name
|
||||
*/
|
||||
String getMethod(int x, int z);
|
||||
|
||||
/**
|
||||
* Called to generate a region. Execute sync, if multicore internally, wait
|
||||
* for the task to complete
|
||||
*
|
||||
* @param x
|
||||
* the x
|
||||
* @param z
|
||||
* the z
|
||||
* @param listener
|
||||
* signal chunks generating & generated. Parallel capable.
|
||||
*/
|
||||
void generateRegion(int x, int z, PregenListener listener);
|
||||
|
||||
/**
|
||||
* Called to generate a chunk. You can go async so long as save will wait on the threads to finish
|
||||
*
|
||||
* @param x
|
||||
* the x
|
||||
* @param z
|
||||
* the z
|
||||
*/
|
||||
void generateChunk(int x, int z, PregenListener listener);
|
||||
|
||||
Mantle getMantle();
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.World;
|
||||
|
||||
public class AsyncOrMedievalPregenMethod implements PregeneratorMethod {
|
||||
private final PregeneratorMethod method;
|
||||
|
||||
public AsyncOrMedievalPregenMethod(World world, int threads) {
|
||||
method = PaperLib.isPaper() ? new AsyncPregenMethod(world, threads) : new MedievalPregenMethod(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
method.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
method.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
method.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod(int x, int z) {
|
||||
return method.getMethod(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateRegion(int x, int z, PregenListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
method.generateChunk(x, z, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mantle getMantle() {
|
||||
return method.getMantle();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
private final World world;
|
||||
private final MultiBurst burst;
|
||||
private final KList<Future<?>> future;
|
||||
|
||||
public AsyncPregenMethod(World world, int threads) {
|
||||
if(!PaperLib.isPaper()) {
|
||||
throw new UnsupportedOperationException("Cannot use PaperAsync on non paper!");
|
||||
}
|
||||
|
||||
this.world = world;
|
||||
burst = MultiBurst.burst;
|
||||
future = new KList<>(1024);
|
||||
}
|
||||
|
||||
private void unloadAndSaveAllChunks() {
|
||||
try {
|
||||
J.sfut(() -> {
|
||||
if(world == null) {
|
||||
Iris.warn("World was null somehow...");
|
||||
return;
|
||||
}
|
||||
|
||||
for(Chunk i : world.getLoadedChunks()) {
|
||||
i.unload(true);
|
||||
}
|
||||
world.save();
|
||||
}).get();
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void completeChunk(int x, int z, PregenListener listener) {
|
||||
try {
|
||||
PaperLib.getChunkAtAsync(world, x, z, true).get();
|
||||
listener.onChunkGenerated(x, z);
|
||||
listener.onChunkCleaned(x, z);
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
J.sleep(5);
|
||||
future.add(burst.complete(() -> completeChunk(x, z, listener)));
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForChunks() {
|
||||
for(Future<?> i : future.copy()) {
|
||||
try {
|
||||
i.get();
|
||||
future.remove(i);
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
unloadAndSaveAllChunks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod(int x, int z) {
|
||||
return "Async";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
waitForChunks();
|
||||
unloadAndSaveAllChunks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
waitForChunks();
|
||||
unloadAndSaveAllChunks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateRegion(int x, int z, PregenListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
if(future.size() > IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism())) { // TODO: FIX
|
||||
waitForChunks();
|
||||
}
|
||||
|
||||
listener.onChunkGenerating(x, z);
|
||||
future.add(burst.complete(() -> completeChunk(x, z, listener)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mantle getMantle() {
|
||||
if(IrisToolbelt.isIrisWorld(world)) {
|
||||
return IrisToolbelt.access(world).getEngine().getMantle().getMantle();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
|
||||
public class DummyPregenMethod implements PregeneratorMethod {
|
||||
@Override
|
||||
public void init() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod(int x, int z) {
|
||||
return "Dummy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateRegion(int x, int z, PregenListener listener) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mantle getMantle() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class HybridPregenMethod implements PregeneratorMethod {
|
||||
private final PregeneratorMethod inWorld;
|
||||
private final World world;
|
||||
|
||||
public HybridPregenMethod(World world, int threads) {
|
||||
this.world = world;
|
||||
inWorld = new AsyncOrMedievalPregenMethod(world, threads);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod(int x, int z) {
|
||||
return "Hybrid<" + inWorld.getMethod(x, z) + ">";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
inWorld.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
inWorld.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
inWorld.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||
return inWorld.supportsRegions(x, z, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateRegion(int x, int z, PregenListener listener) {
|
||||
inWorld.generateRegion(x, z, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
inWorld.generateChunk(x, z, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mantle getMantle() {
|
||||
return inWorld.getMantle();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class MedievalPregenMethod implements PregeneratorMethod {
|
||||
private final World world;
|
||||
private final KList<CompletableFuture<?>> futures;
|
||||
|
||||
public MedievalPregenMethod(World world) {
|
||||
this.world = world;
|
||||
futures = new KList<>();
|
||||
}
|
||||
|
||||
private void waitForChunks() {
|
||||
for(CompletableFuture<?> i : futures) {
|
||||
try {
|
||||
i.get();
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
futures.clear();
|
||||
}
|
||||
|
||||
private void unloadAndSaveAllChunks() {
|
||||
waitForChunks();
|
||||
try {
|
||||
J.sfut(() -> {
|
||||
for(Chunk i : world.getLoadedChunks()) {
|
||||
i.unload(true);
|
||||
}
|
||||
world.save();
|
||||
}).get();
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
unloadAndSaveAllChunks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
unloadAndSaveAllChunks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
unloadAndSaveAllChunks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateRegion(int x, int z, PregenListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod(int x, int z) {
|
||||
return "Medieval";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
if(futures.size() > IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism())) {
|
||||
waitForChunks();
|
||||
}
|
||||
|
||||
listener.onChunkGenerating(x, z);
|
||||
futures.add(J.sfut(() -> {
|
||||
world.getChunkAt(x, z);
|
||||
listener.onChunkGenerated(x, z);
|
||||
listener.onChunkCleaned(x, z);
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mantle getMantle() {
|
||||
if(IrisToolbelt.isIrisWorld(world)) {
|
||||
return IrisToolbelt.access(world).getEngine().getMantle().getMantle();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
666
src/main/java/com/volmit/iris/core/project/IrisProject.java
Normal file
666
src/main/java/com/volmit/iris/core/project/IrisProject.java
Normal file
@@ -0,0 +1,666 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.project;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||
import com.volmit.iris.core.loader.ResourceLoader;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisBlockData;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisEntity;
|
||||
import com.volmit.iris.engine.object.IrisGenerator;
|
||||
import com.volmit.iris.engine.object.IrisLootTable;
|
||||
import com.volmit.iris.engine.object.IrisObject;
|
||||
import com.volmit.iris.engine.object.IrisObjectPlacement;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
import com.volmit.iris.engine.object.IrisSpawner;
|
||||
import com.volmit.iris.engine.object.annotations.Snippet;
|
||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.exceptions.IrisException;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONArray;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.O;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import com.volmit.iris.util.scheduling.jobs.Job;
|
||||
import com.volmit.iris.util.scheduling.jobs.JobCollection;
|
||||
import com.volmit.iris.util.scheduling.jobs.ParallelQueueJob;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.World;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@SuppressWarnings("ALL")
|
||||
@Data
|
||||
public class IrisProject {
|
||||
private File path;
|
||||
private String name;
|
||||
private PlatformChunkGenerator activeProvider;
|
||||
|
||||
public IrisProject(File path) {
|
||||
this.path = path;
|
||||
this.name = path.getName();
|
||||
}
|
||||
|
||||
public static int clean(VolmitSender s, File clean) {
|
||||
int c = 0;
|
||||
if(clean.isDirectory()) {
|
||||
for(File i : clean.listFiles()) {
|
||||
c += clean(s, i);
|
||||
}
|
||||
} else if(clean.getName().endsWith(".json")) {
|
||||
try {
|
||||
clean(clean);
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.error("Failed to beautify " + clean.getAbsolutePath() + " You may have errors in your json!");
|
||||
}
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
public static void clean(File clean) throws IOException {
|
||||
JSONObject obj = new JSONObject(IO.readAll(clean));
|
||||
fixBlocks(obj, clean);
|
||||
|
||||
IO.writeAll(clean, obj.toString(4));
|
||||
}
|
||||
|
||||
public static void fixBlocks(JSONObject obj, File f) {
|
||||
for(String i : obj.keySet()) {
|
||||
Object o = obj.get(i);
|
||||
|
||||
if(i.equals("block") && o instanceof String && !o.toString().trim().isEmpty() && !o.toString().contains(":")) {
|
||||
obj.put(i, "minecraft:" + o);
|
||||
Iris.debug("Updated Block Key: " + o + " to " + obj.getString(i) + " in " + f.getPath());
|
||||
}
|
||||
|
||||
if(o instanceof JSONObject) {
|
||||
fixBlocks((JSONObject) o, f);
|
||||
} else if(o instanceof JSONArray) {
|
||||
fixBlocks((JSONArray) o, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void fixBlocks(JSONArray obj, File f) {
|
||||
for(int i = 0; i < obj.length(); i++) {
|
||||
Object o = obj.get(i);
|
||||
|
||||
if(o instanceof JSONObject) {
|
||||
fixBlocks((JSONObject) o, f);
|
||||
} else if(o instanceof JSONArray) {
|
||||
fixBlocks((JSONArray) o, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return activeProvider != null;
|
||||
}
|
||||
|
||||
public KList<File> collectFiles(File f, String fileExtension) {
|
||||
KList<File> l = new KList<>();
|
||||
|
||||
if(f.isDirectory()) {
|
||||
for(File i : f.listFiles()) {
|
||||
l.addAll(collectFiles(i, fileExtension));
|
||||
}
|
||||
} else if(f.getName().endsWith("." + fileExtension)) {
|
||||
l.add(f);
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
public KList<File> collectFiles(String json) {
|
||||
return collectFiles(path, json);
|
||||
}
|
||||
|
||||
public void open(VolmitSender sender) throws IrisException {
|
||||
open(sender, 1337, (w) ->
|
||||
{
|
||||
});
|
||||
}
|
||||
|
||||
public void openVSCode(VolmitSender sender) {
|
||||
|
||||
IrisDimension d = IrisData.loadAnyDimension(getName());
|
||||
J.attemptAsync(() ->
|
||||
{
|
||||
try {
|
||||
if(d.getLoader() == null) {
|
||||
sender.sendMessage("Could not get dimension loader");
|
||||
return;
|
||||
}
|
||||
File f = d.getLoader().getDataFolder();
|
||||
|
||||
if(!doOpenVSCode(f)) {
|
||||
File ff = new File(d.getLoader().getDataFolder(), d.getLoadKey() + ".code-workspace");
|
||||
Iris.warn("Project missing code-workspace: " + ff.getAbsolutePath() + " Re-creating code workspace.");
|
||||
|
||||
try {
|
||||
IO.writeAll(ff, createCodeWorkspaceConfig());
|
||||
} catch(IOException e1) {
|
||||
Iris.reportError(e1);
|
||||
e1.printStackTrace();
|
||||
}
|
||||
updateWorkspace();
|
||||
if(!doOpenVSCode(f)) {
|
||||
Iris.warn("Tried creating code workspace but failed a second time. Your project is likely corrupt.");
|
||||
}
|
||||
}
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean doOpenVSCode(File f) throws IOException {
|
||||
boolean foundWork = false;
|
||||
for(File i : Objects.requireNonNull(f.listFiles())) {
|
||||
if(i.getName().endsWith(".code-workspace")) {
|
||||
foundWork = true;
|
||||
J.a(() ->
|
||||
{
|
||||
updateWorkspace();
|
||||
});
|
||||
|
||||
if(IrisSettings.get().getStudio().isOpenVSCode()) {
|
||||
if(!GraphicsEnvironment.isHeadless()) {
|
||||
Iris.msg("Opening VSCode. You may see the output from VSCode.");
|
||||
Iris.msg("VSCode output always starts with: '(node:#####) electron'");
|
||||
Desktop.getDesktop().open(i);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
return foundWork;
|
||||
}
|
||||
|
||||
public void open(VolmitSender sender, long seed, Consumer<World> onDone) throws IrisException {
|
||||
if(isOpen()) {
|
||||
close();
|
||||
}
|
||||
|
||||
boolean hasError = false;
|
||||
|
||||
if(hasError) {
|
||||
return;
|
||||
}
|
||||
|
||||
IrisDimension d = IrisData.loadAnyDimension(getName());
|
||||
if(d == null) {
|
||||
sender.sendMessage("Can't find dimension: " + getName());
|
||||
return;
|
||||
} else if(sender.isPlayer()) {
|
||||
sender.player().setGameMode(GameMode.SPECTATOR);
|
||||
}
|
||||
|
||||
openVSCode(sender);
|
||||
|
||||
|
||||
J.a(() -> {
|
||||
try {
|
||||
activeProvider = (PlatformChunkGenerator) IrisToolbelt.createWorld()
|
||||
.seed(seed)
|
||||
.sender(sender)
|
||||
.studio(true)
|
||||
.name("iris/" + UUID.randomUUID())
|
||||
.dimension(d.getLoadKey())
|
||||
.create().getGenerator();
|
||||
onDone.accept(activeProvider.getTarget().getWorld().realWorld());
|
||||
} catch(IrisException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void close() {
|
||||
Iris.debug("Closing Active Provider");
|
||||
IrisToolbelt.evacuate(activeProvider.getTarget().getWorld().realWorld());
|
||||
activeProvider.close();
|
||||
File folder = activeProvider.getTarget().getWorld().worldFolder();
|
||||
Iris.linkMultiverseCore.removeFromConfig(activeProvider.getTarget().getWorld().name());
|
||||
Bukkit.unloadWorld(activeProvider.getTarget().getWorld().name(), false);
|
||||
J.attemptAsync(() -> IO.delete(folder));
|
||||
Iris.debug("Closed Active Provider " + activeProvider.getTarget().getWorld().name());
|
||||
activeProvider = null;
|
||||
}
|
||||
|
||||
public File getCodeWorkspaceFile() {
|
||||
return new File(path, getName() + ".code-workspace");
|
||||
}
|
||||
|
||||
public boolean updateWorkspace() {
|
||||
getPath().mkdirs();
|
||||
File ws = getCodeWorkspaceFile();
|
||||
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
JSONObject j = createCodeWorkspaceConfig();
|
||||
IO.writeAll(ws, j.toString(4));
|
||||
p.end();
|
||||
return true;
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.warn("Project invalid: " + ws.getAbsolutePath() + " Re-creating. You may loose some vs-code workspace settings! But not your actual project!");
|
||||
ws.delete();
|
||||
try {
|
||||
IO.writeAll(ws, createCodeWorkspaceConfig());
|
||||
} catch(IOException e1) {
|
||||
Iris.reportError(e1);
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public JSONObject createCodeWorkspaceConfig() {
|
||||
JSONObject ws = new JSONObject();
|
||||
JSONArray folders = new JSONArray();
|
||||
JSONObject folder = new JSONObject();
|
||||
folder.put("path", ".");
|
||||
folders.put(folder);
|
||||
ws.put("folders", folders);
|
||||
JSONObject settings = new JSONObject();
|
||||
settings.put("workbench.colorTheme", "Monokai");
|
||||
settings.put("workbench.preferredDarkColorTheme", "Solarized Dark");
|
||||
settings.put("workbench.tips.enabled", false);
|
||||
settings.put("workbench.tree.indent", 24);
|
||||
settings.put("files.autoSave", "onFocusChange");
|
||||
JSONObject jc = new JSONObject();
|
||||
jc.put("editor.autoIndent", "brackets");
|
||||
jc.put("editor.acceptSuggestionOnEnter", "smart");
|
||||
jc.put("editor.cursorSmoothCaretAnimation", true);
|
||||
jc.put("editor.dragAndDrop", false);
|
||||
jc.put("files.trimTrailingWhitespace", true);
|
||||
jc.put("diffEditor.ignoreTrimWhitespace", true);
|
||||
jc.put("files.trimFinalNewlines", true);
|
||||
jc.put("editor.suggest.showKeywords", false);
|
||||
jc.put("editor.suggest.showSnippets", false);
|
||||
jc.put("editor.suggest.showWords", false);
|
||||
JSONObject st = new JSONObject();
|
||||
st.put("strings", true);
|
||||
jc.put("editor.quickSuggestions", st);
|
||||
jc.put("editor.suggest.insertMode", "replace");
|
||||
settings.put("[json]", jc);
|
||||
settings.put("json.maxItemsComputed", 30000);
|
||||
JSONArray schemas = new JSONArray();
|
||||
IrisData dm = IrisData.get(getPath());
|
||||
|
||||
for(ResourceLoader<?> r : dm.getLoaders().v()) {
|
||||
if(r.supportsSchemas()) {
|
||||
schemas.put(r.buildSchema());
|
||||
}
|
||||
}
|
||||
|
||||
for(Class<?> i : Iris.getClasses("com.volmit.iris.engine.object.", Snippet.class)) {
|
||||
try {
|
||||
String snipType = i.getDeclaredAnnotation(Snippet.class).value();
|
||||
JSONObject o = new JSONObject();
|
||||
KList<String> fm = new KList<>();
|
||||
|
||||
for(int g = 1; g < 8; g++) {
|
||||
fm.add("/snippet/" + snipType + Form.repeat("/*", g) + ".json");
|
||||
}
|
||||
|
||||
o.put("fileMatch", new JSONArray(fm.toArray()));
|
||||
o.put("url", "./.iris/schema/snippet/" + snipType + "-schema.json");
|
||||
schemas.put(o);
|
||||
File a = new File(dm.getDataFolder(), ".iris/schema/snippet/" + snipType + "-schema.json");
|
||||
J.attemptAsync(() -> {
|
||||
try {
|
||||
IO.writeAll(a, new SchemaBuilder(i, dm).construct().toString(4));
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
settings.put("json.schemas", schemas);
|
||||
ws.put("settings", settings);
|
||||
|
||||
return ws;
|
||||
}
|
||||
|
||||
public File compilePackage(VolmitSender sender, boolean obfuscate, boolean minify) {
|
||||
String dimm = getName();
|
||||
IrisData dm = IrisData.get(path);
|
||||
IrisDimension dimension = dm.getDimensionLoader().load(dimm);
|
||||
File folder = new File(Iris.instance.getDataFolder(), "exports/" + dimension.getLoadKey());
|
||||
folder.mkdirs();
|
||||
Iris.info("Packaging Dimension " + dimension.getName() + " " + (obfuscate ? "(Obfuscated)" : ""));
|
||||
KSet<IrisRegion> regions = new KSet<>();
|
||||
KSet<IrisBiome> biomes = new KSet<>();
|
||||
KSet<IrisEntity> entities = new KSet<>();
|
||||
KSet<IrisSpawner> spawners = new KSet<>();
|
||||
KSet<IrisGenerator> generators = new KSet<>();
|
||||
KSet<IrisLootTable> loot = new KSet<>();
|
||||
KSet<IrisBlockData> blocks = new KSet<>();
|
||||
|
||||
for(String i : dm.getDimensionLoader().getPossibleKeys()) {
|
||||
blocks.add(dm.getBlockLoader().load(i));
|
||||
}
|
||||
|
||||
dimension.getRegions().forEach((i) -> regions.add(dm.getRegionLoader().load(i)));
|
||||
dimension.getLoot().getTables().forEach((i) -> loot.add(dm.getLootLoader().load(i)));
|
||||
regions.forEach((i) -> biomes.addAll(i.getAllBiomes(null)));
|
||||
regions.forEach((r) -> r.getLoot().getTables().forEach((i) -> loot.add(dm.getLootLoader().load(i))));
|
||||
regions.forEach((r) -> r.getEntitySpawners().forEach((sp) -> spawners.add(dm.getSpawnerLoader().load(sp))));
|
||||
dimension.getEntitySpawners().forEach((sp) -> spawners.add(dm.getSpawnerLoader().load(sp)));
|
||||
biomes.forEach((i) -> i.getGenerators().forEach((j) -> generators.add(j.getCachedGenerator(null))));
|
||||
biomes.forEach((r) -> r.getLoot().getTables().forEach((i) -> loot.add(dm.getLootLoader().load(i))));
|
||||
biomes.forEach((r) -> r.getEntitySpawners().forEach((sp) -> spawners.add(dm.getSpawnerLoader().load(sp))));
|
||||
spawners.forEach((i) -> i.getSpawns().forEach((j) -> entities.add(dm.getEntityLoader().load(j.getEntity()))));
|
||||
KMap<String, String> renameObjects = new KMap<>();
|
||||
String a;
|
||||
StringBuilder b = new StringBuilder();
|
||||
StringBuilder c = new StringBuilder();
|
||||
sender.sendMessage("Serializing Objects");
|
||||
|
||||
for(IrisBiome i : biomes) {
|
||||
for(IrisObjectPlacement j : i.getObjects()) {
|
||||
b.append(j.hashCode());
|
||||
KList<String> newNames = new KList<>();
|
||||
|
||||
for(String k : j.getPlace()) {
|
||||
if(renameObjects.containsKey(k)) {
|
||||
newNames.add(renameObjects.get(k));
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = !obfuscate ? k : UUID.randomUUID().toString().replaceAll("-", "");
|
||||
b.append(name);
|
||||
newNames.add(name);
|
||||
renameObjects.put(k, name);
|
||||
}
|
||||
|
||||
j.setPlace(newNames);
|
||||
}
|
||||
}
|
||||
|
||||
KMap<String, KList<String>> lookupObjects = renameObjects.flip();
|
||||
StringBuilder gb = new StringBuilder();
|
||||
ChronoLatch cl = new ChronoLatch(1000);
|
||||
O<Integer> ggg = new O<>();
|
||||
ggg.set(0);
|
||||
biomes.forEach((i) -> i.getObjects().forEach((j) -> j.getPlace().forEach((k) ->
|
||||
{
|
||||
try {
|
||||
File f = dm.getObjectLoader().findFile(lookupObjects.get(k).get(0));
|
||||
IO.copyFile(f, new File(folder, "objects/" + k + ".iob"));
|
||||
gb.append(IO.hash(f));
|
||||
ggg.set(ggg.get() + 1);
|
||||
|
||||
if(cl.flip()) {
|
||||
int g = ggg.get();
|
||||
ggg.set(0);
|
||||
sender.sendMessage("Wrote another " + g + " Objects");
|
||||
}
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
})));
|
||||
|
||||
b.append(IO.hash(gb.toString()));
|
||||
c.append(IO.hash(b.toString()));
|
||||
b = new StringBuilder();
|
||||
|
||||
Iris.info("Writing Dimensional Scaffold");
|
||||
|
||||
try {
|
||||
a = new JSONObject(new Gson().toJson(dimension)).toString(minify ? 0 : 4);
|
||||
IO.writeAll(new File(folder, "dimensions/" + dimension.getLoadKey() + ".json"), a);
|
||||
b.append(IO.hash(a));
|
||||
|
||||
for(IrisGenerator i : generators) {
|
||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||
IO.writeAll(new File(folder, "generators/" + i.getLoadKey() + ".json"), a);
|
||||
b.append(IO.hash(a));
|
||||
}
|
||||
|
||||
c.append(IO.hash(b.toString()));
|
||||
b = new StringBuilder();
|
||||
|
||||
for(IrisRegion i : regions) {
|
||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||
IO.writeAll(new File(folder, "regions/" + i.getLoadKey() + ".json"), a);
|
||||
b.append(IO.hash(a));
|
||||
}
|
||||
|
||||
for(IrisBlockData i : blocks) {
|
||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||
IO.writeAll(new File(folder, "blocks/" + i.getLoadKey() + ".json"), a);
|
||||
b.append(IO.hash(a));
|
||||
}
|
||||
|
||||
for(IrisBiome i : biomes) {
|
||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||
IO.writeAll(new File(folder, "biomes/" + i.getLoadKey() + ".json"), a);
|
||||
b.append(IO.hash(a));
|
||||
}
|
||||
|
||||
for(IrisEntity i : entities) {
|
||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||
IO.writeAll(new File(folder, "entities/" + i.getLoadKey() + ".json"), a);
|
||||
b.append(IO.hash(a));
|
||||
}
|
||||
|
||||
for(IrisLootTable i : loot) {
|
||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||
IO.writeAll(new File(folder, "loot/" + i.getLoadKey() + ".json"), a);
|
||||
b.append(IO.hash(a));
|
||||
}
|
||||
|
||||
c.append(IO.hash(b.toString()));
|
||||
String finalHash = IO.hash(c.toString());
|
||||
JSONObject meta = new JSONObject();
|
||||
meta.put("hash", finalHash);
|
||||
meta.put("time", M.ms());
|
||||
meta.put("version", dimension.getVersion());
|
||||
IO.writeAll(new File(folder, "package.json"), meta.toString(minify ? 0 : 4));
|
||||
File p = new File(Iris.instance.getDataFolder(), "exports/" + dimension.getLoadKey() + ".iris");
|
||||
Iris.info("Compressing Package");
|
||||
ZipUtil.pack(folder, p, 9);
|
||||
IO.delete(folder);
|
||||
|
||||
sender.sendMessage("Package Compiled!");
|
||||
return p;
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
sender.sendMessage("Failed!");
|
||||
return null;
|
||||
}
|
||||
|
||||
public void compile(VolmitSender sender) {
|
||||
IrisData data = IrisData.get(getPath());
|
||||
KList<Job> jobs = new KList<>();
|
||||
KList<File> files = new KList<>();
|
||||
KList<File> objects = new KList<>();
|
||||
files(getPath(), files);
|
||||
filesObjects(getPath(), objects);
|
||||
|
||||
jobs.add(new ParallelQueueJob<File>() {
|
||||
@Override
|
||||
public void execute(File f) {
|
||||
try {
|
||||
IrisObject o = new IrisObject(0, 0, 0);
|
||||
o.read(f);
|
||||
|
||||
if(o.getBlocks().isEmpty()) {
|
||||
sender.sendMessageRaw("<hover:show_text:'Error:\n" +
|
||||
"<yellow>" + f.getPath() +
|
||||
"'><red>- IOB " + f.getName() + " has 0 blocks!");
|
||||
}
|
||||
|
||||
if(o.getW() == 0 || o.getH() == 0 || o.getD() == 0) {
|
||||
sender.sendMessageRaw("<hover:show_text:'Error:\n" +
|
||||
"<yellow>" + f.getPath() + "\n<red>The width height or depth has a zero in it (bad format)" +
|
||||
"'><red>- IOB " + f.getName() + " is not 3D!");
|
||||
}
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "IOB";
|
||||
}
|
||||
}.queue(objects));
|
||||
|
||||
jobs.add(new ParallelQueueJob<File>() {
|
||||
@Override
|
||||
public void execute(File f) {
|
||||
try {
|
||||
JSONObject p = new JSONObject(IO.readAll(f));
|
||||
fixBlocks(p);
|
||||
scanForErrors(data, f, p, sender);
|
||||
IO.writeAll(f, p.toString(4));
|
||||
|
||||
} catch(Throwable e) {
|
||||
sender.sendMessageRaw("<hover:show_text:'Error:\n" +
|
||||
"<yellow>" + f.getPath() +
|
||||
"\n<red>" + e.getMessage() +
|
||||
"'><red>- JSON Error " + f.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "JSON";
|
||||
}
|
||||
}.queue(files));
|
||||
|
||||
new JobCollection("Compile", jobs).execute(sender);
|
||||
}
|
||||
|
||||
private void scanForErrors(IrisData data, File f, JSONObject p, VolmitSender sender) {
|
||||
String key = data.toLoadKey(f);
|
||||
ResourceLoader<?> loader = data.getTypedLoaderFor(f);
|
||||
|
||||
if(loader == null) {
|
||||
sender.sendMessageBasic("Can't find loader for " + f.getPath());
|
||||
return;
|
||||
}
|
||||
|
||||
IrisRegistrant load = loader.load(key);
|
||||
compare(load.getClass(), p, sender, new KList<>());
|
||||
load.scanForErrors(p, sender);
|
||||
}
|
||||
|
||||
public void compare(Class<?> c, JSONObject j, VolmitSender sender, KList<String> path) {
|
||||
try {
|
||||
Object o = c.getClass().getConstructor().newInstance();
|
||||
} catch(Throwable e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void files(File clean, KList<File> files) {
|
||||
if(clean.isDirectory()) {
|
||||
for(File i : clean.listFiles()) {
|
||||
files(i, files);
|
||||
}
|
||||
} else if(clean.getName().endsWith(".json")) {
|
||||
try {
|
||||
files.add(clean);
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void filesObjects(File clean, KList<File> files) {
|
||||
if(clean.isDirectory()) {
|
||||
for(File i : clean.listFiles()) {
|
||||
filesObjects(i, files);
|
||||
}
|
||||
} else if(clean.getName().endsWith(".iob")) {
|
||||
try {
|
||||
files.add(clean);
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fixBlocks(JSONObject obj) {
|
||||
for(String i : obj.keySet()) {
|
||||
Object o = obj.get(i);
|
||||
|
||||
if(i.equals("block") && o instanceof String && !o.toString().trim().isEmpty() && !o.toString().contains(":")) {
|
||||
obj.put(i, "minecraft:" + o);
|
||||
}
|
||||
|
||||
if(o instanceof JSONObject) {
|
||||
fixBlocks((JSONObject) o);
|
||||
} else if(o instanceof JSONArray) {
|
||||
fixBlocks((JSONArray) o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fixBlocks(JSONArray obj) {
|
||||
for(int i = 0; i < obj.length(); i++) {
|
||||
Object o = obj.get(i);
|
||||
|
||||
if(o instanceof JSONObject) {
|
||||
fixBlocks((JSONObject) o);
|
||||
} else if(o instanceof JSONArray) {
|
||||
fixBlocks((JSONArray) o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
670
src/main/java/com/volmit/iris/core/project/SchemaBuilder.java
Normal file
670
src/main/java/com/volmit/iris/core/project/SchemaBuilder.java
Normal file
@@ -0,0 +1,670 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.project;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||
import com.volmit.iris.core.loader.ResourceLoader;
|
||||
import com.volmit.iris.engine.object.annotations.*;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.json.JSONArray;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SchemaBuilder {
|
||||
private static final String SYMBOL_LIMIT__N = "*";
|
||||
private static final String SYMBOL_TYPE__N = "";
|
||||
private static final JSONArray POTION_TYPES = getPotionTypes();
|
||||
private static final JSONArray ENCHANT_TYPES = getEnchantTypes();
|
||||
private static final JSONArray ITEM_TYPES = new JSONArray(B.getItemTypes());
|
||||
private static final JSONArray FONT_TYPES = new JSONArray(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
|
||||
private final KMap<String, JSONObject> definitions;
|
||||
private final Class<?> root;
|
||||
private final KList<String> warnings;
|
||||
private final IrisData data;
|
||||
|
||||
public SchemaBuilder(Class<?> root, IrisData data) {
|
||||
this.data = data;
|
||||
warnings = new KList<>();
|
||||
this.definitions = new KMap<>();
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
private static JSONArray getPotionTypes() {
|
||||
JSONArray a = new JSONArray();
|
||||
|
||||
for(PotionEffectType gg : PotionEffectType.values()) {
|
||||
a.put(gg.getName().toUpperCase().replaceAll("\\Q \\E", "_"));
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
private static JSONArray getEnchantTypes() {
|
||||
JSONArray array = new JSONArray();
|
||||
for(Enchantment e : Enchantment.values()) {
|
||||
array.put(e.getKey().getKey());
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public JSONObject construct() {
|
||||
JSONObject schema = new JSONObject();
|
||||
schema.put("$schema", "http://json-schema.org/draft-07/schema#");
|
||||
schema.put("$id", "https://volmit.com/iris-schema/" + root.getSimpleName().toLowerCase() + ".json");
|
||||
|
||||
JSONObject props = buildProperties(root);
|
||||
|
||||
for(String i : props.keySet()) {
|
||||
if(!schema.has(i)) {
|
||||
schema.put(i, props.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
JSONObject defs = new JSONObject();
|
||||
|
||||
for(Map.Entry<String, JSONObject> entry : definitions.entrySet()) {
|
||||
defs.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
schema.put("definitions", defs);
|
||||
|
||||
for(String i : warnings) {
|
||||
Iris.warn(root.getSimpleName() + ": " + i);
|
||||
}
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
||||
private JSONObject buildProperties(Class<?> c) {
|
||||
JSONObject o = new JSONObject();
|
||||
JSONObject properties = new JSONObject();
|
||||
o.put("description", getDescription(c));
|
||||
o.put("type", getType(c));
|
||||
JSONArray required = new JSONArray();
|
||||
|
||||
if(c.isAssignableFrom(IrisRegistrant.class) || IrisRegistrant.class.isAssignableFrom(c)) {
|
||||
for(Field k : IrisRegistrant.class.getDeclaredFields()) {
|
||||
k.setAccessible(true);
|
||||
|
||||
if(Modifier.isStatic(k.getModifiers()) || Modifier.isFinal(k.getModifiers()) || Modifier.isTransient(k.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JSONObject property = buildProperty(k, c);
|
||||
|
||||
if(property.getBoolean("!required")) {
|
||||
required.put(k.getName());
|
||||
}
|
||||
|
||||
property.remove("!required");
|
||||
properties.put(k.getName(), property);
|
||||
}
|
||||
}
|
||||
|
||||
for(Field k : c.getDeclaredFields()) {
|
||||
k.setAccessible(true);
|
||||
|
||||
if(Modifier.isStatic(k.getModifiers()) || Modifier.isFinal(k.getModifiers()) || Modifier.isTransient(k.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JSONObject property = buildProperty(k, c);
|
||||
|
||||
property.remove("!required");
|
||||
properties.put(k.getName(), property);
|
||||
}
|
||||
|
||||
if(required.length() > 0) {
|
||||
o.put("required", required);
|
||||
}
|
||||
|
||||
o.put("properties", properties);
|
||||
|
||||
|
||||
if(c.isAnnotationPresent(Snippet.class)) {
|
||||
JSONObject anyOf = new JSONObject();
|
||||
JSONArray arr = new JSONArray();
|
||||
JSONObject str = new JSONObject();
|
||||
str.put("type", "string");
|
||||
arr.put(o);
|
||||
arr.put(str);
|
||||
anyOf.put("anyOf", arr);
|
||||
|
||||
return anyOf;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
private JSONObject buildProperty(Field k, Class<?> cl) {
|
||||
JSONObject prop = new JSONObject();
|
||||
String type = getType(k.getType());
|
||||
KList<String> description = new KList<>();
|
||||
prop.put("!required", k.isAnnotationPresent(Required.class));
|
||||
prop.put("type", type);
|
||||
String fancyType = "Unknown Type";
|
||||
|
||||
switch(type) {
|
||||
case "boolean" -> fancyType = "Boolean";
|
||||
case "integer" -> {
|
||||
fancyType = "Integer";
|
||||
if(k.isAnnotationPresent(MinNumber.class)) {
|
||||
int min = (int) k.getDeclaredAnnotation(MinNumber.class).value();
|
||||
prop.put("minimum", min);
|
||||
description.add(SYMBOL_LIMIT__N + " Minimum allowed is " + min);
|
||||
}
|
||||
if(k.isAnnotationPresent(MaxNumber.class)) {
|
||||
int max = (int) k.getDeclaredAnnotation(MaxNumber.class).value();
|
||||
prop.put("maximum", max);
|
||||
description.add(SYMBOL_LIMIT__N + " Maximum allowed is " + max);
|
||||
}
|
||||
}
|
||||
case "number" -> {
|
||||
fancyType = "Number";
|
||||
if(k.isAnnotationPresent(MinNumber.class)) {
|
||||
double min = k.getDeclaredAnnotation(MinNumber.class).value();
|
||||
prop.put("minimum", min);
|
||||
description.add(SYMBOL_LIMIT__N + " Minimum allowed is " + min);
|
||||
}
|
||||
if(k.isAnnotationPresent(MaxNumber.class)) {
|
||||
double max = k.getDeclaredAnnotation(MaxNumber.class).value();
|
||||
prop.put("maximum", max);
|
||||
description.add(SYMBOL_LIMIT__N + " Maximum allowed is " + max);
|
||||
}
|
||||
}
|
||||
case "string" -> {
|
||||
fancyType = "Text";
|
||||
if(k.isAnnotationPresent(MinNumber.class)) {
|
||||
int min = (int) k.getDeclaredAnnotation(MinNumber.class).value();
|
||||
prop.put("minLength", min);
|
||||
description.add(SYMBOL_LIMIT__N + " Minimum Length allowed is " + min);
|
||||
}
|
||||
if(k.isAnnotationPresent(MaxNumber.class)) {
|
||||
int max = (int) k.getDeclaredAnnotation(MaxNumber.class).value();
|
||||
prop.put("maxLength", max);
|
||||
description.add(SYMBOL_LIMIT__N + " Maximum Length allowed is " + max);
|
||||
}
|
||||
|
||||
|
||||
if(k.isAnnotationPresent(RegistryListResource.class)) {
|
||||
RegistryListResource rr = k.getDeclaredAnnotation(RegistryListResource.class);
|
||||
ResourceLoader<?> loader = data.getLoaders().get(rr.value());
|
||||
|
||||
if(loader != null) {
|
||||
String key = "erz" + loader.getFolderName();
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", new JSONArray(loader.getPossibleKeys()));
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
fancyType = "Iris " + loader.getResourceTypeName();
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid " + loader.getFolderName() + " (use ctrl+space for auto complete!)");
|
||||
} else {
|
||||
Iris.error("Cannot find Registry Loader for type " + rr.value() + " used in " + k.getDeclaringClass().getCanonicalName() + " in field " + k.getName());
|
||||
}
|
||||
} else if(k.isAnnotationPresent(RegistryListBlockType.class)) {
|
||||
String key = "enum-block-type";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
JSONArray ja = new JSONArray();
|
||||
|
||||
for(String i : data.getBlockLoader().getPossibleKeys()) {
|
||||
ja.put(i);
|
||||
}
|
||||
|
||||
for(String i : B.getBlockTypes()) {
|
||||
ja.put(i);
|
||||
}
|
||||
|
||||
j.put("enum", ja);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
fancyType = "Block Type";
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Block Type (use ctrl+space for auto complete!)");
|
||||
|
||||
} else if(k.isAnnotationPresent(RegistryListItemType.class)) {
|
||||
String key = "enum-item-type";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", ITEM_TYPES);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
fancyType = "Item Type";
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Item Type (use ctrl+space for auto complete!)");
|
||||
|
||||
} else if(k.isAnnotationPresent(RegistryListSpecialEntity.class)) {
|
||||
String key = "enum-reg-specialentity";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
KList<String> list = new KList<>();
|
||||
list.addAll(Iris.linkMythicMobs.getMythicMobTypes().stream().map(s -> "MythicMobs:" + s).collect(Collectors.toList()));
|
||||
//TODO add Citizens stuff here too
|
||||
j.put("enum", list.toJSONStringArray());
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
fancyType = "Mythic Mob Type";
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Mythic Mob Type (use ctrl+space for auto complete!) Define mythic mobs with the mythic mobs plugin configuration files.");
|
||||
} else if(k.isAnnotationPresent(RegistryListFont.class)) {
|
||||
String key = "enum-font";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", FONT_TYPES);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
fancyType = "Font Family";
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Font Family (use ctrl+space for auto complete!)");
|
||||
|
||||
} else if(k.isAnnotationPresent(RegistryListEnchantment.class)) {
|
||||
String key = "enum-enchantment";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", ENCHANT_TYPES);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
fancyType = "Enchantment Type";
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Enchantment Type (use ctrl+space for auto complete!)");
|
||||
} else if(k.getType().equals(PotionEffectType.class)) {
|
||||
String key = "enum-potion-effect-type";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", POTION_TYPES);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
fancyType = "Potion Effect Type";
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
||||
|
||||
} else if(k.getType().isEnum()) {
|
||||
fancyType = k.getType().getSimpleName().replaceAll("\\QIris\\E", "");
|
||||
JSONArray a = new JSONArray();
|
||||
boolean advanced = k.getType().isAnnotationPresent(Desc.class);
|
||||
for(Object gg : k.getType().getEnumConstants()) {
|
||||
if(advanced) {
|
||||
try {
|
||||
JSONObject j = new JSONObject();
|
||||
String name = ((Enum<?>) gg).name();
|
||||
j.put("const", name);
|
||||
Desc dd = k.getType().getField(name).getAnnotation(Desc.class);
|
||||
j.put("description", dd == null ? ("No Description for " + name) : dd.value());
|
||||
a.put(j);
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
a.put(((Enum<?>) gg).name());
|
||||
}
|
||||
}
|
||||
|
||||
String key = (advanced ? "oneof-" : "") + "enum-" + k.getType().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put(advanced ? "oneOf" : "enum", a);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid " + k.getType().getSimpleName().replaceAll("\\QIris\\E", "") + " (use ctrl+space for auto complete!)");
|
||||
|
||||
}
|
||||
}
|
||||
case "object" -> {
|
||||
fancyType = k.getType().getSimpleName().replaceAll("\\QIris\\E", "") + " (Object)";
|
||||
String key = "obj-" + k.getType().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
||||
if(!definitions.containsKey(key)) {
|
||||
definitions.put(key, new JSONObject());
|
||||
definitions.put(key, buildProperties(k.getType()));
|
||||
}
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
}
|
||||
case "array" -> {
|
||||
fancyType = "List of Something...?";
|
||||
ArrayType t = k.getDeclaredAnnotation(ArrayType.class);
|
||||
if(t != null) {
|
||||
if(t.min() > 0) {
|
||||
prop.put("minItems", t.min());
|
||||
if(t.min() == 1) {
|
||||
description.add(SYMBOL_LIMIT__N + " At least one entry must be defined, or just remove this list.");
|
||||
} else {
|
||||
description.add(SYMBOL_LIMIT__N + " Requires at least " + t.min() + " entries.");
|
||||
}
|
||||
}
|
||||
|
||||
String arrayType = getType(t.type());
|
||||
|
||||
switch(arrayType) {
|
||||
case "integer" -> fancyType = "List of Integers";
|
||||
case "number" -> fancyType = "List of Numbers";
|
||||
case "object" -> {
|
||||
fancyType = "List of " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + "s (Objects)";
|
||||
String key = "obj-" + t.type().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
||||
if(!definitions.containsKey(key)) {
|
||||
definitions.put(key, new JSONObject());
|
||||
definitions.put(key, buildProperties(t.type()));
|
||||
}
|
||||
JSONObject items = new JSONObject();
|
||||
items.put("$ref", "#/definitions/" + key);
|
||||
prop.put("items", items);
|
||||
}
|
||||
case "string" -> {
|
||||
fancyType = "List of Text";
|
||||
|
||||
if(k.isAnnotationPresent(RegistryListResource.class)) {
|
||||
RegistryListResource rr = k.getDeclaredAnnotation(RegistryListResource.class);
|
||||
ResourceLoader<?> loader = data.getLoaders().get(rr.value());
|
||||
|
||||
if(loader != null) {
|
||||
fancyType = "List<" + loader.getResourceTypeName() + ">";
|
||||
String key = "erz" + loader.getFolderName();
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", new JSONArray(loader.getPossibleKeys()));
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
JSONObject items = new JSONObject();
|
||||
items.put("$ref", "#/definitions/" + key);
|
||||
prop.put("items", items);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid " + loader.getResourceTypeName() + " (use ctrl+space for auto complete!)");
|
||||
} else {
|
||||
Iris.error("Cannot find Registry Loader for type (list schema) " + rr.value() + " used in " + k.getDeclaringClass().getCanonicalName() + " in field " + k.getName());
|
||||
}
|
||||
} else if(k.isAnnotationPresent(RegistryListBlockType.class)) {
|
||||
fancyType = "List of Block Types";
|
||||
String key = "enum-block-type";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
JSONArray ja = new JSONArray();
|
||||
|
||||
for(String i : data.getBlockLoader().getPossibleKeys()) {
|
||||
ja.put(i);
|
||||
}
|
||||
|
||||
for(String i : B.getBlockTypes()) {
|
||||
ja.put(i);
|
||||
}
|
||||
|
||||
j.put("enum", ja);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
JSONObject items = new JSONObject();
|
||||
items.put("$ref", "#/definitions/" + key);
|
||||
prop.put("items", items);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Block Type (use ctrl+space for auto complete!)");
|
||||
} else if(k.isAnnotationPresent(RegistryListItemType.class)) {
|
||||
fancyType = "List of Item Types";
|
||||
String key = "enum-item-type";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", ITEM_TYPES);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
JSONObject items = new JSONObject();
|
||||
items.put("$ref", "#/definitions/" + key);
|
||||
prop.put("items", items);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Item Type (use ctrl+space for auto complete!)");
|
||||
} else if(k.isAnnotationPresent(RegistryListFont.class)) {
|
||||
String key = "enum-font";
|
||||
fancyType = "List of Font Families";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", FONT_TYPES);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
JSONObject items = new JSONObject();
|
||||
items.put("$ref", "#/definitions/" + key);
|
||||
prop.put("items", items);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Font Family (use ctrl+space for auto complete!)");
|
||||
} else if(k.isAnnotationPresent(RegistryListEnchantment.class)) {
|
||||
fancyType = "List of Enchantment Types";
|
||||
String key = "enum-enchantment";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", ENCHANT_TYPES);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
JSONObject items = new JSONObject();
|
||||
items.put("$ref", "#/definitions/" + key);
|
||||
prop.put("items", items);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Enchantment Type (use ctrl+space for auto complete!)");
|
||||
} else if(t.type().equals(PotionEffectType.class)) {
|
||||
fancyType = "List of Potion Effect Types";
|
||||
String key = "enum-potion-effect-type";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", POTION_TYPES);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
JSONObject items = new JSONObject();
|
||||
items.put("$ref", "#/definitions/" + key);
|
||||
prop.put("items", items);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
||||
} else if(t.type().isEnum()) {
|
||||
fancyType = "List of " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + "s";
|
||||
JSONArray a = new JSONArray();
|
||||
boolean advanced = t.type().isAnnotationPresent(Desc.class);
|
||||
for(Object gg : t.type().getEnumConstants()) {
|
||||
if(advanced) {
|
||||
try {
|
||||
JSONObject j = new JSONObject();
|
||||
String name = ((Enum<?>) gg).name();
|
||||
j.put("const", name);
|
||||
Desc dd = t.type().getField(name).getAnnotation(Desc.class);
|
||||
j.put("description", dd == null ? ("No Description for " + name) : dd.value());
|
||||
a.put(j);
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
a.put(((Enum<?>) gg).name());
|
||||
}
|
||||
}
|
||||
|
||||
String key = (advanced ? "oneof-" : "") + "enum-" + t.type().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put(advanced ? "oneOf" : "enum", a);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
JSONObject items = new JSONObject();
|
||||
items.put("$ref", "#/definitions/" + key);
|
||||
prop.put("items", items);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + " (use ctrl+space for auto complete!)");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warnings.add("Undefined array type for field " + k.getName() + " (" + k.getType().getSimpleName() + ") in class " + cl.getSimpleName());
|
||||
}
|
||||
}
|
||||
default -> warnings.add("Unexpected Schema Type: " + type + " for field " + k.getName() + " (" + k.getType().getSimpleName() + ") in class " + cl.getSimpleName());
|
||||
}
|
||||
|
||||
KList<String> d = new KList<>();
|
||||
d.add(k.getName());
|
||||
d.add(getFieldDescription(k));
|
||||
d.add(" ");
|
||||
d.add(fancyType);
|
||||
d.add(getDescription(k.getType()));
|
||||
|
||||
if(k.getType().isAnnotationPresent(Snippet.class)) {
|
||||
String sm = k.getType().getDeclaredAnnotation(Snippet.class).value();
|
||||
d.add(" ");
|
||||
d.add("You can instead specify \"snippet/" + sm + "/some-name.json\" to use a snippet file instead of specifying it here.");
|
||||
}
|
||||
|
||||
try {
|
||||
k.setAccessible(true);
|
||||
Object value = k.get(cl.newInstance());
|
||||
|
||||
if(value != null) {
|
||||
if(value instanceof List) {
|
||||
d.add(" ");
|
||||
d.add("* Default Value is an empty list");
|
||||
} else if(!cl.isPrimitive() && !(value instanceof Number) && !(value instanceof String) && !(cl.isEnum())) {
|
||||
d.add(" ");
|
||||
d.add("* Default Value is a default object (create this object to see default properties)");
|
||||
} else {
|
||||
d.add(" ");
|
||||
d.add("* Default Value is " + value);
|
||||
}
|
||||
}
|
||||
} catch(Throwable ignored) {
|
||||
|
||||
}
|
||||
|
||||
description.forEach((g) -> d.add(g.trim()));
|
||||
prop.put("type", type);
|
||||
prop.put("description", d.toString("\n"));
|
||||
|
||||
if(k.getType().isAnnotationPresent(Snippet.class)) {
|
||||
JSONObject anyOf = new JSONObject();
|
||||
JSONArray arr = new JSONArray();
|
||||
JSONObject str = new JSONObject();
|
||||
str.put("type", "string");
|
||||
String key = "enum-snippet-" + k.getType().getDeclaredAnnotation(Snippet.class).value();
|
||||
str.put("$ref", "#/definitions/" + key);
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
JSONArray snl = new JSONArray();
|
||||
data.getPossibleSnippets(k.getType().getDeclaredAnnotation(Snippet.class).value()).forEach(snl::put);
|
||||
j.put("enum", snl);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
arr.put(prop);
|
||||
arr.put(str);
|
||||
prop.put("description", d.toString("\n"));
|
||||
str.put("description", d.toString("\n"));
|
||||
anyOf.put("anyOf", arr);
|
||||
anyOf.put("description", d.toString("\n"));
|
||||
anyOf.put("!required", k.isAnnotationPresent(Required.class));
|
||||
|
||||
return anyOf;
|
||||
}
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
private String getType(Class<?> c) {
|
||||
if(c.equals(int.class) || c.equals(Integer.class) || c.equals(long.class) || c.equals(Long.class)) {
|
||||
return "integer";
|
||||
}
|
||||
|
||||
if(c.equals(float.class) || c.equals(double.class) || c.equals(Float.class) || c.equals(Double.class)) {
|
||||
return "number";
|
||||
}
|
||||
|
||||
if(c.equals(boolean.class) || c.equals(Boolean.class)) {
|
||||
return "boolean";
|
||||
}
|
||||
|
||||
if(c.equals(String.class) || c.isEnum() || c.equals(Enchantment.class) || c.equals(PotionEffectType.class)) {
|
||||
return "string";
|
||||
}
|
||||
|
||||
if(c.equals(KList.class)) {
|
||||
return "array";
|
||||
}
|
||||
|
||||
if(c.equals(KMap.class)) {
|
||||
return "object";
|
||||
}
|
||||
|
||||
if(!c.isAnnotationPresent(Desc.class) && c.getCanonicalName().startsWith("com.volmit.iris.")) {
|
||||
warnings.addIfMissing("Unsupported Type: " + c.getCanonicalName() + " Did you forget @Desc?");
|
||||
}
|
||||
|
||||
return "object";
|
||||
}
|
||||
|
||||
private String getFieldDescription(Field r) {
|
||||
|
||||
if(r.isAnnotationPresent(Desc.class)) {
|
||||
return r.getDeclaredAnnotation(Desc.class).value();
|
||||
}
|
||||
|
||||
// suppress warnings on bukkit classes
|
||||
if(r.getDeclaringClass().getName().startsWith("org.bukkit.")) {
|
||||
return "Bukkit package classes and enums have no descriptions";
|
||||
}
|
||||
|
||||
warnings.addIfMissing("Missing @Desc on field " + r.getName() + " (" + r.getType() + ") in " + r.getDeclaringClass().getCanonicalName());
|
||||
return "No Field Description";
|
||||
}
|
||||
|
||||
private String getDescription(Class<?> r) {
|
||||
if(r.isAnnotationPresent(Desc.class)) {
|
||||
return r.getDeclaredAnnotation(Desc.class).value();
|
||||
}
|
||||
|
||||
if(!r.isPrimitive() && !r.equals(KList.class) && !r.equals(KMap.class) && r.getCanonicalName().startsWith("com.volmit.")) {
|
||||
warnings.addIfMissing("Missing @Desc on " + r.getSimpleName() + " in " + (r.getDeclaringClass() != null ? r.getDeclaringClass().getCanonicalName() : " NOSRC"));
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
39
src/main/java/com/volmit/iris/core/report/Report.java
Normal file
39
src/main/java/com/volmit/iris/core/report/Report.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.report;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class Report {
|
||||
@Builder.Default
|
||||
private final ReportType type = ReportType.NOTICE;
|
||||
@Builder.Default
|
||||
private final String title = "Problem...";
|
||||
@Builder.Default
|
||||
private final String message = "No Message";
|
||||
@Builder.Default
|
||||
private final String suggestion = "No Suggestion";
|
||||
|
||||
public String toString() {
|
||||
return type + ": " + title + ": " + message + ": Suggestion: " + suggestion;
|
||||
}
|
||||
}
|
||||
26
src/main/java/com/volmit/iris/core/report/ReportType.java
Normal file
26
src/main/java/com/volmit/iris/core/report/ReportType.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.report;
|
||||
|
||||
public enum ReportType {
|
||||
ERROR,
|
||||
SEVERE_WARNING,
|
||||
WARNING,
|
||||
NOTICE,
|
||||
}
|
||||
141
src/main/java/com/volmit/iris/core/service/BoardSVC.java
Normal file
141
src/main/java/com/volmit/iris/core/service/BoardSVC.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.service;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.board.BoardManager;
|
||||
import com.volmit.iris.util.board.BoardProvider;
|
||||
import com.volmit.iris.util.board.BoardSettings;
|
||||
import com.volmit.iris.util.board.ScoreDirection;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.Data;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BoardSVC implements IrisService, BoardProvider {
|
||||
private final KMap<Player, PlayerBoard> boards = new KMap<>();
|
||||
private com.volmit.iris.util.board.BoardManager manager;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
J.ar(this::tick, 20);
|
||||
manager = new BoardManager(Iris.instance, BoardSettings.builder()
|
||||
.boardProvider(this)
|
||||
.scoreDirection(ScoreDirection.DOWN)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
manager.onDisable();
|
||||
boards.clear();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(PlayerChangedWorldEvent e) {
|
||||
J.s(() -> updatePlayer(e.getPlayer()));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(PlayerJoinEvent e) {
|
||||
J.s(() -> updatePlayer(e.getPlayer()));
|
||||
}
|
||||
|
||||
public void updatePlayer(Player p) {
|
||||
if(IrisToolbelt.isIrisStudioWorld(p.getWorld())) {
|
||||
manager.remove(p);
|
||||
manager.setup(p);
|
||||
} else {
|
||||
manager.remove(p);
|
||||
boards.remove(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle(Player player) {
|
||||
return C.GREEN + "Iris";
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if(!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
boards.forEach((k, v) -> v.update());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getLines(Player player) {
|
||||
PlayerBoard pb = boards.computeIfAbsent(player, PlayerBoard::new);
|
||||
synchronized(pb.lines) {
|
||||
return pb.lines;
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class PlayerBoard {
|
||||
private final Player player;
|
||||
private final KList<String> lines;
|
||||
|
||||
public PlayerBoard(Player player) {
|
||||
this.player = player;
|
||||
this.lines = new KList<>();
|
||||
update();
|
||||
}
|
||||
|
||||
public void update() {
|
||||
synchronized(lines) {
|
||||
lines.clear();
|
||||
|
||||
if(!IrisToolbelt.isIrisStudioWorld(player.getWorld())) {
|
||||
return;
|
||||
}
|
||||
|
||||
Engine engine = IrisToolbelt.access(player.getWorld()).getEngine();
|
||||
int x = player.getLocation().getBlockX();
|
||||
int y = player.getLocation().getBlockY() - player.getWorld().getMinHeight();
|
||||
int z = player.getLocation().getBlockZ();
|
||||
|
||||
lines.add("&7&m ");
|
||||
lines.add(C.GREEN + "Speed" + C.GRAY + ": " + Form.f(engine.getGeneratedPerSecond(), 0) + "/s " + Form.duration(1000D / engine.getGeneratedPerSecond(), 0));
|
||||
lines.add(C.AQUA + "Cache" + C.GRAY + ": " + Form.f(IrisData.cacheSize()));
|
||||
lines.add(C.AQUA + "Mantle" + C.GRAY + ": " + engine.getMantle().getLoadedRegionCount());
|
||||
lines.add("&7&m ");
|
||||
lines.add(C.AQUA + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName());
|
||||
lines.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiomeOrMantle(x, y, z).getName());
|
||||
lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z) + player.getWorld().getMinHeight()));
|
||||
lines.add(C.AQUA + "Slope" + C.GRAY + ": " + Form.f(engine.getComplex().getSlopeStream().get(x, z), 2));
|
||||
lines.add(C.AQUA + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond()));
|
||||
lines.add("&7&m ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
99
src/main/java/com/volmit/iris/core/service/CommandSVC.java
Normal file
99
src/main/java/com/volmit/iris/core/service/CommandSVC.java
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.service;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.commands.CommandIris;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.data.cache.AtomicCache;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.decree.DecreeSystem;
|
||||
import com.volmit.iris.util.decree.virtual.VirtualDecreeCommand;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.server.ServerCommandEvent;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class CommandSVC implements IrisService, DecreeSystem {
|
||||
private final KMap<String, CompletableFuture<String>> futures = new KMap<>();
|
||||
private CompletableFuture<String> consoleFuture = null;
|
||||
private final transient AtomicCache<VirtualDecreeCommand> commandCache = new AtomicCache<>();
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
Iris.instance.getCommand("iris").setExecutor(this);
|
||||
J.a(() -> getRoot().cacheAll());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(PlayerCommandPreprocessEvent e) {
|
||||
String msg = e.getMessage().startsWith("/") ? e.getMessage().substring(1) : e.getMessage();
|
||||
|
||||
if(msg.startsWith("irisdecree ")) {
|
||||
String[] args = msg.split("\\Q \\E");
|
||||
CompletableFuture<String> future = futures.get(args[1]);
|
||||
|
||||
if(future != null) {
|
||||
future.complete(args[2]);
|
||||
e.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if((msg.startsWith("locate ") || msg.startsWith("locatebiome ")) && IrisToolbelt.isIrisWorld(e.getPlayer().getWorld())) {
|
||||
new VolmitSender(e.getPlayer()).sendMessage(C.RED + "Locating biomes & objects is disabled in Iris Worlds. Use /iris studio goto <biome>");
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(ServerCommandEvent e) {
|
||||
if(consoleFuture != null && !consoleFuture.isCancelled() && !consoleFuture.isDone()) {
|
||||
if(!e.getCommand().contains(" ")) {
|
||||
String pick = e.getCommand().trim().toLowerCase(Locale.ROOT);
|
||||
consoleFuture.complete(pick);
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualDecreeCommand getRoot() {
|
||||
return commandCache.aquireNastyPrint(() -> VirtualDecreeCommand.createRoot(new CommandIris()));
|
||||
}
|
||||
|
||||
public void post(String password, CompletableFuture<String> future) {
|
||||
futures.put(password, future);
|
||||
}
|
||||
|
||||
public void postConsole(CompletableFuture<String> future) {
|
||||
consoleFuture = future;
|
||||
}
|
||||
}
|
||||
246
src/main/java/com/volmit/iris/core/service/ConversionSVC.java
Normal file
246
src/main/java/com/volmit/iris/core/service/ConversionSVC.java
Normal file
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.service;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.object.IrisDirection;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPieceConnector;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPool;
|
||||
import com.volmit.iris.engine.object.IrisObject;
|
||||
import com.volmit.iris.engine.object.IrisPosition;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.function.Consumer2;
|
||||
import com.volmit.iris.util.io.Converter;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.nbt.io.NBTUtil;
|
||||
import com.volmit.iris.util.nbt.io.NamedTag;
|
||||
import com.volmit.iris.util.nbt.mca.NBTWorld;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
import com.volmit.iris.util.nbt.tag.IntTag;
|
||||
import com.volmit.iris.util.nbt.tag.ListTag;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.type.Jigsaw;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class ConversionSVC implements IrisService {
|
||||
private KList<Converter> converters;
|
||||
private File folder;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
folder = Iris.instance.getDataFolder("convert");
|
||||
converters = new KList<>();
|
||||
|
||||
J.s(() ->
|
||||
J.attemptAsync(() ->
|
||||
{
|
||||
|
||||
}), 5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
|
||||
}
|
||||
|
||||
private String toPoolName(String poolReference) {
|
||||
return poolReference.split("\\Q:\\E")[1];
|
||||
}
|
||||
|
||||
public void convertStructures(File in, File out, VolmitSender s) {
|
||||
KMap<String, IrisJigsawPool> pools = new KMap<>();
|
||||
KList<File> roots = new KList<>();
|
||||
AtomicInteger total = new AtomicInteger(0);
|
||||
AtomicInteger at = new AtomicInteger(0);
|
||||
File destPools = new File(out.getAbsolutePath() + "/jigsaw-pools");
|
||||
destPools.mkdirs();
|
||||
findAllNBT(in, (folder, file) -> {
|
||||
total.getAndIncrement();
|
||||
if(roots.addIfMissing(folder)) {
|
||||
String b = in.toURI().relativize(folder.toURI()).getPath();
|
||||
if(b.startsWith("/")) {
|
||||
b = b.substring(1);
|
||||
}
|
||||
|
||||
if(b.endsWith("/")) {
|
||||
b = b.substring(0, b.length() - 1);
|
||||
}
|
||||
|
||||
pools.put(b, new IrisJigsawPool());
|
||||
}
|
||||
});
|
||||
findAllNBT(in, (folder, file) -> {
|
||||
at.getAndIncrement();
|
||||
String b = in.toURI().relativize(folder.toURI()).getPath();
|
||||
if(b.startsWith("/")) {
|
||||
b = b.substring(1);
|
||||
}
|
||||
|
||||
if(b.endsWith("/")) {
|
||||
b = b.substring(0, b.length() - 1);
|
||||
}
|
||||
IrisJigsawPool jpool = pools.get(b);
|
||||
File destObjects = new File(out.getAbsolutePath() + "/objects/" + in.toURI().relativize(folder.toURI()).getPath());
|
||||
File destPieces = new File(out.getAbsolutePath() + "/jigsaw-pieces/" + in.toURI().relativize(folder.toURI()).getPath());
|
||||
destObjects.mkdirs();
|
||||
destPieces.mkdirs();
|
||||
|
||||
try {
|
||||
NamedTag tag = NBTUtil.read(file);
|
||||
CompoundTag compound = (CompoundTag) tag.getTag();
|
||||
|
||||
if(compound.containsKey("blocks") && compound.containsKey("palette") && compound.containsKey("size")) {
|
||||
String id = in.toURI().relativize(folder.toURI()).getPath() + file.getName().split("\\Q.\\E")[0];
|
||||
@SuppressWarnings("unchecked") ListTag<IntTag> size = (ListTag<IntTag>) compound.getListTag("size");
|
||||
int w = size.get(0).asInt();
|
||||
int h = size.get(1).asInt();
|
||||
int d = size.get(2).asInt();
|
||||
KList<BlockData> palette = new KList<>();
|
||||
@SuppressWarnings("unchecked") ListTag<CompoundTag> paletteList = (ListTag<CompoundTag>) compound.getListTag("palette");
|
||||
for(int i = 0; i < paletteList.size(); i++) {
|
||||
CompoundTag cp = paletteList.get(i);
|
||||
palette.add(NBTWorld.getBlockData(cp));
|
||||
}
|
||||
IrisJigsawPiece piece = new IrisJigsawPiece();
|
||||
IrisObject object = new IrisObject(w, h, d);
|
||||
@SuppressWarnings("unchecked") ListTag<CompoundTag> blockList = (ListTag<CompoundTag>) compound.getListTag("blocks");
|
||||
for(int i = 0; i < blockList.size(); i++) {
|
||||
CompoundTag cp = blockList.get(i);
|
||||
@SuppressWarnings("unchecked") ListTag<IntTag> pos = (ListTag<IntTag>) cp.getListTag("pos");
|
||||
int x = pos.get(0).asInt();
|
||||
int y = pos.get(1).asInt();
|
||||
int z = pos.get(2).asInt();
|
||||
BlockData bd = palette.get(cp.getInt("state")).clone();
|
||||
|
||||
if(bd.getMaterial().equals(Material.JIGSAW) && cp.containsKey("nbt")) {
|
||||
piece.setObject(in.toURI().relativize(folder.toURI()).getPath() + file.getName().split("\\Q.\\E")[0]);
|
||||
IrisPosition spos = new IrisPosition(object.getSigned(x, y, z));
|
||||
CompoundTag nbt = cp.getCompoundTag("nbt");
|
||||
CompoundTag finalState = new CompoundTag();
|
||||
finalState.putString("Name", nbt.getString("final_state"));
|
||||
BlockData jd = bd.clone();
|
||||
bd = NBTWorld.getBlockData(finalState);
|
||||
String joint = nbt.getString("joint");
|
||||
String pool = nbt.getString("pool");
|
||||
String poolId = toPoolName(pool);
|
||||
String name = nbt.getString("name");
|
||||
String target = nbt.getString("target");
|
||||
pools.computeIfAbsent(poolId, (k) -> new IrisJigsawPool());
|
||||
IrisJigsawPieceConnector connector = new IrisJigsawPieceConnector();
|
||||
connector.setName(name);
|
||||
connector.setTargetName(target);
|
||||
connector.setRotateConnector(false);
|
||||
connector.setPosition(spos);
|
||||
connector.getPools().add(poolId);
|
||||
connector.setDirection(IrisDirection.getDirection(((Jigsaw) jd).getOrientation()));
|
||||
|
||||
if(target.equals("minecraft:building_entrance")) {
|
||||
connector.setInnerConnector(true);
|
||||
}
|
||||
|
||||
piece.getConnectors().add(connector);
|
||||
}
|
||||
|
||||
if(!bd.getMaterial().equals(Material.STRUCTURE_VOID) && !bd.getMaterial().equals(Material.AIR)) {
|
||||
object.setUnsigned(x, y, z, bd);
|
||||
}
|
||||
}
|
||||
|
||||
jpool.getPieces().addIfMissing(id);
|
||||
object.write(new File(destObjects, file.getName().split("\\Q.\\E")[0] + ".iob"));
|
||||
IO.writeAll(new File(destPieces, file.getName().split("\\Q.\\E")[0] + ".json"), new JSONObject(new Gson().toJson(piece)).toString(4));
|
||||
Iris.info("[Jigsaw]: (" + Form.pc((double) at.get() / (double) total.get(), 0) + ") Exported Piece: " + id);
|
||||
}
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
});
|
||||
|
||||
for(String i : pools.k()) {
|
||||
try {
|
||||
IO.writeAll(new File(destPools, i + ".json"), new JSONObject(new Gson().toJson(pools.get(i))).toString(4));
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
Iris.info("Done! Exported " + Form.f((total.get() * 2) + pools.size()) + " Files!");
|
||||
}
|
||||
|
||||
public void findAllNBT(File path, Consumer2<File, File> inFile) {
|
||||
if(path == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(path.isFile() && path.getName().endsWith(".nbt")) {
|
||||
inFile.accept(path.getParentFile(), path);
|
||||
return;
|
||||
}
|
||||
|
||||
for(File i : path.listFiles()) {
|
||||
if(i.isDirectory()) {
|
||||
findAllNBT(i, inFile);
|
||||
} else if(i.isFile() && i.getName().endsWith(".nbt")) {
|
||||
inFile.accept(path, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void check(VolmitSender s) {
|
||||
int m = 0;
|
||||
Iris.instance.getDataFolder("convert");
|
||||
|
||||
for(File i : folder.listFiles()) {
|
||||
for(Converter j : converters) {
|
||||
if(i.getName().endsWith("." + j.getInExtension())) {
|
||||
File out = new File(folder, i.getName().replaceAll("\\Q." + j.getInExtension() + "\\E", "." + j.getOutExtension()));
|
||||
m++;
|
||||
j.convert(i, out);
|
||||
s.sendMessage("Converted " + i.getName() + " -> " + out.getName());
|
||||
}
|
||||
}
|
||||
|
||||
if(i.isDirectory() && i.getName().equals("structures")) {
|
||||
File f = new File(folder, "jigsaw");
|
||||
|
||||
if(!f.exists()) {
|
||||
s.sendMessage("Converting NBT Structures into Iris Jigsaw Structures...");
|
||||
f.mkdirs();
|
||||
J.a(() -> convertStructures(i, f, s));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s.sendMessage("Converted " + m + " File" + (m == 1 ? "" : "s"));
|
||||
}
|
||||
}
|
||||
54
src/main/java/com/volmit/iris/core/service/DolphinSVC.java
Normal file
54
src/main/java/com/volmit/iris/core/service/DolphinSVC.java
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.service;
|
||||
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
|
||||
public class DolphinSVC implements IrisService {
|
||||
@Override
|
||||
public void onEnable() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents dolphins from being fed, to locate a treasure map.
|
||||
* Note: This results in odd dolphin behaviour, but it's the best we can do.
|
||||
*/
|
||||
@EventHandler
|
||||
public void on(PlayerInteractEntityEvent event) {
|
||||
if(!IrisToolbelt.isIrisWorld(event.getPlayer().getWorld())) {
|
||||
return;
|
||||
}
|
||||
|
||||
Material hand = event.getPlayer().getInventory().getItem(event.getHand()).getType();
|
||||
if(event.getRightClicked().getType().equals(EntityType.DOLPHIN) && (hand.equals(Material.TROPICAL_FISH) || hand.equals(Material.PUFFERFISH) || hand.equals(Material.COD) || hand.equals(Material.SALMON))) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user