Compare commits
1462 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15396b6032 | ||
|
|
75a520c3ae | ||
|
|
d7fd7db3cc | ||
|
|
144731bfb0 | ||
|
|
7c1d4a092e | ||
|
|
a28ece6424 | ||
|
|
39c5c6a6f0 | ||
|
|
77975a710c | ||
|
|
d95dc98652 | ||
|
|
7afa6a7f44 | ||
|
|
a4339b8b2b | ||
|
|
7897ca9b97 | ||
|
|
4f957017ab | ||
|
|
fa60ff2814 | ||
|
|
65ef189921 | ||
|
|
5b3b2cf4d5 | ||
|
|
d89184da43 | ||
|
|
898bddee7c | ||
|
|
860e4a2999 | ||
|
|
39ef3ab4ce | ||
|
|
e57f4c9877 | ||
|
|
30214e68b3 | ||
|
|
59a480cb30 | ||
|
|
46c6a6f6f7 | ||
|
|
b6acf1af0a | ||
|
|
16f4e300a8 | ||
|
|
b18b4cdc90 | ||
|
|
79d90ca75d | ||
|
|
b2b47353bf | ||
|
|
b7fe2bedae | ||
|
|
00e1d69348 | ||
|
|
88d1165909 | ||
|
|
b22efb8c83 | ||
|
|
a7c78c4193 | ||
|
|
5c5acb2d48 | ||
|
|
414f27a3b6 | ||
|
|
009eea1988 | ||
|
|
c9eed5a936 | ||
|
|
5d20f3a89b | ||
|
|
677e0e6f58 | ||
|
|
49c64faece | ||
|
|
f944d3d579 | ||
|
|
4dc2164468 | ||
|
|
e9612ce9f0 | ||
|
|
b19eb3fc04 | ||
|
|
699364580e | ||
|
|
085a974350 | ||
|
|
4436a5ced9 | ||
|
|
a21f6d335f | ||
|
|
2469cf0851 | ||
|
|
a82ba0567b | ||
|
|
6022fcd109 | ||
|
|
038d132da9 | ||
|
|
52238e3aa4 | ||
|
|
f2ce32cbb2 | ||
|
|
7dc492892e | ||
|
|
4e92aa2000 | ||
|
|
3c8e21ac6a | ||
|
|
8f5aa02428 | ||
|
|
f31759bb96 | ||
|
|
938b4e5a00 | ||
|
|
c6f6b8e46e | ||
|
|
3a9c0377ac | ||
|
|
324e5151aa | ||
|
|
ad8455377c | ||
|
|
3c963fb1bc | ||
|
|
af3467035b | ||
|
|
b57abf8b60 | ||
|
|
0acd339e33 | ||
|
|
e897458e94 | ||
|
|
a72adef051 | ||
|
|
a8ffd6c520 | ||
|
|
9cb8c6d83d | ||
|
|
59435c8372 | ||
|
|
fc9abeb908 | ||
|
|
ea3802bfc7 | ||
|
|
994f6f7e84 | ||
|
|
ba91fb8eb7 | ||
|
|
e6d7330f6e | ||
|
|
be1561b0cb | ||
|
|
b271f5b630 | ||
|
|
d5a2f13442 | ||
|
|
f03d3d89f3 | ||
|
|
717a620ff4 | ||
|
|
9dfd4d0049 | ||
|
|
290450de5b | ||
|
|
d970eb45e3 | ||
|
|
b7f030eb13 | ||
|
|
f43e308dad | ||
|
|
bd329f57d6 | ||
|
|
06bf2711a4 | ||
|
|
7ff9ad7351 | ||
|
|
91acda56c1 | ||
|
|
0f29a01292 | ||
|
|
902f3695ee | ||
|
|
d5e239c610 | ||
|
|
36064c63e3 | ||
|
|
01a8a8bb4d | ||
|
|
4a979058c2 | ||
|
|
e06640935d | ||
|
|
956cbe792b | ||
|
|
e9e5fea306 | ||
|
|
f683496440 | ||
|
|
b66eb173d8 | ||
|
|
816ab161df | ||
|
|
bccdd86f30 | ||
|
|
9a5ac14bc3 | ||
|
|
dc14f42593 | ||
|
|
18c5f508b1 | ||
|
|
d8cf65e24c | ||
|
|
3de9cfa1d7 | ||
|
|
df156444e7 | ||
|
|
8a3dd53aa2 | ||
|
|
b855849e4a | ||
|
|
6b59c1cd83 | ||
|
|
ad1c75d050 | ||
|
|
dcb84f9faf | ||
|
|
d5babe88e3 | ||
|
|
b30eb26eb7 | ||
|
|
b5f639f518 | ||
|
|
ec1124499f | ||
|
|
095cc27ea6 | ||
|
|
a2f40a5565 | ||
|
|
1f1a5bde3e | ||
|
|
4a4b336814 | ||
|
|
1a839bce86 | ||
|
|
2e747a481a | ||
|
|
fdfe381b6e | ||
|
|
9e01d1a69d | ||
|
|
5e8a3137c1 | ||
|
|
8c3ecfdb06 | ||
|
|
fbca85fe0a | ||
|
|
bf8276f501 | ||
|
|
1fc3974e1b | ||
|
|
c857c8a438 | ||
|
|
5b9e11cc6c | ||
|
|
10b1ce2a3d | ||
|
|
5b3ae4ae15 | ||
|
|
90d589939a | ||
|
|
da225d15c7 | ||
|
|
21549d2518 | ||
|
|
e6863825d2 | ||
|
|
25c8623e30 | ||
|
|
d5f7fc842c | ||
|
|
da0fea5186 | ||
|
|
6abb458c27 | ||
|
|
9cc738d867 | ||
|
|
171e348b49 | ||
|
|
3c071bcf49 | ||
|
|
4030e71b31 | ||
|
|
9f070323c2 | ||
|
|
8ae70f5f9a | ||
|
|
f5cb6f2542 | ||
|
|
871fcc9579 | ||
|
|
a9bb8b1310 | ||
|
|
b955539383 | ||
|
|
8f8e038575 | ||
|
|
b2de197050 | ||
|
|
c60bd6f0dc | ||
|
|
8468214dd7 | ||
|
|
919db8cc76 | ||
|
|
5ce5f347aa | ||
|
|
758921c077 | ||
|
|
c22ede229e | ||
|
|
1ca6db9cf5 | ||
|
|
c5ed535519 | ||
|
|
6c86a64c74 | ||
|
|
d24f7cb549 | ||
|
|
f5d6313399 | ||
|
|
dc7ffbc8b8 | ||
|
|
f9da6f8904 | ||
|
|
1ada42738f | ||
|
|
04df23b88a | ||
|
|
200aa3e32b | ||
|
|
083321d6c7 | ||
|
|
00be5b7fa5 | ||
|
|
55537f09dc | ||
|
|
d43157fd22 | ||
|
|
60a430025a | ||
|
|
3f53315a07 | ||
|
|
6e3de78026 | ||
|
|
a4963f351d | ||
|
|
df5c31a0e7 | ||
|
|
17af905d52 | ||
|
|
f2139fad6e | ||
|
|
785ba7910d | ||
|
|
3030308f09 | ||
|
|
4ed471f77b | ||
|
|
373c73f492 | ||
|
|
bc3da30d45 | ||
|
|
77736f227f | ||
|
|
6d49bd39be | ||
|
|
0d0fe394d3 | ||
|
|
aed57aaac3 | ||
|
|
b20cdb97c5 | ||
|
|
d95662233c | ||
|
|
ce7e91f17b | ||
|
|
db6b8abce6 | ||
|
|
3e2da3595f | ||
|
|
60fe1e5570 | ||
|
|
67ed6ddd18 | ||
|
|
b265ddac03 | ||
|
|
ee26f51d7a | ||
|
|
0483e3f900 | ||
|
|
9939d6065a | ||
|
|
c226127648 | ||
|
|
e0b1c49e0b | ||
|
|
558fb26dcb | ||
|
|
78a4572388 | ||
|
|
6f6590d5bb | ||
|
|
efb9df7b1b | ||
|
|
a04b385f56 | ||
|
|
01d6aee754 | ||
|
|
603c871e6e | ||
|
|
71543f2ab2 | ||
|
|
7f415588f4 | ||
|
|
c6c374f672 | ||
|
|
d226ffe633 | ||
|
|
182dfc5f38 | ||
|
|
366822e4d1 | ||
|
|
8f53822a6e | ||
|
|
c814ef0012 | ||
|
|
30e6bb2625 | ||
|
|
f5a0528c73 | ||
|
|
f5a2ed900d | ||
|
|
2f9bf6e13f | ||
|
|
13b92519f1 | ||
|
|
61a28aca91 | ||
|
|
7c00b54191 | ||
|
|
dbd31b9031 | ||
|
|
083c21ea3f | ||
|
|
6fb7f4fe26 | ||
|
|
a21942e401 | ||
|
|
bf89ef1e5e | ||
|
|
2d2052e39f | ||
|
|
7bf85d9f84 | ||
|
|
ed1557b5ac | ||
|
|
5e0f404602 | ||
|
|
0185f8bc5a | ||
|
|
94d9ca4727 | ||
|
|
d79ab3ec3e | ||
|
|
50cc340b20 | ||
|
|
dac17aa2b7 | ||
|
|
29242249bd | ||
|
|
22a93fc649 | ||
|
|
c8ab2bd1ba | ||
|
|
9e718b633e | ||
|
|
90d1770b3e | ||
|
|
3f6d5b9dfe | ||
|
|
6d41b894ab | ||
|
|
0c4592fbc8 | ||
|
|
dc2ff1e933 | ||
|
|
6f8ae1b5a3 | ||
|
|
76e5c51a12 | ||
|
|
45f6fde689 | ||
|
|
83dc70b054 | ||
|
|
ec886456c8 | ||
|
|
4377eacfd5 | ||
|
|
c92433c5f9 | ||
|
|
deca57c2d9 | ||
|
|
00cb441704 | ||
|
|
173ac324a4 | ||
|
|
3a8ba568b5 | ||
|
|
b60acf2c37 | ||
|
|
6f27fd1ea2 | ||
|
|
8a6f3db20e | ||
|
|
4886ee35e9 | ||
|
|
cbb3afa95c | ||
|
|
7e0f68b24d | ||
|
|
cc0cdeb6c0 | ||
|
|
01a76d1c9e | ||
|
|
5c0827b208 | ||
|
|
05b8c772d8 | ||
|
|
9dfb5888ec | ||
|
|
66f56d9e98 | ||
|
|
3f996cf294 | ||
|
|
47dc9c7b31 | ||
|
|
e4e1bac2aa | ||
|
|
01771c5288 | ||
|
|
58a21c3cc7 | ||
|
|
effd226c3e | ||
|
|
8ccca23a24 | ||
|
|
84935e1bb0 | ||
|
|
32baf06c97 | ||
|
|
0756da0dd1 | ||
|
|
845b64945e | ||
|
|
7b623e964c | ||
|
|
e3cceea1af | ||
|
|
c4fe53955b | ||
|
|
0068952ba6 | ||
|
|
a3b3745d01 | ||
|
|
95c3476144 | ||
|
|
4cb3bef1a7 | ||
|
|
248f59131b | ||
|
|
72841afd96 | ||
|
|
eb9c3c8033 | ||
|
|
e23837a4ba | ||
|
|
625f2640d8 | ||
|
|
01c67b77cb | ||
|
|
63b39cdb72 | ||
|
|
be0397355f | ||
|
|
689b5af2fb | ||
|
|
d36a00a6fe | ||
|
|
8dfa349484 | ||
|
|
2906c61d06 | ||
|
|
e1ba9f16f6 | ||
|
|
826ddf4aad | ||
|
|
d20048fe11 | ||
|
|
edbe795aa5 | ||
|
|
087cd2c55a | ||
|
|
ca62deaaa9 | ||
|
|
d33a4f9f87 | ||
|
|
f64d078f29 | ||
|
|
da465c7786 | ||
|
|
9c12125e89 | ||
|
|
2a6d7c5a13 | ||
|
|
71e38862b9 | ||
|
|
b58a63b200 | ||
|
|
ee8b4f478d | ||
|
|
1941f22676 | ||
|
|
35ffbef557 | ||
|
|
24db94a55b | ||
|
|
46bda97362 | ||
|
|
a1b9f7d1b3 | ||
|
|
32db058dbe | ||
|
|
2f7c5994a7 | ||
|
|
2664bb84be | ||
|
|
bdcfb7ab45 | ||
|
|
5cf47f4198 | ||
|
|
515ee060d2 | ||
|
|
90c2473448 | ||
|
|
c5a90759e5 | ||
|
|
cccce6badd | ||
|
|
decc570867 | ||
|
|
caa34c959e | ||
|
|
b8fa15e546 | ||
|
|
47d5be679d | ||
|
|
fc7f689ea4 | ||
|
|
7c028ffcb8 | ||
|
|
10c3f9e44a | ||
|
|
b2a634e5e7 | ||
|
|
ae0a70703b | ||
|
|
9076325fa1 | ||
|
|
08d7390775 | ||
|
|
cbe188abab | ||
|
|
abbc25798d | ||
|
|
a3ede6cf0b | ||
|
|
e997768a0a | ||
|
|
671098cc28 | ||
|
|
1a686c44a1 | ||
|
|
9e737cd3fe | ||
|
|
deed84f9a3 | ||
|
|
868cd4fb0b | ||
|
|
a5697a7d4b | ||
|
|
2222330b43 | ||
|
|
cde192b59a | ||
|
|
c98eb2edd7 | ||
|
|
dd7062f0f7 | ||
|
|
8adefb7b72 | ||
|
|
5e13f71fde | ||
|
|
d257adf0c1 | ||
|
|
34d2a0d3a0 | ||
|
|
efae0d3b6a | ||
|
|
a393e21326 | ||
|
|
5641b4901c | ||
|
|
4da21ba363 | ||
|
|
508abba2ec | ||
|
|
87ff876db3 | ||
|
|
4720f1b876 | ||
|
|
e35d09fe62 | ||
|
|
fb74dfa02f | ||
|
|
461d87dbef | ||
|
|
cf5d172922 | ||
|
|
227fb388b8 | ||
|
|
89d495fdb1 | ||
|
|
82e659dd80 | ||
|
|
f20b9c828c | ||
|
|
efe5668c5a | ||
|
|
0331d8c6c4 | ||
|
|
15882016ca | ||
|
|
b4b9a44126 | ||
|
|
063d2ce6c0 | ||
|
|
3985620289 | ||
|
|
23d0dfe6bf | ||
|
|
0a5b1d1380 | ||
|
|
24b0f445b8 | ||
|
|
57cd20e2a1 | ||
|
|
3f49807348 | ||
|
|
13ddca750a | ||
|
|
c209b0bdaf | ||
|
|
264052a95f | ||
|
|
b004146015 | ||
|
|
3901ae1720 | ||
|
|
bcf798c247 | ||
|
|
2dffd525a3 | ||
|
|
d31389efca | ||
|
|
ee8683c734 | ||
|
|
8224cc3fce | ||
|
|
94a340d3ee | ||
|
|
f8048be429 | ||
|
|
3714077fbe | ||
|
|
6984be2172 | ||
|
|
48f359ca9b | ||
|
|
9b28eaa3b3 | ||
|
|
2f47f13ef7 | ||
|
|
80acea4708 | ||
|
|
cc689fd114 | ||
|
|
be5d9154a7 | ||
|
|
bb9d7fedf7 | ||
|
|
71f064bda1 | ||
|
|
e30d7e998d | ||
|
|
a3270dd908 | ||
|
|
48d568978b | ||
|
|
9a7324ce54 | ||
|
|
d254d971a9 | ||
|
|
800f0f4511 | ||
|
|
60b2842d82 | ||
|
|
f8c7ff0159 | ||
|
|
4d62b0321f | ||
|
|
6ca2855365 | ||
|
|
ced97888e4 | ||
|
|
9f68fe520b | ||
|
|
8c32acbc30 | ||
|
|
bfc9b07651 | ||
|
|
e53b578043 | ||
|
|
b2ed066faa | ||
|
|
5cc461edb0 | ||
|
|
9b22777dfb | ||
|
|
3bd08bb047 | ||
|
|
139d6cd5cc | ||
|
|
309b0adb9e | ||
|
|
c25e6b586b | ||
|
|
f46b22e4a7 | ||
|
|
2b6856634c | ||
|
|
20305b5d36 | ||
|
|
9e16d7385a | ||
|
|
c573fd34a1 | ||
|
|
da7873cbd8 | ||
|
|
a15f8131fa | ||
|
|
0d27e3afdc | ||
|
|
bdcae408e6 | ||
|
|
bc4783e9cd | ||
|
|
8143cb7be0 | ||
|
|
8e90527609 | ||
|
|
8949fd279e | ||
|
|
901d594768 | ||
|
|
3964c8e826 | ||
|
|
044a124bc7 | ||
|
|
4f22db8db5 | ||
|
|
80ef3cee34 | ||
|
|
254284760f | ||
|
|
71ee7558ab | ||
|
|
5f4a3e341f | ||
|
|
81f25b76fd | ||
|
|
649c6ddfb3 | ||
|
|
3bd3d3aa37 | ||
|
|
fa9573e6dc | ||
|
|
b4d19bf71b | ||
|
|
0f019f58bd | ||
|
|
572166b157 | ||
|
|
e16dba3336 | ||
|
|
b52d645459 | ||
|
|
73b24d2966 | ||
|
|
006c796da7 | ||
|
|
160fdee596 | ||
|
|
5cc50b0ff3 | ||
|
|
3ba2498815 | ||
|
|
0a0ec12e6c | ||
|
|
9c826a5fdd | ||
|
|
50d01ef6f8 | ||
|
|
b860b2bbfb | ||
|
|
7773a3b17b | ||
|
|
c605418e33 | ||
|
|
55270996ff | ||
|
|
789fcac439 | ||
|
|
466118319f | ||
|
|
8117aa8046 | ||
|
|
6847d2f373 | ||
|
|
f85c078de8 | ||
|
|
9cc08ada22 | ||
|
|
ec1afdfdc4 | ||
|
|
92d3d3cd9c | ||
|
|
8d23e335ae | ||
|
|
ec61598a52 | ||
|
|
c0c0ebb71f | ||
|
|
c22f6a844e | ||
|
|
8b4112f705 | ||
|
|
465afc3128 | ||
|
|
6730954a2e | ||
|
|
d03049799e | ||
|
|
3a3622bb58 | ||
|
|
38ec05807a | ||
|
|
5d4ab9ecd7 | ||
|
|
0ab5f5bb14 | ||
|
|
4b14008080 | ||
|
|
e23054d606 | ||
|
|
dc5ca76df0 | ||
|
|
a8b423836e | ||
|
|
a4bd160995 | ||
|
|
558ee579e1 | ||
|
|
41829b8660 | ||
|
|
b8eaabe0de | ||
|
|
a94735c5a5 | ||
|
|
ba48373bbc | ||
|
|
512b65a592 | ||
|
|
103ee371bd | ||
|
|
179f44cd37 | ||
|
|
1bf173b1ee | ||
|
|
356c2cfa80 | ||
|
|
5b61a183cd | ||
|
|
d5e1b47b52 | ||
|
|
63795d9df8 | ||
|
|
8e179552ec | ||
|
|
d1271f3e4b | ||
|
|
24e6f5b841 | ||
|
|
7118c972a8 | ||
|
|
e4742133ca | ||
|
|
ada6ef229c | ||
|
|
f0c0900770 | ||
|
|
a4a6eb6cee | ||
|
|
362c7d38a6 | ||
|
|
7b4d488b11 | ||
|
|
0c5f781702 | ||
|
|
ff5c48a2a0 | ||
|
|
1a55f19ab2 | ||
|
|
59456b67a1 | ||
|
|
1a12510081 | ||
|
|
d83f48891a | ||
|
|
747c6186d4 | ||
|
|
b3ef412368 | ||
|
|
bfdcb971fc | ||
|
|
487bc1866a | ||
|
|
0b99d71bd4 | ||
|
|
8d811550e2 | ||
|
|
09486946fc | ||
|
|
3f988cec72 | ||
|
|
c35dde5569 | ||
|
|
79d757856e | ||
|
|
cd0c48985d | ||
|
|
b2f35220e3 | ||
|
|
d9ecaa701b | ||
|
|
9355496915 | ||
|
|
79939db170 | ||
|
|
24d3afca18 | ||
|
|
334b62b0a2 | ||
|
|
16fb70b0ef | ||
|
|
c2fcffb0d8 | ||
|
|
681fc6de3d | ||
|
|
9640acfb74 | ||
|
|
94b12704dc | ||
|
|
74468855c2 | ||
|
|
031b1abe0a | ||
|
|
0e6d9ea933 | ||
|
|
6e5ad304e4 | ||
|
|
a689c2cb4d | ||
|
|
cd53cf0991 | ||
|
|
5e2bf1f931 | ||
|
|
033dadae2c | ||
|
|
1b0de739f9 | ||
|
|
351f1a80c7 | ||
|
|
def1094357 | ||
|
|
4dec658a77 | ||
|
|
a5fe8970c6 | ||
|
|
1cf2bd4892 | ||
|
|
9111860fce | ||
|
|
0cac972061 | ||
|
|
fa9257182b | ||
|
|
4fc18d35ce | ||
|
|
c2720bbc33 | ||
|
|
5d86390e28 | ||
|
|
ec89db7cb1 | ||
|
|
d15968d291 | ||
|
|
5e5df8848d | ||
|
|
a0f66a5f94 | ||
|
|
d3a15fba96 | ||
|
|
14dc293a09 | ||
|
|
a97690d219 | ||
|
|
9c626a17f0 | ||
|
|
3354ef246b | ||
|
|
e7e64379dd | ||
|
|
78dc94b0ed | ||
|
|
be38bba0e4 | ||
|
|
6c963a2de7 | ||
|
|
6d517396b3 | ||
|
|
6246a1d39c | ||
|
|
9c1063c7cc | ||
|
|
ed71777a17 | ||
|
|
353433a383 | ||
|
|
7e047ef726 | ||
|
|
c60f6d155f | ||
|
|
42486cd784 | ||
|
|
5b27f4786d | ||
|
|
01f759a992 | ||
|
|
cc0d7af610 | ||
|
|
00a2c1aad0 | ||
|
|
e40ab50e10 | ||
|
|
99b3420423 | ||
|
|
644d00b268 | ||
|
|
71c4f27d60 | ||
|
|
6cb2c0e8a7 | ||
|
|
d3745d043c | ||
|
|
b1b89290b9 | ||
|
|
ca8fa02687 | ||
|
|
ce9bfdbcae | ||
|
|
5f29633689 | ||
|
|
cab71958d0 | ||
|
|
9c995be22e | ||
|
|
f0a0b4cfc9 | ||
|
|
395f7e0324 | ||
|
|
b80129e17b | ||
|
|
e57b5b6966 | ||
|
|
316adf63ee | ||
|
|
588523b311 | ||
|
|
b8232326bc | ||
|
|
4fa04b9e23 | ||
|
|
6fdbe1d5f0 | ||
|
|
66ce3e75ec | ||
|
|
ec30232c4e | ||
|
|
6cb6a76ef3 | ||
|
|
46eeb8b960 | ||
|
|
294ab0a81b | ||
|
|
aa80f06f7b | ||
|
|
dd738a0108 | ||
|
|
3be5296572 | ||
|
|
cfa844f960 | ||
|
|
3b7afec360 | ||
|
|
a9412c4f62 | ||
|
|
2f57705f13 | ||
|
|
ee47bffb1c | ||
|
|
909c64468f | ||
|
|
d7d7b73c54 | ||
|
|
f820121e08 | ||
|
|
0b036acb75 | ||
|
|
4d4ae7b2db | ||
|
|
7f896723be | ||
|
|
36deb5e225 | ||
|
|
116422f1e7 | ||
|
|
a3d1dd91d9 | ||
|
|
41964cd130 | ||
|
|
d9a92dc10e | ||
|
|
9c1f897fff | ||
|
|
e64cd905d6 | ||
|
|
fc80c23dde | ||
|
|
84b69a683a | ||
|
|
79bf77f4be | ||
|
|
78c35221be | ||
|
|
1d257c1a35 | ||
|
|
ef92236cb4 | ||
|
|
90bc18e1bd | ||
|
|
9f6c45f4a0 | ||
|
|
b7842bbb26 | ||
|
|
589430055e | ||
|
|
8f6fe08b1c | ||
|
|
f354b6bcca | ||
|
|
d02a017c03 | ||
|
|
6d58997f71 | ||
|
|
7d72c4dc63 | ||
|
|
3b9700793c | ||
|
|
0c03c47eb9 | ||
|
|
2d35a024e2 | ||
|
|
eac11045ff | ||
|
|
a7cc6185ad | ||
|
|
d855840fe2 | ||
|
|
81419eddbe | ||
|
|
fc41ad36f7 | ||
|
|
676a064b6b | ||
|
|
9e1ba3e235 | ||
|
|
ad23544f24 | ||
|
|
296f9b9da5 | ||
|
|
47398f71a8 | ||
|
|
a36f872b61 | ||
|
|
dbebe2ab29 | ||
|
|
ccb973d1dd | ||
|
|
132b1fe0c4 | ||
|
|
8702ebd706 | ||
|
|
4734261097 | ||
|
|
78f55765c1 | ||
|
|
bdb4ae2f85 | ||
|
|
850b0d0210 | ||
|
|
fa0f161106 | ||
|
|
59aff44a55 | ||
|
|
aa74679998 | ||
|
|
61db253d4a | ||
|
|
fef8ee925b | ||
|
|
5cb5434ffe | ||
|
|
2f71a4092f | ||
|
|
a97573c5a9 | ||
|
|
108baa467d | ||
|
|
193015f1cd | ||
|
|
b64432dafd | ||
|
|
d66bb3a539 | ||
|
|
5ca5025fb1 | ||
|
|
497a68e792 | ||
|
|
737fa4fa69 | ||
|
|
3d3e33912e | ||
|
|
235fee091e | ||
|
|
00e3a59463 | ||
|
|
269c48b65b | ||
|
|
adbe55b0db | ||
|
|
f5222674ff | ||
|
|
c19a7e8452 | ||
|
|
aab79a90fb | ||
|
|
f3b6f0a29b | ||
|
|
d1fb436d6d | ||
|
|
1734d02291 | ||
|
|
f8c7739d5a | ||
|
|
7a1f332731 | ||
|
|
9cd19c0470 | ||
|
|
c9ca08ff1c | ||
|
|
c14532ecae | ||
|
|
b66cc8d8d7 | ||
|
|
b6ed5fbd6f | ||
|
|
2fec2156f6 | ||
|
|
35b3231b84 | ||
|
|
f77c32cbb2 | ||
|
|
7ec5aa28b3 | ||
|
|
373d004752 | ||
|
|
0ee137fe05 | ||
|
|
9c5d75c439 | ||
|
|
adbfcdf16a | ||
|
|
0716ecad55 | ||
|
|
9160ee546c | ||
|
|
7897d2858c | ||
|
|
b88364ab48 | ||
|
|
7727da40b4 | ||
|
|
17e68f7a93 | ||
|
|
120aa7c12a | ||
|
|
53214f0ddc | ||
|
|
d89a1fac70 | ||
|
|
0c00000910 | ||
|
|
f4f46eb924 | ||
|
|
b873adf5fc | ||
|
|
72fb66e5b2 | ||
|
|
af691c980d | ||
|
|
b3be906e28 | ||
|
|
1c22e2ed28 | ||
|
|
95fd073432 | ||
|
|
fcb9ebb8c3 | ||
|
|
4ab063679b | ||
|
|
db13bffad6 | ||
|
|
b719a0cd35 | ||
|
|
d506685bba | ||
|
|
8cf2068a70 | ||
|
|
14e4203ee7 | ||
|
|
447562b2f1 | ||
|
|
02c03e9c67 | ||
|
|
f8ddf952ca | ||
|
|
8436599c79 | ||
|
|
4c51519b8a | ||
|
|
0f199fa4b4 | ||
|
|
b28aff4a7b | ||
|
|
ba227d64fb | ||
|
|
7656aedb6b | ||
|
|
6e967dce70 | ||
|
|
232415f1d7 | ||
|
|
b2ed0ee884 | ||
|
|
6ffc8ba3c5 | ||
|
|
82f0d6a542 | ||
|
|
40e0303786 | ||
|
|
0e3bb40eb4 | ||
|
|
730cb14f6a | ||
|
|
c18ab184b7 | ||
|
|
b85cbe515e | ||
|
|
b58f202e9e | ||
|
|
fde23ceea0 | ||
|
|
aab2437c4c | ||
|
|
b7f7be839d | ||
|
|
6b7a63aba5 | ||
|
|
0c46d5088c | ||
|
|
254425d9ad | ||
|
|
c7ff20d47d | ||
|
|
1db5a9f3c2 | ||
|
|
34cf8466d6 | ||
|
|
8c20203084 | ||
|
|
a7ed7a71d5 | ||
|
|
2583541c0f | ||
|
|
1674b2dfd6 | ||
|
|
96de7c8321 | ||
|
|
7879648090 | ||
|
|
5772f5e7da | ||
|
|
54db6bda85 | ||
|
|
4ffcf252b7 | ||
|
|
b3b44214e0 | ||
|
|
89942416ac | ||
|
|
974d3498c1 | ||
|
|
1804111f88 | ||
|
|
5b2dc021a6 | ||
|
|
37d7b3d7fb | ||
|
|
33d4ab9edb | ||
|
|
f7f2b3438c | ||
|
|
0ed7934df0 | ||
|
|
55920e6242 | ||
|
|
820920e5f9 | ||
|
|
8e21c627a7 | ||
|
|
6973ed7d55 | ||
|
|
0980495a28 | ||
|
|
5c6b659ce3 | ||
|
|
35e263223d | ||
|
|
07ba378095 | ||
|
|
6e10f86546 | ||
|
|
fc6ee11ffe | ||
|
|
84cd87370f | ||
|
|
822fe9ab7a | ||
|
|
57b22a9cab | ||
|
|
278c4f17e5 | ||
|
|
b0d4607798 | ||
|
|
3f7dc66ac0 | ||
|
|
1c2b1fb757 | ||
|
|
eb31483a15 | ||
|
|
8fb7cdaba6 | ||
|
|
61d81046ae | ||
|
|
0c3d7e09e0 | ||
|
|
a9f9ddcacf | ||
|
|
a559c3581e | ||
|
|
dd5389c738 | ||
|
|
ac25e17286 | ||
|
|
9de4c89e76 | ||
|
|
2f6846d8c3 | ||
|
|
c3e60531c4 | ||
|
|
44aff82a6c | ||
|
|
7619e7643d | ||
|
|
353ef05b93 | ||
|
|
2801e4ed80 | ||
|
|
173dd0a90e | ||
|
|
e5412aeb1b | ||
|
|
0eec955a3d | ||
|
|
47038ac06d | ||
|
|
8041c305ad | ||
|
|
e0d249898e | ||
|
|
a1f5982a85 | ||
|
|
3c688d3fec | ||
|
|
889a9a7a05 | ||
|
|
ce6c39b7aa | ||
|
|
2a1fdded72 | ||
|
|
2b757fe107 | ||
|
|
a8d78453ff | ||
|
|
2b88396aac | ||
|
|
f856ad16ba | ||
|
|
f36d47c13f | ||
|
|
4f98bc95a2 | ||
|
|
ec3dc867c1 | ||
|
|
7fea7e91aa | ||
|
|
1ea545ccb2 | ||
|
|
e5e2d0ab03 | ||
|
|
c94e7aa031 | ||
|
|
5d1af6fb76 | ||
|
|
3b400ac3f3 | ||
|
|
308176ee81 | ||
|
|
8a84ebb58d | ||
|
|
158d11d3ba | ||
|
|
beec1eeaba | ||
|
|
63a1f4e2de | ||
|
|
7d845951e9 | ||
|
|
48d9ea6aa1 | ||
|
|
ae83e604ba | ||
|
|
c156968be6 | ||
|
|
effe2312e0 | ||
|
|
1c389dc7f8 | ||
|
|
972ca71978 | ||
|
|
fb35adb494 | ||
|
|
22813b71ff | ||
|
|
02243d1f5c | ||
|
|
e2b2e8fb4e | ||
|
|
390ceb8887 | ||
|
|
2167a3d7fe | ||
|
|
6f2033a455 | ||
|
|
2ae7863cae | ||
|
|
02b42c51da | ||
|
|
0ba26b22c0 | ||
|
|
017552f573 | ||
|
|
01a3c772e7 | ||
|
|
5693605f31 | ||
|
|
481881aa8b | ||
|
|
544660c4bb | ||
|
|
3d8d84177b | ||
|
|
789e354400 | ||
|
|
4fdb817d4a | ||
|
|
4055361501 | ||
|
|
416007593f | ||
|
|
4ed9f10c1b | ||
|
|
178cb12f85 | ||
|
|
c0582cd527 | ||
|
|
39e47db8c7 | ||
|
|
ed4156850b | ||
|
|
5364522a5a | ||
|
|
3382d56590 | ||
|
|
1e30c46322 | ||
|
|
3eb72d6d86 | ||
|
|
2d01c41159 | ||
|
|
0b3dddcc9e | ||
|
|
bc7085826e | ||
|
|
f78ee66049 | ||
|
|
fecaf768ab | ||
|
|
ec59cb602c | ||
|
|
2ea1671739 | ||
|
|
f7e4936445 | ||
|
|
d37e8c2e75 | ||
|
|
fb8dcc5f86 | ||
|
|
4c4c361093 | ||
|
|
9c29706297 | ||
|
|
4dcac119d8 | ||
|
|
f9dfd5b0b5 | ||
|
|
10dcd9cb2d | ||
|
|
c80e800ac9 | ||
|
|
eafcbf0914 | ||
|
|
4f561a3875 | ||
|
|
5cc92506c9 | ||
|
|
2c8eb1e5b8 | ||
|
|
6c18634b0d | ||
|
|
c7bd9dd0fa | ||
|
|
d8ec231a5e | ||
|
|
5c803594fb | ||
|
|
cececa190a | ||
|
|
38a3f1839e | ||
|
|
2eb57ab680 | ||
|
|
f6f1ddb826 | ||
|
|
fcdbd4b117 | ||
|
|
a5c44e7998 | ||
|
|
8afea88023 | ||
|
|
75443e4dfc | ||
|
|
fbfb491dca | ||
|
|
082c17da85 | ||
|
|
88ebf4f9db | ||
|
|
18825b1697 | ||
|
|
551b11877d | ||
|
|
0bd1b4eedc | ||
|
|
d401d7838c | ||
|
|
8b2e273d41 | ||
|
|
bdff6f9560 | ||
|
|
bb500a53ef | ||
|
|
7ff0811764 | ||
|
|
36b49b6d8b | ||
|
|
e8edfb1170 | ||
|
|
bc6fcbc86d | ||
|
|
8853ca303e | ||
|
|
914a6fc89b | ||
|
|
028be85468 | ||
|
|
5ffc285e1c | ||
|
|
604e6f8c47 | ||
|
|
4ac4f10ea0 | ||
|
|
4c07733857 | ||
|
|
7dc0f4dbc5 | ||
|
|
22f64fa2a5 | ||
|
|
5b0f1b5c03 | ||
|
|
c6e0292d03 | ||
|
|
17eee61a93 | ||
|
|
3817b159cf | ||
|
|
331cf2e269 | ||
|
|
96622848d9 | ||
|
|
bcdc8867e6 | ||
|
|
eaeb67b91f | ||
|
|
ebd444cc5f | ||
|
|
ff1ab9dd42 | ||
|
|
7e2c830f9c | ||
|
|
0cc2214951 | ||
|
|
47443d5ae7 | ||
|
|
cd2c605036 | ||
|
|
847e46d270 | ||
|
|
3d6cfcafd0 | ||
|
|
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 | ||
|
|
315cbaec47 | ||
|
|
68535bfcaa |
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -17,7 +17,7 @@ assignees: ''
|
||||
|
||||
**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 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.*
|
||||
**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.*
|
||||
|
||||
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.
|
||||
|
||||
|
||||
5
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
If your pull request is **not** translation or serverlist-related, read the list of requirements below and check each box:
|
||||
|
||||
- [ ] I have read the [contribution guidelines](https://github.com/Anuken/Mindustry/blob/master/CONTRIBUTING.md).
|
||||
- [ ] I have ensured that my code compiles, if applicable.
|
||||
- [ ] I have ensured that any new features in this PR function correctly in-game, if applicable.
|
||||
11
.github/workflows/deployment.yml
vendored
@@ -6,15 +6,15 @@ on:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
buildJava14:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 14
|
||||
- name: Set up JDK 16
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 14
|
||||
java-version: 16
|
||||
- name: Set env
|
||||
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||
- name: Add Arc release
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
cp -a Mindustry/core/build/javadoc/. docs/
|
||||
cd docs
|
||||
git add .
|
||||
git commit -m "Update ${RELEASE_VERSION:1}"
|
||||
git commit --allow-empty -m "Update ${RELEASE_VERSION:1}"
|
||||
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/MindustryGame/docs
|
||||
cd ../Mindustry
|
||||
- name: Update F-Droid build string
|
||||
@@ -47,7 +47,8 @@ jobs:
|
||||
git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds
|
||||
cd ../MindustryBuilds
|
||||
echo "Updating version to ${RELEASE_VERSION:1}"
|
||||
echo versionName=6-fdroid-${RELEASE_VERSION:1}$'\n'versionCode=${RELEASE_VERSION:1} > version_fdroid.txt
|
||||
BNUM=$(($GITHUB_RUN_NUMBER + 1000))
|
||||
echo versionName=7-fdroid-${RELEASE_VERSION:1}$'\n'versionCode=${BNUM} > version_fdroid.txt
|
||||
git add .
|
||||
git commit -m "Updating to build ${RELEASE_VERSION:1}"
|
||||
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/MindustryBuilds
|
||||
|
||||
8
.github/workflows/pr.yml
vendored
@@ -1,17 +1,17 @@
|
||||
name: Pull Request Tests
|
||||
|
||||
on: [pull_request]
|
||||
on: [pull_request, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
buildJava14:
|
||||
testPR:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 14
|
||||
- name: Set up JDK 16
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 14
|
||||
java-version: 16
|
||||
- name: Run unit tests and build JAR
|
||||
run: ./gradlew test desktop:dist
|
||||
- name: Upload desktop JAR for testing
|
||||
|
||||
14
.github/workflows/push.yml
vendored
@@ -3,17 +3,11 @@ name: Tests
|
||||
on: [push, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
buildJava14:
|
||||
runPush:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 14
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 14
|
||||
- name: Run unit tests
|
||||
run: ./gradlew clean cleanTest test
|
||||
- name: Trigger BE build
|
||||
if: ${{ github.repository == 'Anuken/Mindustry' }}
|
||||
run: |
|
||||
@@ -23,3 +17,9 @@ jobs:
|
||||
git tag ${BNUM}
|
||||
git config --global user.name "Build Uploader"
|
||||
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/MindustryBuilds ${BNUM}
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 17
|
||||
- name: Run unit tests
|
||||
run: ./gradlew clean cleanTest test --stacktrace
|
||||
|
||||
9
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
logs/
|
||||
/fastlane/metadata/android/en-US/changelogs/
|
||||
/core/assets/mindustry-saves/
|
||||
/core/assets/mindustry-maps/
|
||||
/core/assets/bundles/output/
|
||||
@@ -102,6 +103,10 @@ com_crashlytics_export_strings.xml
|
||||
.externalToolBuilders/
|
||||
*.launch
|
||||
|
||||
## VSCode
|
||||
|
||||
.vscode/
|
||||
|
||||
## NetBeans
|
||||
|
||||
/nbproject/private/
|
||||
@@ -157,3 +162,7 @@ gradle-app.setting
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
android/libs/
|
||||
|
||||
# ignored due to frequent branch conflicts.
|
||||
core/assets/logicids.dat
|
||||
core/assets/icons/icons.properties
|
||||
@@ -26,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.
|
||||
- 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.
|
||||
- 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)
|
||||
- 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.
|
||||
|
||||
|
||||
@@ -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).
|
||||
|
||||
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-17](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
|
||||
|
||||
@@ -38,7 +38,7 @@ Server builds are bundled with each released build (in Releases). If you'd rathe
|
||||
|
||||
### Android
|
||||
|
||||
1. Install the Android SDK [here.](https://developer.android.com/studio#downloads) Make sure you're downloading the "Command line tools only", as Android Studio is not required.
|
||||
1. Install the Android SDK [here.](https://developer.android.com/studio#command-tools) Make sure you're downloading the "Command line tools only", as Android Studio is not required.
|
||||
2. Set the `ANDROID_HOME` environment variable to point to your unzipped Android SDK directory.
|
||||
3. Run `gradlew android:assembleDebug` (or `./gradlew` if on linux/mac). This will create an unsigned APK in `android/build/outputs/apk`.
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ This is done by letting clients `GET` a [JSON list of servers](https://github.co
|
||||
|
||||
You may want to add your server to this list. The steps for getting this done are as follows:
|
||||
|
||||
0. **Take note of the fact that modded servers are not allowed on this list.** Such servers confuse users, and there's currently no easy way to fix mod incompatibilities after a failed connection.
|
||||
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.
|
||||
*Consider enabling a rate limit:* `config messageRateLimit 2` will make it so that players can only send messages every 2 seconds, for example.
|
||||
|
||||
@@ -31,9 +31,11 @@ There are two ways to test the translation bundle:
|
||||
1) Assuming you have the PC version downloaded, download your bundle file, name it `bundle.properties`, then place it in the same folder as the Mindustry desktop executable and run it. *You should get a popup message in-game confirming that you have loaded an external translation.*
|
||||
2) For advanced users: simply download your fork of mindustry and compile/run the game.
|
||||
|
||||
#### Translating for stores (Steam, Google Play)
|
||||
#### Translating for stores (Steam, ~~Google Play~~)
|
||||
|
||||
If you would like to translate the descriptions for Google Play or Steam, see the [Fastlane Metadata folder](https://github.com/Anuken/Mindustry/tree/master/fastlane/metadata) and submit a pull request for files there. On Google Play, you would create or edit the folder with the correct local code; for Steam, I have to update the translations manually, so just name the folder with the language name, and include the same files as the English folder does.
|
||||
NOTE: The Google Play description is in the process of being re-written, please do not translate it.
|
||||
|
||||
If you would like to translate the descriptions for ~~Google Play~~ or Steam, see the [Fastlane Metadata folder](https://github.com/Anuken/Mindustry/tree/master/fastlane/metadata) and submit a pull request for files there. On Google Play, you would create or edit the folder with the correct local code; for Steam, I have to update the translations manually, so just name the folder with the language name, and include the same files as the English folder does.
|
||||
|
||||
**And that's it.**
|
||||
|
||||
|
||||
@@ -14,10 +14,11 @@
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:isGame="true"
|
||||
android:theme="@style/ArcTheme"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:appCategory="game"
|
||||
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"/>
|
||||
<activity
|
||||
android:name="mindustry.android.AndroidLauncher"
|
||||
|
||||
@@ -7,9 +7,7 @@ buildscript{
|
||||
}
|
||||
|
||||
dependencies{
|
||||
//IMPORTANT NOTICE: any version of the plugin after 3.4.1 will break builds
|
||||
//it appears abstract methods don't get desugared properly (if at all)
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
classpath 'com.android.tools.build:gradle:7.0.3'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,35 +18,19 @@ configurations{ natives }
|
||||
repositories{
|
||||
mavenCentral()
|
||||
maven{ url "https://maven.google.com" }
|
||||
jcenter() //remove later once google 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){
|
||||
dependsOn "assembleRelease"
|
||||
|
||||
from "build/outputs/apk/release/android-release.apk"
|
||||
from "build/outputs/apk/standard/release/android-standard-release.apk"
|
||||
into "../deploy/"
|
||||
rename("android-release.apk", "${generateDeployName('android')}.apk")
|
||||
rename("android-standard-release.apk", "${generateDeployName('android')}.apk")
|
||||
}
|
||||
|
||||
android{
|
||||
buildToolsVersion '29.0.3'
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion '30.0.3'
|
||||
compileSdkVersion 30
|
||||
sourceSets{
|
||||
main{
|
||||
manifest.srcFile 'AndroidManifest.xml'
|
||||
@@ -59,9 +41,13 @@ android{
|
||||
assets.srcDirs = ['assets', 'src/main/assets', '../core/assets/']
|
||||
jniLibs.srcDirs = ['libs']
|
||||
}
|
||||
gp{
|
||||
java.srcDirs = ['srcgp']
|
||||
}
|
||||
|
||||
androidTest.setRoot('tests')
|
||||
}
|
||||
|
||||
packagingOptions{
|
||||
exclude 'META-INF/robovm/ios/robovm.xml'
|
||||
}
|
||||
@@ -73,7 +59,7 @@ android{
|
||||
|
||||
applicationId "io.anuke.mindustry"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 29
|
||||
targetSdkVersion 30
|
||||
|
||||
versionName versionNameResult
|
||||
versionCode = (System.getenv("TRAVIS_BUILD_ID") != null ? System.getenv("TRAVIS_BUILD_ID").toInteger() : vcode)
|
||||
@@ -109,6 +95,17 @@ android{
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes{
|
||||
all{
|
||||
minifyEnabled = true
|
||||
shrinkResources = true
|
||||
//this is the ONLY WAY I could find to force r8 to keep its filthy hands off of my default interfaces.
|
||||
//may have undesirable side effects
|
||||
debuggable = true
|
||||
proguardFiles("proguard-rules.pro")
|
||||
}
|
||||
}
|
||||
|
||||
if(project.hasProperty("RELEASE_STORE_FILE") || System.getenv("CI") == "true"){
|
||||
buildTypes{
|
||||
release{
|
||||
@@ -116,10 +113,37 @@ android{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Specifies one flavor dimension.
|
||||
flavorDimensions "version"
|
||||
productFlavors{
|
||||
standard{
|
||||
|
||||
}
|
||||
gp{
|
||||
applicationIdSuffix ".gp"
|
||||
versionNameSuffix "-gp"
|
||||
}
|
||||
}
|
||||
}
|
||||
// called every time gradle gets executed, takes the native dependencies of
|
||||
// the natives configuration, and extracts them to the proper libs/ folders
|
||||
// so they get packed with the APK.
|
||||
|
||||
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"
|
||||
|
||||
//TODO dynamically find best android platform jar instead of hard-coding to 30
|
||||
def sdkFile = new File((String)findSdkDir(), "/platforms/android-30/android.jar")
|
||||
if(sdkFile.exists()) compileOnly files(sdkFile.absolutePath)
|
||||
}
|
||||
|
||||
task copyAndroidNatives(){
|
||||
configurations.natives.files.each{ jar ->
|
||||
copy{
|
||||
@@ -131,29 +155,13 @@ task copyAndroidNatives(){
|
||||
}
|
||||
|
||||
task run(type: Exec){
|
||||
def path
|
||||
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"
|
||||
commandLine "$adb", 'shell', 'am', 'start', '-n', 'io.anuke.mindustry/mindustry.android.AndroidLauncher'
|
||||
commandLine "${findSdkDir()}/platform-tools/adb", 'shell', 'am', 'start', '-n', 'io.anuke.mindustry/mindustry.android.AndroidLauncher'
|
||||
}
|
||||
|
||||
if(!project.ext.hasSprites()){
|
||||
println "Scheduling sprite pack."
|
||||
run.dependsOn ":tools:pack"
|
||||
deploy.dependsOn ":tools:pack"
|
||||
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,6 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_name">Mindustry</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<resources>
|
||||
|
||||
<style name="ArcTheme" parent="android:Theme">
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:colorBackgroundCacheHint">@null</item>
|
||||
@@ -8,5 +7,4 @@
|
||||
<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;
|
||||
Runnable permCallback;
|
||||
|
||||
Object gpService;
|
||||
Class<?> serviceClass;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState){
|
||||
UncaughtExceptionHandler handler = Thread.getDefaultUncaughtExceptionHandler();
|
||||
@@ -44,14 +47,13 @@ public class AndroidLauncher extends AndroidApplication{
|
||||
if(handler != null){
|
||||
handler.uncaughtException(thread, error);
|
||||
}else{
|
||||
error.printStackTrace();
|
||||
Log.err(error);
|
||||
System.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
if(doubleScaleTablets && isTablet(this.getContext())){
|
||||
if(doubleScaleTablets && isTablet(this)){
|
||||
Scl.setAddition(0.5f);
|
||||
}
|
||||
|
||||
@@ -64,7 +66,7 @@ public class AndroidLauncher extends AndroidApplication{
|
||||
|
||||
@Override
|
||||
public rhino.Context getScriptContext(){
|
||||
return AndroidRhinoContext.enter(getContext().getCacheDir());
|
||||
return AndroidRhinoContext.enter(getCacheDir());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,8 +74,28 @@ public class AndroidLauncher extends AndroidApplication{
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader loadJar(Fi jar, String mainClass) throws Exception{
|
||||
return new DexClassLoader(jar.file().getPath(), getFilesDir().getPath(), null, getClassLoader());
|
||||
public ClassLoader loadJar(Fi jar, ClassLoader parent) throws Exception{
|
||||
return new DexClassLoader(jar.file().getPath(), getFilesDir().getPath(), null, parent){
|
||||
@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 | NoClassDefFoundError e){
|
||||
//use parent if not found
|
||||
return parent.loadClass(name);
|
||||
}
|
||||
}
|
||||
|
||||
if(resolve){
|
||||
resolveClass(loadedClass);
|
||||
}
|
||||
return loadedClass;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,9 +188,20 @@ public class AndroidLauncher extends AndroidApplication{
|
||||
|
||||
try{
|
||||
//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);
|
||||
|
||||
//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
|
||||
if(!Core.files.local("files_moved").exists()){
|
||||
Log.info("Moving files to external storage...");
|
||||
@@ -210,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){
|
||||
try{
|
||||
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.merge.*;
|
||||
import dalvik.system.*;
|
||||
import mindustry.mod.*;
|
||||
import rhino.*;
|
||||
|
||||
import java.io.*;
|
||||
@@ -30,23 +31,6 @@ public class AndroidRhinoContext{
|
||||
* @return a context prepared for android
|
||||
*/
|
||||
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;
|
||||
if(!ContextFactory.hasExplicitGlobal()){
|
||||
@@ -175,7 +159,7 @@ public class AndroidRhinoContext{
|
||||
}catch(IOException e){
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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:
|
||||
* "@" -> block name
|
||||
* "$size" -> block size
|
||||
* "@size" -> block size
|
||||
* "#" "#1" "#2" -> index number, for arrays
|
||||
* */
|
||||
String value();
|
||||
@@ -177,12 +177,12 @@ public class Annotations{
|
||||
//region remote
|
||||
|
||||
public enum PacketPriority{
|
||||
/** Does not get handled unless client is connected. */
|
||||
low,
|
||||
/** Gets put in a queue and processed if not connected. */
|
||||
normal,
|
||||
/** Gets handled immediately, regardless of connection status. */
|
||||
high,
|
||||
/** Does not get handled unless client is connected. */
|
||||
low
|
||||
}
|
||||
|
||||
/** A set of two booleans, one specifying server and one specifying client. */
|
||||
|
||||
@@ -2,15 +2,10 @@ package mindustry.annotations;
|
||||
|
||||
import arc.files.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.Log;
|
||||
import arc.util.Log.*;
|
||||
import arc.util.*;
|
||||
import arc.util.Log.*;
|
||||
import com.squareup.javapoet.*;
|
||||
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 javax.annotation.processing.*;
|
||||
@@ -22,7 +17,6 @@ import javax.tools.Diagnostic.*;
|
||||
import javax.tools.*;
|
||||
import java.io.*;
|
||||
import java.lang.annotation.*;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
||||
@@ -31,19 +25,16 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
||||
public static final String packageName = "mindustry.gen";
|
||||
|
||||
public static Types typeu;
|
||||
public static JavacElements elementu;
|
||||
public static Elements elementu;
|
||||
public static Filer filer;
|
||||
public static Messager messager;
|
||||
public static Trees trees;
|
||||
public static TreeMaker maker;
|
||||
|
||||
protected int round;
|
||||
protected int rounds = 1;
|
||||
protected RoundEnvironment env;
|
||||
protected Fi rootDirectory;
|
||||
|
||||
protected Context context;
|
||||
|
||||
public static String getMethodName(Element element){
|
||||
return ((TypeElement)element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName();
|
||||
}
|
||||
@@ -100,7 +91,7 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
||||
}
|
||||
|
||||
public static TypeName tname(String pack, String simple){
|
||||
return ClassName.get(pack, simple );
|
||||
return ClassName.get(pack, simple);
|
||||
}
|
||||
|
||||
public static TypeName tname(String name){
|
||||
@@ -186,7 +177,7 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -194,15 +185,11 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
||||
public synchronized void init(ProcessingEnvironment env){
|
||||
super.init(env);
|
||||
|
||||
JavacProcessingEnvironment javacProcessingEnv = (JavacProcessingEnvironment)env;
|
||||
|
||||
trees = Trees.instance(env);
|
||||
typeu = env.getTypeUtils();
|
||||
elementu = javacProcessingEnv.getElementUtils();
|
||||
elementu = env.getElementUtils();
|
||||
filer = env.getFiler();
|
||||
messager = env.getMessager();
|
||||
context = ((JavacProcessingEnvironment)env).getContext();
|
||||
maker = TreeMaker.instance(javacProcessingEnv.getContext());
|
||||
|
||||
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")
|
||||
.toUri().toURL().toString().substring(OS.isWindows ? 6 : "file:".length()))
|
||||
.parent().parent().parent().parent().parent().parent().parent().toString().replace("%20", " ");
|
||||
rootDirectory = Fi.get(path);
|
||||
rootDirectory = Fi.get(path).parent();
|
||||
}catch(IOException e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
@@ -143,6 +143,7 @@ public class EntityIO{
|
||||
if(sl) cont("if(!islocal)");
|
||||
|
||||
if(sf){
|
||||
//TODO adding + targetSuf to the assignment fixes units being interpolated incorrectly during physics, but makes interpolation snap instead.
|
||||
st(field.name + lastSuf + " = this." + field.name);
|
||||
}
|
||||
|
||||
|
||||
@@ -101,6 +101,8 @@ public class EntityProcess extends BaseProcessor{
|
||||
|
||||
inter.addJavadoc("Interface for {@link $L}", component.fullName());
|
||||
|
||||
skipDeprecated(inter);
|
||||
|
||||
//implement extra interfaces these components may have, e.g. position
|
||||
for(Stype extraInterface : component.interfaces().select(i -> !isCompInterface(i))){
|
||||
//javapoet completely chokes on this if I add `addSuperInterface` or create the type name with TypeName.get
|
||||
@@ -132,6 +134,7 @@ public class EntityProcess extends BaseProcessor{
|
||||
.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))){
|
||||
String cname = field.name();
|
||||
|
||||
@@ -273,7 +276,10 @@ public class EntityProcess extends BaseProcessor{
|
||||
name += "Entity";
|
||||
}
|
||||
|
||||
if(ann.legacy()){
|
||||
boolean legacy = ann.legacy();
|
||||
|
||||
if(legacy){
|
||||
baseClass = tname(packageName + "." + name);
|
||||
name += "Legacy" + Strings.capitalize(type.name());
|
||||
}
|
||||
|
||||
@@ -338,7 +344,8 @@ public class EntityProcess extends BaseProcessor{
|
||||
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
|
||||
if(!isShadowed || !isVisible){
|
||||
//legacy classes have no extra fields
|
||||
if((!isShadowed || !isVisible) && !legacy){
|
||||
builder.addField(spec);
|
||||
}
|
||||
|
||||
@@ -348,7 +355,7 @@ public class EntityProcess extends BaseProcessor{
|
||||
allFields.add(f);
|
||||
|
||||
//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);
|
||||
|
||||
syncedFields.add(f);
|
||||
@@ -442,11 +449,14 @@ public class EntityProcess extends BaseProcessor{
|
||||
}
|
||||
}
|
||||
|
||||
boolean specialIO = false;
|
||||
|
||||
if(hasIO){
|
||||
//SPECIAL CASE: I/O code
|
||||
//note that serialization is generated even for non-serializing entities for manual usage
|
||||
if((first.name().equals("read") || first.name().equals("write"))){
|
||||
io.write(mbuilder, first.name().equals("write"));
|
||||
specialIO = true;
|
||||
}
|
||||
|
||||
//SPECIAL CASE: sync I/O code
|
||||
@@ -525,8 +535,10 @@ public class EntityProcess extends BaseProcessor{
|
||||
mbuilder.addStatement("mindustry.gen.Groups.queueFree(($T)this)", Poolable.class);
|
||||
}
|
||||
|
||||
if(!legacy || specialIO){
|
||||
builder.addMethod(mbuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
//add pool reset method and implement Poolable
|
||||
if(ann.pooled()){
|
||||
@@ -560,7 +572,9 @@ public class EntityProcess extends BaseProcessor{
|
||||
.returns(tname(packageName + "." + name))
|
||||
.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));
|
||||
skipDeprecated(builder);
|
||||
|
||||
definitions.add(new EntityDefinition(packageName + "." + name, builder, type, typeIsBase ? null : baseClass, components, groups, allFieldSpecs, legacy));
|
||||
}
|
||||
|
||||
//generate groups
|
||||
@@ -665,11 +679,28 @@ public class EntityProcess extends BaseProcessor{
|
||||
//build mapping class for sync IDs
|
||||
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(ParameterizedTypeName.get(ClassName.get(ObjectMap.class),
|
||||
tname(String.class), tname(Prov.class)),
|
||||
"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)
|
||||
.returns(TypeName.get(Prov.class)).addParameter(int.class, "id").addStatement("return idMap[id]").build())
|
||||
|
||||
.addMethod(MethodSpec.methodBuilder("map").addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||
.returns(TypeName.get(Prov.class)).addParameter(String.class, "name").addStatement("return nameMap.get(name)").build());
|
||||
|
||||
@@ -698,11 +729,6 @@ public class EntityProcess extends BaseProcessor{
|
||||
}else{
|
||||
//round 3: generate actual classes and implement interfaces
|
||||
|
||||
//write base classes
|
||||
for(TypeSpec.Builder b : baseClasses){
|
||||
write(b, imports.asArray());
|
||||
}
|
||||
|
||||
//implement each definition
|
||||
for(EntityDefinition def : definitions){
|
||||
|
||||
@@ -725,6 +751,14 @@ public class EntityProcess extends BaseProcessor{
|
||||
|
||||
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
|
||||
for(Smethod method : inter.methods()){
|
||||
String var = method.name();
|
||||
@@ -732,14 +766,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
|
||||
if(field == null || methodNames.contains(method.simpleString())) continue;
|
||||
|
||||
MethodSpec result = null;
|
||||
|
||||
//getter
|
||||
if(!method.isVoid()){
|
||||
def.builder.addMethod(MethodSpec.overriding(method.e).addStatement("return " + var).build());
|
||||
result = MethodSpec.overriding(method.e).addStatement("return " + var).build();
|
||||
}
|
||||
|
||||
//setter
|
||||
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 +803,16 @@ public class EntityProcess extends BaseProcessor{
|
||||
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
|
||||
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
|
||||
for(Stype interf : allInterfaces){
|
||||
@@ -767,10 +831,18 @@ public class EntityProcess extends BaseProcessor{
|
||||
|
||||
//create null builder
|
||||
String baseName = interf.name().substring(0, interf.name().length() - 1);
|
||||
|
||||
//prevent Nulls bloat
|
||||
if(!nullList.contains(Strings.camelize(baseName))){
|
||||
continue;
|
||||
}
|
||||
|
||||
String className = "Null" + baseName;
|
||||
TypeSpec.Builder nullBuilder = TypeSpec.classBuilder(className)
|
||||
.addModifiers(Modifier.FINAL);
|
||||
|
||||
skipDeprecated(nullBuilder);
|
||||
|
||||
nullBuilder.addSuperinterface(interf.tname());
|
||||
if(superclass != null) nullBuilder.superclass(tname(baseName(superclass)));
|
||||
|
||||
@@ -806,7 +878,7 @@ public class EntityProcess extends BaseProcessor{
|
||||
|
||||
nullsBuilder.addField(FieldSpec.builder(type, Strings.camelize(baseName)).initializer("new " + className + "()").addModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.PUBLIC).build());
|
||||
|
||||
write(nullBuilder);
|
||||
write(nullBuilder, imports.asArray());
|
||||
}
|
||||
|
||||
write(nullsBuilder);
|
||||
@@ -900,7 +972,7 @@ public class EntityProcess extends BaseProcessor{
|
||||
}
|
||||
|
||||
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);
|
||||
return comps.toString("", s -> s.name().replace("Comp", ""));
|
||||
}
|
||||
@@ -914,6 +986,11 @@ public class EntityProcess extends BaseProcessor{
|
||||
throw new IllegalArgumentException("Missing types.");
|
||||
}
|
||||
|
||||
void skipDeprecated(TypeSpec.Builder builder){
|
||||
//deprecations are irrelevant in generated code
|
||||
builder.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "\"deprecation\"").build());
|
||||
}
|
||||
|
||||
class GroupDefinition{
|
||||
final String name;
|
||||
final ClassName baseType;
|
||||
@@ -944,9 +1021,10 @@ public class EntityProcess extends BaseProcessor{
|
||||
final Selement naming;
|
||||
final String name;
|
||||
final @Nullable TypeName extend;
|
||||
final boolean legacy;
|
||||
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.name = name;
|
||||
this.naming = naming;
|
||||
@@ -954,6 +1032,7 @@ public class EntityProcess extends BaseProcessor{
|
||||
this.components = components;
|
||||
this.extend = extend;
|
||||
this.fieldSpecs = fieldSpec;
|
||||
this.legacy = legacy;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package mindustry.annotations.impl;
|
||||
|
||||
import arc.*;
|
||||
import arc.audio.*;
|
||||
import arc.files.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.struct.*;
|
||||
@@ -20,8 +22,8 @@ public class AssetsProcess extends BaseProcessor{
|
||||
|
||||
@Override
|
||||
public void process(RoundEnvironment env) throws Exception{
|
||||
processSounds("Sounds", rootDirectory + "/core/assets/sounds", "arc.audio.Sound");
|
||||
processSounds("Musics", rootDirectory + "/core/assets/music", "arc.audio.Music");
|
||||
processSounds("Sounds", rootDirectory + "/core/assets/sounds", "arc.audio.Sound", true);
|
||||
processSounds("Musics", rootDirectory + "/core/assets/music", "arc.audio.Music", false);
|
||||
processUI(env.getElementsAnnotatedWith(StyleDefaults.class));
|
||||
}
|
||||
|
||||
@@ -43,7 +45,7 @@ public class AssetsProcess extends BaseProcessor{
|
||||
|
||||
texIcons.each((key, val) -> {
|
||||
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";
|
||||
|
||||
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());
|
||||
@@ -87,18 +89,18 @@ public class AssetsProcess extends BaseProcessor{
|
||||
filename = filename.substring(0, filename.indexOf("."));
|
||||
|
||||
String sfilen = filename;
|
||||
String dtype = p.name().endsWith(".9.png") ? "arc.scene.style.NinePatchDrawable" : "arc.scene.style.TextureRegionDrawable";
|
||||
String dtype = "arc.scene.style.Drawable";
|
||||
|
||||
String varname = capitalize(sfilen);
|
||||
|
||||
if(SourceVersion.isKeyword(varname)) varname += "s";
|
||||
|
||||
type.addField(ClassName.bestGuess(dtype), varname, Modifier.STATIC, Modifier.PUBLIC);
|
||||
load.addStatement(varname + " = (" + dtype + ")arc.Core.atlas.drawable($S)", sfilen);
|
||||
load.addStatement(varname + " = arc.Core.atlas.drawable($S)", sfilen);
|
||||
});
|
||||
|
||||
for(Element elem : elements){
|
||||
Seq.with(((TypeElement)elem).getEnclosedElements()).each(e -> e.getKind() == ElementKind.FIELD, field -> {
|
||||
Seq.with(elem.getEnclosedElements()).each(e -> e.getKind() == ElementKind.FIELD, field -> {
|
||||
String fname = field.getSimpleName().toString();
|
||||
if(fname.startsWith("default")){
|
||||
loadStyles.addStatement("arc.Core.scene.addStyle(" + field.asType().toString() + ".class, mindustry.ui.Styles." + fname + ")");
|
||||
@@ -115,17 +117,40 @@ public class AssetsProcess extends BaseProcessor{
|
||||
JavaFile.builder(packageName, type.build()).build().writeTo(BaseProcessor.filer);
|
||||
}
|
||||
|
||||
void processSounds(String classname, String path, String rtype) throws Exception{
|
||||
void processSounds(String classname, String path, String rtype, boolean genid) throws Exception{
|
||||
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);
|
||||
CodeBlock.Builder staticb = CodeBlock.builder();
|
||||
|
||||
if(genid){
|
||||
type.addField(FieldSpec.builder(IntMap.class, "idToSound", Modifier.STATIC, Modifier.PRIVATE).initializer("new IntMap()").build());
|
||||
type.addField(FieldSpec.builder(ObjectIntMap.class, "soundToId", Modifier.STATIC, Modifier.PRIVATE).initializer("new ObjectIntMap()").build());
|
||||
|
||||
type.addMethod(MethodSpec.methodBuilder("getSoundId")
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||
.addParameter(Sound.class, "sound")
|
||||
.returns(int.class)
|
||||
.addStatement("return soundToId.get(sound, -1)").build());
|
||||
|
||||
type.addMethod(MethodSpec.methodBuilder("getSound")
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||
.addParameter(int.class, "id")
|
||||
.returns(Sound.class)
|
||||
.addStatement("return (Sound)idToSound.get(id, () -> Sounds.none)").build());
|
||||
}
|
||||
|
||||
HashSet<String> names = new HashSet<>();
|
||||
Fi.get(path).walk(p -> {
|
||||
Seq<Fi> files = new Seq<>();
|
||||
Fi.get(path).walk(files::add);
|
||||
|
||||
files.sortComparing(Fi::name);
|
||||
int id = 0;
|
||||
|
||||
for(Fi p : files){
|
||||
String name = p.nameWithoutExtension();
|
||||
|
||||
if(names.contains(name)){
|
||||
BaseProcessor.err("Duplicate file name: " + p.toString() + "!");
|
||||
BaseProcessor.err("Duplicate file name: " + p + "!");
|
||||
}else{
|
||||
names.add(name);
|
||||
}
|
||||
@@ -134,20 +159,29 @@ public class AssetsProcess extends BaseProcessor{
|
||||
|
||||
String filepath = path.substring(path.lastIndexOf("/") + 1) + p.path().substring(p.path().lastIndexOf(path) + path.length());
|
||||
|
||||
String filename = "\"" + filepath + "\"";
|
||||
loadBegin.addStatement("arc.Core.assets.load(" + filename + ", " + rtype + ".class).loaded = a -> " + name + " = (" + rtype + ")a", filepath, filepath.replace(".ogg", ".mp3"));
|
||||
if(genid){
|
||||
staticb.addStatement("soundToId.put($L, $L)", name, id);
|
||||
|
||||
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());
|
||||
});
|
||||
loadBegin.addStatement("$T.assets.load($S, $L.class).loaded = a -> { $L = ($L)a; soundToId.put(a, $L); idToSound.put($L, a); }",
|
||||
Core.class, filepath, rtype, name, rtype, id, id);
|
||||
}else{
|
||||
loadBegin.addStatement("$T.assets.load($S, $L.class).loaded = a -> { $L = ($L)a; }", Core.class, filepath, rtype, name, rtype);
|
||||
}
|
||||
|
||||
type.addField(FieldSpec.builder(ClassName.bestGuess(rtype), name, Modifier.STATIC, Modifier.PUBLIC).initializer("new " + rtype + "()").build());
|
||||
|
||||
id ++;
|
||||
}
|
||||
|
||||
if(genid){
|
||||
type.addStaticBlock(staticb.build());
|
||||
}
|
||||
|
||||
if(classname.equals("Sounds")){
|
||||
type.addField(FieldSpec.builder(ClassName.bestGuess(rtype), "none", Modifier.STATIC, Modifier.PUBLIC).initializer("new arc.audio." + rtype.substring(rtype.lastIndexOf(".") + 1) + "()").build());
|
||||
type.addField(FieldSpec.builder(ClassName.bestGuess(rtype), "none", Modifier.STATIC, Modifier.PUBLIC).initializer("new " + rtype + "()").build());
|
||||
}
|
||||
|
||||
type.addMethod(loadBegin.build());
|
||||
type.addMethod(dispose.build());
|
||||
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
|
||||
public void process(RoundEnvironment env) throws Exception{
|
||||
TypeSpec.Builder regionClass = TypeSpec.classBuilder("ContentRegions")
|
||||
.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "\"deprecation\"").build())
|
||||
.addModifiers(Modifier.PUBLIC);
|
||||
MethodSpec.Builder method = MethodSpec.methodBuilder("loadRegions")
|
||||
.addParameter(tname("mindustry.ctype.MappableContent"), "content")
|
||||
@@ -34,7 +35,7 @@ public class LoadRegionProcessor extends BaseProcessor{
|
||||
}
|
||||
|
||||
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){
|
||||
Load an = field.annotation(Load.class);
|
||||
@@ -45,7 +46,7 @@ public class LoadRegionProcessor extends BaseProcessor{
|
||||
|
||||
//not an array
|
||||
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{
|
||||
//is an array, create length string
|
||||
int[] lengths = an.lengths();
|
||||
|
||||
@@ -26,7 +26,8 @@ public class LogicStatementProcessor extends BaseProcessor{
|
||||
MethodSpec.Builder reader = MethodSpec.methodBuilder("read")
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||
.returns(tname("mindustry.logic.LStatement"))
|
||||
.addParameter(String[].class, "tokens");
|
||||
.addParameter(String[].class, "tokens")
|
||||
.addParameter(int.class, "length");
|
||||
|
||||
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
|
||||
reader.addStatement("if(tokens.length > $L) result.$L = $L(tokens[$L])",
|
||||
reader.addStatement("if(length > $L) result.$L = $L(tokens[$L])",
|
||||
index + 1,
|
||||
field.name(),
|
||||
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;
|
||||
|
||||
import mindustry.annotations.Annotations.*;
|
||||
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import mindustry.annotations.util.*;
|
||||
|
||||
/** Class that repesents a remote method to be constructed and put into a class. */
|
||||
public class MethodEntry{
|
||||
@@ -10,6 +9,8 @@ public class MethodEntry{
|
||||
public final String className;
|
||||
/** Fully qualified target method to call. */
|
||||
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. */
|
||||
public final Loc where;
|
||||
/**
|
||||
@@ -26,12 +27,13 @@ public class MethodEntry{
|
||||
/** Unique method ID. */
|
||||
public final int id;
|
||||
/** The element method associated with this entry. */
|
||||
public final ExecutableElement element;
|
||||
public final Smethod element;
|
||||
/** The assigned packet priority. Only used in clients. */
|
||||
public final PacketPriority priority;
|
||||
|
||||
public MethodEntry(String className, String targetMethod, Loc where, Variant target,
|
||||
Loc local, boolean unreliable, boolean forward, int id, ExecutableElement element, PacketPriority priority){
|
||||
public MethodEntry(String className, String targetMethod, String packetClassName, Loc where, Variant target,
|
||||
Loc local, boolean unreliable, boolean forward, int id, Smethod element, PacketPriority priority){
|
||||
this.packetClassName = packetClassName;
|
||||
this.className = className;
|
||||
this.forward = forward;
|
||||
this.targetMethod = targetMethod;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mindustry.annotations.remote;
|
||||
|
||||
import arc.struct.*;
|
||||
import com.squareup.javapoet.*;
|
||||
import arc.util.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.annotations.*;
|
||||
import mindustry.annotations.util.*;
|
||||
@@ -9,7 +9,6 @@ import mindustry.annotations.util.TypeIOResolver.*;
|
||||
|
||||
import javax.annotation.processing.*;
|
||||
import javax.lang.model.element.*;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/** The annotation processor for generating remote method call code. */
|
||||
@@ -18,52 +17,24 @@ import java.util.*;
|
||||
"mindustry.annotations.Annotations.TypeIOHandler"
|
||||
})
|
||||
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. */
|
||||
private 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;
|
||||
}
|
||||
public static final String callLocation = "Call";
|
||||
|
||||
@Override
|
||||
public void process(RoundEnvironment roundEnv) throws Exception{
|
||||
//round 1: find all annotations, generate *writers*
|
||||
if(round == 1){
|
||||
//get serializers
|
||||
serializer = TypeIOResolver.resolve(this);
|
||||
//class serializers
|
||||
ClassSerializer serializer = TypeIOResolver.resolve(this);
|
||||
//last method ID used
|
||||
int lastMethodID = 0;
|
||||
//find all elements with the Remote annotation
|
||||
elements = methods(Remote.class);
|
||||
//map of all classes to generate by name
|
||||
classMap = new HashMap<>();
|
||||
//all elements with the Remote annotation
|
||||
Seq<Smethod> elements = methods(Remote.class);
|
||||
//list of all method entries
|
||||
methods = new Seq<>();
|
||||
//list of all method entries
|
||||
classes = new Seq<>();
|
||||
Seq<MethodEntry> methods = new Seq<>();
|
||||
|
||||
Seq<Smethod> orderedElements = elements.copy();
|
||||
orderedElements.sort((a, b) -> -a.toString().compareTo(b.toString()));
|
||||
orderedElements.sortComparing(Selement::toString);
|
||||
|
||||
//create methods
|
||||
for(Smethod element : orderedElements){
|
||||
@@ -79,45 +50,25 @@ public class RemoteProcess extends BaseProcessor{
|
||||
err("A @Remote method's targets() cannot be equal to 'none'", element);
|
||||
}
|
||||
|
||||
//get and create class entry if needed
|
||||
if(!classMap.containsKey(callLocation)){
|
||||
ClassEntry clas = new ClassEntry(callLocation);
|
||||
classMap.put(callLocation, clas);
|
||||
classes.add(clas);
|
||||
String packetName = Strings.capitalize(element.name()) + "CallPacket";
|
||||
int[] index = {1};
|
||||
|
||||
while(methods.contains(m -> m.packetClassName.equals(packetName + (index[0] == 1 ? "" : index[0])))){
|
||||
index[0] ++;
|
||||
}
|
||||
|
||||
ClassEntry entry = classMap.get(callLocation);
|
||||
|
||||
//create and add entry
|
||||
MethodEntry method = new MethodEntry(entry.name, BaseProcessor.getMethodName(element.e), annotation.targets(), annotation.variants(),
|
||||
annotation.called(), annotation.unreliable(), annotation.forward(), lastMethodID++, element.e, annotation.priority());
|
||||
MethodEntry method = new MethodEntry(
|
||||
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);
|
||||
}
|
||||
|
||||
//create read/write generators
|
||||
RemoteWriteGenerator writegen = new RemoteWriteGenerator(serializer);
|
||||
|
||||
//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);
|
||||
}
|
||||
//generate the methods to invoke, as well as the packet classes
|
||||
CallGenerator.generate(serializer, methods);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 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";
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import com.sun.tools.javac.code.Attribute.Enum;
|
||||
import com.sun.tools.javac.code.Attribute.Error;
|
||||
import com.sun.tools.javac.code.Attribute.Visitor;
|
||||
import com.sun.tools.javac.code.Attribute.*;
|
||||
import com.sun.tools.javac.code.Scope.*;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.code.Type.ArrayType;
|
||||
@@ -64,36 +65,13 @@ public class AnnotationProxyMaker{
|
||||
LinkedHashMap map = new LinkedHashMap();
|
||||
ClassSymbol cl = (ClassSymbol)this.anno.type.tsym;
|
||||
|
||||
//try to use Java 8 API for this if possible
|
||||
try{
|
||||
Class entryClass = Class.forName("com.sun.tools.javac.code.Scope$Entry");
|
||||
Object members = cl.members();
|
||||
Field field = members.getClass().getField("elems");
|
||||
Object elems = field.get(members);
|
||||
Field siblingField = entryClass.getField("sibling");
|
||||
Field symField = entryClass.getField("sym");
|
||||
for(Object currEntry = elems; currEntry != null; currEntry = siblingField.get(currEntry)){
|
||||
handleSymbol((Symbol)symField.get(currEntry), map);
|
||||
for(Symbol s : cl.members().getSymbols(LookupKind.NON_RECURSIVE)){
|
||||
if(s.getKind() == ElementKind.METHOD){
|
||||
MethodSymbol var4 = (MethodSymbol)s;
|
||||
Attribute var5 = var4.getDefaultValue();
|
||||
if(var5 != null){
|
||||
map.put(var4, var5);
|
||||
}
|
||||
|
||||
}catch(Throwable e){
|
||||
//otherwise try other API
|
||||
|
||||
try{
|
||||
Class lookupClass = Class.forName("com.sun.tools.javac.code.Scope$LookupKind");
|
||||
Field nonRecField = lookupClass.getField("NON_RECURSIVE");
|
||||
Object nonRec = nonRecField.get(null);
|
||||
Scope scope = cl.members();
|
||||
Method getSyms = scope.getClass().getMethod("getSymbols", lookupClass);
|
||||
Iterable<Symbol> it = (Iterable<Symbol>)getSyms.invoke(scope, nonRec);
|
||||
Iterator<Symbol> i = it.iterator();
|
||||
while(i.hasNext()){
|
||||
handleSymbol(i.next(), map);
|
||||
}
|
||||
|
||||
}catch(Throwable death){
|
||||
//I tried
|
||||
throw new RuntimeException(death);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,17 +82,6 @@ public class AnnotationProxyMaker{
|
||||
return map;
|
||||
}
|
||||
|
||||
private void handleSymbol(Symbol sym, LinkedHashMap map){
|
||||
|
||||
if(sym.getKind() == ElementKind.METHOD){
|
||||
MethodSymbol var4 = (MethodSymbol)sym;
|
||||
Attribute var5 = var4.getDefaultValue();
|
||||
if(var5 != null){
|
||||
map.put(var4, var5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object generateValue(MethodSymbol var1, Attribute var2){
|
||||
AnnotationProxyMaker.ValueVisitor var3 = new AnnotationProxyMaker.ValueVisitor(var1);
|
||||
return var3.getValue(var2);
|
||||
|
||||
@@ -12,6 +12,10 @@ import java.lang.Class;
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
/**
|
||||
* Wrapper over Element with added utility functions.
|
||||
* I would have preferred to use extension methods for this, but Java doesn't have any.
|
||||
* */
|
||||
public class Selement<T extends Element>{
|
||||
public final T e;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package mindustry.annotations.util;
|
||||
|
||||
import com.sun.source.tree.*;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
import mindustry.annotations.*;
|
||||
|
||||
import javax.lang.model.element.*;
|
||||
@@ -16,10 +15,6 @@ public class Svar extends Selement<VariableElement>{
|
||||
return up().asType().toString() + "#" + super.toString().replace("mindustry.gen.", "");
|
||||
}
|
||||
|
||||
public JCVariableDecl jtree(){
|
||||
return (JCVariableDecl)BaseProcessor.elementu.getTree(e);
|
||||
}
|
||||
|
||||
public Stype enclosingType(){
|
||||
return new Stype((TypeElement)up());
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ mindustry.entities.comp.PosTeamDef=28
|
||||
mindustry.entities.comp.PuddleComp=13
|
||||
mindustry.type.Weather.WeatherStateComp=14
|
||||
mindustry.world.blocks.campaign.LaunchPad.LaunchPayloadComp=15
|
||||
mindustry.world.blocks.campaign.PayloadLaunchPad.LargeLaunchPayloadComp=34
|
||||
mindustry.world.blocks.defense.ForceProjector.ForceDrawComp=22
|
||||
mono=16
|
||||
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 @@
|
||||
{version:2,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
@@ -0,0 +1 @@
|
||||
{version:6,fields:[{name:color,type:arc.graphics.Color},{name:data,type:java.lang.Object},{name:effect,type:mindustry.entities.Effect},{name:lifetime,type:float},{name:offsetPos,type:float},{name:offsetRot,type:float},{name:offsetX,type:float},{name:offsetY,type:float},{name:parent,type:mindustry.gen.Posc},{name:rotWithParent,type:boolean},{name:rotation,type:float},{name:time,type:float},{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}]}
|
||||
@@ -0,0 +1 @@
|
||||
{version:1,fields:[{name:amount,type:float},{name:liquid,type:mindustry.type.Liquid},{name:tile,type:mindustry.world.Tile},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/alpha/2.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:2,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/arkyid/2.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:2,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/beta/2.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:2,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/block/6.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:6,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/corvus/6.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:6,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/flare/6.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:6,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/gamma/2.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:2,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/mace/6.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:6,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/mega/4.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:4,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/mono/5.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:5,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/nova/4.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:4,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/oct/4.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:4,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/poly/4.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:4,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/pulsar/2.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:2,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/quad/5.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:5,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/quasar/2.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:2,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/risso/6.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:6,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/spiroct/5.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:5,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
1
annotations/src/main/resources/revisions/toxopid/2.json
Normal file
@@ -0,0 +1 @@
|
||||
{version:2,fields:[{name:ammo,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:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
|
||||
127
build.gradle
@@ -16,26 +16,30 @@ buildscript{
|
||||
}
|
||||
|
||||
dependencies{
|
||||
classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.11'
|
||||
classpath "com.github.anuken:packr:-SNAPSHOT"
|
||||
classpath "com.mobidevelop.robovm:robovm-gradle-plugin:2.3.14"
|
||||
classpath "com.github.Anuken.Arc:packer:$arcHash"
|
||||
classpath "com.github.Anuken.Arc:arc-core:$arcHash"
|
||||
}
|
||||
}
|
||||
|
||||
plugins{
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.6.0-RC'
|
||||
id "org.jetbrains.kotlin.kapt" version "1.6.0-RC"
|
||||
}
|
||||
|
||||
allprojects{
|
||||
apply plugin: 'maven'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
version = 'release'
|
||||
group = 'com.github.Anuken'
|
||||
|
||||
ext{
|
||||
versionNumber = '6'
|
||||
if(!project.hasProperty("versionModifier")) versionModifier = 'release'
|
||||
versionNumber = '7'
|
||||
if(!project.hasProperty("versionModifier")) versionModifier = 'pre-alpha'
|
||||
if(!project.hasProperty("versionType")) versionType = 'official'
|
||||
appName = 'Mindustry'
|
||||
steamworksVersion = '891ed912791e01fe9ee6237a6497e5212b85c256'
|
||||
rhinoVersion = '378626d8abc552bba57864358358045d2f2dbe9b'
|
||||
steamworksVersion = '0b86023401880bb5e586bc404bedbaae9b1f1c94'
|
||||
rhinoVersion = '3c6bbadf73a904eefcc28b6fd8aa742ac575e878'
|
||||
|
||||
loadVersionProps = {
|
||||
return new Properties().with{p -> p.load(file('../core/assets/version.properties').newReader()); return p }
|
||||
@@ -83,13 +87,11 @@ allprojects{
|
||||
}
|
||||
|
||||
hasSprites = {
|
||||
return new File(rootDir, "core/assets/sprites/sprites.atlas").exists()
|
||||
return new File(rootDir, "core/assets/sprites/sprites.aatls").exists()
|
||||
}
|
||||
|
||||
getModifierString = {
|
||||
if(versionModifier != "release"){
|
||||
return "[${versionModifier.toUpperCase()}]"
|
||||
}
|
||||
if(versionModifier != "release") return "[${versionModifier.toUpperCase()}]"
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -107,8 +109,7 @@ allprojects{
|
||||
def v = System.getenv("ANDROID_HOME")
|
||||
if(v != null) return v
|
||||
//rootDir is null here, amazing. brilliant.
|
||||
def file = new File("local.properties")
|
||||
if(!file.exists()) file = new File("../local.properties")
|
||||
def file = new File(rootDir, "local.properties")
|
||||
def props = new Properties().with{p -> p.load(file.newReader()); return p }
|
||||
return props.get("sdk.dir")
|
||||
}
|
||||
@@ -195,10 +196,21 @@ allprojects{
|
||||
|
||||
tasks.withType(JavaCompile){
|
||||
targetCompatibility = 8
|
||||
sourceCompatibility = 14
|
||||
sourceCompatibility = JavaVersion.VERSION_16
|
||||
options.encoding = "UTF-8"
|
||||
options.compilerArgs += ["-Xlint:deprecation"]
|
||||
dependsOn clearCache
|
||||
|
||||
options.forkOptions.jvmArgs += [
|
||||
'--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED',
|
||||
'--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED',
|
||||
'--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED',
|
||||
'--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED',
|
||||
'--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED',
|
||||
'--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED',
|
||||
'--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED',
|
||||
'--add-opens=java.base/sun.reflect.annotation=ALL-UNNAMED'
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,26 +218,20 @@ configure(project(":annotations")){
|
||||
tasks.withType(JavaCompile){
|
||||
targetCompatibility = 8
|
||||
sourceCompatibility = 8
|
||||
options.fork = true
|
||||
}
|
||||
}
|
||||
|
||||
//compile with java 8 compatibility for everything except the annotation project
|
||||
configure(subprojects - project(":annotations")){
|
||||
tasks.withType(JavaCompile){
|
||||
if(JavaVersion.current() != JavaVersion.VERSION_1_8){
|
||||
options.compilerArgs.addAll(['--release', '8', '--enable-preview'])
|
||||
}
|
||||
|
||||
doFirst{
|
||||
options.compilerArgs = options.compilerArgs.findAll{it != '--enable-preview' }
|
||||
}
|
||||
options.compilerArgs.addAll(['--release', '8'])
|
||||
}
|
||||
|
||||
tasks.withType(Javadoc){
|
||||
options{
|
||||
addStringOption('Xdoclint:none', '-quiet')
|
||||
addBooleanOption('-enable-preview', true)
|
||||
addStringOption('-release', '14')
|
||||
addStringOption('-release', '16')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,9 +243,9 @@ project(":desktop"){
|
||||
|
||||
dependencies{
|
||||
implementation project(":core")
|
||||
implementation arcModule("extensions:discord")
|
||||
implementation arcModule("natives:natives-desktop")
|
||||
implementation arcModule("natives:natives-freetype-desktop")
|
||||
implementation 'com.github.MinnDevelopment:java-discord-rpc:v2.0.1'
|
||||
|
||||
if(debugged()) implementation project(":debug")
|
||||
|
||||
@@ -261,7 +267,7 @@ project(":ios"){
|
||||
props.load(new FileInputStream(vfile))
|
||||
}else{
|
||||
props['app.id'] = 'io.anuke.mindustry'
|
||||
props['app.version'] = '6.0'
|
||||
props['app.version'] = '7.0'
|
||||
props['app.mainclass'] = 'mindustry.IOSLauncher'
|
||||
props['app.executable'] = 'IOSLauncher'
|
||||
props['app.name'] = 'Mindustry'
|
||||
@@ -287,6 +293,15 @@ project(":ios"){
|
||||
|
||||
project(":core"){
|
||||
apply plugin: "java-library"
|
||||
apply plugin: "kotlin"
|
||||
apply plugin: "kotlin-kapt"
|
||||
|
||||
kapt{
|
||||
javacOptions{
|
||||
option("-source", "16")
|
||||
option("-target", "1.8")
|
||||
}
|
||||
}
|
||||
|
||||
compileJava.options.fork = true
|
||||
|
||||
@@ -314,35 +329,55 @@ project(":core"){
|
||||
}
|
||||
}
|
||||
def changelogs = file("../fastlane/metadata/android/en-US/changelogs/")
|
||||
changelogs.mkdirs()
|
||||
try{
|
||||
new File(changelogs, androidVersion + ".txt").text = (result)
|
||||
}catch(Exception ignored){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar, dependsOn: classes){
|
||||
classifier = 'sources'
|
||||
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{
|
||||
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("extensions:flabel")
|
||||
api arcModule("extensions:freetype")
|
||||
api arcModule("extensions:g3d")
|
||||
api arcModule("extensions:fx")
|
||||
api arcModule("extensions:arcnet")
|
||||
api "com.github.Anuken:rhino:$rhinoVersion"
|
||||
if(localArc() && debugged()) api arcModule("extensions:recorder")
|
||||
if(localArc()) api arcModule(":extensions:packer")
|
||||
|
||||
annotationProcessor 'com.github.Anuken:jabel:0.6.0'
|
||||
compileOnly project(":annotations")
|
||||
annotationProcessor project(":annotations")
|
||||
annotationProcessor 'com.github.Anuken:jabel:34e4c172e65b3928cd9eabe1993654ea79c409cd'
|
||||
|
||||
kapt project(":annotations")
|
||||
}
|
||||
|
||||
afterEvaluate{
|
||||
@@ -366,6 +401,11 @@ project(":core"){
|
||||
destinationDir = new File(buildDir, 'javadoc')
|
||||
}
|
||||
}
|
||||
|
||||
//comp** classes are only used for code generation
|
||||
jar{
|
||||
exclude("mindustry/entities/comp/**")
|
||||
}
|
||||
}
|
||||
|
||||
project(":server"){
|
||||
@@ -382,16 +422,18 @@ project(":tests"){
|
||||
|
||||
dependencies{
|
||||
testImplementation project(":core")
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-params:5.3.1"
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-api:5.3.1"
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-params:5.7.1"
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-api:5.7.1"
|
||||
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{
|
||||
//fork every test so mods don't interact with each other
|
||||
forkEvery = 1
|
||||
useJUnitPlatform()
|
||||
workingDir = new File("../core/assets")
|
||||
testLogging {
|
||||
testLogging{
|
||||
exceptionFormat = 'full'
|
||||
showStandardStreams = true
|
||||
}
|
||||
@@ -419,6 +461,21 @@ project(":annotations"){
|
||||
}
|
||||
}
|
||||
|
||||
configure([":core", ":desktop", ":server", ":tools"].collect{project(it)}){
|
||||
java{
|
||||
withJavadocJar()
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
publishing{
|
||||
publications{
|
||||
maven(MavenPublication){
|
||||
from components.java
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task deployAll{
|
||||
task cleanDeployOutput{
|
||||
doFirst{
|
||||
@@ -436,8 +493,10 @@ task deployAll{
|
||||
dependsOn "desktop:packrWindows64"
|
||||
dependsOn "desktop:packrWindows32"
|
||||
dependsOn "desktop:packrMacOS"
|
||||
if(versionModifier != "steam"){
|
||||
dependsOn "server:deploy"
|
||||
dependsOn "android:deploy"
|
||||
}
|
||||
}
|
||||
|
||||
task resolveDependencies{
|
||||
|
||||
|
Before Width: | Height: | Size: 4.1 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/force-projector-team.png
Normal file
|
After Width: | Height: | Size: 751 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.2 KiB |
BIN
core/assets-raw/sprites/blocks/defense/shock-mine-team-top.png
Normal file
|
After Width: | Height: | Size: 158 B |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 895 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: 1.1 KiB After Width: | Height: | Size: 1012 B |
|
Before Width: | Height: | Size: 558 B After Width: | Height: | Size: 685 B |
|
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: 245 B After Width: | Height: | Size: 245 B |
|
Before Width: | Height: | Size: 238 B After Width: | Height: | Size: 238 B |
|
Before Width: | Height: | Size: 231 B After Width: | Height: | Size: 231 B |
|
Before Width: | Height: | Size: 233 B After Width: | Height: | Size: 233 B |
|
Before Width: | Height: | Size: 162 B After Width: | Height: | Size: 162 B |
|
Before Width: | Height: | Size: 171 B After Width: | Height: | Size: 171 B |
|
Before Width: | Height: | Size: 521 B After Width: | Height: | Size: 467 B |