Compare commits
1812 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb2ed1c549 | ||
|
|
d86d2dbdb9 | ||
|
|
0546d6cf55 | ||
|
|
9b3a8c201f | ||
|
|
1bf3345b2f | ||
|
|
a8dd868df2 | ||
|
|
6dc6c2ebba | ||
|
|
3b3abdf87e | ||
|
|
e0e124ee57 | ||
|
|
cfba83018e | ||
|
|
79581edaa0 | ||
|
|
0b7c9dc8b1 | ||
|
|
665207b9b0 | ||
|
|
0cd4ef575d | ||
|
|
91f50883b1 | ||
|
|
756c717a9b | ||
|
|
2cea277320 | ||
|
|
dd36b71c7f | ||
|
|
5e3e07f002 | ||
|
|
0ffe2ed51a | ||
|
|
02e6257a66 | ||
|
|
57fd72f476 | ||
|
|
d2d7596ef1 | ||
|
|
149c48a03e | ||
|
|
bdeba22561 | ||
|
|
640c7851cf | ||
|
|
c0991a9baa | ||
|
|
5af6e8c5de | ||
|
|
2d4677aa27 | ||
|
|
984b646103 | ||
|
|
0949852758 | ||
|
|
d4c409252b | ||
|
|
38a9ad9ec1 | ||
|
|
c70be45a25 | ||
|
|
186e8f707e | ||
|
|
e3351e0c23 | ||
|
|
b08f198629 | ||
|
|
1b3e99fbb0 | ||
|
|
f74c153a47 | ||
|
|
2613ff6796 | ||
|
|
c404e7e1c6 | ||
|
|
d468a4f328 | ||
|
|
4417a83424 | ||
|
|
45dc72faf6 | ||
|
|
42c643f769 | ||
|
|
b7d5f9a7ab | ||
|
|
7e7d6120ad | ||
|
|
d6566830ac | ||
|
|
12dfd71345 | ||
|
|
60b6e93f7c | ||
|
|
128174faa4 | ||
|
|
7ab0c86978 | ||
|
|
5f0ec79b0f | ||
|
|
15affaad9b | ||
|
|
a74bc0c077 | ||
|
|
9088d9eb39 | ||
|
|
f11f390c1f | ||
|
|
865ee952c9 | ||
|
|
efcae883fb | ||
|
|
fe9ff212b2 | ||
|
|
210fb349de | ||
|
|
69d8af7874 | ||
|
|
183c922b6b | ||
|
|
964104db65 | ||
|
|
2d8f7cb680 | ||
|
|
aef92fd3b0 | ||
|
|
a0f80a8865 | ||
|
|
6b5a743583 | ||
|
|
28252173b4 | ||
|
|
2e733273a0 | ||
|
|
39f4e90fff | ||
|
|
22d1700fb2 | ||
|
|
31c39e0148 | ||
|
|
e5b80c37eb | ||
|
|
2a451aa41f | ||
|
|
1a03151966 | ||
|
|
51040f9f3d | ||
|
|
3ad16ab8aa | ||
|
|
b58e64ea16 | ||
|
|
7fe9e7f9c2 | ||
|
|
2d9204d638 | ||
|
|
de9c82d1d2 | ||
|
|
a756dec379 | ||
|
|
5601f97266 | ||
|
|
347b38ba26 | ||
|
|
d6016f1b04 | ||
|
|
7ec713ab66 | ||
|
|
446c2d2dcb | ||
|
|
c5261cf2e5 | ||
|
|
cb0382a15b | ||
|
|
3527acd33e | ||
|
|
83854169b7 | ||
|
|
dfd2b22917 | ||
|
|
c4803d29da | ||
|
|
a0acf1a040 | ||
|
|
8d9d6385f9 | ||
|
|
af2830602d | ||
|
|
e4bd3fab7c | ||
|
|
e3ea1bdaae | ||
|
|
a180aae838 | ||
|
|
abcea8dd39 | ||
|
|
448604062d | ||
|
|
bcdbca7337 | ||
|
|
dd500a747b | ||
|
|
32d8f59b5a | ||
|
|
86bf068ac3 | ||
|
|
ec2c273c97 | ||
|
|
a587477fc0 | ||
|
|
e3da0f713e | ||
|
|
6f609aa4ee | ||
|
|
c9ff84d03b | ||
|
|
b04c04f69f | ||
|
|
adf6465029 | ||
|
|
a8a163ebe2 | ||
|
|
7dcfd648f7 | ||
|
|
1895c7b8e0 | ||
|
|
91c0235ff5 | ||
|
|
25b2458a92 | ||
|
|
28203ca6e9 | ||
|
|
93fd3c6e18 | ||
|
|
95da46bfa2 | ||
|
|
8c1702cff5 | ||
|
|
8962992ef9 | ||
|
|
a7de30ba53 | ||
|
|
2651a30f79 | ||
|
|
1c9589eb26 | ||
|
|
850ebe8156 | ||
|
|
8a51a4be32 | ||
|
|
a452cd94c6 | ||
|
|
0966b49ff7 | ||
|
|
0582cfac2b | ||
|
|
5deb8a879e | ||
|
|
f4db208d75 | ||
|
|
f73c49b246 | ||
|
|
93a197e7d9 | ||
|
|
861ca2c6ae | ||
|
|
1fffbf3a79 | ||
|
|
82742339a3 | ||
|
|
11d85621e2 | ||
|
|
a64efce5a0 | ||
|
|
9be4461b54 | ||
|
|
7f01959438 | ||
|
|
a09771b569 | ||
|
|
79695086c6 | ||
|
|
4a922e4c10 | ||
|
|
bfc059769f | ||
|
|
b0ab33f125 | ||
|
|
faa8c68c20 | ||
|
|
45f5e2ae90 | ||
|
|
0859f92fea | ||
|
|
698e4bc740 | ||
|
|
300e3f2320 | ||
|
|
d4f22c4838 | ||
|
|
758b3bcb24 | ||
|
|
782c7a9ff3 | ||
|
|
8d12dbbe70 | ||
|
|
75abe7661d | ||
|
|
c318d4fa70 | ||
|
|
7a3a39d3b1 | ||
|
|
a4895fef8b | ||
|
|
685adeee9d | ||
|
|
c8d2b7a39e | ||
|
|
41082e9429 | ||
|
|
04b7aad1bf | ||
|
|
d0b70fd70d | ||
|
|
3c008e6bd8 | ||
|
|
ade313fc1b | ||
|
|
d96626e0c4 | ||
|
|
d0da46e715 | ||
|
|
9144f57b16 | ||
|
|
4ab115d007 | ||
|
|
b4dad32b2b | ||
|
|
c80f2d6cf4 | ||
|
|
f87054c667 | ||
|
|
2f2dc01c6b | ||
|
|
9f087214a1 | ||
|
|
6e05319424 | ||
|
|
151c4f13df | ||
|
|
c6242fe7f1 | ||
|
|
7243ae4e95 | ||
|
|
3e636cba6b | ||
|
|
5f28e26176 | ||
|
|
0a7d5b20c7 | ||
|
|
f9c48d0a02 | ||
|
|
dd9ec950be | ||
|
|
a1cae3bc29 | ||
|
|
944b9ae2cf | ||
|
|
8ec62e9dba | ||
|
|
af676ea030 | ||
|
|
89fdda0ef6 | ||
|
|
4283f9f8d7 | ||
|
|
527856e1b0 | ||
|
|
1bbb52877f | ||
|
|
6ceb1d5058 | ||
|
|
de9371f0bb | ||
|
|
b8daa422ee | ||
|
|
677bad5c60 | ||
|
|
fcf1bdd701 | ||
|
|
8fc61215a5 | ||
|
|
6b33064196 | ||
|
|
c29d75f5d1 | ||
|
|
9f7568552f | ||
|
|
00ca247d0f | ||
|
|
a2a4302c8c | ||
|
|
86ae13ed95 | ||
|
|
a264a1cd65 | ||
|
|
4932d11d7b | ||
|
|
3f27cebfb6 | ||
|
|
9cd482d389 | ||
|
|
c674b5c256 | ||
|
|
1c4184db4b | ||
|
|
0247301272 | ||
|
|
1cbd58820e | ||
|
|
eb7e65668c | ||
|
|
f91cc2eace | ||
|
|
942204bff1 | ||
|
|
43e13038f4 | ||
|
|
6d28098180 | ||
|
|
f1cf1efe32 | ||
|
|
c345ad37b9 | ||
|
|
ac20b17e0b | ||
|
|
a06ee52fb5 | ||
|
|
41ccda03a8 | ||
|
|
3f7edc9018 | ||
|
|
8f390468dc | ||
|
|
c6b4db8a4e | ||
|
|
978a5a80e3 | ||
|
|
c964704fe1 | ||
|
|
1313ed2761 | ||
|
|
4c5f27037b | ||
|
|
bf17788485 | ||
|
|
c0dce6ca41 | ||
|
|
17873d93cc | ||
|
|
48c1421afe | ||
|
|
5d88dbf3b9 | ||
|
|
91f472d88f | ||
|
|
5533721f3c | ||
|
|
0c85a6ee47 | ||
|
|
8128542a1f | ||
|
|
7a93c21d10 | ||
|
|
e248f44099 | ||
|
|
f854d0b1e6 | ||
|
|
fbe45aba74 | ||
|
|
79e079671c | ||
|
|
4cd411d5ee | ||
|
|
9aae443e72 | ||
|
|
462a64bf21 | ||
|
|
eba6514fb5 | ||
|
|
1eebf0d270 | ||
|
|
dd7542032c | ||
|
|
5b8c4c4f8e | ||
|
|
bab8c20f3b | ||
|
|
662473936c | ||
|
|
c9a1de1148 | ||
|
|
e16ce5b651 | ||
|
|
fa99a9b335 | ||
|
|
28b235ef07 | ||
|
|
ea75a357ca | ||
|
|
60ceb63731 | ||
|
|
f5c8965616 | ||
|
|
f42b147b06 | ||
|
|
22b27dc168 | ||
|
|
551ebb6b31 | ||
|
|
8b95d2db0d | ||
|
|
b7c185ca1b | ||
|
|
8b50590cc5 | ||
|
|
1ea4567912 | ||
|
|
dadbaa1380 | ||
|
|
0bf25cdd01 | ||
|
|
2f07a21d66 | ||
|
|
39d725d5ff | ||
|
|
dd0b5f791c | ||
|
|
e3fdc1d57c | ||
|
|
e22af83ed1 | ||
|
|
265f38dcc6 | ||
|
|
008b2c57c5 | ||
|
|
256482a486 | ||
|
|
e4c434e26e | ||
|
|
be71664436 | ||
|
|
db897d037d | ||
|
|
86d50e9147 | ||
|
|
0764fcb476 | ||
|
|
9a225d96ef | ||
|
|
5eb80ead93 | ||
|
|
760962c2b4 | ||
|
|
b11b087d53 | ||
|
|
2d8b3918d2 | ||
|
|
6398fed47b | ||
|
|
1e1d7d2e92 | ||
|
|
716fed08c3 | ||
|
|
6fcdb9d505 | ||
|
|
8d1a34b652 | ||
|
|
ac8c81a0d5 | ||
|
|
5f7e2d97ef | ||
|
|
927077c54c | ||
|
|
a861da1a67 | ||
|
|
c53e14dd31 | ||
|
|
622f735953 | ||
|
|
d820e7d31a | ||
|
|
0193d586d1 | ||
|
|
a56a0aa14f | ||
|
|
7853767ee5 | ||
|
|
9e519ab801 | ||
|
|
5995f0e215 | ||
|
|
7f50969dbc | ||
|
|
76db20e410 | ||
|
|
d9c5e5e08d | ||
|
|
451568d5b2 | ||
|
|
e8e23961f4 | ||
|
|
0e1c4ccd6d | ||
|
|
73f0593acf | ||
|
|
b779ec3759 | ||
|
|
41423d43bb | ||
|
|
7dc3dfd29e | ||
|
|
6eea8bebdf | ||
|
|
8cd7e1c307 | ||
|
|
3910d7769b | ||
|
|
f22f5a8ad9 | ||
|
|
f14d4d91b0 | ||
|
|
fc68a8af19 | ||
|
|
0c3e110326 | ||
|
|
434ee7de97 | ||
|
|
6e1880f409 | ||
|
|
e8fa899c40 | ||
|
|
d9b2f4ae67 | ||
|
|
137792131e | ||
|
|
fbddc0abc9 | ||
|
|
d9b6ada0b3 | ||
|
|
f005b83ed3 | ||
|
|
d41362a71d | ||
|
|
6cfb88a2e8 | ||
|
|
865d0082cc | ||
|
|
24c8d6e040 | ||
|
|
a55039447a | ||
|
|
aef7709764 | ||
|
|
c99b79762a | ||
|
|
0d8f95354f | ||
|
|
7e7e6b70e2 | ||
|
|
56b8986a0b | ||
|
|
3b8aa0484e | ||
|
|
2b9d516922 | ||
|
|
bdf958ed17 | ||
|
|
5fc4e1f5a5 | ||
|
|
24f0a17395 | ||
|
|
08d200e1fa | ||
|
|
782442f144 | ||
|
|
7e6f3e3761 | ||
|
|
6f8d43bc78 | ||
|
|
ad46fa93a5 | ||
|
|
4fec3bfcf9 | ||
|
|
ef49a16c9e | ||
|
|
93f3d6039e | ||
|
|
19778c743c | ||
|
|
28a2e7c697 | ||
|
|
d538e63c4c | ||
|
|
31f8d6c830 | ||
|
|
02e68d27a3 | ||
|
|
0aa2d5f18c | ||
|
|
5a5854420e | ||
|
|
6a8127e7cd | ||
|
|
1bd4c96ee8 | ||
|
|
d66d7e09e3 | ||
|
|
e85e43c162 | ||
|
|
dee020bd71 | ||
|
|
d548a11c60 | ||
|
|
59bf2e3571 | ||
|
|
6ebabbb56a | ||
|
|
179cedd6cc | ||
|
|
3b56f36bbd | ||
|
|
be0765f5ea | ||
|
|
1715741e37 | ||
|
|
aaa41fbf72 | ||
|
|
2096d006be | ||
|
|
e455f7d170 | ||
|
|
7a0e772a05 | ||
|
|
7f3b8f7e56 | ||
|
|
5a493ebf0e | ||
|
|
70bcb0a940 | ||
|
|
3105478328 | ||
|
|
ae8833e679 | ||
|
|
afbac48a45 | ||
|
|
4a9eeeeac3 | ||
|
|
e7d9cddbae | ||
|
|
a6fe1275c7 | ||
|
|
2f3fd9de3b | ||
|
|
8b2e78ab1e | ||
|
|
d04eaa81e0 | ||
|
|
b71d5837e9 | ||
|
|
332b1ce100 | ||
|
|
c17040b1ab | ||
|
|
a3bd7ba3ad | ||
|
|
2a7525cdf1 | ||
|
|
de458f5c26 | ||
|
|
db931bace2 | ||
|
|
43602caab2 | ||
|
|
793e957d0d | ||
|
|
66594a2b32 | ||
|
|
e81219dd3e | ||
|
|
d11a26c568 | ||
|
|
cf3543ec07 | ||
|
|
886d8752b7 | ||
|
|
496d6b139e | ||
|
|
3ce064ca11 | ||
|
|
1be7f3b36c | ||
|
|
3fddd6eea7 | ||
|
|
339fc8113b | ||
|
|
025bf5ffc3 | ||
|
|
1dc2906343 | ||
|
|
eea276118f | ||
|
|
36aa9d5696 | ||
|
|
1fc1efc410 | ||
|
|
7924d9b9ef | ||
|
|
3336e6cdde | ||
|
|
4ec81b0669 | ||
|
|
d10123295c | ||
|
|
0929593efc | ||
|
|
ace6eed653 | ||
|
|
a40731624a | ||
|
|
268672adb8 | ||
|
|
af20db4cf7 | ||
|
|
8a76e7ea25 | ||
|
|
d72db58b3f | ||
|
|
975043d439 | ||
|
|
40b5ee391d | ||
|
|
e87e678d0f | ||
|
|
d098a9ddc2 | ||
|
|
7145ffaf28 | ||
|
|
d4afc3ecde | ||
|
|
1ecc49f9b7 | ||
|
|
7ffd46aee9 | ||
|
|
afd6570ced | ||
|
|
49c099a03c | ||
|
|
851fa09e0c | ||
|
|
b0c8426d0f | ||
|
|
9384d661c1 | ||
|
|
a06e0a325b | ||
|
|
a8c31d838f | ||
|
|
46cf48e012 | ||
|
|
bfa9d65314 | ||
|
|
aa7936100e | ||
|
|
b20ef104b9 | ||
|
|
53b99a650c | ||
|
|
2025d6ad2d | ||
|
|
c7cbe50876 | ||
|
|
267d822771 | ||
|
|
786d638ad0 | ||
|
|
89997ad8d4 | ||
|
|
036ab282e0 | ||
|
|
e9df213d0a | ||
|
|
150aab3530 | ||
|
|
96607ef753 | ||
|
|
075ddf104b | ||
|
|
671ca5c94f | ||
|
|
e7ed7c0765 | ||
|
|
92db8349dc | ||
|
|
ea3f6cf4a0 | ||
|
|
dd191493c0 | ||
|
|
2c08b82fef | ||
|
|
f7c5315599 | ||
|
|
ad6e458636 | ||
|
|
f04e763667 | ||
|
|
d545dc0d02 | ||
|
|
f895dfe341 | ||
|
|
c5bea40e7d | ||
|
|
e08052d7d6 | ||
|
|
78a7d15f3e | ||
|
|
b2e2cfb48d | ||
|
|
f694e42c78 | ||
|
|
8e52d8a272 | ||
|
|
1a6843ef2c | ||
|
|
4b9fa9a79e | ||
|
|
c15a8b52d2 | ||
|
|
bd36ca821d | ||
|
|
d4e6817232 | ||
|
|
096b54305d | ||
|
|
8b52561a31 | ||
|
|
b1e8001ae8 | ||
|
|
8aba480148 | ||
|
|
429ff738f9 | ||
|
|
ae2736d393 | ||
|
|
fc28fbc662 | ||
|
|
4f37f29ae8 | ||
|
|
c4da670a7c | ||
|
|
57dca33c2b | ||
|
|
4a1419af0e | ||
|
|
25c61590d1 | ||
|
|
f6925953ad | ||
|
|
e1b0e07f3c | ||
|
|
b2d16f69da | ||
|
|
a60772a81e | ||
|
|
6151ebf716 | ||
|
|
cccb8d6d19 | ||
|
|
a2c7c38a3e | ||
|
|
b51d34e893 | ||
|
|
79a62cd74c | ||
|
|
18c669ae3e | ||
|
|
8474c921ec | ||
|
|
7c7c57c64e | ||
|
|
f7e8412b4b | ||
|
|
0d3be917b2 | ||
|
|
5c85ba84db | ||
|
|
07d11f02d8 | ||
|
|
fce30e6ae5 | ||
|
|
24195dac81 | ||
|
|
830fe03898 | ||
|
|
4690aae197 | ||
|
|
b82dca89b3 | ||
|
|
dce79a621a | ||
|
|
d6f00a5d2d | ||
|
|
545b75a091 | ||
|
|
979daca221 | ||
|
|
fb2fed7c28 | ||
|
|
0ec71750b7 | ||
|
|
51f7858b78 | ||
|
|
ab83b872a2 | ||
|
|
879adb7458 | ||
|
|
39cbd607ef | ||
|
|
7478cdf4a4 | ||
|
|
b75a8d5260 | ||
|
|
120c694a42 | ||
|
|
569293e577 | ||
|
|
4f0f2499be | ||
|
|
d34dd0c603 | ||
|
|
b6c645b701 | ||
|
|
0c28bb7dcf | ||
|
|
2bb303e709 | ||
|
|
cc65feb392 | ||
|
|
c12b9ee3e3 | ||
|
|
d863c971c2 | ||
|
|
3ccdf45ed1 | ||
|
|
efa5c5db7b | ||
|
|
d73cf9fcff | ||
|
|
93dafc82eb | ||
|
|
87142b06c3 | ||
|
|
3075616b03 | ||
|
|
019898dfc3 | ||
|
|
ae838b9392 | ||
|
|
4d9a30b7c7 | ||
|
|
ea82773157 | ||
|
|
8289da1415 | ||
|
|
19eb6334b7 | ||
|
|
e992be1bfb | ||
|
|
7e216d198e | ||
|
|
a89d50e74d | ||
|
|
05dc13c922 | ||
|
|
1de4dd1bfe | ||
|
|
72aa87128e | ||
|
|
8f91576f85 | ||
|
|
4019c49fff | ||
|
|
5f83c92829 | ||
|
|
4c9cda7e40 | ||
|
|
01f7b1c9a6 | ||
|
|
1a30edc55f | ||
|
|
49bccffd7c | ||
|
|
526157a514 | ||
|
|
d025ba63e1 | ||
|
|
662515ce2e | ||
|
|
c55ff4ad5e | ||
|
|
666c0f3582 | ||
|
|
0c00760ae0 | ||
|
|
2146b35e5a | ||
|
|
44d10a355e | ||
|
|
5037c4e00e | ||
|
|
e4ecfc4ee7 | ||
|
|
ae6be1db3b | ||
|
|
d06eee99ba | ||
|
|
8349c8a5b8 | ||
|
|
2df7484649 | ||
|
|
1bb97cae39 | ||
|
|
f5ac3ff7b0 | ||
|
|
f6eba3edae | ||
|
|
781410ea04 | ||
|
|
c0d9712beb | ||
|
|
0672878920 | ||
|
|
b0cdac59f0 | ||
|
|
4b6a83dd82 | ||
|
|
25ae7b97aa | ||
|
|
afbde49fa2 | ||
|
|
befda9baaa | ||
|
|
502c7eb388 | ||
|
|
ad2a18f929 | ||
|
|
830eb86a0f | ||
|
|
e5413cebdc | ||
|
|
1a75951840 | ||
|
|
08e36aca98 | ||
|
|
aabbfd624a | ||
|
|
2f836d779a | ||
|
|
d7f848f8cd | ||
|
|
6f7f980563 | ||
|
|
e2515fc4bf | ||
|
|
d06a7bb7a2 | ||
|
|
dbdfdac94b | ||
|
|
3b2a0cfd66 | ||
|
|
5b652ae51f | ||
|
|
9e8a2b8296 | ||
|
|
e6787c5146 | ||
|
|
d8552915f7 | ||
|
|
61d9dea487 | ||
|
|
02d8f679b5 | ||
|
|
544828d9fb | ||
|
|
ca726d579e | ||
|
|
8257fb5e11 | ||
|
|
0d287e6d59 | ||
|
|
4d9dc66a96 | ||
|
|
868d4e05f7 | ||
|
|
a3bf39d86b | ||
|
|
d76795e0ae | ||
|
|
a2e075ee54 | ||
|
|
2df2a0971a | ||
|
|
158e23bd5e | ||
|
|
467402ef73 | ||
|
|
f78719afc0 | ||
|
|
e6513702d6 | ||
|
|
aeddf7014c | ||
|
|
1613f49c16 | ||
|
|
57a833c2fb | ||
|
|
6de53343a4 | ||
|
|
7bb4b09308 | ||
|
|
68020fa7d4 | ||
|
|
b94aba0301 | ||
|
|
0316009a9c | ||
|
|
820f7f0ef2 | ||
|
|
6d105ad3e7 | ||
|
|
f043a5f340 | ||
|
|
73d6f95d2e | ||
|
|
fb48070388 | ||
|
|
fa7697fc40 | ||
|
|
b46a5c0bda | ||
|
|
1072c310ad | ||
|
|
d5448b59a2 | ||
|
|
78317e6126 | ||
|
|
5a58f9c71a | ||
|
|
06b8dd61c7 | ||
|
|
a81b5778a0 | ||
|
|
a7188c4884 | ||
|
|
0bf0d48a02 | ||
|
|
dc5cd196ed | ||
|
|
f8f9bf228b | ||
|
|
d0dc1ea132 | ||
|
|
ff9fad6a2c | ||
|
|
76dbdb59ce | ||
|
|
0013402962 | ||
|
|
1ef7ae7079 | ||
|
|
07a39d0da8 | ||
|
|
b8bfb30c56 | ||
|
|
00342ddaae | ||
|
|
fb40c0b9de | ||
|
|
5d9506eb12 | ||
|
|
080fe8c3c4 | ||
|
|
48745d7380 | ||
|
|
41b50d67af | ||
|
|
b65dffca9d | ||
|
|
66bdfcf877 | ||
|
|
b0082c92c5 | ||
|
|
fdd1c01ac3 | ||
|
|
1ffdd9fd99 | ||
|
|
f64ad2db9f | ||
|
|
7bfe9bf914 | ||
|
|
214f3bb9b5 | ||
|
|
3f51149883 | ||
|
|
2c368953f9 | ||
|
|
9d5454e5ce | ||
|
|
631e4d9eef | ||
|
|
957583071d | ||
|
|
c942331117 | ||
|
|
710a55dc2d | ||
|
|
4bbb4b9a19 | ||
|
|
a2e5dae27f | ||
|
|
d5645b8a7b | ||
|
|
a9f9946a39 | ||
|
|
561deacce4 | ||
|
|
e528e35e06 | ||
|
|
af39d6a6ee | ||
|
|
7a21c02476 | ||
|
|
557e5710cd | ||
|
|
fa52255d04 | ||
|
|
e16622afcc | ||
|
|
f2468f0b3d | ||
|
|
30c9231df6 | ||
|
|
7532aadaf8 | ||
|
|
3d226246b9 | ||
|
|
d6c852a082 | ||
|
|
07a27e913c | ||
|
|
092d152bdc | ||
|
|
8b756d221b | ||
|
|
f33d684dce | ||
|
|
56e41309b1 | ||
|
|
91b24433b9 | ||
|
|
9050937900 | ||
|
|
2e6b90d4d5 | ||
|
|
146b2589e2 | ||
|
|
abd07e1525 | ||
|
|
541da5c0c9 | ||
|
|
21f642ad0c | ||
|
|
0d084d380d | ||
|
|
0fe158d080 | ||
|
|
0cc64c6a8d | ||
|
|
cd684996e1 | ||
|
|
0350e6bbf4 | ||
|
|
4fe5972d89 | ||
|
|
27c8efc672 | ||
|
|
aef0faf79c | ||
|
|
ea7d1dd91e | ||
|
|
ea2b57ec4b | ||
|
|
949f5eccd7 | ||
|
|
e525d89e43 | ||
|
|
6498ce3c4f | ||
|
|
cbf30c599b | ||
|
|
54c406f83d | ||
|
|
7b2957ab41 | ||
|
|
e22fccf5b1 | ||
|
|
ce8b32f022 | ||
|
|
0d0aef3dea | ||
|
|
386da22f6e | ||
|
|
f76b514892 | ||
|
|
77dc959e4a | ||
|
|
a99151441c | ||
|
|
852b0a97fe | ||
|
|
38843c25fb | ||
|
|
ce2750ba60 | ||
|
|
1d3dbddaef | ||
|
|
d8177daada | ||
|
|
3cbcd779eb | ||
|
|
33fc36a2d4 | ||
|
|
c06146110d | ||
|
|
1802aab683 | ||
|
|
49fe47f1f8 | ||
|
|
a13c9d0761 | ||
|
|
3d8479355c | ||
|
|
86c702861e | ||
|
|
47ec13eef4 | ||
|
|
d8cd0d867c | ||
|
|
d5ede6b1bb | ||
|
|
fd931564aa | ||
|
|
6b19178a13 | ||
|
|
64acd6c1e4 | ||
|
|
560914bebe | ||
|
|
2edec90dfb | ||
|
|
10c1305eae | ||
|
|
852c98f004 | ||
|
|
292f771eb1 | ||
|
|
1acc771edc | ||
|
|
ee61d0dcfa | ||
|
|
e5f2073de2 | ||
|
|
816be9e9bd | ||
|
|
2107af1f0f | ||
|
|
3bb85b4bda | ||
|
|
e86a3e9d09 | ||
|
|
957426c27f | ||
|
|
8bc90a19d2 | ||
|
|
668144cf2a | ||
|
|
c5ed056601 | ||
|
|
ea9d415b92 | ||
|
|
c181204700 | ||
|
|
ca78cb1a3f | ||
|
|
fdafa0933f | ||
|
|
ae92813169 | ||
|
|
8a248dc787 | ||
|
|
f90f611a6d | ||
|
|
1c0d148607 | ||
|
|
95c8b7ae60 | ||
|
|
25d013b768 | ||
|
|
9de8c4d8ac | ||
|
|
7e4ffe6a7d | ||
|
|
b90372a226 | ||
|
|
9adbfcac0f | ||
|
|
d1eb7743ad | ||
|
|
fc3352bcb1 | ||
|
|
9b3360d932 | ||
|
|
3784bfac77 | ||
|
|
54754cd177 | ||
|
|
c48034e420 | ||
|
|
3299279c89 | ||
|
|
a6c3ebc467 | ||
|
|
9f510f61c7 | ||
|
|
3ae48b8753 | ||
|
|
f41725b8dc | ||
|
|
115df3aedd | ||
|
|
3c136ad0ba | ||
|
|
48ee3d255d | ||
|
|
b05f867800 | ||
|
|
55b790a0d4 | ||
|
|
57f6c9dfd9 | ||
|
|
2f9c95afd0 | ||
|
|
4fe1457d96 | ||
|
|
2589a27cb5 | ||
|
|
8704e14fd7 | ||
|
|
2b17dbe390 | ||
|
|
919012608a | ||
|
|
5675a5b035 | ||
|
|
6724752980 | ||
|
|
0e078a9c60 | ||
|
|
c0b1dfc55a | ||
|
|
3d201f7042 | ||
|
|
f1a5aae30a | ||
|
|
9142da2b70 | ||
|
|
022c76bf45 | ||
|
|
bc6db72df0 | ||
|
|
d512aa5b21 | ||
|
|
7cdf7a21fe | ||
|
|
9a5a6e1ce2 | ||
|
|
5a258d2830 | ||
|
|
96ee32f8ed | ||
|
|
a667a94c8e | ||
|
|
d0572a2a0d | ||
|
|
47eea79b60 | ||
|
|
03b37235b3 | ||
|
|
6969fbb1e7 | ||
|
|
ccc59aa61b | ||
|
|
c658865907 | ||
|
|
a13d51e09a | ||
|
|
f827337259 | ||
|
|
b83c76f728 | ||
|
|
5666fd4999 | ||
|
|
5930e3c350 | ||
|
|
4630e5b3a4 | ||
|
|
f16990edcb | ||
|
|
13896589c2 | ||
|
|
8b5cf5309a | ||
|
|
baedba0d5b | ||
|
|
9f926ef71e | ||
|
|
18a3f8bb68 | ||
|
|
623b7ada11 | ||
|
|
6b6d52e2fd | ||
|
|
fc91b6b135 | ||
|
|
f9c33453f2 | ||
|
|
ad4650f408 | ||
|
|
8ca08a0f14 | ||
|
|
792fdef95d | ||
|
|
457514a2c8 | ||
|
|
027d080c55 | ||
|
|
bf8f059c25 | ||
|
|
a73165353f | ||
|
|
613b5a7703 | ||
|
|
988791f18d | ||
|
|
1fb608220f | ||
|
|
56b87a2141 | ||
|
|
3aee9bddd4 | ||
|
|
65f97edbc5 | ||
|
|
d393230add | ||
|
|
75d2b0fb69 | ||
|
|
0cc9b0b0a3 | ||
|
|
9b6c125233 | ||
|
|
1f2b331bf6 | ||
|
|
ec73426bbc | ||
|
|
770d8506c5 | ||
|
|
10cd15a088 | ||
|
|
481e19b1ec | ||
|
|
e326e3a273 | ||
|
|
d747b1d96a | ||
|
|
f64cb3ad9a | ||
|
|
c4ea5a8256 | ||
|
|
fa8d43bbc9 | ||
|
|
77f31fd86c | ||
|
|
18fe2a1737 | ||
|
|
e816f6110d | ||
|
|
632887ddd2 | ||
|
|
c53a6a7c04 | ||
|
|
532a4bc140 | ||
|
|
88086f5ba9 | ||
|
|
0be39d43a2 | ||
|
|
e9abe273c7 | ||
|
|
775ebd6e94 | ||
|
|
b86201ea9b | ||
|
|
e3ccde31d8 | ||
|
|
32d1d7264c | ||
|
|
27d9718d4f | ||
|
|
f812460164 | ||
|
|
da8ea84397 | ||
|
|
52e47a28c4 | ||
|
|
b9b8fc66b1 | ||
|
|
c026d44cd3 | ||
|
|
eb75cd5ae8 | ||
|
|
7e10487926 | ||
|
|
ae921bf266 | ||
|
|
ca62d2aa07 | ||
|
|
2ba093c640 | ||
|
|
e3f388692f | ||
|
|
4fc805abbf | ||
|
|
cd81482b6b | ||
|
|
3972e34dde | ||
|
|
01b24959c8 | ||
|
|
40908589b9 | ||
|
|
774be56bde | ||
|
|
68f19fdbcf | ||
|
|
50aab01a2e | ||
|
|
ead0158ef9 | ||
|
|
d06a74e7a2 | ||
|
|
8fab335b9d | ||
|
|
25b22b4f93 | ||
|
|
0061690631 | ||
|
|
26ad53ec50 | ||
|
|
4aa2d9097f | ||
|
|
82f8e78ec8 | ||
|
|
f91910e84f | ||
|
|
2da128678a | ||
|
|
18a382b07a | ||
|
|
83a4f56679 | ||
|
|
ffad9cb9a9 | ||
|
|
6a63956b71 | ||
|
|
32a1d91faf | ||
|
|
634d9d1a40 | ||
|
|
f9adcfeed1 | ||
|
|
02ef633529 | ||
|
|
f3b1ef02e3 | ||
|
|
2d3a9b605a | ||
|
|
718a40d742 | ||
|
|
650d47991e | ||
|
|
6ec76409ef | ||
|
|
136c8cfcd2 | ||
|
|
bceb7b5809 | ||
|
|
a342a7d638 | ||
|
|
956f4659c7 | ||
|
|
593a7b060c | ||
|
|
81ce3a28a1 | ||
|
|
32070a37f7 | ||
|
|
95c04eb085 | ||
|
|
c2602fe6a0 | ||
|
|
9ce5164a7e | ||
|
|
ee79bc5501 | ||
|
|
3dc70be516 | ||
|
|
e44c3899e8 | ||
|
|
e7885a405e | ||
|
|
c6b60a2620 | ||
|
|
9b6c44757a | ||
|
|
0cbc4c0cc5 | ||
|
|
e83cfe6cab | ||
|
|
912ea94828 | ||
|
|
6417073a82 | ||
|
|
994194452d | ||
|
|
c716c16746 | ||
|
|
f188563052 | ||
|
|
07e8b4334b | ||
|
|
c0e955dc1f | ||
|
|
2927348a6c | ||
|
|
96c8e0f415 | ||
|
|
21f05c9d8a | ||
|
|
9b1c66ba15 | ||
|
|
8b9b11f77f | ||
|
|
9c846bd2c9 | ||
|
|
7372bf37c2 | ||
|
|
0a5a301573 | ||
|
|
462a5b941e | ||
|
|
21fd20ea5b | ||
|
|
a0c7b33ff1 | ||
|
|
b762a5028b | ||
|
|
2f83ba7f5c | ||
|
|
01d972f015 | ||
|
|
0435140bb5 | ||
|
|
ff84d788a6 | ||
|
|
4c2f330e51 | ||
|
|
bd0f47c325 | ||
|
|
13fbcb9ba8 | ||
|
|
9774095df4 | ||
|
|
f231849a42 | ||
|
|
c7d059a58f | ||
|
|
c420ad1a16 | ||
|
|
99aec4ad15 | ||
|
|
1be91961d6 | ||
|
|
9f51e23206 | ||
|
|
ebf4435af4 | ||
|
|
f4bf8fd998 | ||
|
|
5516435619 | ||
|
|
315cbaec47 | ||
|
|
5c24254d84 | ||
|
|
fdf08ed51d | ||
|
|
42fb6ffa0d | ||
|
|
0c4750781a | ||
|
|
69eb8faf67 | ||
|
|
0ab4f01d5d | ||
|
|
6361b7e57d | ||
|
|
961331c832 | ||
|
|
8cdb4c0831 | ||
|
|
6bd8f99be3 | ||
|
|
4b71b4f80a | ||
|
|
5712190dab | ||
|
|
af636f74fc | ||
|
|
0cfdacdd28 | ||
|
|
68535bfcaa | ||
|
|
3eb0857906 | ||
|
|
0f3716b8dd | ||
|
|
dbe2f7eefa | ||
|
|
3497212b95 | ||
|
|
2ae864f4d3 | ||
|
|
200eb26b78 | ||
|
|
e9c93ab3a0 | ||
|
|
e70221f6dd | ||
|
|
c4d72eef39 | ||
|
|
42ae5e90b0 | ||
|
|
fe92ce557f | ||
|
|
bf81565e93 | ||
|
|
981dec098a | ||
|
|
d65506e420 | ||
|
|
73d009666e | ||
|
|
a9c4ccdf48 | ||
|
|
035d7fed77 | ||
|
|
0374ec5e4a | ||
|
|
0a92e64498 | ||
|
|
0b6194cfc9 | ||
|
|
044fb30b1b | ||
|
|
727b47dba5 | ||
|
|
ab19e6ffbd | ||
|
|
f5410c5712 | ||
|
|
b79a6f6b32 | ||
|
|
b672434e83 | ||
|
|
9b087dc55d | ||
|
|
8d10cafc99 | ||
|
|
6e1eedc1ab | ||
|
|
f5ce75e962 | ||
|
|
0d643a3ece | ||
|
|
9632fc5f1f | ||
|
|
84bb3ee3de | ||
|
|
83b20a90e6 | ||
|
|
f89f1e2346 | ||
|
|
cc6b0c328f | ||
|
|
e17bcd6a01 | ||
|
|
6357c17f8a | ||
|
|
add3fd9fb3 | ||
|
|
98e6303765 | ||
|
|
0e1e399788 | ||
|
|
d84a36b8ee | ||
|
|
db40f154c5 | ||
|
|
e714d44a0e | ||
|
|
6eb604585b | ||
|
|
7555d43418 | ||
|
|
3ef67cab69 | ||
|
|
72686b3ef8 | ||
|
|
990562dd71 | ||
|
|
2239ca6372 | ||
|
|
f174d1b2b4 | ||
|
|
a04e7d5612 | ||
|
|
16778ea16c | ||
|
|
a606d9d85c | ||
|
|
8d18649323 | ||
|
|
c02d603a7a | ||
|
|
8e4b35eb07 | ||
|
|
fda9357b4b | ||
|
|
4517b55f76 | ||
|
|
f014339dbc | ||
|
|
9f8fce72d3 | ||
|
|
834e4f175b | ||
|
|
bba52e99e0 | ||
|
|
42d350f87f | ||
|
|
4339042078 | ||
|
|
946bfa1bfd | ||
|
|
f86291c587 | ||
|
|
da96b23441 | ||
|
|
d2ae9cf809 | ||
|
|
beed2e0b8f | ||
|
|
92e7cec198 | ||
|
|
eda6770e11 | ||
|
|
7cc3e23e9a | ||
|
|
7bf263fdfa | ||
|
|
43757a247e | ||
|
|
1e8621d9d4 | ||
|
|
0940abe98c | ||
|
|
4a71564d03 | ||
|
|
9397bd57c4 | ||
|
|
85a668c202 | ||
|
|
90372171b2 | ||
|
|
2523088b4c | ||
|
|
f5c270347c | ||
|
|
032b254e93 | ||
|
|
a21cc32be9 | ||
|
|
06f832bfae | ||
|
|
79423e4c60 | ||
|
|
c92f662994 | ||
|
|
eeed998c7c | ||
|
|
8ac027af70 | ||
|
|
15b865e550 | ||
|
|
1e7e66c424 | ||
|
|
0524447c78 | ||
|
|
b6f1b67b24 | ||
|
|
715d94967e | ||
|
|
a21f79ac6a | ||
|
|
986caa857e | ||
|
|
1a14860b62 | ||
|
|
d144e9c91c | ||
|
|
9d740e1e37 | ||
|
|
054e2337ff | ||
|
|
71488313e1 | ||
|
|
a44f3c379f | ||
|
|
e1125a38da | ||
|
|
f3d5cb315e | ||
|
|
d3f99105b2 | ||
|
|
7f49f0c6fa | ||
|
|
ceb298ca0b | ||
|
|
0aaa77a5ea | ||
|
|
79d4925761 | ||
|
|
7ea12e97ec | ||
|
|
8521d5cd1b | ||
|
|
17177f87aa | ||
|
|
24c71e49c7 | ||
|
|
ac06fa8f96 | ||
|
|
eda134a18c | ||
|
|
852013cd63 | ||
|
|
5b163d7843 | ||
|
|
806cea4b33 | ||
|
|
952639a72e | ||
|
|
e4e428f84a | ||
|
|
9a577adf5f | ||
|
|
e3c68b485d | ||
|
|
75a4d2901f | ||
|
|
bbdcef62e4 | ||
|
|
118ae8e87d | ||
|
|
40a6a9e1c7 | ||
|
|
22221a0f28 | ||
|
|
c39f4c1b7d | ||
|
|
082b04a143 | ||
|
|
4f683cac8b | ||
|
|
0d2b660ed1 | ||
|
|
f9fe396d1f | ||
|
|
a4f4b9367f | ||
|
|
09a84550f4 | ||
|
|
9e05f7604d | ||
|
|
e5982faf35 | ||
|
|
7f863abb06 | ||
|
|
b328d098a1 | ||
|
|
0dd3c2cb5a | ||
|
|
9d9cbdffd5 | ||
|
|
8d43590657 | ||
|
|
6783069f95 | ||
|
|
b33b3a7919 | ||
|
|
b0bf80d8b7 | ||
|
|
abcd27184d | ||
|
|
5de2c0c512 | ||
|
|
bd25294096 | ||
|
|
a8bae56b2c | ||
|
|
d80678dfeb | ||
|
|
a4f9518d1e | ||
|
|
91692f362f | ||
|
|
6815f3305f | ||
|
|
0cc3340bd6 | ||
|
|
8da18984d2 | ||
|
|
056afa572e | ||
|
|
9f5183b36f | ||
|
|
0d81681af5 | ||
|
|
4b1554db54 | ||
|
|
c58289dd47 | ||
|
|
cfd67bb1fc | ||
|
|
9a777f3ce5 | ||
|
|
b8efed9eaf | ||
|
|
cd7d2163b9 | ||
|
|
59c85a486f | ||
|
|
8bc349b68c | ||
|
|
b12cac7b30 | ||
|
|
bd85d1d7ca | ||
|
|
9a88426ff7 | ||
|
|
d0bf3d6fa1 | ||
|
|
bc2c7be45d | ||
|
|
74a7dc5eb9 | ||
|
|
3db04da20a | ||
|
|
d0cba1aff2 | ||
|
|
4ad234ad75 | ||
|
|
e6717b37ce | ||
|
|
15116ca384 | ||
|
|
446dd6abe5 | ||
|
|
ff254d4fdf | ||
|
|
eaa5e6f5a1 | ||
|
|
b90f51224c | ||
|
|
475bef1d78 | ||
|
|
dd9095bfba | ||
|
|
50125166a6 | ||
|
|
47e321f57d | ||
|
|
144751bdce | ||
|
|
6cc3676f5e | ||
|
|
6ab96e2787 | ||
|
|
659c481c83 | ||
|
|
a18e1854ab | ||
|
|
6c67dc1266 | ||
|
|
0c581c520f | ||
|
|
c6c18696c0 | ||
|
|
4b1c55b876 | ||
|
|
5ab090f28d | ||
|
|
8a5bd7571e | ||
|
|
3cb0cc9a3c | ||
|
|
ff93c21269 | ||
|
|
0512e54df5 | ||
|
|
cec1eb5608 | ||
|
|
1c6ebd3f6a | ||
|
|
16f7a8e9d2 | ||
|
|
889c53dc1b | ||
|
|
f4d0dfd0da | ||
|
|
aee5d46dfa | ||
|
|
6286b0b275 | ||
|
|
5223a89bf1 | ||
|
|
5b11dbc085 | ||
|
|
df1f8b8bb4 | ||
|
|
ffa7256e5a | ||
|
|
bbf84185cc | ||
|
|
901c23f295 | ||
|
|
1c8d368d3b | ||
|
|
37ebae20d7 | ||
|
|
e25f0c6ae2 | ||
|
|
484b480076 | ||
|
|
926497ba77 | ||
|
|
ddd9f2259c | ||
|
|
d6546a38c0 | ||
|
|
d171048004 | ||
|
|
4aebba0a0c | ||
|
|
8afb6006ce | ||
|
|
d117eb249e | ||
|
|
768d14088a | ||
|
|
86f16bfc94 | ||
|
|
8fa6b76bf9 | ||
|
|
19af1a0cc8 | ||
|
|
409d27e3df | ||
|
|
d47abd4f83 | ||
|
|
e6c4a6cf69 | ||
|
|
7c80af85e3 | ||
|
|
6983f57459 | ||
|
|
adeeaa6e27 | ||
|
|
075e7cf5d8 | ||
|
|
98c4ee6e74 | ||
|
|
87f9a077ac | ||
|
|
bc26d3ba7b | ||
|
|
daaea591e4 | ||
|
|
175d66ad72 | ||
|
|
c444cbf623 | ||
|
|
c54f398063 | ||
|
|
2d6db1583b | ||
|
|
b3beb92557 | ||
|
|
0f8304674f | ||
|
|
3b3daf0e25 | ||
|
|
28e18332a0 | ||
|
|
dcc4764914 | ||
|
|
ee4ace1146 | ||
|
|
1faffadcab | ||
|
|
2da7afc081 | ||
|
|
e5b341c63e | ||
|
|
a544888f16 | ||
|
|
57ad1d5366 | ||
|
|
42d66d1136 | ||
|
|
999cc9c651 | ||
|
|
9537051590 | ||
|
|
827372633d | ||
|
|
dcf0b15b2c | ||
|
|
c93bc0e457 | ||
|
|
1460a15942 | ||
|
|
15a07a4a18 | ||
|
|
e07a203d56 | ||
|
|
cead92b2c7 | ||
|
|
8d4ab2d7fb | ||
|
|
9bd2057237 | ||
|
|
5ec5f1aa93 | ||
|
|
5e10c9d416 | ||
|
|
881491d151 | ||
|
|
863159a5fe | ||
|
|
849943a0de | ||
|
|
b5abc23c9d | ||
|
|
c2b03a3fdc | ||
|
|
4e1d999838 | ||
|
|
4af971776f | ||
|
|
86d2788232 | ||
|
|
5654e3120d | ||
|
|
b4e7928622 | ||
|
|
25125f5a9b | ||
|
|
5d4b8a43e3 | ||
|
|
557cb1c532 | ||
|
|
5594395ac1 | ||
|
|
81b593c031 | ||
|
|
2a1ddf2573 | ||
|
|
fdb8da5767 | ||
|
|
738aa26a20 | ||
|
|
5e0ba2f4af | ||
|
|
91b2d1a9bf | ||
|
|
e636ceb317 | ||
|
|
2eeb230694 | ||
|
|
70cc6d07b0 | ||
|
|
4d5c2c83fd | ||
|
|
cf91bcbd49 | ||
|
|
18b19e964a | ||
|
|
bf1ace4791 | ||
|
|
dcd56a2d87 | ||
|
|
67c1db0fcc | ||
|
|
6027fff543 | ||
|
|
0c3c9fce2a | ||
|
|
78c2f82adf | ||
|
|
2d3b33bd9c | ||
|
|
dd6ae80817 | ||
|
|
304bfb5a40 | ||
|
|
58c1718d01 | ||
|
|
29fe5dab06 | ||
|
|
f9024e5500 | ||
|
|
25b77d1430 | ||
|
|
f9cfc8a2b8 | ||
|
|
8e74870857 | ||
|
|
b32e4005dd | ||
|
|
7094f3c848 | ||
|
|
c8adfbce96 | ||
|
|
ff94dd4d75 | ||
|
|
d61bb66418 | ||
|
|
b0f62f25e6 | ||
|
|
bdbc9b865b | ||
|
|
21c97571e0 | ||
|
|
8e92be9037 | ||
|
|
f6428b8857 | ||
|
|
db76ffe46a | ||
|
|
cb3b43cc48 | ||
|
|
587c63fc92 | ||
|
|
97fa8057ba | ||
|
|
d792956056 | ||
|
|
6a2bb7b01f | ||
|
|
edbced6642 | ||
|
|
8c0477f6bd | ||
|
|
4e00c4b015 | ||
|
|
42f0364319 | ||
|
|
a687aeb789 | ||
|
|
6ececea004 | ||
|
|
6570d23512 | ||
|
|
7ec3ab5a17 | ||
|
|
6af015cc05 | ||
|
|
7938e02e78 | ||
|
|
bac4bb8c8f | ||
|
|
5ac1c32652 | ||
|
|
dec5a2aaaf | ||
|
|
7b1c60c24f | ||
|
|
8b8d990852 | ||
|
|
6583cc0b5d | ||
|
|
5c3ae425ae | ||
|
|
744b1b2037 | ||
|
|
a313ca8a26 | ||
|
|
87204df3ee | ||
|
|
bc70c08820 | ||
|
|
2c2828617f | ||
|
|
70c6cd2e87 | ||
|
|
a8a629c5ef | ||
|
|
8e6dd98a5a | ||
|
|
39b8627a60 | ||
|
|
a451ad895c | ||
|
|
d13b69c36f | ||
|
|
2af988d71f | ||
|
|
63318f9b67 | ||
|
|
7f032edd6f | ||
|
|
aff5b8bed6 | ||
|
|
22a50eec60 | ||
|
|
d64f603e08 | ||
|
|
3d2c094056 | ||
|
|
64e99f613e | ||
|
|
51b4078288 | ||
|
|
db8d099fcc | ||
|
|
002be46915 | ||
|
|
9fa2691b02 | ||
|
|
df418c5a7d | ||
|
|
6686584003 | ||
|
|
78c8c57649 | ||
|
|
ca65fd31e5 | ||
|
|
e2109f2f56 | ||
|
|
6b63cd7a46 | ||
|
|
e19c857d74 | ||
|
|
b18f418c61 | ||
|
|
12ee38476c | ||
|
|
48c8357ff7 | ||
|
|
a0702559f3 | ||
|
|
55db91e53e | ||
|
|
a333fa3722 | ||
|
|
5284750c6a | ||
|
|
9c616fd03b | ||
|
|
d4bee41103 | ||
|
|
2e586c4403 | ||
|
|
129f21e3a9 | ||
|
|
435f15a450 | ||
|
|
3eac8cb6ad | ||
|
|
ea96bf2675 | ||
|
|
e4c3664cc6 | ||
|
|
664cd6a3a0 | ||
|
|
c26a9bd123 | ||
|
|
5008573aa5 | ||
|
|
395f7193ea | ||
|
|
775e17a726 | ||
|
|
900ec8db6a | ||
|
|
e23a7c213c | ||
|
|
96513e4967 | ||
|
|
b64df565a4 | ||
|
|
382e27e1e4 | ||
|
|
0dd95e736d | ||
|
|
0ae6a33971 | ||
|
|
380c9ab113 | ||
|
|
1028ade80d | ||
|
|
a8e34381ef | ||
|
|
5f5987cef2 | ||
|
|
430538ea7e | ||
|
|
ee966d1198 | ||
|
|
076363ac87 | ||
|
|
327442f6fe | ||
|
|
c03400ccbc | ||
|
|
a5ad45ff30 | ||
|
|
3161e23285 | ||
|
|
e82ee227a5 | ||
|
|
f8a859620d | ||
|
|
30107db81e | ||
|
|
05f7a15115 | ||
|
|
305e2642ba | ||
|
|
cb95059c3e | ||
|
|
20aa2384ea | ||
|
|
c5574d3ae0 | ||
|
|
45b43e7772 | ||
|
|
a461c184be | ||
|
|
00e1cf7e9d | ||
|
|
86887f2ec1 | ||
|
|
bff0c2e6f3 | ||
|
|
fcaf1e49cb | ||
|
|
448fef980b | ||
|
|
7832b6cafd | ||
|
|
3a259d0001 | ||
|
|
11168efffa | ||
|
|
367da94e34 | ||
|
|
f8bce3cea0 | ||
|
|
daed19e79b | ||
|
|
0e565f00ff | ||
|
|
d4ab674b1c | ||
|
|
884abb54e6 | ||
|
|
026d3ef9ab | ||
|
|
0abf333168 | ||
|
|
a124c2a2b4 | ||
|
|
a43957a1fa | ||
|
|
d0f3e413c6 | ||
|
|
469d5945b2 | ||
|
|
c00228f960 | ||
|
|
ee28f4564b | ||
|
|
5a8d0071df | ||
|
|
4c7b86196c | ||
|
|
b946fd6a3b | ||
|
|
6f139641da | ||
|
|
c413be3ce0 | ||
|
|
19a804db91 | ||
|
|
f6d35822fb | ||
|
|
8f1f015f3d | ||
|
|
ed1b3ba608 | ||
|
|
f3831eb9c5 | ||
|
|
1ed2b2eb2e | ||
|
|
039f5ef8db | ||
|
|
be6b294087 | ||
|
|
0ab593b7a5 | ||
|
|
67c35e12ae | ||
|
|
7acc5e0858 | ||
|
|
0553cafbe9 | ||
|
|
9d78459d7d | ||
|
|
c0c5257ed8 | ||
|
|
a476e3cf19 | ||
|
|
4c777fba5c | ||
|
|
fe4497a4da | ||
|
|
8843e49ac8 | ||
|
|
a232839cfd | ||
|
|
5c483400e0 | ||
|
|
3a05a2b0ef | ||
|
|
26e90c99d3 | ||
|
|
fe59031fce | ||
|
|
56e326ab1b | ||
|
|
1a3af01b24 | ||
|
|
7954d7e4e9 | ||
|
|
7a0bac95a5 | ||
|
|
625486ade9 | ||
|
|
6a33f41fb4 | ||
|
|
38f722e0b6 | ||
|
|
9c773f48ee | ||
|
|
d142777fca | ||
|
|
2332595f2d | ||
|
|
cdb1003133 | ||
|
|
ca2dabe769 | ||
|
|
0c1817eb12 | ||
|
|
c0c8235e3d | ||
|
|
d868ff81bf | ||
|
|
16f64a90a8 | ||
|
|
8dae9babab | ||
|
|
d33cea6003 | ||
|
|
9870098457 | ||
|
|
4102c380d2 | ||
|
|
44204db2bb | ||
|
|
a87e58db93 | ||
|
|
082a43da35 | ||
|
|
ca35b113f0 | ||
|
|
f23e63decf | ||
|
|
c09b1e0d6e | ||
|
|
3b9f775f82 | ||
|
|
af122a76a4 | ||
|
|
5c89fa2d2b | ||
|
|
bbee3ae9cd | ||
|
|
e76dee8cbe | ||
|
|
dd4b130c7a | ||
|
|
639702ae1a | ||
|
|
9df4eac2f8 | ||
|
|
18b0cd4e99 | ||
|
|
371a14af87 | ||
|
|
fc85aae500 | ||
|
|
051a3a07c3 | ||
|
|
a4a8470064 | ||
|
|
5ba99ecb42 | ||
|
|
f67f09934e | ||
|
|
149ce3bccf | ||
|
|
fb580326b2 | ||
|
|
00a25f31b8 | ||
|
|
e535f94832 | ||
|
|
04169f6bcb | ||
|
|
4f3e353b75 | ||
|
|
c41dfa46aa | ||
|
|
ba9bc472e8 | ||
|
|
a7c18fc598 | ||
|
|
67169a2ffc | ||
|
|
2a9f362e15 | ||
|
|
80f027471c | ||
|
|
682c1692df | ||
|
|
da97d1e1eb | ||
|
|
979e39f588 | ||
|
|
4fb97b60a9 | ||
|
|
bc114dfefc | ||
|
|
29be8176c1 | ||
|
|
d322de8686 | ||
|
|
67c6e0179f | ||
|
|
e3f2966db3 | ||
|
|
9e53b3b7e6 | ||
|
|
8f186a16b3 | ||
|
|
532aa88dca | ||
|
|
9a3b21d77a | ||
|
|
b488cd8dff | ||
|
|
06faa368cc | ||
|
|
118b438519 | ||
|
|
a7a3b94caf | ||
|
|
a1c26a610c | ||
|
|
8f58f40b1a | ||
|
|
856a8c11aa | ||
|
|
7bab4d67e1 | ||
|
|
3a2514e937 | ||
|
|
23fc86fac1 | ||
|
|
3d6fd8a351 | ||
|
|
66b540988b | ||
|
|
3c51d82a1a | ||
|
|
d6c5eb121c | ||
|
|
b63501b1c7 | ||
|
|
25015a61ae | ||
|
|
c2d808b921 | ||
|
|
810238d0f9 | ||
|
|
bb16d1c613 | ||
|
|
b8cb17c0c5 | ||
|
|
f4c6870ee9 | ||
|
|
9ca3cd49b8 | ||
|
|
e6544b73db | ||
|
|
2e30cd31c2 | ||
|
|
e6078bd4f6 | ||
|
|
340efc3298 | ||
|
|
b0477394e6 | ||
|
|
699750762f | ||
|
|
ee3348d160 | ||
|
|
6dc2486ce0 | ||
|
|
724a0018b8 | ||
|
|
19e03e665e | ||
|
|
3b20c68a6f | ||
|
|
3712a90f90 | ||
|
|
98206446e6 | ||
|
|
6e62859d0e | ||
|
|
1e8f49e45a | ||
|
|
c188e23d06 | ||
|
|
8b5acefdfe | ||
|
|
cff957feaf | ||
|
|
4deb8fd626 | ||
|
|
1f1701f1d6 | ||
|
|
e6c99e0c6d | ||
|
|
e6c15b526a | ||
|
|
4de516b527 | ||
|
|
815a483d2c | ||
|
|
2816aeb6e9 | ||
|
|
f40e523764 | ||
|
|
8a424111f0 | ||
|
|
efeb29f47a | ||
|
|
7a81fde64e | ||
|
|
47922834f9 | ||
|
|
2d66790aab | ||
|
|
b7b4dc8f43 | ||
|
|
69960017d3 | ||
|
|
b1a4d51210 | ||
|
|
1d8fbf7aa9 | ||
|
|
2c0884ed46 | ||
|
|
4cda52caf7 | ||
|
|
9c54792341 | ||
|
|
56b947fb9e | ||
|
|
eb21ce24b6 | ||
|
|
2a6b0fd0ce | ||
|
|
47e622dee3 | ||
|
|
99125e9218 | ||
|
|
66918f0322 | ||
|
|
6634e6f8a5 | ||
|
|
525643cb17 | ||
|
|
b8a2c609cb | ||
|
|
968277477a | ||
|
|
4fbfb50380 | ||
|
|
d06b32c20b | ||
|
|
805412f812 | ||
|
|
de4b88013d | ||
|
|
525dc0cd7e | ||
|
|
8b6fc7f3ac | ||
|
|
8dd66fb942 | ||
|
|
7e5c69a107 | ||
|
|
c8357c7b84 | ||
|
|
f7170dc39a | ||
|
|
e4a95ab4c4 | ||
|
|
40dd3d5677 | ||
|
|
3aabfaf14b | ||
|
|
2cc0ae3d81 | ||
|
|
ab8a381ad9 | ||
|
|
ced6369b25 | ||
|
|
c545e03852 | ||
|
|
cf16983b34 | ||
|
|
0d4c28daf2 | ||
|
|
e39eceee28 | ||
|
|
ca29909bec | ||
|
|
869c329fbf | ||
|
|
c8b425116e | ||
|
|
fe2daa9327 | ||
|
|
aeaeb87fbb | ||
|
|
0a290d2e10 | ||
|
|
9863cbc991 | ||
|
|
91c50ae126 | ||
|
|
ef62bb49bc | ||
|
|
dae46ceb6d | ||
|
|
6b3919e8f7 | ||
|
|
ed89a70cbc | ||
|
|
20637fa358 | ||
|
|
1d8ec9abd9 | ||
|
|
d3f58c0e83 | ||
|
|
84474040c0 | ||
|
|
18d7f8ddfb | ||
|
|
ef63c5073a | ||
|
|
3fe4ae38b6 | ||
|
|
0b515395e8 | ||
|
|
22116314c5 | ||
|
|
35da950986 | ||
|
|
465219540c | ||
|
|
0e354dbf23 | ||
|
|
d1563ee55e | ||
|
|
49f4b1fd67 | ||
|
|
ba6d40cc22 | ||
|
|
dc15c9a7e4 | ||
|
|
27e22a84d3 | ||
|
|
33c3d587dd | ||
|
|
fa3a19d766 | ||
|
|
0d4add667f | ||
|
|
7f214f1343 | ||
|
|
e1ddf115e0 | ||
|
|
56f1d0548e | ||
|
|
38471d68d7 | ||
|
|
17a571f22a | ||
|
|
dd9c3fc8d6 | ||
|
|
a70e29127b | ||
|
|
6be2b6021b | ||
|
|
488147759a | ||
|
|
9a7d359626 | ||
|
|
0437d50a5c | ||
|
|
f49f151901 | ||
|
|
245e5d515a | ||
|
|
2b8c11c451 | ||
|
|
11d864f2b5 | ||
|
|
977b55bf32 | ||
|
|
b06be81f1e | ||
|
|
93313664f0 | ||
|
|
25cb2b0abf | ||
|
|
b841af3a48 | ||
|
|
709f43b83c | ||
|
|
aabc094dd9 | ||
|
|
58acc0a970 | ||
|
|
c874089f27 | ||
|
|
91b05e4789 | ||
|
|
1cc73a4077 | ||
|
|
4ac26d86f5 | ||
|
|
a693289867 | ||
|
|
010e5341dc | ||
|
|
51790e0bf9 | ||
|
|
fd80cbcae5 | ||
|
|
45bb6fa2ee | ||
|
|
40b67349d9 | ||
|
|
735cb74483 | ||
|
|
bc55e43def | ||
|
|
084d7e8355 | ||
|
|
22e60612ac | ||
|
|
b271c4be32 | ||
|
|
f26b3358ef | ||
|
|
3d6390a76a | ||
|
|
ff20928bec | ||
|
|
59387389a4 | ||
|
|
fb200c6d11 | ||
|
|
8418770bbf | ||
|
|
eaa7b04c3d | ||
|
|
6131ef23fc | ||
|
|
1467a3a7fd | ||
|
|
f5023aa846 | ||
|
|
d10fd8e738 | ||
|
|
8ca833f753 | ||
|
|
b002d8b446 | ||
|
|
f5e06cca54 | ||
|
|
642b877ab0 | ||
|
|
2a618a6600 | ||
|
|
fa48f1b2e0 | ||
|
|
69063e9dc5 | ||
|
|
c2bedc0210 | ||
|
|
103f5a65b6 | ||
|
|
e0f2c2f46f | ||
|
|
8ee3f2b2e6 | ||
|
|
7697a21003 | ||
|
|
40bf0741f0 | ||
|
|
d13c407846 | ||
|
|
43fea03996 | ||
|
|
87da58df69 | ||
|
|
72a453654e | ||
|
|
25c31c5250 | ||
|
|
fac1bccda1 | ||
|
|
2f465493f0 | ||
|
|
6633b07fb2 | ||
|
|
b285165818 | ||
|
|
e65971db47 | ||
|
|
5fd66d38bb | ||
|
|
15f33b45c7 | ||
|
|
17e66f1008 | ||
|
|
bcaf5e4c3d | ||
|
|
ea653bf5c3 | ||
|
|
6fd36d97f0 | ||
|
|
61bec243dc | ||
|
|
7d43856735 | ||
|
|
9f8e1b93f1 | ||
|
|
058b2ddfce | ||
|
|
7a59c7bc24 | ||
|
|
1637360952 | ||
|
|
38f4154d18 | ||
|
|
7ffbb93ba7 | ||
|
|
8004b6ce1d | ||
|
|
77ba760a94 | ||
|
|
12d045c631 | ||
|
|
97254a6672 | ||
|
|
8e7382b0c0 | ||
|
|
2282cb89b1 | ||
|
|
06929ee8f3 | ||
|
|
ec19381c4e | ||
|
|
2144ac57c4 | ||
|
|
7c79ee469e | ||
|
|
741e6b55b0 | ||
|
|
6f75116197 | ||
|
|
4a52392ce9 | ||
|
|
45b355508d | ||
|
|
1cfa5db611 | ||
|
|
dcbe06229c | ||
|
|
ab66247f8a | ||
|
|
6c87035a72 | ||
|
|
075be1a862 | ||
|
|
370fd149cd | ||
|
|
849dd7e2eb | ||
|
|
143be734c5 | ||
|
|
23c33d87c1 | ||
|
|
01a68c210c | ||
|
|
fe01282421 | ||
|
|
226ff9aa03 | ||
|
|
ad6a3bf150 | ||
|
|
bb3f97b976 | ||
|
|
2093031333 | ||
|
|
bf60505584 | ||
|
|
27eca77f96 | ||
|
|
5d92b4dd2e | ||
|
|
fa04314db2 | ||
|
|
8d91a9b014 | ||
|
|
ecea8eab01 | ||
|
|
dc00870c2a | ||
|
|
3db2fea32b | ||
|
|
335e7489ce | ||
|
|
3271020e7c | ||
|
|
daf96241e1 | ||
|
|
ef7d814049 | ||
|
|
410c609785 | ||
|
|
f82b08e91d | ||
|
|
07b12890e8 | ||
|
|
c014f86f2b | ||
|
|
a634ca4858 | ||
|
|
ef2ff385b8 | ||
|
|
31d401340c | ||
|
|
c3df430a4e | ||
|
|
7515d1aca7 | ||
|
|
224cd7bb44 | ||
|
|
071d98dbfa | ||
|
|
8a3c4b4ddd | ||
|
|
95caa247f5 | ||
|
|
aeeabcb38f | ||
|
|
2d7a5e637d | ||
|
|
a28366ee80 | ||
|
|
e96a9a2f32 | ||
|
|
b8fca9a091 | ||
|
|
816402ae56 | ||
|
|
b8ed189bcb | ||
|
|
e4b0ea92da | ||
|
|
ca931987c4 | ||
|
|
f9a0d7a3c6 | ||
|
|
840f6e43c3 | ||
|
|
89872902e7 | ||
|
|
d6065865f5 | ||
|
|
b56aa4adc2 | ||
|
|
b36c074e72 | ||
|
|
4df0393e00 | ||
|
|
7bfbca7234 | ||
|
|
dfcd94c4bc | ||
|
|
ee3c99991e | ||
|
|
11a8c227d2 | ||
|
|
f37ecda3a7 | ||
|
|
a3054c75b4 | ||
|
|
428e1f22d5 | ||
|
|
faf1ea3102 | ||
|
|
c287a173e3 | ||
|
|
2aa70fdae5 | ||
|
|
5aeb77fd65 | ||
|
|
53f0a4516f | ||
|
|
451a4faa5b | ||
|
|
2e09373fdc | ||
|
|
df635777c3 | ||
|
|
b2f973735b | ||
|
|
3a2a591c43 | ||
|
|
5d4cbf6af5 | ||
|
|
d83405c946 | ||
|
|
1d24dd6d4d |
6
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -17,9 +17,11 @@ assignees: ''
|
|||||||
|
|
||||||
**Link(s) to mod(s) used**: *The mod repositories or zip files that are related to the issue, if applicable.*
|
**Link(s) to mod(s) used**: *The mod repositories or zip files that are related to the issue, if applicable.*
|
||||||
|
|
||||||
**Save file**: *The (zipped) save file you were playing on when the bug happened. THIS IS REQUIRED FOR ANY ISSUE HAPPENING IN-GAME, REGARDLESS OF WHETHER YOU THINK IT HAPPENS EVERYWHERE. DO NOT DELETE OR OMIT THIS LINE UNLESS YOU ARE SURE THAT THE ISSUE DOES NOT HAPPEN IN-GAME.*
|
**Save file**: *The (zipped) save file you were playing on when the bug happened. THIS IS REQUIRED FOR ANY ISSUE HAPPENING IN-GAME OR IN MULTIPLAYER, REGARDLESS OF WHETHER YOU THINK IT HAPPENS EVERYWHERE. DO NOT DELETE OR OMIT THIS LINE UNLESS YOU ARE SURE THAT THE ISSUE DOES NOT HAPPEN IN-GAME. IF YOU DO NOT HAVE A SAVE, DON'T WASTE TIME OPENING THIS ISSUE.*
|
||||||
|
|
||||||
**Crash report**: *The contents of relevant crash report files. REQUIRED if you are reporting a crash.*
|
If you remove the line above without reading it properly and understanding what it means, I will reap your soul. Even if you're playing on someone's server, you can still save the game to a slot.
|
||||||
|
|
||||||
|
**(Crash) logs**: *Either crash reports from the crash folder, or the file you get when you go into Settings -> Game Data -> Export Crash logs. REQUIRED if you are reporting a crash.*
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
54
.github/workflows/deployment.yml
vendored
@@ -6,54 +6,62 @@ on:
|
|||||||
- 'v*'
|
- 'v*'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
buildJava14:
|
deploy:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Set up JDK 14
|
- name: Set up JDK 16
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v1
|
||||||
with:
|
with:
|
||||||
java-version: 14
|
java-version: 16
|
||||||
- name: Create artifacts
|
- name: Set env
|
||||||
run: |
|
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||||
./gradlew desktop:dist server:dist core:javadoc -Pbuildversion=${GITHUB_REF:1}"
|
|
||||||
- name: Update docs
|
|
||||||
run: |
|
|
||||||
cd ../
|
|
||||||
git clone --depth=1 https://github.com/MindustryGame/docs.git
|
|
||||||
cp -a Mindustry/core/build/docs/javadoc/. docs/
|
|
||||||
cd docs
|
|
||||||
git add .
|
|
||||||
git commit -m "Update ${GITHUB_REF:1}"
|
|
||||||
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/MindustryGame/docs
|
|
||||||
cd ../Mindustry
|
|
||||||
- name: Add Arc release
|
- name: Add Arc release
|
||||||
run: |
|
run: |
|
||||||
git clone --depth=1 --branch=master https://github.com/Anuken/Arc ../Arc
|
git clone --depth=1 --branch=master https://github.com/Anuken/Arc ../Arc
|
||||||
cd ../Arc
|
cd ../Arc
|
||||||
git tag ${GITHUB_REF}
|
git tag ${RELEASE_VERSION}
|
||||||
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/Arc ${GITHUB_REF};
|
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/Arc ${RELEASE_VERSION};
|
||||||
|
cd ../Mindustry
|
||||||
|
- name: Create artifacts
|
||||||
|
run: |
|
||||||
|
./gradlew desktop:dist server:dist core:mergedJavadoc -Pbuildversion=${RELEASE_VERSION:1}
|
||||||
|
- name: Update docs
|
||||||
|
run: |
|
||||||
|
cd ../
|
||||||
|
git config --global user.email "cli@github.com"
|
||||||
|
git config --global user.name "Github Actions"
|
||||||
|
git clone --depth=1 https://github.com/MindustryGame/docs.git
|
||||||
|
cd docs
|
||||||
|
find . -maxdepth 1 ! -name ".git" ! -name . -exec rm -r {} \;
|
||||||
|
cd ../
|
||||||
|
cp -a Mindustry/core/build/javadoc/. docs/
|
||||||
|
cd docs
|
||||||
|
git add .
|
||||||
|
git commit -m "Update ${RELEASE_VERSION:1}"
|
||||||
|
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/MindustryGame/docs
|
||||||
cd ../Mindustry
|
cd ../Mindustry
|
||||||
- name: Update F-Droid build string
|
- name: Update F-Droid build string
|
||||||
run: |
|
run: |
|
||||||
git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds
|
git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds
|
||||||
cd ../MindustryBuilds
|
cd ../MindustryBuilds
|
||||||
echo "Updating version to ${GITHUB_REF:1}"
|
echo "Updating version to ${RELEASE_VERSION:1}"
|
||||||
echo versionName=6-fdroid-${GITHUB_REF:1}$'\n'versionCode=${GITHUB_REF:1} > version_fdroid.txt
|
echo versionName=7-fdroid-${RELEASE_VERSION:1}$'\n'versionCode=${GITHUB_RUN_NUMBER} > version_fdroid.txt
|
||||||
git add .
|
git add .
|
||||||
git commit -m "Updating to build ${GITHUB_REF:1}"
|
git commit -m "Updating to build ${RELEASE_VERSION:1}"
|
||||||
|
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/MindustryBuilds
|
||||||
cd ../Mindustry
|
cd ../Mindustry
|
||||||
- name: Upload client artifacts
|
- name: Upload client artifacts
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
with:
|
with:
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
file: desktop/libs/Mindustry.jar
|
file: desktop/build/libs/Mindustry.jar
|
||||||
tag: ${{ github.ref }}
|
tag: ${{ github.ref }}
|
||||||
- name: Upload server artifacts
|
- name: Upload server artifacts
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
with:
|
with:
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
file: server/libs/server-release.jar
|
file: server/build/libs/server-release.jar
|
||||||
tag: ${{ github.ref }}
|
tag: ${{ github.ref }}
|
||||||
|
|
||||||
|
|||||||
8
.github/workflows/pr.yml
vendored
@@ -1,17 +1,17 @@
|
|||||||
name: Pull Request Tests
|
name: Pull Request Tests
|
||||||
|
|
||||||
on: [pull_request]
|
on: [pull_request, workflow_dispatch]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
buildJava14:
|
testPR:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Set up JDK 14
|
- name: Set up JDK 16
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v1
|
||||||
with:
|
with:
|
||||||
java-version: 14
|
java-version: 16
|
||||||
- name: Run unit tests and build JAR
|
- name: Run unit tests and build JAR
|
||||||
run: ./gradlew test desktop:dist
|
run: ./gradlew test desktop:dist
|
||||||
- name: Upload desktop JAR for testing
|
- name: Upload desktop JAR for testing
|
||||||
|
|||||||
17
.github/workflows/push.yml
vendored
@@ -1,20 +1,15 @@
|
|||||||
name: Tests
|
name: Tests
|
||||||
|
|
||||||
on: [push]
|
on: [push, workflow_dispatch]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
buildJava14:
|
runPush:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Set up JDK 14
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
|
||||||
java-version: 14
|
|
||||||
- name: Run unit tests
|
|
||||||
run: ./gradlew test
|
|
||||||
- name: Trigger BE build
|
- name: Trigger BE build
|
||||||
|
if: ${{ github.repository == 'Anuken/Mindustry' }}
|
||||||
run: |
|
run: |
|
||||||
git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds
|
git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds
|
||||||
cd ../MindustryBuilds
|
cd ../MindustryBuilds
|
||||||
@@ -22,3 +17,9 @@ jobs:
|
|||||||
git tag ${BNUM}
|
git tag ${BNUM}
|
||||||
git config --global user.name "Build Uploader"
|
git config --global user.name "Build Uploader"
|
||||||
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/MindustryBuilds ${BNUM}
|
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/MindustryBuilds ${BNUM}
|
||||||
|
- name: Set up JDK 16
|
||||||
|
uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: 16
|
||||||
|
- name: Run unit tests
|
||||||
|
run: ./gradlew clean cleanTest test
|
||||||
|
|||||||
11
.gitignore
vendored
@@ -43,10 +43,17 @@ ios/robovm.properties
|
|||||||
packr-out/
|
packr-out/
|
||||||
config/
|
config/
|
||||||
*.gif
|
*.gif
|
||||||
|
/tests/out
|
||||||
|
|
||||||
/core/assets/basepartnames
|
/core/assets/basepartnames
|
||||||
version.properties
|
version.properties
|
||||||
|
|
||||||
|
#sprites
|
||||||
|
|
||||||
|
core/assets/sprites/sprites*
|
||||||
|
core/assets/sprites/fallback/
|
||||||
|
core/assets/sprites/block_colors.png
|
||||||
|
|
||||||
.attach_*
|
.attach_*
|
||||||
## Java
|
## Java
|
||||||
|
|
||||||
@@ -95,6 +102,10 @@ com_crashlytics_export_strings.xml
|
|||||||
.externalToolBuilders/
|
.externalToolBuilders/
|
||||||
*.launch
|
*.launch
|
||||||
|
|
||||||
|
## VSCode
|
||||||
|
|
||||||
|
.vscode/
|
||||||
|
|
||||||
## NetBeans
|
## NetBeans
|
||||||
|
|
||||||
/nbproject/private/
|
/nbproject/private/
|
||||||
|
|||||||
@@ -15,9 +15,6 @@ If you are submitting a new block, make sure it has a name and description, and
|
|||||||
If you are interested in adding a large mechanic/feature or changing large amounts of code, first contact me (Anuken) via [Discord](https://discord.gg/mindustry) (preferred method) or via e-mail (*anukendev@gmail.com*).
|
If you are interested in adding a large mechanic/feature or changing large amounts of code, first contact me (Anuken) via [Discord](https://discord.gg/mindustry) (preferred method) or via e-mail (*anukendev@gmail.com*).
|
||||||
For most changes, this should not be necessary. I just want to know if you're doing something big so I can offer advice and/or make sure you're not wasting your time on it.
|
For most changes, this should not be necessary. I just want to know if you're doing something big so I can offer advice and/or make sure you're not wasting your time on it.
|
||||||
|
|
||||||
### Do not include packed sprites in your pull request.
|
|
||||||
When making a pull request that changes or adds new sprites, do not add the modified atlas & `spritesX.png` files to your final pull request. These are a frequent source of conflicts.
|
|
||||||
|
|
||||||
|
|
||||||
## Style Guidelines
|
## Style Guidelines
|
||||||
|
|
||||||
@@ -29,7 +26,7 @@ This means:
|
|||||||
- `camelCase`, **even for constants or enums**. Why? Because `SCREAMING_CASE` is ugly, annoying to type and does not achieve anything useful. Constants are *less* dangerous than variables, not more. Any reasonable IDE should highlight them for you anyway.
|
- `camelCase`, **even for constants or enums**. Why? Because `SCREAMING_CASE` is ugly, annoying to type and does not achieve anything useful. Constants are *less* dangerous than variables, not more. Any reasonable IDE should highlight them for you anyway.
|
||||||
- No underscores for anything. (Yes, I know `Bindings` violates this principle, but that's for legacy reasons and really should be cleaned up some day)
|
- No underscores for anything. (Yes, I know `Bindings` violates this principle, but that's for legacy reasons and really should be cleaned up some day)
|
||||||
- Do not use braceless `if/else` statements. `if(x) statement else statement2` should **never** be done. In very specific situations, having braceless if-statements on one line is allowed: `if(cond) return;` would be valid.
|
- Do not use braceless `if/else` statements. `if(x) statement else statement2` should **never** be done. In very specific situations, having braceless if-statements on one line is allowed: `if(cond) return;` would be valid.
|
||||||
- Prefer single-line javadoc `/** @return for example */` instead of multiline javadoc whenver possible
|
- Prefer single-line javadoc `/** @return for example */` instead of multiline javadoc whenever possible
|
||||||
- Short method/variable names (multipleLongWords should be avoided if it's possible to do so reasonably, especially for variables)
|
- Short method/variable names (multipleLongWords should be avoided if it's possible to do so reasonably, especially for variables)
|
||||||
- Use wildcard imports - `import some.package.*` - for everything. This makes incorrect class usage more obvious (*e.g. arc.util.Timer vs java.util.Timer*) and leads to cleaner-looking code.
|
- Use wildcard imports - `import some.package.*` - for everything. This makes incorrect class usage more obvious (*e.g. arc.util.Timer vs java.util.Timer*) and leads to cleaner-looking code.
|
||||||
|
|
||||||
|
|||||||
52
ISSUES.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# Why was my issue closed?
|
||||||
|
|
||||||
|
This document goes over some common causes for issue closures.
|
||||||
|
|
||||||
|
## You did not fill in the template
|
||||||
|
|
||||||
|
I can't debug the problem unless you provide the information the template asks for.
|
||||||
|
If you cannot put in the effort to fill out a template, then don't expect me to put in the effort to fix it.
|
||||||
|
|
||||||
|
## Your issue was already reported
|
||||||
|
|
||||||
|
If the problem in your issue has already been encountered before, it will be closed - especially if your report doesn't provide any new information.
|
||||||
|
Make sure you search the *closed* issues before making an issue.
|
||||||
|
|
||||||
|
I do not link the specific issue(s) that report the same problem, because searching takes time - if you're interested in finding them, you should be able to do so without my help.
|
||||||
|
|
||||||
|
To be clear: I do **not** expect users to look at *all* previous issues, or do a comprehensive stack trace analysis to see if their crash was already reported.
|
||||||
|
|
||||||
|
## Your issue was already fixed
|
||||||
|
|
||||||
|
The problem you reported has been addressed. Note that this does **not** mean that the latest stable version of Mindustry has the fix!
|
||||||
|
It simply means that I have committed (or am about to commit) a patch that fixes it *on the current development branch*.
|
||||||
|
|
||||||
|
## Your issue is missing a crash report or log
|
||||||
|
|
||||||
|
If the game crashes without a specific cause, and you don't send me a log, I can't fix it. There is no way for me to know what went wrong.
|
||||||
|
|
||||||
|
During a normal crash, the game should tell you where the log is saved. If not, you should still be able to look in the game's crash folder on most operating systems, or export the logs in *Settings -> Game Data -> Export Crash Logs*.
|
||||||
|
|
||||||
|
## Your issue is missing saves or screenshots
|
||||||
|
|
||||||
|
Even if you think your problem happens everywhere and saves/screenshots are redundant, this is frequently not the case.
|
||||||
|
If I cannot reproduce the problem on my own saves and you have not linked any of your own, then the problem is likely to be save-specific. If you do not send me any, the problem cannot be investigated further.
|
||||||
|
|
||||||
|
## Your issue is related to an external program
|
||||||
|
|
||||||
|
If Mindustry causes something else to crash or misbehave, I am very unlikely to fix it. Unless the problem is serious, widespread and/or clearly a bug *in Mindustry*, it is not my responsibility.
|
||||||
|
|
||||||
|
Similarly, if you use another (invasive) program to change how Mindustry works, and something goes wrong, that is not my problem. Don't do it.
|
||||||
|
|
||||||
|
## Your issue is caused by mods
|
||||||
|
|
||||||
|
Crashes and bugs related to installed mods should be reported in the relevant mod repository, not here.
|
||||||
|
*Note that problems with the Mindustry modding API are a separate problem, and do not apply.*
|
||||||
|
|
||||||
|
## I cannot reproduce your issue
|
||||||
|
|
||||||
|
If I follow your instructions and am repeatedly unable to reproduce the problem you've reported, then it is very unlikely to be fixed.
|
||||||
|
Either the problem is device-specific, or there is not enough information given for me to be able to reproduce it.
|
||||||
|
|
||||||
|
I may attempt to change some code if I think it will make the issue less likely to occur, but without knowing for sure, the issue cannot be considered truly "fixed".
|
||||||
|
As I cannot make any further progress on the problem, there is no reason to keep it open. If it is a common bug/crash, other people will come along with information that may shed some light on the issue.
|
||||||
@@ -1,7 +1,7 @@
|
|||||||

|

|
||||||
|
|
||||||
[](https://travis-ci.org/Anuken/Mindustry)
|
[](https://github.com/Anuken/Mindustry/actions)
|
||||||
[](https://discord.gg/mindustry)
|
[](https://discord.gg/mindustry)
|
||||||
|
|
||||||
A sandbox tower defense game written in Java.
|
A sandbox tower defense game written in Java.
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ See [CONTRIBUTING](CONTRIBUTING.md).
|
|||||||
Bleeding-edge builds are generated automatically for every commit. You can see them [here](https://github.com/Anuken/MindustryBuilds/releases).
|
Bleeding-edge builds are generated automatically for every commit. You can see them [here](https://github.com/Anuken/MindustryBuilds/releases).
|
||||||
|
|
||||||
If you'd rather compile on your own, follow these instructions.
|
If you'd rather compile on your own, follow these instructions.
|
||||||
First, make sure you have [JDK 14](https://adoptopenjdk.net/) installed. Open a terminal in the root directory, `cd` to the Mindustry folder and run the following commands:
|
First, make sure you have [JDK 16](https://adoptopenjdk.net/archive.html?variant=openjdk16&jvmVariant=hotspot) installed. **Other JDK versions will not work.** Open a terminal in the Mindustry directory and run the following commands:
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
|
|
||||||
@@ -61,5 +61,5 @@ Post feature requests and feedback [here](https://github.com/Anuken/Mindustry-Su
|
|||||||
|
|
||||||
## Downloads
|
## Downloads
|
||||||
|
|
||||||
| [](https://anuke.itch.io/mindustry) | [](https://play.google.com/store/apps/details?id=io.anuke.mindustry) | [](https://f-droid.org/packages/io.anuke.mindustry) | [](https://flathub.org/apps/details/com.github.Anuken.Mindustry) |
|
| [](https://anuke.itch.io/mindustry) | [](https://play.google.com/store/apps/details?id=io.anuke.mindustry) | [](https://f-droid.org/packages/io.anuke.mindustry) | [](https://flathub.org/apps/details/com.github.Anuken.Mindustry)
|
||||||
|--- |--- |--- |--- |
|
|--- |--- |--- |--- |
|
||||||
|
|||||||
@@ -1,22 +1,23 @@
|
|||||||
### Adding a server to the list
|
### Adding a server to the list
|
||||||
|
|
||||||
Mindustry now has a public list of servers that everyone can see and connect to.
|
Mindustry now has a public list of servers that everyone can see and connect to.
|
||||||
This is done by letting clients `GET` a [JSON list of servers](https://github.com/Anuken/Mindustry/blob/master/servers.json) in this repository.
|
This is done by letting clients `GET` a [JSON list of servers](https://github.com/Anuken/Mindustry/blob/master/servers_v6.json) in this repository.
|
||||||
|
|
||||||
You may want to add your server to this list. The steps for getting this done are as follows:
|
You may want to add your server to this list. The steps for getting this done are as follows:
|
||||||
|
|
||||||
1. **Ensure your server is properly moderated.** For the most part, this applies to survival servers, but PvP servers can be affected as well.
|
1. **Ensure your server is properly moderated.** For the most part, this applies to survival servers, but PvP servers can be affected as well.
|
||||||
You'll need to either hire some moderators, or make use of (currently non-existent) anti-grief and anti-curse plugins.
|
You'll need to either hire some moderators, or make use of (currently non-existent) anti-grief and anti-curse plugins.
|
||||||
*Consider enabling a rate limit:* `config messageRateLimit 2` will make it so that players can only send messages every 2 seconds, for example.
|
*Consider enabling a rate limit:* `config messageRateLimit 2` will make it so that players can only send messages every 2 seconds, for example.
|
||||||
2. **Set an appropriate MOTD, name and description.** This is set with `config <name/desc/motd> <value>`. "Appropriate" means that:
|
2. Make sure that your server is able to handle inappropriate content - this includes NSFW display/sorter art and abusive messages. **Servers that allow such content will be removed immediately.** Consider banning display blocks if it is a problem for your server: `rules add bannedBlocks ["logic-display", "large-logic-display"]`.
|
||||||
|
3. **Set an appropriate MOTD, name and description.** This is set with `config <name/desc/motd> <value>`. "Appropriate" means that:
|
||||||
- Your name or description must reflect the type of server you're hosting.
|
- Your name or description must reflect the type of server you're hosting.
|
||||||
Since new players may be exposed to the server list early on, put in a phrase like "Co-op survival" or "PvP" so players know what they're getting into. Yes, this is also displayed in the server mode info text, but having extra info in the name doesn't hurt.
|
Since new players may be exposed to the server list early on, put in a phrase like "Co-op survival" or "PvP" so players know what they're getting into. Yes, this is also displayed in the server mode info text, but having extra info in the name doesn't hurt.
|
||||||
- Make sure players know where to refer to for server support. It should be fairly clear that the server owner is not me, but you.
|
- Make sure players know where to refer to for server support. It should be fairly clear that the server owner is not me, but you.
|
||||||
- Try to be professional in your text; use common sense.
|
- Try to be professional in your text; use common sense.
|
||||||
3. **Get some good maps.** *(optional, but highly recommended)*. Add some maps to your server and set the map rotation to custom-only. You can get maps from the Steam workshop by subscribing and exporting them; using the `#maps` channel on Discord is also an option.
|
4. **Get some good maps.** *(optional, but highly recommended)*. Add some maps to your server and set the map rotation to custom-only. You can get maps from the Steam workshop by subscribing and exporting them; using the `#maps` channel on Discord is also an option.
|
||||||
4. **Check your server configuration.** *(optional)* I would recommend adding a message rate limit of 1 second (`config messageRateLimit 1`), and disabling connect/disconnect messages to reduce spam (`config showConnectMessages false`).
|
5. **Check your server configuration.** *(optional)* I would recommend adding a message rate limit of 1 second (`config messageRateLimit 1`), and disabling connect/disconnect messages to reduce spam (`config showConnectMessages false`).
|
||||||
5. Finally, **submit a pull request** to add your server's IP to the list.
|
6. Finally, **submit a pull request** to add your server's IP to the list.
|
||||||
This should be fairly straightforward: Press the edit button on the [server file](https://github.com/Anuken/Mindustry/blob/master/servers.json), then add a JSON object with a single key, indicating your server address.
|
This should be fairly straightforward: Press the edit button on the [server file](https://github.com/Anuken/Mindustry/blob/master/servers_v6.json), then add a JSON object with a single key, indicating your server address.
|
||||||
For example, if your server address is `google.com`, you would add a comma after the last entry and insert:
|
For example, if your server address is `google.com`, you would add a comma after the last entry and insert:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
android:appCategory="game"
|
android:appCategory="game"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/ArcTheme" android:fullBackupContent="@xml/backup_rules">
|
android:fullBackupContent="@xml/backup_rules">
|
||||||
<meta-data android:name="android.max_aspect" android:value="2.1"/>
|
<meta-data android:name="android.max_aspect" android:value="2.1"/>
|
||||||
<activity
|
<activity
|
||||||
android:name="mindustry.android.AndroidLauncher"
|
android:name="mindustry.android.AndroidLauncher"
|
||||||
|
|||||||
@@ -4,13 +4,10 @@ buildscript{
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
||||||
jcenter()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
//IMPORTANT NOTICE: any version of the plugin after 3.4.1 will break builds
|
classpath 'com.android.tools.build:gradle:7.1.0-alpha02'
|
||||||
//it appears abstract methods don't get desugared properly (if at all)
|
|
||||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,36 +17,21 @@ configurations{ natives }
|
|||||||
|
|
||||||
repositories{
|
repositories{
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
jcenter()
|
|
||||||
maven{ url "https://maven.google.com" }
|
maven{ url "https://maven.google.com" }
|
||||||
}
|
jcenter() //remove later once google/JetBrains fixes the dependency
|
||||||
|
|
||||||
dependencies{
|
|
||||||
implementation project(":core")
|
|
||||||
|
|
||||||
implementation arcModule("backends:backend-android")
|
|
||||||
implementation 'com.jakewharton.android.repackaged:dalvik-dx:9.0.0_r3'
|
|
||||||
|
|
||||||
natives "com.github.Anuken.Arc:natives-android:${getArcHash()}"
|
|
||||||
natives "com.github.Anuken.Arc:natives-freetype-android:${getArcHash()}"
|
|
||||||
natives "com.github.Anuken.Arc:natives-box2d-android:${getArcHash()}"
|
|
||||||
|
|
||||||
//android dependencies magically disappear during compilation, thanks gradle!
|
|
||||||
def sdkFile = new File((String)findSdkDir(), "/platforms/android-29/android.jar")
|
|
||||||
if(sdkFile.exists()) compileOnly files(sdkFile.absolutePath)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task deploy(type: Copy){
|
task deploy(type: Copy){
|
||||||
dependsOn "assembleRelease"
|
dependsOn "assembleRelease"
|
||||||
|
|
||||||
from "build/outputs/apk/release/android-release.apk"
|
from "build/outputs/apk/standard/release/android-standard-release.apk"
|
||||||
into "../deploy/"
|
into "../deploy/"
|
||||||
rename("android-release.apk", "${generateDeployName('android')}.apk")
|
rename("android-standard-release.apk", "${generateDeployName('android')}.apk")
|
||||||
}
|
}
|
||||||
|
|
||||||
android{
|
android{
|
||||||
buildToolsVersion '29.0.3'
|
buildToolsVersion '30.0.2'
|
||||||
compileSdkVersion 29
|
compileSdkVersion 30
|
||||||
sourceSets{
|
sourceSets{
|
||||||
main{
|
main{
|
||||||
manifest.srcFile 'AndroidManifest.xml'
|
manifest.srcFile 'AndroidManifest.xml'
|
||||||
@@ -60,9 +42,13 @@ android{
|
|||||||
assets.srcDirs = ['assets', 'src/main/assets', '../core/assets/']
|
assets.srcDirs = ['assets', 'src/main/assets', '../core/assets/']
|
||||||
jniLibs.srcDirs = ['libs']
|
jniLibs.srcDirs = ['libs']
|
||||||
}
|
}
|
||||||
|
gp{
|
||||||
|
java.srcDirs = ['srcgp']
|
||||||
|
}
|
||||||
|
|
||||||
androidTest.setRoot('tests')
|
androidTest.setRoot('tests')
|
||||||
}
|
}
|
||||||
|
|
||||||
packagingOptions{
|
packagingOptions{
|
||||||
exclude 'META-INF/robovm/ios/robovm.xml'
|
exclude 'META-INF/robovm/ios/robovm.xml'
|
||||||
}
|
}
|
||||||
@@ -74,7 +60,7 @@ android{
|
|||||||
|
|
||||||
applicationId "io.anuke.mindustry"
|
applicationId "io.anuke.mindustry"
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 29
|
targetSdkVersion 30
|
||||||
|
|
||||||
versionName versionNameResult
|
versionName versionNameResult
|
||||||
versionCode = (System.getenv("TRAVIS_BUILD_ID") != null ? System.getenv("TRAVIS_BUILD_ID").toInteger() : vcode)
|
versionCode = (System.getenv("TRAVIS_BUILD_ID") != null ? System.getenv("TRAVIS_BUILD_ID").toInteger() : vcode)
|
||||||
@@ -110,6 +96,14 @@ android{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildTypes{
|
||||||
|
all{
|
||||||
|
minifyEnabled = true
|
||||||
|
shrinkResources = true
|
||||||
|
proguardFiles("proguard-rules.pro")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(project.hasProperty("RELEASE_STORE_FILE") || System.getenv("CI") == "true"){
|
if(project.hasProperty("RELEASE_STORE_FILE") || System.getenv("CI") == "true"){
|
||||||
buildTypes{
|
buildTypes{
|
||||||
release{
|
release{
|
||||||
@@ -117,10 +111,37 @@ android{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Specifies one flavor dimension.
|
||||||
|
flavorDimensions "version"
|
||||||
|
productFlavors{
|
||||||
|
standard{
|
||||||
|
|
||||||
}
|
}
|
||||||
// called every time gradle gets executed, takes the native dependencies of
|
gp{
|
||||||
// the natives configuration, and extracts them to the proper libs/ folders
|
applicationIdSuffix ".gp"
|
||||||
// so they get packed with the APK.
|
versionNameSuffix "-gp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies{
|
||||||
|
implementation project(":core")
|
||||||
|
|
||||||
|
implementation arcModule("backends:backend-android")
|
||||||
|
implementation 'com.jakewharton.android.repackaged:dalvik-dx:9.0.0_r3'
|
||||||
|
|
||||||
|
natives "com.github.Anuken.Arc:natives-android:${getArcHash()}"
|
||||||
|
natives "com.github.Anuken.Arc:natives-freetype-android:${getArcHash()}"
|
||||||
|
|
||||||
|
gpImplementation "com.google.android.gms:play-services-games:21.0.0"
|
||||||
|
gpImplementation "com.google.android.gms:play-services-auth:19.0.0"
|
||||||
|
|
||||||
|
//android dependencies magically disappear during compilation, thanks gradle!
|
||||||
|
def sdkFile = new File((String)findSdkDir(), "/platforms/android-29/android.jar")
|
||||||
|
if(sdkFile.exists()) compileOnly files(sdkFile.absolutePath)
|
||||||
|
}
|
||||||
|
|
||||||
task copyAndroidNatives(){
|
task copyAndroidNatives(){
|
||||||
configurations.natives.files.each{ jar ->
|
configurations.natives.files.each{ jar ->
|
||||||
copy{
|
copy{
|
||||||
@@ -132,23 +153,13 @@ task copyAndroidNatives(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
task run(type: Exec){
|
task run(type: Exec){
|
||||||
def path
|
commandLine "${findSdkDir()}/platform-tools/adb", 'shell', 'am', 'start', '-n', 'io.anuke.mindustry/mindustry.android.AndroidLauncher'
|
||||||
def localProperties = project.file("../local.properties")
|
|
||||||
if(localProperties.exists()){
|
|
||||||
Properties properties = new Properties()
|
|
||||||
localProperties.withInputStream{ instr ->
|
|
||||||
properties.load(instr)
|
|
||||||
}
|
|
||||||
def sdkDir = properties.getProperty('sdk.dir')
|
|
||||||
if(sdkDir){
|
|
||||||
path = sdkDir
|
|
||||||
}else{
|
|
||||||
path = "$System.env.ANDROID_HOME"
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
path = "$System.env.ANDROID_HOME"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def adb = path + "/platform-tools/adb"
|
if(!project.ext.hasSprites()){
|
||||||
commandLine "$adb", 'shell', 'am', 'start', '-n', 'io.anuke.mindustry/mindustry.android.AndroidLauncher'
|
tasks.whenTaskAdded{ task ->
|
||||||
|
if(task.name == 'assembleDebug' || task.name == 'assembleRelease'){
|
||||||
|
task.dependsOn ":tools:pack"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
android/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
-dontobfuscate
|
||||||
|
|
||||||
|
#these are essential packages that should not be "optimized" in any way
|
||||||
|
#the main purpose of d8 here is to shrink the absurdly-large google play games libraries
|
||||||
|
-keep class mindustry.** { *; }
|
||||||
|
-keep class arc.** { *; }
|
||||||
|
-keep class net.jpountz.** { *; }
|
||||||
|
-keep class rhino.** { *; }
|
||||||
|
-keep class com.android.dex.** { *; }
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<style name="ArcTheme" parent="android:Theme.Material.NoActionBar">
|
|
||||||
<item name="android:windowBackground">@android:color/transparent</item>
|
|
||||||
<item name="android:colorBackgroundCacheHint">@null</item>
|
|
||||||
<item name="android:windowAnimationStyle">@android:style/Animation</item>
|
|
||||||
<item name="android:windowNoTitle">true</item>
|
|
||||||
<item name="android:windowContentOverlay">@null</item>
|
|
||||||
<item name="android:windowFullscreen">true</item>
|
|
||||||
</style>
|
|
||||||
</resources>
|
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<string name="app_name">Mindustry</string>
|
<string name="app_name">Mindustry</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
<resources>
|
|
||||||
|
|
||||||
<style name="ArcTheme" parent="android:Theme">
|
|
||||||
<item name="android:windowBackground">@android:color/transparent</item>
|
|
||||||
<item name="android:colorBackgroundCacheHint">@null</item>
|
|
||||||
<item name="android:windowAnimationStyle">@android:style/Animation</item>
|
|
||||||
<item name="android:windowNoTitle">true</item>
|
|
||||||
<item name="android:windowContentOverlay">@null</item>
|
|
||||||
<item name="android:windowFullscreen">true</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
</resources>
|
|
||||||
@@ -33,6 +33,9 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
FileChooser chooser;
|
FileChooser chooser;
|
||||||
Runnable permCallback;
|
Runnable permCallback;
|
||||||
|
|
||||||
|
Object gpService;
|
||||||
|
Class<?> serviceClass;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState){
|
protected void onCreate(Bundle savedInstanceState){
|
||||||
UncaughtExceptionHandler handler = Thread.getDefaultUncaughtExceptionHandler();
|
UncaughtExceptionHandler handler = Thread.getDefaultUncaughtExceptionHandler();
|
||||||
@@ -44,13 +47,13 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
if(handler != null){
|
if(handler != null){
|
||||||
handler.uncaughtException(thread, error);
|
handler.uncaughtException(thread, error);
|
||||||
}else{
|
}else{
|
||||||
error.printStackTrace();
|
Log.err(error);
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
if(doubleScaleTablets && isTablet(this.getContext())){
|
if(doubleScaleTablets && isTablet(this)){
|
||||||
Scl.setAddition(0.5f);
|
Scl.setAddition(0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +66,7 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public rhino.Context getScriptContext(){
|
public rhino.Context getScriptContext(){
|
||||||
return AndroidRhinoContext.enter(getContext().getCacheDir());
|
return AndroidRhinoContext.enter(getCacheDir());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -71,9 +74,28 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<?> loadJar(Fi jar, String mainClass) throws Exception{
|
public ClassLoader loadJar(Fi jar, ClassLoader parent) throws Exception{
|
||||||
DexClassLoader loader = new DexClassLoader(jar.file().getPath(), getFilesDir().getPath(), null, getClassLoader());
|
return new DexClassLoader(jar.file().getPath(), getFilesDir().getPath(), null, parent){
|
||||||
return Class.forName(mainClass, true, loader);
|
@Override
|
||||||
|
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
|
||||||
|
//check for loaded state
|
||||||
|
Class<?> loadedClass = findLoadedClass(name);
|
||||||
|
if(loadedClass == null){
|
||||||
|
try{
|
||||||
|
//try to load own class first
|
||||||
|
loadedClass = findClass(name);
|
||||||
|
}catch(ClassNotFoundException e){
|
||||||
|
//use parent if not found
|
||||||
|
loadedClass = super.loadClass(name, resolve);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(resolve){
|
||||||
|
resolveClass(loadedClass);
|
||||||
|
}
|
||||||
|
return loadedClass;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -161,15 +183,25 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
}, new AndroidApplicationConfiguration(){{
|
}, new AndroidApplicationConfiguration(){{
|
||||||
useImmersiveMode = true;
|
useImmersiveMode = true;
|
||||||
hideStatusBar = true;
|
hideStatusBar = true;
|
||||||
stencil = 8;
|
|
||||||
}});
|
}});
|
||||||
checkFiles(getIntent());
|
checkFiles(getIntent());
|
||||||
|
|
||||||
try{
|
try{
|
||||||
//new external folder
|
//new external folder
|
||||||
Fi data = Core.files.absolute(getContext().getExternalFilesDir(null).getAbsolutePath());
|
Fi data = Core.files.absolute(((Context)this).getExternalFilesDir(null).getAbsolutePath());
|
||||||
Core.settings.setDataDirectory(data);
|
Core.settings.setDataDirectory(data);
|
||||||
|
|
||||||
|
//delete unused cache folder to free up space
|
||||||
|
try{
|
||||||
|
Fi cache = Core.settings.getDataDirectory().child("cache");
|
||||||
|
if(cache.exists()){
|
||||||
|
cache.deleteDirectory();
|
||||||
|
}
|
||||||
|
}catch(Throwable t){
|
||||||
|
Log.err("Failed to delete cached folder", t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//move to internal storage if there's no file indicating that it moved
|
//move to internal storage if there's no file indicating that it moved
|
||||||
if(!Core.files.local("files_moved").exists()){
|
if(!Core.files.local("files_moved").exists()){
|
||||||
Log.info("Moving files to external storage...");
|
Log.info("Moving files to external storage...");
|
||||||
@@ -211,6 +243,24 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume(){
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
//TODO enable once GPGS is set up on the GP console
|
||||||
|
if(false && getPackageName().endsWith(".gp")){
|
||||||
|
try{
|
||||||
|
if(gpService == null){
|
||||||
|
serviceClass = Class.forName("mindustry.android.GPGameService");
|
||||||
|
gpService = serviceClass.getConstructor().newInstance();
|
||||||
|
}
|
||||||
|
serviceClass.getMethod("onResume", Context.class).invoke(gpService, this);
|
||||||
|
}catch(Exception e){
|
||||||
|
Log.err("Failed to update Google Play Services", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void checkFiles(Intent intent){
|
private void checkFiles(Intent intent){
|
||||||
try{
|
try{
|
||||||
Uri uri = intent.getData();
|
Uri uri = intent.getData();
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import com.android.dx.dex.cf.*;
|
|||||||
import com.android.dx.dex.file.DexFile;
|
import com.android.dx.dex.file.DexFile;
|
||||||
import com.android.dx.merge.*;
|
import com.android.dx.merge.*;
|
||||||
import dalvik.system.*;
|
import dalvik.system.*;
|
||||||
|
import mindustry.mod.*;
|
||||||
import rhino.*;
|
import rhino.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@@ -30,23 +31,6 @@ public class AndroidRhinoContext{
|
|||||||
* @return a context prepared for android
|
* @return a context prepared for android
|
||||||
*/
|
*/
|
||||||
public static Context enter(File cacheDirectory){
|
public static Context enter(File cacheDirectory){
|
||||||
if(!SecurityController.hasGlobal())
|
|
||||||
SecurityController.initGlobal(new SecurityController(){
|
|
||||||
@Override
|
|
||||||
public GeneratedClassLoader createClassLoader(ClassLoader classLoader, Object o){
|
|
||||||
return Context.getCurrentContext().createClassLoader(classLoader);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getDynamicSecurityDomain(Object o){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object callWithDomain(Object o, Context context, Callable callable, Scriptable scriptable, Scriptable scriptable1, Object[] objects){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
AndroidContextFactory factory;
|
AndroidContextFactory factory;
|
||||||
if(!ContextFactory.hasExplicitGlobal()){
|
if(!ContextFactory.hasExplicitGlobal()){
|
||||||
@@ -175,7 +159,7 @@ public class AndroidRhinoContext{
|
|||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
android.content.Context context = ((AndroidApplication) Core.app).getContext();
|
android.content.Context context = (android.content.Context)((AndroidApplication)Core.app);
|
||||||
return new DexClassLoader(dexFile.getPath(), VERSION.SDK_INT >= 21 ? context.getCodeCacheDir().getPath() : context.getCacheDir().getAbsolutePath(), null, getParent()).loadClass(name);
|
return new DexClassLoader(dexFile.getPath(), VERSION.SDK_INT >= 21 ? context.getCodeCacheDir().getPath() : context.getCacheDir().getAbsolutePath(), null, getParent()).loadClass(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
40
android/srcgp/mindustry/android/GPGameService.java
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package mindustry.android;
|
||||||
|
|
||||||
|
import android.content.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import com.google.android.gms.auth.api.signin.*;
|
||||||
|
import com.google.android.gms.games.*;
|
||||||
|
import mindustry.service.*;
|
||||||
|
|
||||||
|
public class GPGameService extends GameService{
|
||||||
|
private GoogleSignInAccount account;
|
||||||
|
|
||||||
|
public void onResume(Context context){
|
||||||
|
Log.info("[GooglePlayService] Resuming.");
|
||||||
|
|
||||||
|
GoogleSignInAccount current = GoogleSignIn.getLastSignedInAccount(context);
|
||||||
|
|
||||||
|
GoogleSignInOptions options =
|
||||||
|
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
|
||||||
|
.requestScopes(Games.SCOPE_GAMES_SNAPSHOTS)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
if(GoogleSignIn.hasPermissions(current, options.getScopeArray())){
|
||||||
|
this.account = current;
|
||||||
|
Log.info("Already signed in to Google Play Games.");
|
||||||
|
}else{
|
||||||
|
GoogleSignIn.getClient(context, options).silentSignIn().addOnCompleteListener(complete -> {
|
||||||
|
if(!complete.isSuccessful()){
|
||||||
|
if(complete.getException() != null){
|
||||||
|
Log.err("Failed to sign in to Google Play Games.", complete.getException());
|
||||||
|
}else{
|
||||||
|
Log.warn("Failed to sign in to Google Play Games.");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
this.account = complete.getResult();
|
||||||
|
Log.info("Signed in to Google Play Games.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -118,7 +118,7 @@ public class Annotations{
|
|||||||
/**
|
/**
|
||||||
* The region name to load. Variables can be used:
|
* The region name to load. Variables can be used:
|
||||||
* "@" -> block name
|
* "@" -> block name
|
||||||
* "$size" -> block size
|
* "@size" -> block size
|
||||||
* "#" "#1" "#2" -> index number, for arrays
|
* "#" "#1" "#2" -> index number, for arrays
|
||||||
* */
|
* */
|
||||||
String value();
|
String value();
|
||||||
@@ -177,12 +177,12 @@ public class Annotations{
|
|||||||
//region remote
|
//region remote
|
||||||
|
|
||||||
public enum PacketPriority{
|
public enum PacketPriority{
|
||||||
|
/** Does not get handled unless client is connected. */
|
||||||
|
low,
|
||||||
/** Gets put in a queue and processed if not connected. */
|
/** Gets put in a queue and processed if not connected. */
|
||||||
normal,
|
normal,
|
||||||
/** Gets handled immediately, regardless of connection status. */
|
/** Gets handled immediately, regardless of connection status. */
|
||||||
high,
|
high,
|
||||||
/** Does not get handled unless client is connected. */
|
|
||||||
low
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A set of two booleans, one specifying server and one specifying client. */
|
/** A set of two booleans, one specifying server and one specifying client. */
|
||||||
|
|||||||
@@ -2,15 +2,10 @@ package mindustry.annotations;
|
|||||||
|
|
||||||
import arc.files.*;
|
import arc.files.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.Log;
|
|
||||||
import arc.util.Log.*;
|
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
|
import arc.util.Log.*;
|
||||||
import com.squareup.javapoet.*;
|
import com.squareup.javapoet.*;
|
||||||
import com.sun.source.util.*;
|
import com.sun.source.util.*;
|
||||||
import com.sun.tools.javac.model.*;
|
|
||||||
import com.sun.tools.javac.processing.*;
|
|
||||||
import com.sun.tools.javac.tree.*;
|
|
||||||
import com.sun.tools.javac.util.*;
|
|
||||||
import mindustry.annotations.util.*;
|
import mindustry.annotations.util.*;
|
||||||
|
|
||||||
import javax.annotation.processing.*;
|
import javax.annotation.processing.*;
|
||||||
@@ -22,7 +17,6 @@ import javax.tools.Diagnostic.*;
|
|||||||
import javax.tools.*;
|
import javax.tools.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
||||||
@@ -31,19 +25,16 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
|||||||
public static final String packageName = "mindustry.gen";
|
public static final String packageName = "mindustry.gen";
|
||||||
|
|
||||||
public static Types typeu;
|
public static Types typeu;
|
||||||
public static JavacElements elementu;
|
public static Elements elementu;
|
||||||
public static Filer filer;
|
public static Filer filer;
|
||||||
public static Messager messager;
|
public static Messager messager;
|
||||||
public static Trees trees;
|
public static Trees trees;
|
||||||
public static TreeMaker maker;
|
|
||||||
|
|
||||||
protected int round;
|
protected int round;
|
||||||
protected int rounds = 1;
|
protected int rounds = 1;
|
||||||
protected RoundEnvironment env;
|
protected RoundEnvironment env;
|
||||||
protected Fi rootDirectory;
|
protected Fi rootDirectory;
|
||||||
|
|
||||||
protected Context context;
|
|
||||||
|
|
||||||
public static String getMethodName(Element element){
|
public static String getMethodName(Element element){
|
||||||
return ((TypeElement)element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName();
|
return ((TypeElement)element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName();
|
||||||
}
|
}
|
||||||
@@ -186,7 +177,7 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
|||||||
Log.err("[CODEGEN ERROR] " + message + ": " + elem);
|
Log.err("[CODEGEN ERROR] " + message + ": " + elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void err(String message, Selement elem){
|
public static void err(String message, Selement elem){
|
||||||
err(message, elem.e);
|
err(message, elem.e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,15 +185,11 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
|||||||
public synchronized void init(ProcessingEnvironment env){
|
public synchronized void init(ProcessingEnvironment env){
|
||||||
super.init(env);
|
super.init(env);
|
||||||
|
|
||||||
JavacProcessingEnvironment javacProcessingEnv = (JavacProcessingEnvironment)env;
|
|
||||||
|
|
||||||
trees = Trees.instance(env);
|
trees = Trees.instance(env);
|
||||||
typeu = env.getTypeUtils();
|
typeu = env.getTypeUtils();
|
||||||
elementu = javacProcessingEnv.getElementUtils();
|
elementu = env.getElementUtils();
|
||||||
filer = env.getFiler();
|
filer = env.getFiler();
|
||||||
messager = env.getMessager();
|
messager = env.getMessager();
|
||||||
context = ((JavacProcessingEnvironment)env).getContext();
|
|
||||||
maker = TreeMaker.instance(javacProcessingEnv.getContext());
|
|
||||||
|
|
||||||
Log.level = LogLevel.info;
|
Log.level = LogLevel.info;
|
||||||
|
|
||||||
@@ -219,7 +206,7 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
|||||||
String path = Fi.get(filer.getResource(StandardLocation.CLASS_OUTPUT, "no", "no")
|
String path = Fi.get(filer.getResource(StandardLocation.CLASS_OUTPUT, "no", "no")
|
||||||
.toUri().toURL().toString().substring(OS.isWindows ? 6 : "file:".length()))
|
.toUri().toURL().toString().substring(OS.isWindows ? 6 : "file:".length()))
|
||||||
.parent().parent().parent().parent().parent().parent().parent().toString().replace("%20", " ");
|
.parent().parent().parent().parent().parent().parent().parent().toString().replace("%20", " ");
|
||||||
rootDirectory = Fi.get(path);
|
rootDirectory = Fi.get(path).parent();
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ public class EntityIO{
|
|||||||
if(sl) cont("if(!islocal)");
|
if(sl) cont("if(!islocal)");
|
||||||
|
|
||||||
if(sf){
|
if(sf){
|
||||||
st(field.name + lastSuf + " = this." + field.name);
|
st(field.name + lastSuf + " = this." + field.name + targetSuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
io(field.type, "this." + (sf ? field.name + targetSuf : field.name) + " = ");
|
io(field.type, "this." + (sf ? field.name + targetSuf : field.name) + " = ");
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
.build())).addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT).build());
|
.build())).addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//generate interface getters and setters for all "standard" fields
|
||||||
for(Svar field : component.fields().select(e -> !e.is(Modifier.STATIC) && !e.is(Modifier.PRIVATE) && !e.has(Import.class))){
|
for(Svar field : component.fields().select(e -> !e.is(Modifier.STATIC) && !e.is(Modifier.PRIVATE) && !e.has(Import.class))){
|
||||||
String cname = field.name();
|
String cname = field.name();
|
||||||
|
|
||||||
@@ -273,7 +274,10 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
name += "Entity";
|
name += "Entity";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ann.legacy()){
|
boolean legacy = ann.legacy();
|
||||||
|
|
||||||
|
if(legacy){
|
||||||
|
baseClass = tname(packageName + "." + name);
|
||||||
name += "Legacy" + Strings.capitalize(type.name());
|
name += "Legacy" + Strings.capitalize(type.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +342,8 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
boolean isVisible = !f.is(Modifier.STATIC) && !f.is(Modifier.PRIVATE) && !f.has(ReadOnly.class);
|
boolean isVisible = !f.is(Modifier.STATIC) && !f.is(Modifier.PRIVATE) && !f.has(ReadOnly.class);
|
||||||
|
|
||||||
//add the field only if it isn't visible or it wasn't implemented by the base class
|
//add the field only if it isn't visible or it wasn't implemented by the base class
|
||||||
if(!isShadowed || !isVisible){
|
//legacy classes have no extra fields
|
||||||
|
if((!isShadowed || !isVisible) && !legacy){
|
||||||
builder.addField(spec);
|
builder.addField(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,7 +353,7 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
allFields.add(f);
|
allFields.add(f);
|
||||||
|
|
||||||
//add extra sync fields
|
//add extra sync fields
|
||||||
if(f.has(SyncField.class) && isSync){
|
if(f.has(SyncField.class) && isSync && !legacy){
|
||||||
if(!f.tname().toString().equals("float")) err("All SyncFields must be of type float", f);
|
if(!f.tname().toString().equals("float")) err("All SyncFields must be of type float", f);
|
||||||
|
|
||||||
syncedFields.add(f);
|
syncedFields.add(f);
|
||||||
@@ -442,11 +447,14 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean specialIO = false;
|
||||||
|
|
||||||
if(hasIO){
|
if(hasIO){
|
||||||
//SPECIAL CASE: I/O code
|
//SPECIAL CASE: I/O code
|
||||||
//note that serialization is generated even for non-serializing entities for manual usage
|
//note that serialization is generated even for non-serializing entities for manual usage
|
||||||
if((first.name().equals("read") || first.name().equals("write"))){
|
if((first.name().equals("read") || first.name().equals("write"))){
|
||||||
io.write(mbuilder, first.name().equals("write"));
|
io.write(mbuilder, first.name().equals("write"));
|
||||||
|
specialIO = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//SPECIAL CASE: sync I/O code
|
//SPECIAL CASE: sync I/O code
|
||||||
@@ -525,8 +533,10 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
mbuilder.addStatement("mindustry.gen.Groups.queueFree(($T)this)", Poolable.class);
|
mbuilder.addStatement("mindustry.gen.Groups.queueFree(($T)this)", Poolable.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!legacy || specialIO){
|
||||||
builder.addMethod(mbuilder.build());
|
builder.addMethod(mbuilder.build());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//add pool reset method and implement Poolable
|
//add pool reset method and implement Poolable
|
||||||
if(ann.pooled()){
|
if(ann.pooled()){
|
||||||
@@ -560,7 +570,7 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
.returns(tname(packageName + "." + name))
|
.returns(tname(packageName + "." + name))
|
||||||
.addStatement(ann.pooled() ? "return Pools.obtain($L.class, " +name +"::new)" : "return new $L()", name).build());
|
.addStatement(ann.pooled() ? "return Pools.obtain($L.class, " +name +"::new)" : "return new $L()", name).build());
|
||||||
|
|
||||||
definitions.add(new EntityDefinition(packageName + "." + name, builder, type, typeIsBase ? null : baseClass, components, groups, allFieldSpecs));
|
definitions.add(new EntityDefinition(packageName + "." + name, builder, type, typeIsBase ? null : baseClass, components, groups, allFieldSpecs, legacy));
|
||||||
}
|
}
|
||||||
|
|
||||||
//generate groups
|
//generate groups
|
||||||
@@ -665,11 +675,28 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
//build mapping class for sync IDs
|
//build mapping class for sync IDs
|
||||||
TypeSpec.Builder idBuilder = TypeSpec.classBuilder("EntityMapping").addModifiers(Modifier.PUBLIC)
|
TypeSpec.Builder idBuilder = TypeSpec.classBuilder("EntityMapping").addModifiers(Modifier.PUBLIC)
|
||||||
.addField(FieldSpec.builder(TypeName.get(Prov[].class), "idMap", Modifier.PUBLIC, Modifier.STATIC).initializer("new Prov[256]").build())
|
.addField(FieldSpec.builder(TypeName.get(Prov[].class), "idMap", Modifier.PUBLIC, Modifier.STATIC).initializer("new Prov[256]").build())
|
||||||
|
|
||||||
.addField(FieldSpec.builder(ParameterizedTypeName.get(ClassName.get(ObjectMap.class),
|
.addField(FieldSpec.builder(ParameterizedTypeName.get(ClassName.get(ObjectMap.class),
|
||||||
tname(String.class), tname(Prov.class)),
|
tname(String.class), tname(Prov.class)),
|
||||||
"nameMap", Modifier.PUBLIC, Modifier.STATIC).initializer("new ObjectMap<>()").build())
|
"nameMap", Modifier.PUBLIC, Modifier.STATIC).initializer("new ObjectMap<>()").build())
|
||||||
|
|
||||||
|
.addField(FieldSpec.builder(ParameterizedTypeName.get(ClassName.get(IntMap.class), tname(String.class)),
|
||||||
|
"customIdMap", Modifier.PUBLIC, Modifier.STATIC).initializer("new IntMap<>()").build())
|
||||||
|
|
||||||
|
.addMethod(MethodSpec.methodBuilder("register").addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||||
|
.returns(TypeName.get(int.class))
|
||||||
|
.addParameter(String.class, "name").addParameter(Prov.class, "constructor")
|
||||||
|
.addStatement("int next = arc.util.Structs.indexOf(idMap, v -> v == null)")
|
||||||
|
.addStatement("idMap[next] = constructor")
|
||||||
|
.addStatement("nameMap.put(name, constructor)")
|
||||||
|
.addStatement("customIdMap.put(next, name)")
|
||||||
|
.addStatement("return next")
|
||||||
|
.addJavadoc("Use this method for obtaining a classId for custom modded unit types. Only call this once for each type. Modded types should return this id in their overridden classId method.")
|
||||||
|
.build())
|
||||||
|
|
||||||
.addMethod(MethodSpec.methodBuilder("map").addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
.addMethod(MethodSpec.methodBuilder("map").addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||||
.returns(TypeName.get(Prov.class)).addParameter(int.class, "id").addStatement("return idMap[id]").build())
|
.returns(TypeName.get(Prov.class)).addParameter(int.class, "id").addStatement("return idMap[id]").build())
|
||||||
|
|
||||||
.addMethod(MethodSpec.methodBuilder("map").addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
.addMethod(MethodSpec.methodBuilder("map").addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||||
.returns(TypeName.get(Prov.class)).addParameter(String.class, "name").addStatement("return nameMap.get(name)").build());
|
.returns(TypeName.get(Prov.class)).addParameter(String.class, "name").addStatement("return nameMap.get(name)").build());
|
||||||
|
|
||||||
@@ -698,11 +725,6 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
}else{
|
}else{
|
||||||
//round 3: generate actual classes and implement interfaces
|
//round 3: generate actual classes and implement interfaces
|
||||||
|
|
||||||
//write base classes
|
|
||||||
for(TypeSpec.Builder b : baseClasses){
|
|
||||||
write(b, imports.asArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
//implement each definition
|
//implement each definition
|
||||||
for(EntityDefinition def : definitions){
|
for(EntityDefinition def : definitions){
|
||||||
|
|
||||||
@@ -725,6 +747,14 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
|
|
||||||
def.builder.addSuperinterface(inter.tname());
|
def.builder.addSuperinterface(inter.tname());
|
||||||
|
|
||||||
|
if(def.legacy) continue;
|
||||||
|
|
||||||
|
@Nullable TypeSpec.Builder superclass = null;
|
||||||
|
|
||||||
|
if(def.extend != null){
|
||||||
|
superclass = baseClasses.find(b -> (packageName + "." + Reflect.get(b, "name")).equals(def.extend.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
//generate getter/setter for each method
|
//generate getter/setter for each method
|
||||||
for(Smethod method : inter.methods()){
|
for(Smethod method : inter.methods()){
|
||||||
String var = method.name();
|
String var = method.name();
|
||||||
@@ -732,14 +762,36 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
//make sure it's a real variable AND that the component doesn't already implement it somewhere with custom logic
|
//make sure it's a real variable AND that the component doesn't already implement it somewhere with custom logic
|
||||||
if(field == null || methodNames.contains(method.simpleString())) continue;
|
if(field == null || methodNames.contains(method.simpleString())) continue;
|
||||||
|
|
||||||
|
MethodSpec result = null;
|
||||||
|
|
||||||
//getter
|
//getter
|
||||||
if(!method.isVoid()){
|
if(!method.isVoid()){
|
||||||
def.builder.addMethod(MethodSpec.overriding(method.e).addStatement("return " + var).build());
|
result = MethodSpec.overriding(method.e).addStatement("return " + var).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
//setter
|
//setter
|
||||||
if(method.isVoid() && !Seq.with(field.annotations).contains(f -> f.type.toString().equals("@mindustry.annotations.Annotations.ReadOnly"))){
|
if(method.isVoid() && !Seq.with(field.annotations).contains(f -> f.type.toString().equals("@mindustry.annotations.Annotations.ReadOnly"))){
|
||||||
def.builder.addMethod(MethodSpec.overriding(method.e).addStatement("this." + var + " = " + var).build());
|
result = MethodSpec.overriding(method.e).addStatement("this." + var + " = " + var).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
//add getter/setter to parent class, if possible. when this happens, skip adding getters setters *here* because they are defined in the superclass.
|
||||||
|
if(result != null && superclass != null){
|
||||||
|
FieldSpec superField = Seq.with(superclass.fieldSpecs).find(f -> f.name.equals(var));
|
||||||
|
|
||||||
|
//found the right field, try to check for the method already existing now
|
||||||
|
if(superField != null){
|
||||||
|
MethodSpec fr = result;
|
||||||
|
MethodSpec targetMethod = Seq.with(superclass.methodSpecs).find(m -> m.name.equals(var) && m.returnType.equals(fr.returnType));
|
||||||
|
//if the method isn't added yet, add it. in any case, skip.
|
||||||
|
if(targetMethod == null){
|
||||||
|
superclass.addMethod(result);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result != null){
|
||||||
|
def.builder.addMethod(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -747,8 +799,16 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
write(def.builder, imports.asArray());
|
write(def.builder, imports.asArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//write base classes last
|
||||||
|
for(TypeSpec.Builder b : baseClasses){
|
||||||
|
write(b, imports.asArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO nulls were an awful idea
|
||||||
//store nulls
|
//store nulls
|
||||||
TypeSpec.Builder nullsBuilder = TypeSpec.classBuilder("Nulls").addModifiers(Modifier.PUBLIC).addModifiers(Modifier.FINAL);
|
TypeSpec.Builder nullsBuilder = TypeSpec.classBuilder("Nulls").addModifiers(Modifier.PUBLIC).addModifiers(Modifier.FINAL);
|
||||||
|
//TODO should be dynamic
|
||||||
|
ObjectSet<String> nullList = ObjectSet.with("unit");
|
||||||
|
|
||||||
//create mock types of all components
|
//create mock types of all components
|
||||||
for(Stype interf : allInterfaces){
|
for(Stype interf : allInterfaces){
|
||||||
@@ -767,6 +827,12 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
|
|
||||||
//create null builder
|
//create null builder
|
||||||
String baseName = interf.name().substring(0, interf.name().length() - 1);
|
String baseName = interf.name().substring(0, interf.name().length() - 1);
|
||||||
|
|
||||||
|
//prevent Nulls bloat
|
||||||
|
if(!nullList.contains(Strings.camelize(baseName))){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
String className = "Null" + baseName;
|
String className = "Null" + baseName;
|
||||||
TypeSpec.Builder nullBuilder = TypeSpec.classBuilder(className)
|
TypeSpec.Builder nullBuilder = TypeSpec.classBuilder(className)
|
||||||
.addModifiers(Modifier.FINAL);
|
.addModifiers(Modifier.FINAL);
|
||||||
@@ -900,7 +966,7 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
}
|
}
|
||||||
|
|
||||||
String createName(Selement<?> elem){
|
String createName(Selement<?> elem){
|
||||||
Seq<Stype> comps = types(elem.annotation(EntityDef.class), EntityDef::value).map(this::interfaceToComp);;
|
Seq<Stype> comps = types(elem.annotation(EntityDef.class), EntityDef::value).map(this::interfaceToComp);
|
||||||
comps.sortComparing(Selement::name);
|
comps.sortComparing(Selement::name);
|
||||||
return comps.toString("", s -> s.name().replace("Comp", ""));
|
return comps.toString("", s -> s.name().replace("Comp", ""));
|
||||||
}
|
}
|
||||||
@@ -944,9 +1010,10 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
final Selement naming;
|
final Selement naming;
|
||||||
final String name;
|
final String name;
|
||||||
final @Nullable TypeName extend;
|
final @Nullable TypeName extend;
|
||||||
|
final boolean legacy;
|
||||||
int classID;
|
int classID;
|
||||||
|
|
||||||
public EntityDefinition(String name, Builder builder, Selement naming, TypeName extend, Seq<Stype> components, Seq<GroupDefinition> groups, Seq<FieldSpec> fieldSpec){
|
public EntityDefinition(String name, Builder builder, Selement naming, TypeName extend, Seq<Stype> components, Seq<GroupDefinition> groups, Seq<FieldSpec> fieldSpec, boolean legacy){
|
||||||
this.builder = builder;
|
this.builder = builder;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.naming = naming;
|
this.naming = naming;
|
||||||
@@ -954,6 +1021,7 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
this.components = components;
|
this.components = components;
|
||||||
this.extend = extend;
|
this.extend = extend;
|
||||||
this.fieldSpecs = fieldSpec;
|
this.fieldSpecs = fieldSpec;
|
||||||
|
this.legacy = legacy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class AssetsProcess extends BaseProcessor{
|
|||||||
|
|
||||||
texIcons.each((key, val) -> {
|
texIcons.each((key, val) -> {
|
||||||
String[] split = val.split("\\|");
|
String[] split = val.split("\\|");
|
||||||
String name = Strings.kebabToCamel(split[1]).replace("Medium", "").replace("Icon", "");
|
String name = Strings.kebabToCamel(split[1]).replace("Medium", "").replace("Icon", "").replace("Ui", "");
|
||||||
if(SourceVersion.isKeyword(name) || name.equals("char")) name += "i";
|
if(SourceVersion.isKeyword(name) || name.equals("char")) name += "i";
|
||||||
|
|
||||||
ichtype.addField(FieldSpec.builder(char.class, name, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).addJavadoc(String.format("\\u%04x", Integer.parseInt(key))).initializer("'" + ((char)Integer.parseInt(key)) + "'").build());
|
ichtype.addField(FieldSpec.builder(char.class, name, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).addJavadoc(String.format("\\u%04x", Integer.parseInt(key))).initializer("'" + ((char)Integer.parseInt(key)) + "'").build());
|
||||||
@@ -117,7 +117,6 @@ public class AssetsProcess extends BaseProcessor{
|
|||||||
|
|
||||||
void processSounds(String classname, String path, String rtype) throws Exception{
|
void processSounds(String classname, String path, String rtype) throws Exception{
|
||||||
TypeSpec.Builder type = TypeSpec.classBuilder(classname).addModifiers(Modifier.PUBLIC);
|
TypeSpec.Builder type = TypeSpec.classBuilder(classname).addModifiers(Modifier.PUBLIC);
|
||||||
MethodSpec.Builder dispose = MethodSpec.methodBuilder("dispose").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
|
||||||
MethodSpec.Builder loadBegin = MethodSpec.methodBuilder("load").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
MethodSpec.Builder loadBegin = MethodSpec.methodBuilder("load").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
||||||
|
|
||||||
HashSet<String> names = new HashSet<>();
|
HashSet<String> names = new HashSet<>();
|
||||||
@@ -137,8 +136,6 @@ public class AssetsProcess extends BaseProcessor{
|
|||||||
String filename = "\"" + filepath + "\"";
|
String filename = "\"" + filepath + "\"";
|
||||||
loadBegin.addStatement("arc.Core.assets.load(" + filename + ", " + rtype + ".class).loaded = a -> " + name + " = (" + rtype + ")a", filepath, filepath.replace(".ogg", ".mp3"));
|
loadBegin.addStatement("arc.Core.assets.load(" + filename + ", " + rtype + ".class).loaded = a -> " + name + " = (" + rtype + ")a", filepath, filepath.replace(".ogg", ".mp3"));
|
||||||
|
|
||||||
dispose.addStatement("arc.Core.assets.unload(" + filename + ")");
|
|
||||||
dispose.addStatement(name + " = null");
|
|
||||||
type.addField(FieldSpec.builder(ClassName.bestGuess(rtype), name, Modifier.STATIC, Modifier.PUBLIC).initializer("new arc.audio." + rtype.substring(rtype.lastIndexOf(".") + 1) + "()").build());
|
type.addField(FieldSpec.builder(ClassName.bestGuess(rtype), name, Modifier.STATIC, Modifier.PUBLIC).initializer("new arc.audio." + rtype.substring(rtype.lastIndexOf(".") + 1) + "()").build());
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -147,7 +144,6 @@ public class AssetsProcess extends BaseProcessor{
|
|||||||
}
|
}
|
||||||
|
|
||||||
type.addMethod(loadBegin.build());
|
type.addMethod(loadBegin.build());
|
||||||
type.addMethod(dispose.build());
|
|
||||||
JavaFile.builder(packageName, type.build()).build().writeTo(BaseProcessor.filer);
|
JavaFile.builder(packageName, type.build()).build().writeTo(BaseProcessor.filer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,154 +0,0 @@
|
|||||||
package mindustry.annotations.impl;
|
|
||||||
|
|
||||||
import com.sun.source.tree.*;
|
|
||||||
import com.sun.source.util.*;
|
|
||||||
import com.sun.tools.javac.code.Scope;
|
|
||||||
import com.sun.tools.javac.code.*;
|
|
||||||
import com.sun.tools.javac.code.Symbol.*;
|
|
||||||
import com.sun.tools.javac.code.Type.*;
|
|
||||||
import com.sun.tools.javac.tree.*;
|
|
||||||
import com.sun.tools.javac.tree.JCTree.*;
|
|
||||||
import mindustry.annotations.Annotations.*;
|
|
||||||
|
|
||||||
import javax.annotation.processing.*;
|
|
||||||
import javax.lang.model.*;
|
|
||||||
import javax.lang.model.element.*;
|
|
||||||
import javax.tools.Diagnostic.*;
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
@SupportedAnnotationTypes({"java.lang.Override"})
|
|
||||||
public class CallSuperProcess extends AbstractProcessor{
|
|
||||||
private Trees trees;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(ProcessingEnvironment pe){
|
|
||||||
super.init(pe);
|
|
||||||
trees = Trees.instance(pe);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
|
|
||||||
for(Element e : roundEnv.getElementsAnnotatedWith(Override.class)){
|
|
||||||
if(e.getAnnotation(OverrideCallSuper.class) != null) return false;
|
|
||||||
|
|
||||||
CodeAnalyzerTreeScanner codeScanner = new CodeAnalyzerTreeScanner();
|
|
||||||
codeScanner.methodName = e.getSimpleName().toString();
|
|
||||||
|
|
||||||
TreePath tp = trees.getPath(e.getEnclosingElement());
|
|
||||||
codeScanner.scan(tp, trees);
|
|
||||||
|
|
||||||
if(codeScanner.callSuperUsed){
|
|
||||||
List list = codeScanner.method.getBody().getStatements();
|
|
||||||
|
|
||||||
if(!doesCallSuper(list, codeScanner.methodName)){
|
|
||||||
processingEnv.getMessager().printMessage(Kind.ERROR, "Overriding method '" + codeScanner.methodName + "' must explicitly call super method from its parent class.", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean doesCallSuper(List list, String methodName){
|
|
||||||
for(Object object : list){
|
|
||||||
if(object instanceof JCTree.JCExpressionStatement){
|
|
||||||
JCTree.JCExpressionStatement expr = (JCExpressionStatement)object;
|
|
||||||
String exprString = expr.toString();
|
|
||||||
if(exprString.startsWith("super." + methodName) && exprString.endsWith(");")) return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourceVersion getSupportedSourceVersion(){
|
|
||||||
return SourceVersion.RELEASE_8;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class CodeAnalyzerTreeScanner extends TreePathScanner<Object, Trees>{
|
|
||||||
String methodName;
|
|
||||||
MethodTree method;
|
|
||||||
boolean callSuperUsed;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object visitClass(ClassTree classTree, Trees trees){
|
|
||||||
Tree extendTree = classTree.getExtendsClause();
|
|
||||||
|
|
||||||
if(extendTree instanceof JCTypeApply){ //generic classes case
|
|
||||||
JCTypeApply generic = (JCTypeApply)extendTree;
|
|
||||||
extendTree = generic.clazz;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(extendTree instanceof JCIdent){
|
|
||||||
JCIdent tree = (JCIdent)extendTree;
|
|
||||||
|
|
||||||
if(tree == null || tree.sym == null) return super.visitClass(classTree, trees);
|
|
||||||
|
|
||||||
com.sun.tools.javac.code.Scope members = tree.sym.members();
|
|
||||||
|
|
||||||
if(checkScope(members))
|
|
||||||
return super.visitClass(classTree, trees);
|
|
||||||
|
|
||||||
if(checkSuperTypes((ClassType)tree.type))
|
|
||||||
return super.visitClass(classTree, trees);
|
|
||||||
|
|
||||||
}
|
|
||||||
callSuperUsed = false;
|
|
||||||
|
|
||||||
return super.visitClass(classTree, trees);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean checkSuperTypes(ClassType type){
|
|
||||||
if(type.supertype_field != null && type.supertype_field.tsym != null){
|
|
||||||
if(checkScope(type.supertype_field.tsym.members()))
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return checkSuperTypes((ClassType)type.supertype_field);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public boolean checkScope(Scope members){
|
|
||||||
Iterable<Symbol> it;
|
|
||||||
try{
|
|
||||||
it = (Iterable<Symbol>)members.getClass().getMethod("getElements").invoke(members);
|
|
||||||
}catch(Throwable t){
|
|
||||||
try{
|
|
||||||
it = (Iterable<Symbol>)members.getClass().getMethod("getSymbols").invoke(members);
|
|
||||||
}catch(Exception e){
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(Symbol s : it){
|
|
||||||
|
|
||||||
if(s instanceof MethodSymbol){
|
|
||||||
MethodSymbol ms = (MethodSymbol)s;
|
|
||||||
|
|
||||||
if(ms.getSimpleName().toString().equals(methodName)){
|
|
||||||
Annotation annotation = ms.getAnnotation(CallSuper.class);
|
|
||||||
if(annotation != null){
|
|
||||||
callSuperUsed = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object visitMethod(MethodTree methodTree, Trees trees){
|
|
||||||
if(methodTree.getName().toString().equals(methodName))
|
|
||||||
method = methodTree;
|
|
||||||
|
|
||||||
return super.visitMethod(methodTree, trees);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,6 +18,7 @@ public class LoadRegionProcessor extends BaseProcessor{
|
|||||||
@Override
|
@Override
|
||||||
public void process(RoundEnvironment env) throws Exception{
|
public void process(RoundEnvironment env) throws Exception{
|
||||||
TypeSpec.Builder regionClass = TypeSpec.classBuilder("ContentRegions")
|
TypeSpec.Builder regionClass = TypeSpec.classBuilder("ContentRegions")
|
||||||
|
.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "\"deprecation\"").build())
|
||||||
.addModifiers(Modifier.PUBLIC);
|
.addModifiers(Modifier.PUBLIC);
|
||||||
MethodSpec.Builder method = MethodSpec.methodBuilder("loadRegions")
|
MethodSpec.Builder method = MethodSpec.methodBuilder("loadRegions")
|
||||||
.addParameter(tname("mindustry.ctype.MappableContent"), "content")
|
.addParameter(tname("mindustry.ctype.MappableContent"), "content")
|
||||||
@@ -34,7 +35,7 @@ public class LoadRegionProcessor extends BaseProcessor{
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(Entry<Stype, Seq<Svar>> entry : fieldMap){
|
for(Entry<Stype, Seq<Svar>> entry : fieldMap){
|
||||||
method.beginControlFlow("if(content instanceof $T)", entry.key.tname());
|
method.beginControlFlow("if(content instanceof $L)", entry.key.fullName());
|
||||||
|
|
||||||
for(Svar field : entry.value){
|
for(Svar field : entry.value){
|
||||||
Load an = field.annotation(Load.class);
|
Load an = field.annotation(Load.class);
|
||||||
@@ -45,7 +46,7 @@ public class LoadRegionProcessor extends BaseProcessor{
|
|||||||
|
|
||||||
//not an array
|
//not an array
|
||||||
if(dims == 0){
|
if(dims == 0){
|
||||||
method.addStatement("(($T)content).$L = $T.atlas.find($L$L)", entry.key.tname(), field.name(), Core.class, parse(an.value()), fallbackString);
|
method.addStatement("(($L)content).$L = $T.atlas.find($L$L)", entry.key.fullName(), field.name(), Core.class, parse(an.value()), fallbackString);
|
||||||
}else{
|
}else{
|
||||||
//is an array, create length string
|
//is an array, create length string
|
||||||
int[] lengths = an.lengths();
|
int[] lengths = an.lengths();
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ public class LogicStatementProcessor extends BaseProcessor{
|
|||||||
MethodSpec.Builder reader = MethodSpec.methodBuilder("read")
|
MethodSpec.Builder reader = MethodSpec.methodBuilder("read")
|
||||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||||
.returns(tname("mindustry.logic.LStatement"))
|
.returns(tname("mindustry.logic.LStatement"))
|
||||||
.addParameter(String[].class, "tokens");
|
.addParameter(String[].class, "tokens")
|
||||||
|
.addParameter(int.class, "length");
|
||||||
|
|
||||||
Seq<Stype> types = types(RegisterStatement.class);
|
Seq<Stype> types = types(RegisterStatement.class);
|
||||||
|
|
||||||
@@ -76,7 +77,7 @@ public class LogicStatementProcessor extends BaseProcessor{
|
|||||||
"");
|
"");
|
||||||
|
|
||||||
//reading primitives, strings and enums is supported; nothing else is
|
//reading primitives, strings and enums is supported; nothing else is
|
||||||
reader.addStatement("if(tokens.length > $L) result.$L = $L(tokens[$L])",
|
reader.addStatement("if(length > $L) result.$L = $L(tokens[$L])",
|
||||||
index + 1,
|
index + 1,
|
||||||
field.name(),
|
field.name(),
|
||||||
field.mirror().toString().equals("java.lang.String") ?
|
field.mirror().toString().equals("java.lang.String") ?
|
||||||
|
|||||||
@@ -0,0 +1,380 @@
|
|||||||
|
package mindustry.annotations.remote;
|
||||||
|
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.util.io.*;
|
||||||
|
import com.squareup.javapoet.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.annotations.*;
|
||||||
|
import mindustry.annotations.util.*;
|
||||||
|
import mindustry.annotations.util.TypeIOResolver.*;
|
||||||
|
|
||||||
|
import javax.lang.model.element.*;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
import static mindustry.annotations.BaseProcessor.*;
|
||||||
|
|
||||||
|
/** Generates code for writing remote invoke packets on the client and server. */
|
||||||
|
public class CallGenerator{
|
||||||
|
|
||||||
|
/** Generates all classes in this list. */
|
||||||
|
public static void generate(ClassSerializer serializer, Seq<MethodEntry> methods) throws IOException{
|
||||||
|
//create builder
|
||||||
|
TypeSpec.Builder callBuilder = TypeSpec.classBuilder(RemoteProcess.callLocation).addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
|
MethodSpec.Builder register = MethodSpec.methodBuilder("registerPackets")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
||||||
|
|
||||||
|
//go through each method entry in this class
|
||||||
|
for(MethodEntry ent : methods){
|
||||||
|
//builder for the packet type
|
||||||
|
TypeSpec.Builder packet = TypeSpec.classBuilder(ent.packetClassName)
|
||||||
|
.addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
|
//temporary data to deserialize later
|
||||||
|
packet.addField(FieldSpec.builder(byte[].class, "DATA", Modifier.PRIVATE).initializer("NODATA").build());
|
||||||
|
|
||||||
|
packet.superclass(tname("mindustry.net.Packet"));
|
||||||
|
|
||||||
|
//return the correct priority
|
||||||
|
if(ent.priority != PacketPriority.normal){
|
||||||
|
packet.addMethod(MethodSpec.methodBuilder("getPriority")
|
||||||
|
.addModifiers(Modifier.PUBLIC)
|
||||||
|
.addAnnotation(Override.class).returns(int.class).addStatement("return $L", ent.priority.ordinal())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
//implement read & write methods
|
||||||
|
makeWriter(packet, ent, serializer);
|
||||||
|
makeReader(packet, ent, serializer);
|
||||||
|
|
||||||
|
//generate handlers
|
||||||
|
if(ent.where.isClient){
|
||||||
|
packet.addMethod(writeHandleMethod(ent, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ent.where.isServer){
|
||||||
|
packet.addMethod(writeHandleMethod(ent, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
//register packet
|
||||||
|
register.addStatement("mindustry.net.Net.registerPacket($L.$L::new)", packageName, ent.packetClassName);
|
||||||
|
|
||||||
|
//add fields to the type
|
||||||
|
for(Svar param : ent.element.params()){
|
||||||
|
packet.addField(param.tname(), param.name(), Modifier.PUBLIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
//write the 'send event to all players' variant: always happens for clients, but only happens if 'all' is enabled on the server method
|
||||||
|
if(ent.where.isClient || ent.target.isAll){
|
||||||
|
writeCallMethod(callBuilder, ent, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//write the 'send event to one player' variant, which is only applicable on the server
|
||||||
|
if(ent.where.isServer && ent.target.isOne){
|
||||||
|
writeCallMethod(callBuilder, ent, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//write the forwarded method version
|
||||||
|
if(ent.where.isServer && ent.forward){
|
||||||
|
writeCallMethod(callBuilder, ent, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//write the completed packet class
|
||||||
|
JavaFile.builder(packageName, packet.build()).build().writeTo(BaseProcessor.filer);
|
||||||
|
}
|
||||||
|
|
||||||
|
callBuilder.addMethod(register.build());
|
||||||
|
|
||||||
|
//build and write resulting class
|
||||||
|
TypeSpec spec = callBuilder.build();
|
||||||
|
JavaFile.builder(packageName, spec).build().writeTo(BaseProcessor.filer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void makeWriter(TypeSpec.Builder typespec, MethodEntry ent, ClassSerializer serializer){
|
||||||
|
MethodSpec.Builder builder = MethodSpec.methodBuilder("write")
|
||||||
|
.addParameter(Writes.class, "WRITE")
|
||||||
|
.addModifiers(Modifier.PUBLIC).addAnnotation(Override.class);
|
||||||
|
Seq<Svar> params = ent.element.params();
|
||||||
|
|
||||||
|
for(int i = 0; i < params.size; i++){
|
||||||
|
//first argument is skipped as it is always the player caller
|
||||||
|
if(!ent.where.isServer && i == 0){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Svar var = params.get(i);
|
||||||
|
|
||||||
|
//name of parameter
|
||||||
|
String varName = var.name();
|
||||||
|
//name of parameter type
|
||||||
|
String typeName = var.mirror().toString();
|
||||||
|
//special case: method can be called from anywhere to anywhere
|
||||||
|
//thus, only write the player when the SERVER is writing data, since the client is the only one who reads the player anyway
|
||||||
|
boolean writePlayerSkipCheck = ent.where == Loc.both && i == 0;
|
||||||
|
|
||||||
|
if(writePlayerSkipCheck){ //write begin check
|
||||||
|
builder.beginControlFlow("if(mindustry.Vars.net.server())");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(BaseProcessor.isPrimitive(typeName)){ //check if it's a primitive, and if so write it
|
||||||
|
builder.addStatement("WRITE.$L($L)", typeName.equals("boolean") ? "bool" : typeName.charAt(0) + "", varName);
|
||||||
|
}else{
|
||||||
|
//else, try and find a serializer
|
||||||
|
String ser = serializer.writers.get(typeName.replace("mindustry.gen.", ""), SerializerResolver.locate(ent.element.e, var.mirror(), true));
|
||||||
|
|
||||||
|
if(ser == null){ //make sure a serializer exists!
|
||||||
|
BaseProcessor.err("No method to write class type: '" + typeName + "'", var);
|
||||||
|
}
|
||||||
|
|
||||||
|
//add statement for writing it
|
||||||
|
builder.addStatement(ser + "(WRITE, " + varName + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(writePlayerSkipCheck){ //write end check
|
||||||
|
builder.endControlFlow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typespec.addMethod(builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void makeReader(TypeSpec.Builder typespec, MethodEntry ent, ClassSerializer serializer){
|
||||||
|
MethodSpec.Builder readbuilder = MethodSpec.methodBuilder("read")
|
||||||
|
.addParameter(Reads.class, "READ")
|
||||||
|
.addParameter(int.class, "LENGTH")
|
||||||
|
.addModifiers(Modifier.PUBLIC).addAnnotation(Override.class);
|
||||||
|
|
||||||
|
//read only into temporary data buffer
|
||||||
|
readbuilder.addStatement("DATA = READ.b(LENGTH)");
|
||||||
|
|
||||||
|
typespec.addMethod(readbuilder.build());
|
||||||
|
|
||||||
|
MethodSpec.Builder builder = MethodSpec.methodBuilder("handled")
|
||||||
|
.addModifiers(Modifier.PUBLIC)
|
||||||
|
.addAnnotation(Override.class);
|
||||||
|
|
||||||
|
//make sure data is present, begin reading it if so
|
||||||
|
builder.addStatement("BAIS.setBytes(DATA)");
|
||||||
|
|
||||||
|
Seq<Svar> params = ent.element.params();
|
||||||
|
|
||||||
|
//go through each parameter
|
||||||
|
for(int i = 0; i < params.size; i++){
|
||||||
|
Svar var = params.get(i);
|
||||||
|
|
||||||
|
//first argument is skipped as it is always the player caller
|
||||||
|
if(!ent.where.isServer && i == 0){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//special case: method can be called from anywhere to anywhere
|
||||||
|
//thus, only read the player when the CLIENT is receiving data, since the client is the only one who cares about the player anyway
|
||||||
|
boolean writePlayerSkipCheck = ent.where == Loc.both && i == 0;
|
||||||
|
|
||||||
|
if(writePlayerSkipCheck){ //write begin check
|
||||||
|
builder.beginControlFlow("if(mindustry.Vars.net.client())");
|
||||||
|
}
|
||||||
|
|
||||||
|
//full type name of parameter
|
||||||
|
String typeName = var.mirror().toString();
|
||||||
|
//name of parameter
|
||||||
|
String varName = var.name();
|
||||||
|
//capitalized version of type name for reading primitives
|
||||||
|
String pname = typeName.equals("boolean") ? "bool" : typeName.charAt(0) + "";
|
||||||
|
|
||||||
|
//write primitives automatically
|
||||||
|
if(BaseProcessor.isPrimitive(typeName)){
|
||||||
|
builder.addStatement("$L = READ.$L()", varName, pname);
|
||||||
|
}else{
|
||||||
|
//else, try and find a serializer
|
||||||
|
String ser = serializer.readers.get(typeName.replace("mindustry.gen.", ""), SerializerResolver.locate(ent.element.e, var.mirror(), false));
|
||||||
|
|
||||||
|
if(ser == null){ //make sure a serializer exists!
|
||||||
|
BaseProcessor.err("No read method to read class type '" + typeName + "' in method " + ent.targetMethod + "; " + serializer.readers, var);
|
||||||
|
}
|
||||||
|
|
||||||
|
//add statement for reading it
|
||||||
|
builder.addStatement("$L = $L(READ)", varName, ser);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(writePlayerSkipCheck){ //write end check
|
||||||
|
builder.endControlFlow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typespec.addMethod(builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a specific variant for a method entry. */
|
||||||
|
private static void writeCallMethod(TypeSpec.Builder classBuilder, MethodEntry ent, boolean toAll, boolean forwarded){
|
||||||
|
Smethod elem = ent.element;
|
||||||
|
Seq<Svar> params = elem.params();
|
||||||
|
|
||||||
|
//create builder
|
||||||
|
MethodSpec.Builder method = MethodSpec.methodBuilder(elem.name() + (forwarded ? "__forward" : "")) //add except suffix when forwarding
|
||||||
|
.addModifiers(Modifier.STATIC)
|
||||||
|
.returns(void.class);
|
||||||
|
|
||||||
|
//forwarded methods aren't intended for use, and are not public
|
||||||
|
if(!forwarded){
|
||||||
|
method.addModifiers(Modifier.PUBLIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
//validate client methods to make sure
|
||||||
|
if(ent.where.isClient){
|
||||||
|
if(params.isEmpty()){
|
||||||
|
BaseProcessor.err("Client invoke methods must have a first parameter of type Player", elem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!params.get(0).mirror().toString().contains("Player")){
|
||||||
|
BaseProcessor.err("Client invoke methods should have a first parameter of type Player", elem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if toAll is false, it's a 'send to one player' variant, so add the player as a parameter
|
||||||
|
if(!toAll){
|
||||||
|
method.addParameter(ClassName.bestGuess("mindustry.net.NetConnection"), "playerConnection");
|
||||||
|
}
|
||||||
|
|
||||||
|
//add sender to ignore
|
||||||
|
if(forwarded){
|
||||||
|
method.addParameter(ClassName.bestGuess("mindustry.net.NetConnection"), "exceptConnection");
|
||||||
|
}
|
||||||
|
|
||||||
|
//call local method if applicable, shouldn't happen when forwarding method as that already happens by default
|
||||||
|
if(!forwarded && ent.local != Loc.none){
|
||||||
|
//add in local checks
|
||||||
|
if(ent.local != Loc.both){
|
||||||
|
method.beginControlFlow("if(" + getCheckString(ent.local) + " || !mindustry.Vars.net.active())");
|
||||||
|
}
|
||||||
|
|
||||||
|
//concatenate parameters
|
||||||
|
int index = 0;
|
||||||
|
StringBuilder results = new StringBuilder();
|
||||||
|
for(Svar var : params){
|
||||||
|
//special case: calling local-only methods uses the local player
|
||||||
|
if(index == 0 && ent.where == Loc.client){
|
||||||
|
results.append("mindustry.Vars.player");
|
||||||
|
}else{
|
||||||
|
results.append(var.name());
|
||||||
|
}
|
||||||
|
if(index != params.size - 1) results.append(", ");
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//add the statement to call it
|
||||||
|
method.addStatement("$N." + elem.name() + "(" + results + ")",
|
||||||
|
((TypeElement)elem.up()).getQualifiedName().toString());
|
||||||
|
|
||||||
|
if(ent.local != Loc.both){
|
||||||
|
method.endControlFlow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//start control flow to check if it's actually client/server so no netcode is called
|
||||||
|
method.beginControlFlow("if(" + getCheckString(ent.where) + ")");
|
||||||
|
|
||||||
|
//add statement to create packet from pool
|
||||||
|
method.addStatement("$1T packet = new $1T()", tname("mindustry.gen." + ent.packetClassName));
|
||||||
|
|
||||||
|
method.addTypeVariables(Seq.with(elem.e.getTypeParameters()).map(BaseProcessor::getTVN));
|
||||||
|
|
||||||
|
for(int i = 0; i < params.size; i++){
|
||||||
|
//first argument is skipped as it is always the player caller
|
||||||
|
if((!ent.where.isServer) && i == 0){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Svar var = params.get(i);
|
||||||
|
|
||||||
|
method.addParameter(var.tname(), var.name());
|
||||||
|
|
||||||
|
//name of parameter
|
||||||
|
String varName = var.name();
|
||||||
|
//special case: method can be called from anywhere to anywhere
|
||||||
|
//thus, only write the player when the SERVER is writing data, since the client is the only one who reads it
|
||||||
|
boolean writePlayerSkipCheck = ent.where == Loc.both && i == 0;
|
||||||
|
|
||||||
|
if(writePlayerSkipCheck){ //write begin check
|
||||||
|
method.beginControlFlow("if(mindustry.Vars.net.server())");
|
||||||
|
}
|
||||||
|
|
||||||
|
method.addStatement("packet.$L = $L", varName, varName);
|
||||||
|
|
||||||
|
if(writePlayerSkipCheck){ //write end check
|
||||||
|
method.endControlFlow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String sendString;
|
||||||
|
|
||||||
|
if(forwarded){ //forward packet
|
||||||
|
if(!ent.local.isClient){ //if the client doesn't get it called locally, forward it back after validation
|
||||||
|
sendString = "mindustry.Vars.net.send(";
|
||||||
|
}else{
|
||||||
|
sendString = "mindustry.Vars.net.sendExcept(exceptConnection, ";
|
||||||
|
}
|
||||||
|
}else if(toAll){ //send to all players / to server
|
||||||
|
sendString = "mindustry.Vars.net.send(";
|
||||||
|
}else{ //send to specific client from server
|
||||||
|
sendString = "playerConnection.send(";
|
||||||
|
}
|
||||||
|
|
||||||
|
//send the actual packet
|
||||||
|
method.addStatement(sendString + "packet, " + (!ent.unreliable) + ")");
|
||||||
|
|
||||||
|
|
||||||
|
//end check for server/client
|
||||||
|
method.endControlFlow();
|
||||||
|
|
||||||
|
//add method to class, finally
|
||||||
|
classBuilder.addMethod(method.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getCheckString(Loc loc){
|
||||||
|
return
|
||||||
|
loc.isClient && loc.isServer ? "mindustry.Vars.net.server() || mindustry.Vars.net.client()" :
|
||||||
|
loc.isClient ? "mindustry.Vars.net.client()" :
|
||||||
|
loc.isServer ? "mindustry.Vars.net.server()" : "false";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Generates handleServer / handleClient methods. */
|
||||||
|
public static MethodSpec writeHandleMethod(MethodEntry ent, boolean isClient){
|
||||||
|
|
||||||
|
//create main method builder
|
||||||
|
MethodSpec.Builder builder = MethodSpec.methodBuilder(isClient ? "handleClient" : "handleServer")
|
||||||
|
.addModifiers(Modifier.PUBLIC)
|
||||||
|
.addAnnotation(Override.class)
|
||||||
|
.returns(void.class);
|
||||||
|
|
||||||
|
Smethod elem = ent.element;
|
||||||
|
Seq<Svar> params = elem.params();
|
||||||
|
|
||||||
|
if(!isClient){
|
||||||
|
//add player parameter
|
||||||
|
builder.addParameter(ClassName.get("mindustry.net", "NetConnection"), "con");
|
||||||
|
|
||||||
|
//skip if player is invalid
|
||||||
|
builder.beginControlFlow("if(con.player == null || con.kicked)");
|
||||||
|
builder.addStatement("return");
|
||||||
|
builder.endControlFlow();
|
||||||
|
|
||||||
|
//make sure to use the actual player who sent the packet
|
||||||
|
builder.addStatement("mindustry.gen.Player player = con.player");
|
||||||
|
}
|
||||||
|
|
||||||
|
//execute the relevant method before the forward
|
||||||
|
//if it throws a ValidateException, the method won't be forwarded
|
||||||
|
builder.addStatement("$N." + elem.name() + "(" + params.toString(", ", s -> s.name()) + ")", ((TypeElement)elem.up()).getQualifiedName().toString());
|
||||||
|
|
||||||
|
//call forwarded method, don't forward on the client reader
|
||||||
|
if(ent.forward && ent.where.isServer && !isClient){
|
||||||
|
//call forwarded method
|
||||||
|
builder.addStatement("$L.$L.$L__forward(con, $L)", packageName, ent.className, elem.name(), params.toString(", ", s -> s.name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package mindustry.annotations.remote;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/** Represents a class witha list method entries to include in it. */
|
|
||||||
public class ClassEntry{
|
|
||||||
/** All methods in this generated class. */
|
|
||||||
public final ArrayList<MethodEntry> methods = new ArrayList<>();
|
|
||||||
/** Simple class name. */
|
|
||||||
public final String name;
|
|
||||||
|
|
||||||
public ClassEntry(String name){
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
package mindustry.annotations.remote;
|
package mindustry.annotations.remote;
|
||||||
|
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.annotations.util.*;
|
||||||
import javax.lang.model.element.ExecutableElement;
|
|
||||||
|
|
||||||
/** Class that repesents a remote method to be constructed and put into a class. */
|
/** Class that repesents a remote method to be constructed and put into a class. */
|
||||||
public class MethodEntry{
|
public class MethodEntry{
|
||||||
@@ -10,6 +9,8 @@ public class MethodEntry{
|
|||||||
public final String className;
|
public final String className;
|
||||||
/** Fully qualified target method to call. */
|
/** Fully qualified target method to call. */
|
||||||
public final String targetMethod;
|
public final String targetMethod;
|
||||||
|
/** Simple name of the generated packet class. */
|
||||||
|
public final String packetClassName;
|
||||||
/** Whether this method can be called on a client/server. */
|
/** Whether this method can be called on a client/server. */
|
||||||
public final Loc where;
|
public final Loc where;
|
||||||
/**
|
/**
|
||||||
@@ -26,12 +27,13 @@ public class MethodEntry{
|
|||||||
/** Unique method ID. */
|
/** Unique method ID. */
|
||||||
public final int id;
|
public final int id;
|
||||||
/** The element method associated with this entry. */
|
/** The element method associated with this entry. */
|
||||||
public final ExecutableElement element;
|
public final Smethod element;
|
||||||
/** The assigned packet priority. Only used in clients. */
|
/** The assigned packet priority. Only used in clients. */
|
||||||
public final PacketPriority priority;
|
public final PacketPriority priority;
|
||||||
|
|
||||||
public MethodEntry(String className, String targetMethod, Loc where, Variant target,
|
public MethodEntry(String className, String targetMethod, String packetClassName, Loc where, Variant target,
|
||||||
Loc local, boolean unreliable, boolean forward, int id, ExecutableElement element, PacketPriority priority){
|
Loc local, boolean unreliable, boolean forward, int id, Smethod element, PacketPriority priority){
|
||||||
|
this.packetClassName = packetClassName;
|
||||||
this.className = className;
|
this.className = className;
|
||||||
this.forward = forward;
|
this.forward = forward;
|
||||||
this.targetMethod = targetMethod;
|
this.targetMethod = targetMethod;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package mindustry.annotations.remote;
|
package mindustry.annotations.remote;
|
||||||
|
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import com.squareup.javapoet.*;
|
import arc.util.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.annotations.*;
|
import mindustry.annotations.*;
|
||||||
import mindustry.annotations.util.*;
|
import mindustry.annotations.util.*;
|
||||||
@@ -9,7 +9,6 @@ import mindustry.annotations.util.TypeIOResolver.*;
|
|||||||
|
|
||||||
import javax.annotation.processing.*;
|
import javax.annotation.processing.*;
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
|
|
||||||
/** The annotation processor for generating remote method call code. */
|
/** The annotation processor for generating remote method call code. */
|
||||||
@@ -18,52 +17,24 @@ import java.util.*;
|
|||||||
"mindustry.annotations.Annotations.TypeIOHandler"
|
"mindustry.annotations.Annotations.TypeIOHandler"
|
||||||
})
|
})
|
||||||
public class RemoteProcess extends BaseProcessor{
|
public class RemoteProcess extends BaseProcessor{
|
||||||
/** Maximum size of each event packet. */
|
|
||||||
public static final int maxPacketSize = 8192;
|
|
||||||
/** Warning on top of each autogenerated file. */
|
|
||||||
public static final String autogenWarning = "Autogenerated file. Do not modify!\n";
|
|
||||||
|
|
||||||
/** Name of class that handles reading and invoking packets on the server. */
|
|
||||||
private static final String readServerName = "RemoteReadServer";
|
|
||||||
/** Name of class that handles reading and invoking packets on the client. */
|
|
||||||
private static final String readClientName = "RemoteReadClient";
|
|
||||||
/** Simple class name of generated class name. */
|
/** Simple class name of generated class name. */
|
||||||
private static final String callLocation = "Call";
|
public static final String callLocation = "Call";
|
||||||
|
|
||||||
//class serializers
|
|
||||||
private ClassSerializer serializer;
|
|
||||||
//all elements with the Remote annotation
|
|
||||||
private Seq<Smethod> elements;
|
|
||||||
//map of all classes to generate by name
|
|
||||||
private HashMap<String, ClassEntry> classMap;
|
|
||||||
//list of all method entries
|
|
||||||
private Seq<MethodEntry> methods;
|
|
||||||
//list of all method entries
|
|
||||||
private Seq<ClassEntry> classes;
|
|
||||||
|
|
||||||
{
|
|
||||||
rounds = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(RoundEnvironment roundEnv) throws Exception{
|
public void process(RoundEnvironment roundEnv) throws Exception{
|
||||||
//round 1: find all annotations, generate *writers*
|
|
||||||
if(round == 1){
|
|
||||||
//get serializers
|
//get serializers
|
||||||
serializer = TypeIOResolver.resolve(this);
|
//class serializers
|
||||||
|
ClassSerializer serializer = TypeIOResolver.resolve(this);
|
||||||
//last method ID used
|
//last method ID used
|
||||||
int lastMethodID = 0;
|
int lastMethodID = 0;
|
||||||
//find all elements with the Remote annotation
|
//find all elements with the Remote annotation
|
||||||
elements = methods(Remote.class);
|
//all elements with the Remote annotation
|
||||||
//map of all classes to generate by name
|
Seq<Smethod> elements = methods(Remote.class);
|
||||||
classMap = new HashMap<>();
|
|
||||||
//list of all method entries
|
//list of all method entries
|
||||||
methods = new Seq<>();
|
Seq<MethodEntry> methods = new Seq<>();
|
||||||
//list of all method entries
|
|
||||||
classes = new Seq<>();
|
|
||||||
|
|
||||||
Seq<Smethod> orderedElements = elements.copy();
|
Seq<Smethod> orderedElements = elements.copy();
|
||||||
orderedElements.sortComparing(Object::toString);
|
orderedElements.sortComparing(Selement::toString);
|
||||||
|
|
||||||
//create methods
|
//create methods
|
||||||
for(Smethod element : orderedElements){
|
for(Smethod element : orderedElements){
|
||||||
@@ -71,53 +42,33 @@ public class RemoteProcess extends BaseProcessor{
|
|||||||
|
|
||||||
//check for static
|
//check for static
|
||||||
if(!element.is(Modifier.STATIC) || !element.is(Modifier.PUBLIC)){
|
if(!element.is(Modifier.STATIC) || !element.is(Modifier.PUBLIC)){
|
||||||
err("All @Remote methods must be public and static: ", element);
|
err("All @Remote methods must be public and static", element);
|
||||||
}
|
}
|
||||||
|
|
||||||
//can't generate none methods
|
//can't generate none methods
|
||||||
if(annotation.targets() == Loc.none){
|
if(annotation.targets() == Loc.none){
|
||||||
err("A @Remote method's targets() cannot be equal to 'none':", element);
|
err("A @Remote method's targets() cannot be equal to 'none'", element);
|
||||||
}
|
}
|
||||||
|
|
||||||
//get and create class entry if needed
|
String packetName = Strings.capitalize(element.name()) + "CallPacket";
|
||||||
if(!classMap.containsKey(callLocation)){
|
int[] index = {1};
|
||||||
ClassEntry clas = new ClassEntry(callLocation);
|
|
||||||
classMap.put(callLocation, clas);
|
|
||||||
classes.add(clas);
|
|
||||||
}
|
|
||||||
|
|
||||||
ClassEntry entry = classMap.get(callLocation);
|
while(methods.contains(m -> m.packetClassName.equals(packetName + (index[0] == 1 ? "" : index[0])))){
|
||||||
|
index[0] ++;
|
||||||
|
}
|
||||||
|
|
||||||
//create and add entry
|
//create and add entry
|
||||||
MethodEntry method = new MethodEntry(entry.name, BaseProcessor.getMethodName(element.e), annotation.targets(), annotation.variants(),
|
MethodEntry method = new MethodEntry(
|
||||||
annotation.called(), annotation.unreliable(), annotation.forward(), lastMethodID++, element.e, annotation.priority());
|
callLocation, BaseProcessor.getMethodName(element.e), packetName + (index[0] == 1 ? "" : index[0]),
|
||||||
|
annotation.targets(), annotation.variants(),
|
||||||
|
annotation.called(), annotation.unreliable(), annotation.forward(), lastMethodID++,
|
||||||
|
element, annotation.priority()
|
||||||
|
);
|
||||||
|
|
||||||
entry.methods.add(method);
|
|
||||||
methods.add(method);
|
methods.add(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
//create read/write generators
|
//generate the methods to invoke, as well as the packet classes
|
||||||
RemoteWriteGenerator writegen = new RemoteWriteGenerator(serializer);
|
CallGenerator.generate(serializer, methods);
|
||||||
|
|
||||||
//generate the methods to invoke (write)
|
|
||||||
writegen.generateFor(classes, packageName);
|
|
||||||
}else if(round == 2){ //round 2: generate all *readers*
|
|
||||||
RemoteReadGenerator readgen = new RemoteReadGenerator(serializer);
|
|
||||||
|
|
||||||
//generate server readers
|
|
||||||
readgen.generateFor(methods.select(method -> method.where.isClient), readServerName, packageName, true);
|
|
||||||
//generate client readers
|
|
||||||
readgen.generateFor(methods.select(method -> method.where.isServer), readClientName, packageName, false);
|
|
||||||
|
|
||||||
//create class for storing unique method hash
|
|
||||||
TypeSpec.Builder hashBuilder = TypeSpec.classBuilder("MethodHash").addModifiers(Modifier.PUBLIC);
|
|
||||||
hashBuilder.addJavadoc(autogenWarning);
|
|
||||||
hashBuilder.addField(FieldSpec.builder(int.class, "HASH", Modifier.STATIC, Modifier.PUBLIC, Modifier.FINAL)
|
|
||||||
.initializer("$1L", Arrays.hashCode(methods.map(m -> m.element).toArray())).build());
|
|
||||||
|
|
||||||
//build and write resulting hash class
|
|
||||||
TypeSpec spec = hashBuilder.build();
|
|
||||||
JavaFile.builder(packageName, spec).build().writeTo(BaseProcessor.filer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,129 +0,0 @@
|
|||||||
package mindustry.annotations.remote;
|
|
||||||
|
|
||||||
import arc.struct.*;
|
|
||||||
import arc.util.io.*;
|
|
||||||
import com.squareup.javapoet.*;
|
|
||||||
import mindustry.annotations.*;
|
|
||||||
import mindustry.annotations.util.TypeIOResolver.*;
|
|
||||||
|
|
||||||
import javax.lang.model.element.*;
|
|
||||||
|
|
||||||
/** Generates code for reading remote invoke packets on the client and server. */
|
|
||||||
public class RemoteReadGenerator{
|
|
||||||
private final ClassSerializer serializers;
|
|
||||||
|
|
||||||
/** Creates a read generator that uses the supplied serializer setup. */
|
|
||||||
public RemoteReadGenerator(ClassSerializer serializers){
|
|
||||||
this.serializers = serializers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a class for reading remote invoke packets.
|
|
||||||
* @param entries List of methods to use.
|
|
||||||
* @param className Simple target class name.
|
|
||||||
* @param packageName Full target package name.
|
|
||||||
* @param needsPlayer Whether this read method requires a reference to the player sender.
|
|
||||||
*/
|
|
||||||
public void generateFor(Seq<MethodEntry> entries, String className, String packageName, boolean needsPlayer) throws Exception{
|
|
||||||
|
|
||||||
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC);
|
|
||||||
classBuilder.addJavadoc(RemoteProcess.autogenWarning);
|
|
||||||
|
|
||||||
//create main method builder
|
|
||||||
MethodSpec.Builder readMethod = MethodSpec.methodBuilder("readPacket")
|
|
||||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
|
||||||
.addParameter(Reads.class, "read") //buffer to read form
|
|
||||||
.addParameter(int.class, "id") //ID of method type to read
|
|
||||||
.returns(void.class);
|
|
||||||
|
|
||||||
if(needsPlayer){
|
|
||||||
//add player parameter
|
|
||||||
readMethod.addParameter(ClassName.get(packageName, "Player"), "player");
|
|
||||||
}
|
|
||||||
|
|
||||||
CodeBlock.Builder readBlock = CodeBlock.builder(); //start building block of code inside read method
|
|
||||||
boolean started = false; //whether an if() statement has been written yet
|
|
||||||
|
|
||||||
for(MethodEntry entry : entries){
|
|
||||||
//write if check for this entry ID
|
|
||||||
if(!started){
|
|
||||||
started = true;
|
|
||||||
readBlock.beginControlFlow("if(id == " + entry.id + ")");
|
|
||||||
}else{
|
|
||||||
readBlock.nextControlFlow("else if(id == " + entry.id + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
readBlock.beginControlFlow("try");
|
|
||||||
|
|
||||||
//concatenated list of variable names for method invocation
|
|
||||||
StringBuilder varResult = new StringBuilder();
|
|
||||||
|
|
||||||
//go through each parameter
|
|
||||||
for(int i = 0; i < entry.element.getParameters().size(); i++){
|
|
||||||
VariableElement var = entry.element.getParameters().get(i);
|
|
||||||
|
|
||||||
if(!needsPlayer || i != 0){ //if client, skip first parameter since it's always of type player and doesn't need to be read
|
|
||||||
//full type name of parameter
|
|
||||||
String typeName = var.asType().toString();
|
|
||||||
//name of parameter
|
|
||||||
String varName = var.getSimpleName().toString();
|
|
||||||
//captialized version of type name for reading primitives
|
|
||||||
String pname = typeName.equals("boolean") ? "bool" : typeName.charAt(0) + "";
|
|
||||||
|
|
||||||
//write primitives automatically
|
|
||||||
if(BaseProcessor.isPrimitive(typeName)){
|
|
||||||
readBlock.addStatement("$L $L = read.$L()", typeName, varName, pname);
|
|
||||||
}else{
|
|
||||||
//else, try and find a serializer
|
|
||||||
String ser = serializers.readers.get(typeName.replace("mindustry.gen.", ""), SerializerResolver.locate(entry.element, var.asType(), false));
|
|
||||||
|
|
||||||
if(ser == null){ //make sure a serializer exists!
|
|
||||||
BaseProcessor.err("No read method to read class type '" + typeName + "' in method " + entry.targetMethod + "; " + serializers.readers, var);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//add statement for reading it
|
|
||||||
readBlock.addStatement(typeName + " " + varName + " = " + ser + "(read)");
|
|
||||||
}
|
|
||||||
|
|
||||||
//append variable name to string builder
|
|
||||||
varResult.append(var.getSimpleName());
|
|
||||||
if(i != entry.element.getParameters().size() - 1) varResult.append(", ");
|
|
||||||
}else{
|
|
||||||
varResult.append("player");
|
|
||||||
if(i != entry.element.getParameters().size() - 1) varResult.append(", ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//execute the relevant method before the forward
|
|
||||||
//if it throws a ValidateException, the method won't be forwarded
|
|
||||||
readBlock.addStatement("$N." + entry.element.getSimpleName() + "(" + varResult.toString() + ")", ((TypeElement)entry.element.getEnclosingElement()).getQualifiedName().toString());
|
|
||||||
|
|
||||||
//call forwarded method, don't forward on the client reader
|
|
||||||
if(entry.forward && entry.where.isServer && needsPlayer){
|
|
||||||
//call forwarded method
|
|
||||||
readBlock.addStatement(packageName + "." + entry.className + "." + entry.element.getSimpleName() +
|
|
||||||
"__forward(player.con" + (varResult.length() == 0 ? "" : ", ") + varResult.toString() + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
readBlock.nextControlFlow("catch (java.lang.Exception e)");
|
|
||||||
readBlock.addStatement("throw new java.lang.RuntimeException(\"Failed to to read remote method '" + entry.element.getSimpleName() + "'!\", e)");
|
|
||||||
readBlock.endControlFlow();
|
|
||||||
}
|
|
||||||
|
|
||||||
//end control flow if necessary
|
|
||||||
if(started){
|
|
||||||
readBlock.nextControlFlow("else");
|
|
||||||
readBlock.addStatement("throw new $1N(\"Invalid read method ID: \" + id + \"\")", RuntimeException.class.getName()); //handle invalid method IDs
|
|
||||||
readBlock.endControlFlow();
|
|
||||||
}
|
|
||||||
|
|
||||||
//add block and method to class
|
|
||||||
readMethod.addCode(readBlock.build());
|
|
||||||
classBuilder.addMethod(readMethod.build());
|
|
||||||
|
|
||||||
//build and write resulting class
|
|
||||||
TypeSpec spec = classBuilder.build();
|
|
||||||
JavaFile.builder(packageName, spec).build().writeTo(BaseProcessor.filer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,228 +0,0 @@
|
|||||||
package mindustry.annotations.remote;
|
|
||||||
|
|
||||||
import arc.struct.*;
|
|
||||||
import arc.util.io.*;
|
|
||||||
import com.squareup.javapoet.*;
|
|
||||||
import mindustry.annotations.Annotations.*;
|
|
||||||
import mindustry.annotations.*;
|
|
||||||
import mindustry.annotations.util.TypeIOResolver.*;
|
|
||||||
|
|
||||||
import javax.lang.model.element.*;
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
/** Generates code for writing remote invoke packets on the client and server. */
|
|
||||||
public class RemoteWriteGenerator{
|
|
||||||
private final ClassSerializer serializers;
|
|
||||||
|
|
||||||
/** Creates a write generator that uses the supplied serializer setup. */
|
|
||||||
public RemoteWriteGenerator(ClassSerializer serializers){
|
|
||||||
this.serializers = serializers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Generates all classes in this list. */
|
|
||||||
public void generateFor(Seq<ClassEntry> entries, String packageName) throws IOException{
|
|
||||||
|
|
||||||
for(ClassEntry entry : entries){
|
|
||||||
//create builder
|
|
||||||
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(entry.name).addModifiers(Modifier.PUBLIC);
|
|
||||||
classBuilder.addJavadoc(RemoteProcess.autogenWarning);
|
|
||||||
|
|
||||||
//add temporary write buffer
|
|
||||||
classBuilder.addField(FieldSpec.builder(ReusableByteOutStream.class, "OUT", Modifier.STATIC, Modifier.PRIVATE, Modifier.FINAL)
|
|
||||||
.initializer("new ReusableByteOutStream($L)", RemoteProcess.maxPacketSize).build());
|
|
||||||
|
|
||||||
//add writer for that buffer
|
|
||||||
classBuilder.addField(FieldSpec.builder(Writes.class, "WRITE", Modifier.STATIC, Modifier.PRIVATE, Modifier.FINAL)
|
|
||||||
.initializer("new Writes(new $T(OUT))", DataOutputStream.class).build());
|
|
||||||
|
|
||||||
//go through each method entry in this class
|
|
||||||
for(MethodEntry methodEntry : entry.methods){
|
|
||||||
//write the 'send event to all players' variant: always happens for clients, but only happens if 'all' is enabled on the server method
|
|
||||||
if(methodEntry.where.isClient || methodEntry.target.isAll){
|
|
||||||
writeMethodVariant(classBuilder, methodEntry, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
//write the 'send event to one player' variant, which is only applicable on the server
|
|
||||||
if(methodEntry.where.isServer && methodEntry.target.isOne){
|
|
||||||
writeMethodVariant(classBuilder, methodEntry, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
//write the forwarded method version
|
|
||||||
if(methodEntry.where.isServer && methodEntry.forward){
|
|
||||||
writeMethodVariant(classBuilder, methodEntry, true, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//build and write resulting class
|
|
||||||
TypeSpec spec = classBuilder.build();
|
|
||||||
JavaFile.builder(packageName, spec).build().writeTo(BaseProcessor.filer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Creates a specific variant for a method entry. */
|
|
||||||
private void writeMethodVariant(TypeSpec.Builder classBuilder, MethodEntry methodEntry, boolean toAll, boolean forwarded){
|
|
||||||
ExecutableElement elem = methodEntry.element;
|
|
||||||
|
|
||||||
//create builder
|
|
||||||
MethodSpec.Builder method = MethodSpec.methodBuilder(elem.getSimpleName().toString() + (forwarded ? "__forward" : "")) //add except suffix when forwarding
|
|
||||||
.addModifiers(Modifier.STATIC)
|
|
||||||
.returns(void.class);
|
|
||||||
|
|
||||||
//forwarded methods aren't intended for use, and are not public
|
|
||||||
if(!forwarded){
|
|
||||||
method.addModifiers(Modifier.PUBLIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
//validate client methods to make sure
|
|
||||||
if(methodEntry.where.isClient){
|
|
||||||
if(elem.getParameters().isEmpty()){
|
|
||||||
BaseProcessor.err("Client invoke methods must have a first parameter of type Player", elem);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!elem.getParameters().get(0).asType().toString().contains("Player")){
|
|
||||||
BaseProcessor.err("Client invoke methods should have a first parameter of type Player", elem);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//if toAll is false, it's a 'send to one player' variant, so add the player as a parameter
|
|
||||||
if(!toAll){
|
|
||||||
method.addParameter(ClassName.bestGuess("mindustry.net.NetConnection"), "playerConnection");
|
|
||||||
}
|
|
||||||
|
|
||||||
//add sender to ignore
|
|
||||||
if(forwarded){
|
|
||||||
method.addParameter(ClassName.bestGuess("mindustry.net.NetConnection"), "exceptConnection");
|
|
||||||
}
|
|
||||||
|
|
||||||
//call local method if applicable, shouldn't happen when forwarding method as that already happens by default
|
|
||||||
if(!forwarded && methodEntry.local != Loc.none){
|
|
||||||
//add in local checks
|
|
||||||
if(methodEntry.local != Loc.both){
|
|
||||||
method.beginControlFlow("if(" + getCheckString(methodEntry.local) + " || !mindustry.Vars.net.active())");
|
|
||||||
}
|
|
||||||
|
|
||||||
//concatenate parameters
|
|
||||||
int index = 0;
|
|
||||||
StringBuilder results = new StringBuilder();
|
|
||||||
for(VariableElement var : elem.getParameters()){
|
|
||||||
//special case: calling local-only methods uses the local player
|
|
||||||
if(index == 0 && methodEntry.where == Loc.client){
|
|
||||||
results.append("mindustry.Vars.player");
|
|
||||||
}else{
|
|
||||||
results.append(var.getSimpleName());
|
|
||||||
}
|
|
||||||
if(index != elem.getParameters().size() - 1) results.append(", ");
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
//add the statement to call it
|
|
||||||
method.addStatement("$N." + elem.getSimpleName() + "(" + results.toString() + ")",
|
|
||||||
((TypeElement)elem.getEnclosingElement()).getQualifiedName().toString());
|
|
||||||
|
|
||||||
if(methodEntry.local != Loc.both){
|
|
||||||
method.endControlFlow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//start control flow to check if it's actually client/server so no netcode is called
|
|
||||||
method.beginControlFlow("if(" + getCheckString(methodEntry.where) + ")");
|
|
||||||
|
|
||||||
//add statement to create packet from pool
|
|
||||||
method.addStatement("$1N packet = $2N.obtain($1N.class, $1N::new)", "mindustry.net.Packets.InvokePacket", "arc.util.pooling.Pools");
|
|
||||||
//assign priority
|
|
||||||
method.addStatement("packet.priority = (byte)" + methodEntry.priority.ordinal());
|
|
||||||
//assign method ID
|
|
||||||
method.addStatement("packet.type = (byte)" + methodEntry.id);
|
|
||||||
//reset stream
|
|
||||||
method.addStatement("OUT.reset()");
|
|
||||||
|
|
||||||
method.addTypeVariables(Seq.with(elem.getTypeParameters()).map(BaseProcessor::getTVN));
|
|
||||||
|
|
||||||
for(int i = 0; i < elem.getParameters().size(); i++){
|
|
||||||
//first argument is skipped as it is always the player caller
|
|
||||||
if((!methodEntry.where.isServer/* || methodEntry.mode == Loc.both*/) && i == 0){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
VariableElement var = elem.getParameters().get(i);
|
|
||||||
|
|
||||||
try{
|
|
||||||
//add parameter to method
|
|
||||||
method.addParameter(TypeName.get(var.asType()), var.getSimpleName().toString());
|
|
||||||
}catch(Throwable t){
|
|
||||||
throw new RuntimeException("Error parsing method " + methodEntry.targetMethod);
|
|
||||||
}
|
|
||||||
|
|
||||||
//name of parameter
|
|
||||||
String varName = var.getSimpleName().toString();
|
|
||||||
//name of parameter type
|
|
||||||
String typeName = var.asType().toString();
|
|
||||||
//captialized version of type name for writing primitives
|
|
||||||
String capName = typeName.equals("byte") ? "" : Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
|
|
||||||
//special case: method can be called from anywhere to anywhere
|
|
||||||
//thus, only write the player when the SERVER is writing data, since the client is the only one who reads it
|
|
||||||
boolean writePlayerSkipCheck = methodEntry.where == Loc.both && i == 0;
|
|
||||||
|
|
||||||
if(writePlayerSkipCheck){ //write begin check
|
|
||||||
method.beginControlFlow("if(mindustry.Vars.net.server())");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(BaseProcessor.isPrimitive(typeName)){ //check if it's a primitive, and if so write it
|
|
||||||
method.addStatement("WRITE.$L($L)", typeName.equals("boolean") ? "bool" : typeName.charAt(0) + "", varName);
|
|
||||||
}else{
|
|
||||||
//else, try and find a serializer
|
|
||||||
String ser = serializers.writers.get(typeName.replace("mindustry.gen.", ""), SerializerResolver.locate(elem, var.asType(), true));
|
|
||||||
|
|
||||||
if(ser == null){ //make sure a serializer exists!
|
|
||||||
BaseProcessor.err("No @WriteClass method to write class type: '" + typeName + "'", var);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//add statement for writing it
|
|
||||||
method.addStatement(ser + "(WRITE, " + varName + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(writePlayerSkipCheck){ //write end check
|
|
||||||
method.endControlFlow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//assign packet bytes
|
|
||||||
method.addStatement("packet.bytes = OUT.getBytes()");
|
|
||||||
//assign packet length
|
|
||||||
method.addStatement("packet.length = OUT.size()");
|
|
||||||
|
|
||||||
String sendString;
|
|
||||||
|
|
||||||
if(forwarded){ //forward packet
|
|
||||||
if(!methodEntry.local.isClient){ //if the client doesn't get it called locally, forward it back after validation
|
|
||||||
sendString = "mindustry.Vars.net.send(";
|
|
||||||
}else{
|
|
||||||
sendString = "mindustry.Vars.net.sendExcept(exceptConnection, ";
|
|
||||||
}
|
|
||||||
}else if(toAll){ //send to all players / to server
|
|
||||||
sendString = "mindustry.Vars.net.send(";
|
|
||||||
}else{ //send to specific client from server
|
|
||||||
sendString = "playerConnection.send(";
|
|
||||||
}
|
|
||||||
|
|
||||||
//send the actual packet
|
|
||||||
method.addStatement(sendString + "packet, " +
|
|
||||||
(methodEntry.unreliable ? "mindustry.net.Net.SendMode.udp" : "mindustry.net.Net.SendMode.tcp") + ")");
|
|
||||||
|
|
||||||
|
|
||||||
//end check for server/client
|
|
||||||
method.endControlFlow();
|
|
||||||
|
|
||||||
//add method to class, finally
|
|
||||||
classBuilder.addMethod(method.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCheckString(Loc loc){
|
|
||||||
return loc.isClient && loc.isServer ? "mindustry.Vars.net.server() || mindustry.Vars.net.client()" :
|
|
||||||
loc.isClient ? "mindustry.Vars.net.client()" :
|
|
||||||
loc.isServer ? "mindustry.Vars.net.server()" : "false";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package mindustry.annotations.util;
|
package mindustry.annotations.util;
|
||||||
|
|
||||||
import com.sun.source.tree.*;
|
import com.sun.source.tree.*;
|
||||||
import com.sun.tools.javac.tree.JCTree.*;
|
|
||||||
import mindustry.annotations.*;
|
import mindustry.annotations.*;
|
||||||
|
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
@@ -16,10 +15,6 @@ public class Svar extends Selement<VariableElement>{
|
|||||||
return up().asType().toString() + "#" + super.toString().replace("mindustry.gen.", "");
|
return up().asType().toString() + "#" + super.toString().replace("mindustry.gen.", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public JCVariableDecl jtree(){
|
|
||||||
return (JCVariableDecl)BaseProcessor.elementu.getTree(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Stype enclosingType(){
|
public Stype enclosingType(){
|
||||||
return new Stype((TypeElement)up());
|
return new Stype((TypeElement)up());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ mindustry.entities.comp.PosTeamDef=28
|
|||||||
mindustry.entities.comp.PuddleComp=13
|
mindustry.entities.comp.PuddleComp=13
|
||||||
mindustry.type.Weather.WeatherStateComp=14
|
mindustry.type.Weather.WeatherStateComp=14
|
||||||
mindustry.world.blocks.campaign.LaunchPad.LaunchPayloadComp=15
|
mindustry.world.blocks.campaign.LaunchPad.LaunchPayloadComp=15
|
||||||
|
mindustry.world.blocks.campaign.PayloadLaunchPad.LargeLaunchPayloadComp=34
|
||||||
mindustry.world.blocks.defense.ForceProjector.ForceDrawComp=22
|
mindustry.world.blocks.defense.ForceProjector.ForceDrawComp=22
|
||||||
mono=16
|
mono=16
|
||||||
nova=17
|
nova=17
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
{version:1,fields:[{name:collided,type:arc.struct.IntSeq},{name:damage,type:float},{name:data,type:java.lang.Object},{name:fdata,type:float},{name:lifetime,type:float},{name:owner,type:mindustry.gen.Entityc},{name:rotation,type:float},{name:team,type:mindustry.game.Team},{name:time,type:float},{name:type,type:mindustry.entities.bullet.BulletType},{name:x,type:float},{name:y,type:float}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:lifetime,type:float},{name:payload,type:mindustry.world.blocks.payloads.Payload},{name:team,type:mindustry.game.Team},{name:time,type:float},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/alpha/1.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:1,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/arkyid/1.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:1,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/beta/1.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:1,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/block/5.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:5,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/corvus/5.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:5,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/flare/5.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:5,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/gamma/1.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:1,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/mace/5.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:5,fields:[{name:ammo,type:float},{name:armor,type:float},{name:baseRotation,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/mega/3.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:3,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:payloads,type:arc.struct.Seq<mindustry.world.blocks.payloads.Payload>},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/mono/4.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:4,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/nova/3.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:3,fields:[{name:ammo,type:float},{name:armor,type:float},{name:baseRotation,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/oct/3.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:3,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:payloads,type:arc.struct.Seq<mindustry.world.blocks.payloads.Payload>},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/poly/3.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:3,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/pulsar/1.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:1,fields:[{name:ammo,type:float},{name:armor,type:float},{name:baseRotation,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/quad/4.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:4,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:payloads,type:arc.struct.Seq<mindustry.world.blocks.payloads.Payload>},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/quasar/1.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:1,fields:[{name:ammo,type:float},{name:armor,type:float},{name:baseRotation,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/risso/5.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:5,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/spiroct/4.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:4,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/toxopid/1.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:1,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:x,type:float},{name:y,type:float}]}
|
||||||
179
build.gradle
@@ -12,31 +12,52 @@ buildscript{
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
||||||
jcenter()
|
|
||||||
maven{ url 'https://jitpack.io' }
|
maven{ url 'https://jitpack.io' }
|
||||||
|
|
||||||
|
//fake repository to download my patched robovm jar from
|
||||||
|
ivy{
|
||||||
|
url 'https://github.com/'
|
||||||
|
|
||||||
|
patternLayout {
|
||||||
|
artifact '/[organisation]/[module]/raw/a-single-jar-file/[revision].jar'
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is required in Gradle 6.0+ as metadata file (ivy.xml)
|
||||||
|
// is mandatory. Docs linked below this code section
|
||||||
|
metadataSources { artifact() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.11'
|
//use local, patched robovm gradle plugin until my PR for gradle 7.0 support is merged
|
||||||
classpath "com.github.anuken:packr:-SNAPSHOT"
|
//https://github.com/Anuken/robovm/raw/a-single-jar-file/robovm-gradle-plugin-2.3.14-SNAPSHOT.jar
|
||||||
|
classpath "Anuken:robovm:robovm-gradle-plugin-2.3.14-SNAPSHOT"
|
||||||
|
//needed for plugin above
|
||||||
|
classpath "com.mobidevelop.robovm:robovm-dist-compiler:2.3.13"
|
||||||
|
|
||||||
classpath "com.github.Anuken.Arc:packer:$arcHash"
|
classpath "com.github.Anuken.Arc:packer:$arcHash"
|
||||||
classpath "com.github.Anuken.Arc:arc-core:$arcHash"
|
classpath "com.github.Anuken.Arc:arc-core:$arcHash"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugins{
|
||||||
|
id 'org.jetbrains.kotlin.jvm' version '1.4.32'
|
||||||
|
id "org.jetbrains.kotlin.kapt" version "1.4.32"
|
||||||
|
}
|
||||||
|
|
||||||
allprojects{
|
allprojects{
|
||||||
apply plugin: 'maven'
|
apply plugin: 'maven-publish'
|
||||||
|
|
||||||
version = 'release'
|
version = 'release'
|
||||||
group = 'com.github.Anuken'
|
group = 'com.github.Anuken'
|
||||||
|
|
||||||
ext{
|
ext{
|
||||||
versionNumber = '6'
|
versionNumber = '7'
|
||||||
if(!project.hasProperty("versionModifier")) versionModifier = 'beta'
|
if(!project.hasProperty("versionModifier")) versionModifier = 'pre-alpha'
|
||||||
if(!project.hasProperty("versionType")) versionType = 'official'
|
if(!project.hasProperty("versionType")) versionType = 'official'
|
||||||
appName = 'Mindustry'
|
appName = 'Mindustry'
|
||||||
steamworksVersion = '891ed912791e01fe9ee6237a6497e5212b85c256'
|
steamworksVersion = '0b86023401880bb5e586bc404bedbaae9b1f1c94'
|
||||||
rhinoVersion = '2617981f706e50b8753155d8e15e326308be3b22'
|
rhinoVersion = '55bf0dac1cfa7770672fd26112512c733ca9d5dc'
|
||||||
|
|
||||||
loadVersionProps = {
|
loadVersionProps = {
|
||||||
return new Properties().with{p -> p.load(file('../core/assets/version.properties').newReader()); return p }
|
return new Properties().with{p -> p.load(file('../core/assets/version.properties').newReader()); return p }
|
||||||
@@ -83,10 +104,12 @@ allprojects{
|
|||||||
return "v$buildVersion"
|
return "v$buildVersion"
|
||||||
}
|
}
|
||||||
|
|
||||||
getModifierString = {
|
hasSprites = {
|
||||||
if(versionModifier != "release"){
|
return new File(rootDir, "core/assets/sprites/sprites.aatls").exists()
|
||||||
return "[${versionModifier.toUpperCase()}]"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getModifierString = {
|
||||||
|
if(versionModifier != "release") return "[${versionModifier.toUpperCase()}]"
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,8 +127,7 @@ allprojects{
|
|||||||
def v = System.getenv("ANDROID_HOME")
|
def v = System.getenv("ANDROID_HOME")
|
||||||
if(v != null) return v
|
if(v != null) return v
|
||||||
//rootDir is null here, amazing. brilliant.
|
//rootDir is null here, amazing. brilliant.
|
||||||
def file = new File("local.properties")
|
def file = new File(rootDir, "local.properties")
|
||||||
if(!file.exists()) file = new File("../local.properties")
|
|
||||||
def props = new Properties().with{p -> p.load(file.newReader()); return p }
|
def props = new Properties().with{p -> p.load(file.newReader()); return p }
|
||||||
return props.get("sdk.dir")
|
return props.get("sdk.dir")
|
||||||
}
|
}
|
||||||
@@ -180,7 +202,6 @@ allprojects{
|
|||||||
maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
||||||
maven{ url "https://oss.sonatype.org/content/repositories/releases/" }
|
maven{ url "https://oss.sonatype.org/content/repositories/releases/" }
|
||||||
maven{ url 'https://jitpack.io' }
|
maven{ url 'https://jitpack.io' }
|
||||||
jcenter()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task clearCache{
|
task clearCache{
|
||||||
@@ -193,10 +214,15 @@ allprojects{
|
|||||||
|
|
||||||
tasks.withType(JavaCompile){
|
tasks.withType(JavaCompile){
|
||||||
targetCompatibility = 8
|
targetCompatibility = 8
|
||||||
sourceCompatibility = 14
|
sourceCompatibility = JavaVersion.VERSION_16
|
||||||
options.encoding = "UTF-8"
|
options.encoding = "UTF-8"
|
||||||
options.compilerArgs += ["-Xlint:deprecation"]
|
options.compilerArgs += ["-Xlint:deprecation"]
|
||||||
dependsOn clearCache
|
dependsOn clearCache
|
||||||
|
|
||||||
|
options.forkOptions.jvmArgs.addAll([
|
||||||
|
'--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED',
|
||||||
|
'--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED'
|
||||||
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,26 +230,20 @@ configure(project(":annotations")){
|
|||||||
tasks.withType(JavaCompile){
|
tasks.withType(JavaCompile){
|
||||||
targetCompatibility = 8
|
targetCompatibility = 8
|
||||||
sourceCompatibility = 8
|
sourceCompatibility = 8
|
||||||
|
options.fork = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//compile with java 8 compatibility for everything except the annotation project
|
//compile with java 8 compatibility for everything except the annotation project
|
||||||
configure(subprojects - project(":annotations")){
|
configure(subprojects - project(":annotations")){
|
||||||
tasks.withType(JavaCompile){
|
tasks.withType(JavaCompile){
|
||||||
if(JavaVersion.current() != JavaVersion.VERSION_1_8){
|
options.compilerArgs.addAll(['--release', '8'])
|
||||||
options.compilerArgs.addAll(['--release', '8', '--enable-preview'])
|
|
||||||
}
|
|
||||||
|
|
||||||
doFirst{
|
|
||||||
options.compilerArgs = options.compilerArgs.findAll{it != '--enable-preview' }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(Javadoc){
|
tasks.withType(Javadoc){
|
||||||
options{
|
options{
|
||||||
addStringOption('Xdoclint:none', '-quiet')
|
addStringOption('Xdoclint:none', '-quiet')
|
||||||
addBooleanOption('-enable-preview', true)
|
addStringOption('-release', '16')
|
||||||
addStringOption('-release', '14')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -235,9 +255,9 @@ project(":desktop"){
|
|||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
implementation project(":core")
|
implementation project(":core")
|
||||||
|
implementation arcModule("extensions:discord")
|
||||||
implementation arcModule("natives:natives-desktop")
|
implementation arcModule("natives:natives-desktop")
|
||||||
implementation arcModule("natives:natives-freetype-desktop")
|
implementation arcModule("natives:natives-freetype-desktop")
|
||||||
implementation 'com.github.MinnDevelopment:java-discord-rpc:v2.0.1'
|
|
||||||
|
|
||||||
if(debugged()) implementation project(":debug")
|
if(debugged()) implementation project(":debug")
|
||||||
|
|
||||||
@@ -253,18 +273,22 @@ project(":ios"){
|
|||||||
|
|
||||||
task incrementConfig{
|
task incrementConfig{
|
||||||
def vfile = file('robovm.properties')
|
def vfile = file('robovm.properties')
|
||||||
|
def bversion = getBuildVersion()
|
||||||
def props = new Properties()
|
def props = new Properties()
|
||||||
if(vfile.exists()){
|
if(vfile.exists()){
|
||||||
props.load(new FileInputStream(vfile))
|
props.load(new FileInputStream(vfile))
|
||||||
}else{
|
}else{
|
||||||
props['app.id'] = 'io.anuke.mindustry'
|
props['app.id'] = 'io.anuke.mindustry'
|
||||||
props['app.version'] = '5.0'
|
props['app.version'] = '6.0'
|
||||||
props['app.mainclass'] = 'mindustry.IOSLauncher'
|
props['app.mainclass'] = 'mindustry.IOSLauncher'
|
||||||
props['app.executable'] = 'IOSLauncher'
|
props['app.executable'] = 'IOSLauncher'
|
||||||
props['app.name'] = 'Mindustry'
|
props['app.name'] = 'Mindustry'
|
||||||
}
|
}
|
||||||
|
|
||||||
props['app.build'] = (!props.containsKey("app.build") ? 40 : props['app.build'].toInteger() + 1) + ""
|
props['app.build'] = (!props.containsKey("app.build") ? 40 : props['app.build'].toInteger() + 1) + ""
|
||||||
|
if(bversion != "custom build"){
|
||||||
|
props['app.version'] = versionNumber + "." + bversion + (bversion.contains(".") ? "" : ".0")
|
||||||
|
}
|
||||||
props.store(vfile.newWriter(), null)
|
props.store(vfile.newWriter(), null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,6 +305,15 @@ project(":ios"){
|
|||||||
|
|
||||||
project(":core"){
|
project(":core"){
|
||||||
apply plugin: "java-library"
|
apply plugin: "java-library"
|
||||||
|
apply plugin: "kotlin"
|
||||||
|
apply plugin: "kotlin-kapt"
|
||||||
|
|
||||||
|
kapt{
|
||||||
|
javacOptions{
|
||||||
|
option("-source", "16")
|
||||||
|
option("-target", "1.8")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
compileJava.options.fork = true
|
compileJava.options.fork = true
|
||||||
|
|
||||||
@@ -297,9 +330,10 @@ project(":core"){
|
|||||||
def props = loadVersionProps()
|
def props = loadVersionProps()
|
||||||
def androidVersion = props['androidBuildCode'].toInteger() - 2
|
def androidVersion = props['androidBuildCode'].toInteger() - 2
|
||||||
def loglines = file("../changelog").text.split("\n")
|
def loglines = file("../changelog").text.split("\n")
|
||||||
|
def notice = "[This is a truncated changelog, see Github for full notes]"
|
||||||
def maxLength = 460
|
def maxLength = 460
|
||||||
|
|
||||||
def androidLogList = loglines.findAll{ line -> !line.endsWith("]") || line.endsWith("[Mobile]") || line.endsWith("[Android]")}
|
def androidLogList = [notice] + loglines.findAll{ line -> !line.endsWith("]") || line.endsWith("[Mobile]") || line.endsWith("[Android]")}
|
||||||
def result = ""
|
def result = ""
|
||||||
androidLogList.forEach{line ->
|
androidLogList.forEach{line ->
|
||||||
if(result.length() + line.length() + 1 < maxLength){
|
if(result.length() + line.length() + 1 < maxLength){
|
||||||
@@ -311,22 +345,74 @@ project(":core"){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task sourcesJar(type: Jar, dependsOn: classes){
|
||||||
|
archiveClassifier = 'sources'
|
||||||
|
from sourceSets.main.allSource
|
||||||
|
}
|
||||||
|
|
||||||
|
task assetsJar(type: Jar, dependsOn: ":tools:pack"){
|
||||||
|
archiveClassifier = 'assets'
|
||||||
|
from files("assets"){
|
||||||
|
exclude "config", "cache", "music", "sounds"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task musicJar(type: Jar){
|
||||||
|
archiveClassifier = 'music'
|
||||||
|
from files("assets"){
|
||||||
|
include "music/*", "sounds/*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
artifacts{
|
||||||
|
archives sourcesJar
|
||||||
|
archives assetsJar
|
||||||
|
}
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
compileJava.dependsOn(preGen)
|
compileJava.dependsOn(preGen)
|
||||||
|
|
||||||
api "org.lz4:lz4-java:1.4.1"
|
api "org.lz4:lz4-java:1.7.1"
|
||||||
api arcModule("arc-core")
|
api arcModule("arc-core")
|
||||||
|
api arcModule("extensions:flabel")
|
||||||
api arcModule("extensions:freetype")
|
api arcModule("extensions:freetype")
|
||||||
api arcModule("extensions:g3d")
|
api arcModule("extensions:g3d")
|
||||||
api arcModule("extensions:fx")
|
api arcModule("extensions:fx")
|
||||||
api arcModule("extensions:arcnet")
|
api arcModule("extensions:arcnet")
|
||||||
api "com.github.Anuken:rhino:$rhinoVersion"
|
api "com.github.Anuken:rhino:$rhinoVersion"
|
||||||
if(localArc() && debugged()) api arcModule("extensions:recorder")
|
if(localArc() && debugged()) api arcModule("extensions:recorder")
|
||||||
|
if(localArc()) api arcModule(":extensions:packer")
|
||||||
|
|
||||||
compileOnly project(":annotations")
|
|
||||||
annotationProcessor project(":annotations")
|
|
||||||
annotationProcessor 'com.github.Anuken:jabel:34e4c172e65b3928cd9eabe1993654ea79c409cd'
|
annotationProcessor 'com.github.Anuken:jabel:34e4c172e65b3928cd9eabe1993654ea79c409cd'
|
||||||
|
compileOnly project(":annotations")
|
||||||
|
kapt project(":annotations")
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate{
|
||||||
|
task mergedJavadoc(type: Javadoc){
|
||||||
|
def blacklist = [project(":ios"), project(":desktop"), project(":server"), project(":annotations")]
|
||||||
|
if(findProject(":android") != null){
|
||||||
|
blacklist += project(":android")
|
||||||
|
}
|
||||||
|
|
||||||
|
source rootProject.subprojects.collect{ project ->
|
||||||
|
if(!blacklist.contains(project) && project.hasProperty("sourceSets")){
|
||||||
|
return project.sourceSets.main.allJava
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
classpath = files(rootProject.subprojects.collect { project ->
|
||||||
|
if(!blacklist.contains(project) && project.hasProperty("sourceSets")){
|
||||||
|
return project.sourceSets.main.compileClasspath
|
||||||
|
}
|
||||||
|
})
|
||||||
|
destinationDir = new File(buildDir, 'javadoc')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//comp** classes are only used for code generation
|
||||||
|
jar{
|
||||||
|
exclude("mindustry/entities/comp/**")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,13 +430,15 @@ project(":tests"){
|
|||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
testImplementation project(":core")
|
testImplementation project(":core")
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-params:5.3.1"
|
testImplementation "org.junit.jupiter:junit-jupiter-params:5.7.1"
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api:5.3.1"
|
testImplementation "org.junit.jupiter:junit-jupiter-api:5.7.1"
|
||||||
testImplementation arcModule("backends:backend-headless")
|
testImplementation arcModule("backends:backend-headless")
|
||||||
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.3.1"
|
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.7.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
test{
|
test{
|
||||||
|
//fork every test so mods don't interact with each other
|
||||||
|
forkEvery = 1
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
workingDir = new File("../core/assets")
|
workingDir = new File("../core/assets")
|
||||||
testLogging{
|
testLogging{
|
||||||
@@ -378,7 +466,21 @@ project(":annotations"){
|
|||||||
dependencies{
|
dependencies{
|
||||||
implementation 'com.squareup:javapoet:1.12.1'
|
implementation 'com.squareup:javapoet:1.12.1'
|
||||||
implementation "com.github.Anuken.Arc:arc-core:$arcHash"
|
implementation "com.github.Anuken.Arc:arc-core:$arcHash"
|
||||||
implementation files("${System.getProperty('java.home')}/../lib/tools.jar")
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configure([":core", ":desktop", ":server", ":tools"].collect{project(it)}){
|
||||||
|
java{
|
||||||
|
withJavadocJar()
|
||||||
|
withSourcesJar()
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing{
|
||||||
|
publications{
|
||||||
|
maven(MavenPublication){
|
||||||
|
from components.java
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,3 +504,12 @@ task deployAll{
|
|||||||
dependsOn "server:deploy"
|
dependsOn "server:deploy"
|
||||||
dependsOn "android:deploy"
|
dependsOn "android:deploy"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task resolveDependencies{
|
||||||
|
doLast{
|
||||||
|
rootProject.allprojects{ project ->
|
||||||
|
Set<Configuration> configurations = project.buildscript.configurations + project.configurations
|
||||||
|
configurations.findAll{c -> c.canBeResolved}.forEach{c -> c.resolve()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
55
core/assets-raw/fontgen/extra/planet.svg
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
version="1.1"
|
||||||
|
id="svg542"
|
||||||
|
sodipodi:docname="planet.svg"
|
||||||
|
inkscape:version="1.0.1 (0767f8302a, 2020-10-17)">
|
||||||
|
<metadata
|
||||||
|
id="metadata548">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs546" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1316"
|
||||||
|
id="namedview544"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:pagecheckerboard="true"
|
||||||
|
inkscape:zoom="15.75"
|
||||||
|
inkscape:cx="-16.385458"
|
||||||
|
inkscape:cy="16.16535"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg542" />
|
||||||
|
<path
|
||||||
|
id="polygon2"
|
||||||
|
style="fill:#ffffff"
|
||||||
|
d="M 5.5 0 L 5 0.5 L 4.5 1 L 3.5 1 L 3 1.5 L 2.5 2 L 2 2.5 L 1.5 3 L 1 3.5 L 1 4.5 L 0.5 5 L 0 5.5 L 0 6.5 L 0 7.5 L 0 8.5 L 0 9.5 L 0 10.5 L 0.5 11 L 1 11.5 L 1 12.5 L 1.5 13 L 2 13.5 L 2.5 14 L 3 14.5 L 3.5 15 L 4.5 15 L 5 15.5 L 5.5 16 L 6.5 16 L 7.5 16 L 8.5 16 L 9.5 16 L 10.5 16 L 11 15.5 L 11.5 15 L 12.5 15 L 13 14.5 L 13.5 14 L 14 13.5 L 14.5 13 L 15 12.5 L 15 11.5 L 15.5 11 L 16 10.5 L 16 9.5 L 16 8.5 L 16 7.5 L 16 6.5 L 16 5.5 L 15.5 5 L 15 4.5 L 15 3.5 L 14.5 3 L 14 2.5 L 13.5 2 L 13 1.5 L 12.5 1 L 11.5 1 L 11 0.5 L 10.5 0 L 9.5 0 L 8.5 0 L 7.5 0 L 6.5 0 L 5.5 0 z M 6.5 1 L 7 1.5 L 7.5 2 L 8.5 2 L 9 2.5 L 9 3.5 L 9.5 4 L 10 4.5 L 10.5 5 L 11 5.5 L 11.5 6 L 12.5 6 L 13.5 6 L 14.5 6 L 15 6.5 L 15 7.5 L 15 8.5 L 15 9.5 L 14.5 10 L 14 10.5 L 14 11.5 L 13.5 12 L 13 12.5 L 12.5 13 L 12 13.5 L 11.5 14 L 10.5 14 L 10 14.5 L 9.5 15 L 8.5 15 L 8 14.5 L 7.5 14 L 7 13.5 L 7 12.5 L 7.5 12 L 8 11.5 L 8.5 11 L 9 10.5 L 9 9.5 L 9 8.5 L 8.5 8 L 8 7.5 L 7.5 7 L 6.5 7 L 5.5 7 L 4.5 7 L 4 7.5 L 3.5 8 L 3 8.5 L 2.5 9 L 2 9.5 L 1.5 10 L 1 9.5 L 1 8.5 L 1 7.5 L 1 6.5 L 1.5 6 L 2 5.5 L 2 4.5 L 2.5 4 L 3 3.5 L 3.5 3 L 4 2.5 L 4.5 2 L 5.5 2 L 6 1.5 L 6.5 1 z M 11.5 9 L 11 9.5 L 11 10.5 L 11.5 11 L 12.5 11 L 13 10.5 L 13 9.5 L 12.5 9 L 11.5 9 z " />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.7 KiB |
BIN
core/assets-raw/icons/planet.png
Normal file
|
After Width: | Height: | Size: 578 B |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 186 B |
BIN
core/assets-raw/sprites/blocks/campaign/payload-launch-pad.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
core/assets-raw/sprites/blocks/defense/shock-mine-team-top.png
Normal file
|
After Width: | Height: | Size: 158 B |
|
After Width: | Height: | Size: 119 B |
|
After Width: | Height: | Size: 149 B |
|
After Width: | Height: | Size: 121 B |
|
After Width: | Height: | Size: 121 B |
|
After Width: | Height: | Size: 121 B |
|
After Width: | Height: | Size: 156 B |
|
After Width: | Height: | Size: 139 B |
|
After Width: | Height: | Size: 115 B |
|
After Width: | Height: | Size: 142 B |
|
After Width: | Height: | Size: 174 B |
|
After Width: | Height: | Size: 322 B |
|
After Width: | Height: | Size: 165 B |
|
After Width: | Height: | Size: 322 B |
BIN
core/assets-raw/sprites/blocks/distribution/ducts/duct-top-0.png
Normal file
|
After Width: | Height: | Size: 329 B |
BIN
core/assets-raw/sprites/blocks/distribution/ducts/duct-top-1.png
Normal file
|
After Width: | Height: | Size: 364 B |
BIN
core/assets-raw/sprites/blocks/distribution/ducts/duct-top-2.png
Normal file
|
After Width: | Height: | Size: 442 B |
BIN
core/assets-raw/sprites/blocks/distribution/ducts/duct-top-3.png
Normal file
|
After Width: | Height: | Size: 560 B |
BIN
core/assets-raw/sprites/blocks/distribution/ducts/duct-top-4.png
Normal file
|
After Width: | Height: | Size: 413 B |
|
Before Width: | Height: | Size: 300 B After Width: | Height: | Size: 300 B |
BIN
core/assets-raw/sprites/blocks/drills/drill-item-3.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
core/assets-raw/sprites/blocks/drills/drill-item-4.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 329 B After Width: | Height: | Size: 478 B |
|
Before Width: | Height: | Size: 236 B After Width: | Height: | Size: 364 B |
|
Before Width: | Height: | Size: 219 B After Width: | Height: | Size: 321 B |
|
Before Width: | Height: | Size: 243 B After Width: | Height: | Size: 380 B |
|
Before Width: | Height: | Size: 521 B After Width: | Height: | Size: 467 B |
|
Before Width: | Height: | Size: 267 B After Width: | Height: | Size: 280 B |
|
Before Width: | Height: | Size: 218 B After Width: | Height: | Size: 228 B |
|
Before Width: | Height: | Size: 200 B After Width: | Height: | Size: 227 B |
|
Before Width: | Height: | Size: 201 B After Width: | Height: | Size: 219 B |
|
Before Width: | Height: | Size: 250 B After Width: | Height: | Size: 214 B |
|
Before Width: | Height: | Size: 631 B After Width: | Height: | Size: 1001 B |
|
Before Width: | Height: | Size: 389 B After Width: | Height: | Size: 393 B |
|
Before Width: | Height: | Size: 137 B |
BIN
core/assets-raw/sprites/blocks/environment/env-error.png
Normal file
|
After Width: | Height: | Size: 287 B |
|
Before Width: | Height: | Size: 338 B After Width: | Height: | Size: 514 B |
|
Before Width: | Height: | Size: 359 B After Width: | Height: | Size: 536 B |