Compare commits
899 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c318f05cfd | ||
|
|
789d200c24 | ||
|
|
2dc4a9e044 | ||
|
|
82577b91d5 | ||
|
|
8fd08a1574 | ||
|
|
7a41fc8ec8 | ||
|
|
798ca929d6 | ||
|
|
7e4e58fb78 | ||
|
|
28b9975c75 | ||
|
|
5536ade389 | ||
|
|
21bc195213 | ||
|
|
b6beacf053 | ||
|
|
94b6c133f4 | ||
|
|
949d7bed89 | ||
|
|
81ce12a38c | ||
|
|
eba65b2934 | ||
|
|
c7f5b7fca1 | ||
|
|
f670d522bf | ||
|
|
a02f7f46c3 | ||
|
|
4b7f254e17 | ||
|
|
9b42be560d | ||
|
|
31b39231a2 | ||
|
|
4eb2c1f646 | ||
|
|
5f89d8588d | ||
|
|
404cbf9b4a | ||
|
|
0aabc09b82 | ||
|
|
a5ebeadd95 | ||
|
|
9e188aaf03 | ||
|
|
870f5caca9 | ||
|
|
28b4ddfc72 | ||
|
|
13a4a26e97 | ||
|
|
81c7e63994 | ||
|
|
7f234ab5bc | ||
|
|
f8d0682810 | ||
|
|
175d6b1fc5 | ||
|
|
1cd8e8a097 | ||
|
|
ed95e38257 | ||
|
|
cab585225d | ||
|
|
3688dde5e5 | ||
|
|
ae6a5b2512 | ||
|
|
6f87611d67 | ||
|
|
6a5e31c908 | ||
|
|
8bda5e16cd | ||
|
|
d70d3d95f0 | ||
|
|
554b7d2ec4 | ||
|
|
ebc4031922 | ||
|
|
c526997aba | ||
|
|
c0e3a1f3ef | ||
|
|
7dc0a7a5c3 | ||
|
|
2943b6ed04 | ||
|
|
5feb212df7 | ||
|
|
327edcd347 | ||
|
|
94cbf4cddf | ||
|
|
08cc87affb | ||
|
|
18020d64cc | ||
|
|
48b7ceac06 | ||
|
|
dbcce9663c | ||
|
|
6ee7dd56fe | ||
|
|
99418e6b88 | ||
|
|
67db5e9dfc | ||
|
|
5f1bc6c6c2 | ||
|
|
05201d7012 | ||
|
|
6b4983537e | ||
|
|
87c8293c78 | ||
|
|
54488564f3 | ||
|
|
f2ac9ed385 | ||
|
|
38f2f1e30a | ||
|
|
02004011ec | ||
|
|
60bb982450 | ||
|
|
67389c0bac | ||
|
|
faa1fee1c0 | ||
|
|
0bae421fbc | ||
|
|
b29d81bf0f | ||
|
|
4792828da1 | ||
|
|
6171e887a8 | ||
|
|
f28fa93f40 | ||
|
|
940ad84493 | ||
|
|
0b168376ed | ||
|
|
f7bd376499 | ||
|
|
9566155bdb | ||
|
|
9994ddb31b | ||
|
|
fadfdaa673 | ||
|
|
4ca546f44a | ||
|
|
8af30c9256 | ||
|
|
42adc38720 | ||
|
|
c1d9dee46c | ||
|
|
69a7104286 | ||
|
|
aba5afe32c | ||
|
|
c1ccf4fceb | ||
|
|
916a4cfc73 | ||
|
|
fd107ab5b8 | ||
|
|
5fa6fccf7b | ||
|
|
0ce226d0c9 | ||
|
|
14e0b471d3 | ||
|
|
ed0df64cf9 | ||
|
|
35bc2c9803 | ||
|
|
a771dc8787 | ||
|
|
244eb91dfb | ||
|
|
7488a6d42b | ||
|
|
696a59f1b9 | ||
|
|
ee5a3269f2 | ||
|
|
f89bf027f7 | ||
|
|
4db432b0a9 | ||
|
|
c82fd9ead5 | ||
|
|
34715b1e06 | ||
|
|
f0870b3236 | ||
|
|
9a286800d6 | ||
|
|
59832b1777 | ||
|
|
561f566506 | ||
|
|
f0cacf6bd5 | ||
|
|
ce4031af74 | ||
|
|
dd7f91b8c2 | ||
|
|
8523e5bf6b | ||
|
|
860727d27a | ||
|
|
f175bf2c82 | ||
|
|
40008f44ac | ||
|
|
3f93b5c63b | ||
|
|
d2ce051c4a | ||
|
|
d5d90bde9a | ||
|
|
fc8d9febf6 | ||
|
|
b43c542213 | ||
|
|
e7533232c0 | ||
|
|
5e1aaf11a7 | ||
|
|
d062dffc13 | ||
|
|
4810bbbbd9 | ||
|
|
967998273f | ||
|
|
24decf8abc | ||
|
|
3bc605894e | ||
|
|
b74ae302ec | ||
|
|
db3dac261a | ||
|
|
87b47b3042 | ||
|
|
720e1a038e | ||
|
|
1753c54e88 | ||
|
|
2d42de83de | ||
|
|
c4e6af455d | ||
|
|
51d619449b | ||
|
|
1160a14f56 | ||
|
|
57fce0ddbc | ||
|
|
b9eb8a750b | ||
|
|
3ce16e0ed1 | ||
|
|
554d9b4047 | ||
|
|
02d565ce58 | ||
|
|
795bc1276b | ||
|
|
499b7b2e67 | ||
|
|
b6c0fe8bf7 | ||
|
|
d5bb1b72b9 | ||
|
|
af86564adc | ||
|
|
5354e02b6f | ||
|
|
4ee17a656f | ||
|
|
32c59b66f6 | ||
|
|
20732f04ff | ||
|
|
06763b34c3 | ||
|
|
6bab6c57f2 | ||
|
|
4eab89d73e | ||
|
|
8d20c46228 | ||
|
|
f5c4586bb7 | ||
|
|
bc6bbdbbe0 | ||
|
|
b77caed0ba | ||
|
|
df976f1212 | ||
|
|
999dd5eb6f | ||
|
|
a1a6a3ab81 | ||
|
|
d067bbfa65 | ||
|
|
3bd40eeb27 | ||
|
|
b124d54055 | ||
|
|
90691de457 | ||
|
|
bee83a3a3e | ||
|
|
fd8f2438fa | ||
|
|
7937d99a73 | ||
|
|
569afb5535 | ||
|
|
fc5a45e113 | ||
|
|
950f4a9f1a | ||
|
|
6a6e80b6d8 | ||
|
|
083c9792a6 | ||
|
|
893bfce767 | ||
|
|
f61f3df732 | ||
|
|
a3be5e332e | ||
|
|
33d65a8593 | ||
|
|
ebbf01c6e5 | ||
|
|
acb8496352 | ||
|
|
ecad5772d2 | ||
|
|
6e6f5714dd | ||
|
|
50ae15aa4f | ||
|
|
4e2c3049a0 | ||
|
|
3a785c166e | ||
|
|
5248a4eb9c | ||
|
|
c9a53aed7b | ||
|
|
bafe5dc784 | ||
|
|
5325488099 | ||
|
|
737ad5c8b7 | ||
|
|
17cea4e274 | ||
|
|
af5b579a2f | ||
|
|
c87eaaa928 | ||
|
|
33418397f8 | ||
|
|
8c7258e839 | ||
|
|
98fff9b81d | ||
|
|
0c63b27eea | ||
|
|
0968981aef | ||
|
|
8db4abdf43 | ||
|
|
9aa4219bf0 | ||
|
|
6c32ab4711 | ||
|
|
a80c5a1efa | ||
|
|
4ba46bff69 | ||
|
|
6a7c97277f | ||
|
|
cc70ff9732 | ||
|
|
2d25948c57 | ||
|
|
8946af4831 | ||
|
|
5e7ca0374c | ||
|
|
21f8e89ba4 | ||
|
|
f0aca90de2 | ||
|
|
097228066a | ||
|
|
7d8782f3dc | ||
|
|
e4ea9d561e | ||
|
|
e284d9de8e | ||
|
|
df6382a1ca | ||
|
|
c1c1a3318c | ||
|
|
796df1cec5 | ||
|
|
28980293c5 | ||
|
|
d878ad2e7e | ||
|
|
1290d1e9d4 | ||
|
|
f229f1e9fe | ||
|
|
0776951018 | ||
|
|
6d47b449b9 | ||
|
|
594c975c70 | ||
|
|
bf57318307 | ||
|
|
abd87793e4 | ||
|
|
7b4e6128ce | ||
|
|
2ae65acc28 | ||
|
|
2ee87ad078 | ||
|
|
d65beea179 | ||
|
|
b19f3ff8cf | ||
|
|
75fae9454d | ||
|
|
5d309c39cf | ||
|
|
649fc5a0e6 | ||
|
|
67cfa5d42f | ||
|
|
5dcacdeea1 | ||
|
|
2f7073bbe4 | ||
|
|
e8df6ed3be | ||
|
|
d9eb4c1296 | ||
|
|
4af0fbf553 | ||
|
|
2da0862cb2 | ||
|
|
66fcf84688 | ||
|
|
5740d40d57 | ||
|
|
6ef2256bf2 | ||
|
|
65f911909b | ||
|
|
2cb6e454c8 | ||
|
|
abfaa47db2 | ||
|
|
e06970eebb | ||
|
|
dadc83800b | ||
|
|
62f2c67321 | ||
|
|
1651844b4f | ||
|
|
fb9f42ff93 | ||
|
|
9c29b982dd | ||
|
|
f52c4964b3 | ||
|
|
46a8edb781 | ||
|
|
8dbdbe6d6c | ||
|
|
778069c15d | ||
|
|
e98457c540 | ||
|
|
7a3a76065c | ||
|
|
c73c97dc7b | ||
|
|
1b0dd279ae | ||
|
|
7dd487ccc5 | ||
|
|
d046591512 | ||
|
|
e4ce115abf | ||
|
|
aedcac5820 | ||
|
|
9f4430ad92 | ||
|
|
2ad8f1c112 | ||
|
|
f0d884e114 | ||
|
|
b618f5be80 | ||
|
|
7b63eac3eb | ||
|
|
df3f2ea9c1 | ||
|
|
30c6280ed1 | ||
|
|
1960b59629 | ||
|
|
6e6edf8322 | ||
|
|
f47fb01614 | ||
|
|
ae30bdd599 | ||
|
|
2c8962cf5f | ||
|
|
eb3e507a11 | ||
|
|
be3147465d | ||
|
|
484721fece | ||
|
|
9c36026991 | ||
|
|
bf5055f944 | ||
|
|
389034bf1a | ||
|
|
3f07102f2a | ||
|
|
d4ccfa31b5 | ||
|
|
5814b2a4b8 | ||
|
|
d3f61af493 | ||
|
|
233ea7bb4a | ||
|
|
6893a30ffb | ||
|
|
ae6d2fb363 | ||
|
|
baa7cb3a10 | ||
|
|
7b90544d91 | ||
|
|
9a5495d8b2 | ||
|
|
1fa769b3e7 | ||
|
|
96766ece4e | ||
|
|
add525396f | ||
|
|
26ae4edd63 | ||
|
|
063893adee | ||
|
|
ff37e99d71 | ||
|
|
3d0b02ee23 | ||
|
|
d7cfbfe6c8 | ||
|
|
dc00e22f13 | ||
|
|
bcde481304 | ||
|
|
5b1341e488 | ||
|
|
6ad70ceee3 | ||
|
|
9c4d2f5490 | ||
|
|
6c5eff1143 | ||
|
|
a893767d0f | ||
|
|
a4f240edc8 | ||
|
|
e0a94f694b | ||
|
|
8654f25a4f | ||
|
|
e877310d85 | ||
|
|
bb59f45ba6 | ||
|
|
3d4c2a2c20 | ||
|
|
e36667cd08 | ||
|
|
cebaa6949e | ||
|
|
019e22aff2 | ||
|
|
5129e2ea73 | ||
|
|
3b63f60462 | ||
|
|
5e29115c2e | ||
|
|
0b4b30286d | ||
|
|
a01f64080d | ||
|
|
d031351bc8 | ||
|
|
1d21d36253 | ||
|
|
8d4cd72b41 | ||
|
|
46ab6d3476 | ||
|
|
3fcf3cbf93 | ||
|
|
ada912c69b | ||
|
|
e204b89eaf | ||
|
|
e903798fc2 | ||
|
|
54497c43b6 | ||
|
|
99e54cc214 | ||
|
|
56ae47cd8d | ||
|
|
0fb336cf7b | ||
|
|
469b3c0a94 | ||
|
|
d90d88c68b | ||
|
|
dcc061af3e | ||
|
|
a2960f5c50 | ||
|
|
565f8a2b4d | ||
|
|
5cb50d57ec | ||
|
|
522e19d4bf | ||
|
|
0db7a78889 | ||
|
|
1ce3b40b4e | ||
|
|
e633528a7a | ||
|
|
6570b411d1 | ||
|
|
ac9e774795 | ||
|
|
8791747453 | ||
|
|
dda3afe9fa | ||
|
|
d4435f980c | ||
|
|
f29673a6e3 | ||
|
|
9816bab151 | ||
|
|
5884c0bcb3 | ||
|
|
96dc00beac | ||
|
|
febc1e53b6 | ||
|
|
3e18fb3ca0 | ||
|
|
28b9de2e7a | ||
|
|
9a41399178 | ||
|
|
db47b9a877 | ||
|
|
7cdd7a3487 | ||
|
|
833f646903 | ||
|
|
35a85860b1 | ||
|
|
00f24dfb79 | ||
|
|
8c6ae2576d | ||
|
|
5416ad33bd | ||
|
|
1e25ba2d8e | ||
|
|
8d08d25f5b | ||
|
|
802e7b12d0 | ||
|
|
9b57550f3d | ||
|
|
28c13c8e52 | ||
|
|
d8f9059989 | ||
|
|
ac9d37d038 | ||
|
|
6323c13704 | ||
|
|
2f7f16daff | ||
|
|
9059238aee | ||
|
|
2677c0e752 | ||
|
|
ba80770564 | ||
|
|
06ad35d934 | ||
|
|
864c4f6bc3 | ||
|
|
f5f0f02abe | ||
|
|
19979dec55 | ||
|
|
926e61b7cc | ||
|
|
15378d3267 | ||
|
|
33fcfda1a0 | ||
|
|
74d7b43d0f | ||
|
|
e392c8f0e6 | ||
|
|
f60ba8587f | ||
|
|
86a7f837cd | ||
|
|
9465497481 | ||
|
|
8c3f3ac304 | ||
|
|
88ba8f6f55 | ||
|
|
c64459dbf4 | ||
|
|
8b0bbffe27 | ||
|
|
94805259d7 | ||
|
|
e796d44f92 | ||
|
|
5e8686db77 | ||
|
|
ee835f6514 | ||
|
|
5de61aaed3 | ||
|
|
6613e4ec42 | ||
|
|
206314f4f4 | ||
|
|
8f12c3f1a8 | ||
|
|
4c224d0b9c | ||
|
|
30dd089c8b | ||
|
|
8d9ec206bf | ||
|
|
8319288776 | ||
|
|
60bf36613f | ||
|
|
a75994cbbf | ||
|
|
e1f7c7b03d | ||
|
|
bb7e2c7cee | ||
|
|
69eb6469f9 | ||
|
|
d2eb3be7f8 | ||
|
|
5aa76639d1 | ||
|
|
3bf72a1af6 | ||
|
|
b745d88299 | ||
|
|
3aedc07ad0 | ||
|
|
dbb164f4be | ||
|
|
b0103d1ce3 | ||
|
|
9c532047d3 | ||
|
|
0003a58210 | ||
|
|
34f2704dc7 | ||
|
|
0ddee379ca | ||
|
|
6dcbe4fabb | ||
|
|
5dbb9fdf3f | ||
|
|
914fa3079d | ||
|
|
2e958d8d8f | ||
|
|
7a5e61fd2e | ||
|
|
6a031d8f53 | ||
|
|
dc6f01c0d3 | ||
|
|
1cc8cbe8a8 | ||
|
|
01ae8bec85 | ||
|
|
258ab87f6b | ||
|
|
8ba2db6c58 | ||
|
|
a7599e85dc | ||
|
|
28389d698e | ||
|
|
c47a220721 | ||
|
|
69f7296baa | ||
|
|
855f56bb45 | ||
|
|
a79d072aaf | ||
|
|
467047a011 | ||
|
|
0288daa39d | ||
|
|
3f075068a9 | ||
|
|
278e7027f2 | ||
|
|
9d654c1f18 | ||
|
|
279187d13b | ||
|
|
360494f971 | ||
|
|
81931eb536 | ||
|
|
a2ef11eb0f | ||
|
|
b872252771 | ||
|
|
b2c388276f | ||
|
|
178928f866 | ||
|
|
7e548f9969 | ||
|
|
a60ce3c54c | ||
|
|
0f173bcc5a | ||
|
|
64dbe8312e | ||
|
|
7f443c71ae | ||
|
|
27276c025c | ||
|
|
e9d03c179c | ||
|
|
dec01c23a9 | ||
|
|
e0eb227ce5 | ||
|
|
20021c5b31 | ||
|
|
f8d6797fc2 | ||
|
|
25051980ce | ||
|
|
fb8becca99 | ||
|
|
25bd8a7eaa | ||
|
|
bbd2424a3f | ||
|
|
83eeeed319 | ||
|
|
c92e8161a1 | ||
|
|
258555c990 | ||
|
|
0f7799422e | ||
|
|
177b565d7c | ||
|
|
a62b336b6c | ||
|
|
3ea61c8b3a | ||
|
|
4c57f9f902 | ||
|
|
6d7941fba4 | ||
|
|
020c6388c2 | ||
|
|
53d35e8c77 | ||
|
|
01f205d352 | ||
|
|
a786167b04 | ||
|
|
1699ab48e8 | ||
|
|
b15c04a532 | ||
|
|
20d3740e75 | ||
|
|
80d57f8c0c | ||
|
|
1de367e89c | ||
|
|
8850a89e30 | ||
|
|
4f72011cf7 | ||
|
|
c569232e74 | ||
|
|
14c526d0c4 | ||
|
|
5c4ac6b702 | ||
|
|
d58cc18136 | ||
|
|
36c01fde94 | ||
|
|
d4d9d59fe4 | ||
|
|
8dbd0a6130 | ||
|
|
3746344cba | ||
|
|
d07fd1bbfe | ||
|
|
02f95c0ed4 | ||
|
|
c98fcbd795 | ||
|
|
d071877963 | ||
|
|
0267cb4006 | ||
|
|
bf571e595c | ||
|
|
c0cad70212 | ||
|
|
7bd6dbb4b4 | ||
|
|
6d932e3d04 | ||
|
|
e154b5179d | ||
|
|
52110d6008 | ||
|
|
103b08fd1d | ||
|
|
cb09d10e7f | ||
|
|
a041c1e60d | ||
|
|
586b4cf4bd | ||
|
|
d0ff149cca | ||
|
|
f8ddc8325c | ||
|
|
59ec09e82c | ||
|
|
2ae5c96690 | ||
|
|
fda9e6bb9c | ||
|
|
29bcb8e07c | ||
|
|
b70de81c2d | ||
|
|
5e89b2568f | ||
|
|
ac1d8215ff | ||
|
|
fefc734bfa | ||
|
|
7f8735842c | ||
|
|
a226983470 | ||
|
|
28526d0a12 | ||
|
|
913e005bae | ||
|
|
7bd9fd5bae | ||
|
|
8986b89d67 | ||
|
|
ef936214f0 | ||
|
|
18fce6b3e3 | ||
|
|
ecda4d74ab | ||
|
|
31124037b5 | ||
|
|
aaf95e0756 | ||
|
|
804e311875 | ||
|
|
61ad9bc47d | ||
|
|
2b23b7876a | ||
|
|
547d334f43 | ||
|
|
7432dc115e | ||
|
|
905defe8ce | ||
|
|
0a8ff0cde7 | ||
|
|
bd5f44030e | ||
|
|
79abb86262 | ||
|
|
fe6f98ec5a | ||
|
|
e39a856e54 | ||
|
|
64e5f8155d | ||
|
|
8328b11f6b | ||
|
|
15778b2ca5 | ||
|
|
b7842014c1 | ||
|
|
a804053904 | ||
|
|
2aee72b47b | ||
|
|
0cb8c600b7 | ||
|
|
aa5348f37e | ||
|
|
0736574a57 | ||
|
|
d56365ce63 | ||
|
|
c82d2f856a | ||
|
|
8432677826 | ||
|
|
0c0c6e5470 | ||
|
|
57019b6e20 | ||
|
|
12ab2249b4 | ||
|
|
22d0992d38 | ||
|
|
f8def04653 | ||
|
|
6349530fc5 | ||
|
|
ad83a7dcc3 | ||
|
|
cfc2239733 | ||
|
|
91552a3a2b | ||
|
|
4e3204bc6d | ||
|
|
a94998bd02 | ||
|
|
81c78eafa6 | ||
|
|
273523480f | ||
|
|
b27fefae88 | ||
|
|
aa00a1b8d1 | ||
|
|
ba62e0eefc | ||
|
|
cb16c75e11 | ||
|
|
3efed0ace3 | ||
|
|
879fb8194f | ||
|
|
049dd89470 | ||
|
|
1f59d4354a | ||
|
|
8dea45d9d5 | ||
|
|
21ba6e257c | ||
|
|
18ebda01a4 | ||
|
|
3acb843109 | ||
|
|
1768aea66f | ||
|
|
4b61f273d5 | ||
|
|
a1dbbbdafc | ||
|
|
dcb840f290 | ||
|
|
e6c4c66199 | ||
|
|
b76cd558aa | ||
|
|
85b077b5c5 | ||
|
|
c34d6e6606 | ||
|
|
a5fd0aebe6 | ||
|
|
aaec04d04a | ||
|
|
b4272e0387 | ||
|
|
77f9d6cb1d | ||
|
|
aaa82b34e4 | ||
|
|
7a6b1129d9 | ||
|
|
1f8918c773 | ||
|
|
e9fe724e59 | ||
|
|
80001246ef | ||
|
|
50461bb7c8 | ||
|
|
c7c7cfde74 | ||
|
|
dcc29c0c48 | ||
|
|
635e299464 | ||
|
|
502c4e51ae | ||
|
|
382fdcbb40 | ||
|
|
468e092422 | ||
|
|
6904d4693f | ||
|
|
3ef7ec3be5 | ||
|
|
70257cbbfa | ||
|
|
6ef31d0ec1 | ||
|
|
d3077bec58 | ||
|
|
a1095353fc | ||
|
|
66fab1b3df | ||
|
|
569d6d4272 | ||
|
|
07c19ce085 | ||
|
|
d86dd4f80b | ||
|
|
f0f89f0894 | ||
|
|
47af2e83f7 | ||
|
|
8ec87872c8 | ||
|
|
f30ea80b42 | ||
|
|
1dd6e66167 | ||
|
|
4e681b2dd1 | ||
|
|
58be00b3ce | ||
|
|
5604ac6b6a | ||
|
|
effdaefdf3 | ||
|
|
5775fad030 | ||
|
|
eabc6d79c3 | ||
|
|
5f4ca6e383 | ||
|
|
c05020e28e | ||
|
|
5206079e23 | ||
|
|
9b01140882 | ||
|
|
4dae27da98 | ||
|
|
f0cab65a6d | ||
|
|
699a47351b | ||
|
|
af004da699 | ||
|
|
b5ad885237 | ||
|
|
07bd0fec70 | ||
|
|
318e51d736 | ||
|
|
ae90db50fe | ||
|
|
64772c195e | ||
|
|
05ead63bdc | ||
|
|
6f5c64420d | ||
|
|
d9d9a00a24 | ||
|
|
c1de67032c | ||
|
|
890d49fdd7 | ||
|
|
ba96ea5a0c | ||
|
|
b481b784bb | ||
|
|
53b6e68a85 | ||
|
|
e3d16418a0 | ||
|
|
e41f560ecd | ||
|
|
d394d9a529 | ||
|
|
a73015fa6e | ||
|
|
87846864cc | ||
|
|
f3b976bdd1 | ||
|
|
3a06e319b0 | ||
|
|
fe31c404ff | ||
|
|
cc23378758 | ||
|
|
5cac949ea8 | ||
|
|
a35e897194 | ||
|
|
8e92edeae1 | ||
|
|
f289a0a9a8 | ||
|
|
65a7e89a8c | ||
|
|
43be3259c9 | ||
|
|
54a4c95a1b | ||
|
|
ddac5cbfbc | ||
|
|
22342d01a5 | ||
|
|
7cffaeb193 | ||
|
|
2534496543 | ||
|
|
fe9b11e771 | ||
|
|
032347840f | ||
|
|
2978bc6ac5 | ||
|
|
a3b0bb323f | ||
|
|
a6246d27d9 | ||
|
|
884b649b53 | ||
|
|
92a2f770b4 | ||
|
|
e88ce078df | ||
|
|
77f0dfb9b1 | ||
|
|
78d1accf07 | ||
|
|
2ec68a7f07 | ||
|
|
bbaa2a2c92 | ||
|
|
341bb67ef4 | ||
|
|
e377cb423b | ||
|
|
81e954c258 | ||
|
|
79d41ba7ac | ||
|
|
e740e4da87 | ||
|
|
b476c47194 | ||
|
|
b2d61a93d9 | ||
|
|
a045ec9d46 | ||
|
|
1daf8d2743 | ||
|
|
295824f440 | ||
|
|
22b59e0cf6 | ||
|
|
ecabdb82e6 | ||
|
|
924b1c1a67 | ||
|
|
0454c4c25a | ||
|
|
3a3b81941b | ||
|
|
0875c29da5 | ||
|
|
0d4cf9f6c4 | ||
|
|
6a525dcf59 | ||
|
|
01f6904f82 | ||
|
|
23bd9a989b | ||
|
|
acfa02475b | ||
|
|
9dba304011 | ||
|
|
69b0020d15 | ||
|
|
ce2896cb38 | ||
|
|
68fd09c222 | ||
|
|
c832a7b93f | ||
|
|
49e19ab34d | ||
|
|
c1c82b451d | ||
|
|
ea6f88b7f6 | ||
|
|
2a6ee6d65b | ||
|
|
583342b430 | ||
|
|
7289c1080c | ||
|
|
9ed4f2b7a3 | ||
|
|
7396f91a5e | ||
|
|
ccc926d812 | ||
|
|
bd39255ead | ||
|
|
add7b1a7d9 | ||
|
|
8e471f9939 | ||
|
|
c61568ef98 | ||
|
|
3260e45e71 | ||
|
|
ea61b560b8 | ||
|
|
f8ad7d485b | ||
|
|
229e624434 | ||
|
|
7a3fb9c759 | ||
|
|
9a7ea0d28c | ||
|
|
ee5e655668 | ||
|
|
58be055f57 | ||
|
|
38e1944503 | ||
|
|
992b402e9c | ||
|
|
81bf28e4ed | ||
|
|
f10734b083 | ||
|
|
bf8f565631 | ||
|
|
9bc1ff8fa2 | ||
|
|
56239b6bbf | ||
|
|
cedd2bfe57 | ||
|
|
7e187a57d8 | ||
|
|
572a30a2c5 | ||
|
|
f3235ef7e8 | ||
|
|
7448eb32cc | ||
|
|
33e8cc4711 | ||
|
|
6cdb016c2c | ||
|
|
ababb7f5ab | ||
|
|
9f2b66e09d | ||
|
|
8de267f6a9 | ||
|
|
ecf9a3cbc9 | ||
|
|
01300b97e2 | ||
|
|
787163fb06 | ||
|
|
3701a3c3d9 | ||
|
|
68c51bb1bc | ||
|
|
df147c700c | ||
|
|
f5fc4d99dd | ||
|
|
2a4aa9e550 | ||
|
|
0a489f1117 | ||
|
|
9cc7c061a3 | ||
|
|
a1e7274ec3 | ||
|
|
51d516a39e | ||
|
|
de7c38231c | ||
|
|
c352ef9382 | ||
|
|
e36b5551e9 | ||
|
|
57856c38d6 | ||
|
|
2a8e02339b | ||
|
|
57f94ca6a2 | ||
|
|
0eaca8b80a | ||
|
|
d2dbab57dc | ||
|
|
cb448a3494 | ||
|
|
3fa6eae05b | ||
|
|
52cc7d699a | ||
|
|
ec4eac3a7d | ||
|
|
fbcfb23676 | ||
|
|
dbb2371801 | ||
|
|
4d6dc9546f | ||
|
|
06b9d328f4 | ||
|
|
48c7daa4ab | ||
|
|
3c83b88127 | ||
|
|
3a63fa5475 | ||
|
|
882790d133 | ||
|
|
bcf72b894d | ||
|
|
9f723c39ef | ||
|
|
56fc40a64d | ||
|
|
091f591ffb | ||
|
|
4d88a8206a | ||
|
|
363bf7c552 | ||
|
|
7ff4e5879d | ||
|
|
0b7decbfdd | ||
|
|
be9ea33aa4 | ||
|
|
d4b2cad94e | ||
|
|
ac039ce7cd | ||
|
|
946e60937d | ||
|
|
6f6601d270 | ||
|
|
71016f0d7c | ||
|
|
c2c2551607 | ||
|
|
d7812ec030 | ||
|
|
f184b0700f | ||
|
|
07f0be8d8d | ||
|
|
dd45b43d7f | ||
|
|
9b505106e3 | ||
|
|
d552f37daf | ||
|
|
6a7ff13859 | ||
|
|
9e3af13efc | ||
|
|
92a968217c | ||
|
|
37b9df3202 | ||
|
|
7dc33111fc | ||
|
|
ab2f260a52 | ||
|
|
1aa4b8cb88 | ||
|
|
dfed36748c | ||
|
|
d35f736548 | ||
|
|
cfecdae970 | ||
|
|
59ade6cf09 | ||
|
|
642842888a | ||
|
|
3ae51edf3a | ||
|
|
d8ccb81015 | ||
|
|
0db6020231 | ||
|
|
738c0a5c9c | ||
|
|
a2f7d3e241 | ||
|
|
9b86ded164 | ||
|
|
6cbb645b10 | ||
|
|
066a1d7591 | ||
|
|
5f82d575ee | ||
|
|
302ae0a83c | ||
|
|
82c4c791cc | ||
|
|
3c0310120d | ||
|
|
21c106e9d5 | ||
|
|
2c8cd2f8dc | ||
|
|
380d9908b4 | ||
|
|
6abef7d645 | ||
|
|
98ac25ac29 | ||
|
|
93bec04c92 | ||
|
|
136559cddd | ||
|
|
3f63a6ed70 | ||
|
|
2fcb3c4420 | ||
|
|
baaeb229cf | ||
|
|
a3bda3a941 | ||
|
|
3d536aa28d | ||
|
|
454267455b | ||
|
|
8e9adeb4b4 | ||
|
|
1f18e7beed | ||
|
|
b5e8e54107 | ||
|
|
f41e426b69 | ||
|
|
6375862a71 | ||
|
|
be2a745d78 | ||
|
|
d89feb2c75 | ||
|
|
b4a20c8fcb | ||
|
|
73087a92f4 | ||
|
|
2b58bd5bd8 | ||
|
|
bce0101278 | ||
|
|
bba418c79d | ||
|
|
cb58eb82fc | ||
|
|
3aafffabc1 | ||
|
|
66b9cdf64c | ||
|
|
d31fbf3b6f | ||
|
|
dbee30a412 | ||
|
|
f3cc881930 | ||
|
|
3d9c9e639d | ||
|
|
d6969d2c74 | ||
|
|
b7e28a73ba | ||
|
|
1e8206757d | ||
|
|
a0e94577fc | ||
|
|
a2a0c2f791 | ||
|
|
63a0fde121 | ||
|
|
c06152de07 | ||
|
|
0b3ccbda20 | ||
|
|
97b7eb0768 | ||
|
|
b712301804 | ||
|
|
76ebe3ff41 | ||
|
|
d988bb1821 | ||
|
|
64f1fbe400 | ||
|
|
c2c837329c | ||
|
|
b6531efe08 | ||
|
|
2c97a4aefe | ||
|
|
f0ffebd58c | ||
|
|
05e407f064 | ||
|
|
6dd2eec1b6 | ||
|
|
df13436688 | ||
|
|
fa0d89b6df | ||
|
|
ab0f8defa4 | ||
|
|
6b3329845b | ||
|
|
fc07c5efa6 | ||
|
|
23188df276 | ||
|
|
5e66dfcc36 | ||
|
|
bc36c57f9f | ||
|
|
5efa7d551e | ||
|
|
8c6cda0d97 | ||
|
|
4fa165bc6a | ||
|
|
da6695ceee | ||
|
|
1043a5bb0d | ||
|
|
c7625278b5 | ||
|
|
b9ef88951e | ||
|
|
14fe35bba0 | ||
|
|
4a32706c5a | ||
|
|
cc92edfa58 | ||
|
|
071d0fbbf7 | ||
|
|
6ff44fddd0 | ||
|
|
8760e99c43 | ||
|
|
423f5f16bb | ||
|
|
1c8c702afd | ||
|
|
d2a739262d | ||
|
|
76d0285e3f | ||
|
|
cb9d3414f2 | ||
|
|
677526cb16 | ||
|
|
08690b9d9e | ||
|
|
d3eb9c9d99 | ||
|
|
a0ef3a0e44 | ||
|
|
87c5ad79f4 | ||
|
|
2e210e7adc | ||
|
|
c56f4783c0 | ||
|
|
a1d351aa37 |
8
.gitignore
vendored
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
/core/assets/mindustry-saves/
|
/core/assets/mindustry-saves/
|
||||||
/core/assets/mindustry-maps/
|
/core/assets/mindustry-maps/
|
||||||
|
/core/assets/bundles/output/
|
||||||
|
/core/assets/.gifimages/
|
||||||
/deploy/
|
/deploy/
|
||||||
/desktop/packr-out/
|
/desktop/packr-out/
|
||||||
/desktop/packr-export/
|
/desktop/packr-export/
|
||||||
@@ -12,13 +14,17 @@
|
|||||||
/core/assets-raw/sprites/generated/
|
/core/assets-raw/sprites/generated/
|
||||||
/annotations/build/
|
/annotations/build/
|
||||||
/kryonet/build/
|
/kryonet/build/
|
||||||
/packer/build/
|
/tools/build/
|
||||||
|
/tests/build/
|
||||||
/server/build/
|
/server/build/
|
||||||
|
/test_files/
|
||||||
/annotations/build/
|
/annotations/build/
|
||||||
/android/assets/mindustry-maps/
|
/android/assets/mindustry-maps/
|
||||||
/android/assets/mindustry-saves/
|
/android/assets/mindustry-saves/
|
||||||
/core/assets/gifexport/
|
/core/assets/gifexport/
|
||||||
/core/assets/version.properties
|
/core/assets/version.properties
|
||||||
|
/core/assets/locales
|
||||||
|
/ios/src/io/anuke/mindustry/gen/
|
||||||
*.gif
|
*.gif
|
||||||
|
|
||||||
version.properties
|
version.properties
|
||||||
|
|||||||
@@ -5,16 +5,19 @@ jdk:
|
|||||||
|
|
||||||
android:
|
android:
|
||||||
components:
|
components:
|
||||||
- android-26
|
- android-28
|
||||||
|
|
||||||
# Additional components
|
# Additional components
|
||||||
- extra-google-google_play_services
|
- extra-google-google_play_services
|
||||||
- extra-google-m2repository
|
- extra-google-m2repository
|
||||||
- extra-android-m2repository
|
- extra-android-m2repository
|
||||||
- addon-google_apis-google-26
|
- addon-google_apis-google-28
|
||||||
|
- build-tools-28.0.3
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
- ./gradlew test
|
||||||
- ./gradlew desktop:dist
|
- ./gradlew desktop:dist
|
||||||
|
- ./gradlew server:dist
|
||||||
|
|
||||||
after_success:
|
after_success:
|
||||||
- chmod +x upload-build.sh
|
- chmod +x upload-build.sh
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||

|

|
||||||
|
|
||||||
[](https://travis-ci.org/Anuken/Mindustry)
|
[](https://travis-ci.org/Anuken/Mindustry)
|
||||||
[](https://waffle.io/Anuken/Mindustry)
|
[](https://discord.gg/mindustry)
|
||||||
|
|
||||||
A pixelated sandbox tower defense game made using [LibGDX](https://libgdx.badlogicgames.com/). Winner of the [GDL Metal Monstrosity Jam](https://itch.io/jam/gdl---metal-monstrosity-jam).
|
A pixelated sandbox tower defense game made using [LibGDX](https://libgdx.badlogicgames.com/). Winner of the [GDL Metal Monstrosity Jam](https://itch.io/jam/gdl---metal-monstrosity-jam).
|
||||||
|
|
||||||
_[Issue tracker](https://waffle.io/Anuken/Mindustry)_
|
|
||||||
_[Trello Board](https://trello.com/b/aE2tcUwF/mindustry-40-plans)_
|
_[Trello Board](https://trello.com/b/aE2tcUwF/mindustry-40-plans)_
|
||||||
_[Wiki](http://mindustry.wikia.com/wiki/Mindustry_Wiki)_
|
_[Wiki](http://mindustry.wikia.com/wiki/Mindustry_Wiki)_
|
||||||
_[Discord](https://discord.gg/r8BkXNd)_
|
_[Discord](https://discord.gg/r8BkXNd)_
|
||||||
@@ -32,7 +31,7 @@ _Building:_ `./gradlew desktop:dist`
|
|||||||
---
|
---
|
||||||
|
|
||||||
Gradle may take up to several minutes to download files. Be patient. <br>
|
Gradle may take up to several minutes to download files. Be patient. <br>
|
||||||
After building, the output .JAR file should be in the output JAR file should be in `/desktop/build/libs/desktop-release.jar.`
|
After building, the output .JAR file should be in `/desktop/build/libs/desktop-release.jar.`
|
||||||
|
|
||||||
### Downloads
|
### Downloads
|
||||||
|
|
||||||
|
|||||||
39
TRANSLATING.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
## Translating for Mindustry
|
||||||
|
|
||||||
|
**DISCLAIMER:** *Currently, 4.0 is far from done, which means that things such as block names, descriptions, and core text will be changing often. If you begin translating now, you might have to re-do large chunks of the bundle before final release.*
|
||||||
|
|
||||||
|
|
||||||
|
To begin, log in to your GitHub account, or if you don't have one yet, create it [here](https://github.com/).
|
||||||
|
|
||||||
|
Consult [this list](https://www.science.co.il/language/Locale-codes.php) to find the locale code for your language. Once you've found it,
|
||||||
|
head over to the translation bundle folder and check the [list of bundles](https://github.com/Anuken/Mindustry/tree/master/core/assets/bundles) that have already been created.
|
||||||
|
You're looking for a file called "`bundle_`(insert locale code here)`.properties`". If you don't find one, create one manually (more info below).
|
||||||
|
|
||||||
|
#### Editing an existing translation
|
||||||
|
|
||||||
|
If a translation bundle already exists, that means someone has already started working on a translation. To edit it or translate text, simply click the file and press the edit (pencil) button in the top right. Once you're done editing, press the green "propose file change" button at the bottom, then "create pull request" (twice).
|
||||||
|
Once this is done, all you need to do is wait for me to approve your changes.
|
||||||
|
|
||||||
|
#### Creating a new translation bundle
|
||||||
|
|
||||||
|
If a translation bundle for your language *doesn't* exist, you need to create one yourself.
|
||||||
|
In the folder with all the bundles in it, click the *'create new file'* button, and name it `bundle_(locale code here).properties`.
|
||||||
|
Then, copy-paste the entire contents of the [English translation bundle](https://raw.githubusercontent.com/Anuken/Mindustry/master/core/assets/bundles/bundle.properties) into the file, and translate all the necessary text to your language.
|
||||||
|
Once you are done, press the *propose new file* button at the bottom, then 'create pull request' twice.
|
||||||
|
|
||||||
|
#### Useful Information
|
||||||
|
|
||||||
|
- When you see text surrounded by square brackets, such as `[RED]`, `[]` or `[accent]`, this indicates a color code. Don't translate it.
|
||||||
|
- `{0}` means an argument that will be replaced when the text is displayed. For example, `Wave: {0}` will replace the `{0}` with whatever wave you are in.
|
||||||
|
- Empty lines are fine, and it doesn't matter in what order you place the text.
|
||||||
|
- `\n` means "new line". If you want to split text into multiple lines, use `\n` to do it.
|
||||||
|
|
||||||
|
#### Testing your translation bundle
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
**And that's it.**
|
||||||
|
|
||||||
|
*(...of course, that's never really it. Bother me on Discord when something inevitably goes wrong.)*
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name="io.anuke.mindustry.AndroidLauncher"
|
android:name="io.anuke.mindustry.AndroidLauncher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:screenOrientation="sensor"
|
android:screenOrientation="user"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ dependencies {
|
|||||||
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a"
|
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a"
|
||||||
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86"
|
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86"
|
||||||
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64"
|
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64"
|
||||||
implementation "com.badlogicgames.gdx:gdx-ai:$aiVersion"
|
|
||||||
implementation "com.badlogicgames.gdx:gdx-controllers-android:$gdxVersion"
|
implementation "com.badlogicgames.gdx:gdx-controllers-android:$gdxVersion"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,13 +31,13 @@ task deploy(type: Copy){
|
|||||||
dependsOn "assembleRelease"
|
dependsOn "assembleRelease"
|
||||||
|
|
||||||
from "build/outputs/apk/google/release/android-google-release.apk"
|
from "build/outputs/apk/google/release/android-google-release.apk"
|
||||||
into "../deploy/";
|
into "../deploy/"
|
||||||
rename ("android-google-release.apk", appName + "-android-" + getVersionString() + ".apk");
|
rename ("android-google-release.apk", appName + "-android-" + getVersionString() + ".apk")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
buildToolsVersion '27.0.3'
|
buildToolsVersion '28.0.3'
|
||||||
compileSdkVersion 27
|
compileSdkVersion 28
|
||||||
sourceSets {
|
sourceSets {
|
||||||
main {
|
main {
|
||||||
manifest.srcFile 'AndroidManifest.xml'
|
manifest.srcFile 'AndroidManifest.xml'
|
||||||
@@ -101,7 +100,7 @@ android {
|
|||||||
keyAlias RELEASE_KEY_ALIAS
|
keyAlias RELEASE_KEY_ALIAS
|
||||||
keyPassword RELEASE_KEY_PASSWORD
|
keyPassword RELEASE_KEY_PASSWORD
|
||||||
}else{
|
}else{
|
||||||
println("No keystore info property found!");
|
println("No keystore info property found!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,11 +115,11 @@ android {
|
|||||||
// the natives configuration, and extracts them to the proper libs/ folders
|
// the natives configuration, and extracts them to the proper libs/ folders
|
||||||
// so they get packed with the APK.
|
// so they get packed with the APK.
|
||||||
task copyAndroidNatives() {
|
task copyAndroidNatives() {
|
||||||
file("libs/armeabi/").mkdirs();
|
file("libs/armeabi/").mkdirs()
|
||||||
file("libs/armeabi-v7a/").mkdirs();
|
file("libs/armeabi-v7a/").mkdirs()
|
||||||
file("libs/arm64-v8a/").mkdirs();
|
file("libs/arm64-v8a/").mkdirs()
|
||||||
file("libs/x86_64/").mkdirs();
|
file("libs/x86_64/").mkdirs()
|
||||||
file("libs/x86/").mkdirs();
|
file("libs/x86/").mkdirs()
|
||||||
|
|
||||||
configurations.natives.files.each { jar ->
|
configurations.natives.files.each { jar ->
|
||||||
def outputDir = null
|
def outputDir = null
|
||||||
@@ -138,6 +137,7 @@ task copyAndroidNatives() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task run(type: Exec) {
|
task run(type: Exec) {
|
||||||
def path
|
def path
|
||||||
def localProperties = project.file("../local.properties")
|
def localProperties = project.file("../local.properties")
|
||||||
@@ -159,47 +159,18 @@ task run(type: Exec) {
|
|||||||
def adb = path + "/platform-tools/adb"
|
def adb = path + "/platform-tools/adb"
|
||||||
commandLine "$adb", 'shell', 'am', 'start', '-n', 'io.anuke.mindustry/io.anuke.mindustry.AndroidLauncher'
|
commandLine "$adb", 'shell', 'am', 'start', '-n', 'io.anuke.mindustry/io.anuke.mindustry.AndroidLauncher'
|
||||||
}
|
}
|
||||||
// sets up the Android Eclipse project, using the old Ant based build.
|
|
||||||
eclipse {
|
|
||||||
// need to specify Java source sets explicitly, SpringSource Gradle Eclipse plugin
|
|
||||||
// ignores any nodes added in classpath.file.withXml
|
|
||||||
sourceSets {
|
|
||||||
main {
|
|
||||||
java.srcDirs "src", 'gen'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jdt {
|
|
||||||
sourceCompatibility = 1.7
|
|
||||||
targetCompatibility = 1.7
|
|
||||||
}
|
|
||||||
|
|
||||||
classpath {
|
|
||||||
plusConfigurations += [project.configurations.compile]
|
|
||||||
containers 'com.android.ide.eclipse.adt.ANDROID_FRAMEWORK', 'com.android.ide.eclipse.adt.LIBRARIES'
|
|
||||||
}
|
|
||||||
|
|
||||||
project {
|
|
||||||
name = appName + "-android"
|
|
||||||
natures 'com.android.ide.eclipse.adt.AndroidNature'
|
|
||||||
buildCommands.clear();
|
|
||||||
buildCommand "com.android.ide.eclipse.adt.ResourceManagerBuilder"
|
|
||||||
buildCommand "com.android.ide.eclipse.adt.PreCompilerBuilder"
|
|
||||||
buildCommand "org.eclipse.jdt.core.javabuilder"
|
|
||||||
buildCommand "com.android.ide.eclipse.adt.ApkBuilder"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// sets up the Android Idea project, using the old Ant based build.
|
// sets up the Android Idea project, using the old Ant based build.
|
||||||
idea {
|
idea {
|
||||||
module {
|
module {
|
||||||
sourceDirs += file("src");
|
sourceDirs += file("src")
|
||||||
scopes = [COMPILE: [plus: [project.configurations.compile]]]
|
scopes = [COMPILE: [plus: [project.configurations.compile]]]
|
||||||
|
|
||||||
iml {
|
iml {
|
||||||
withXml {
|
withXml {
|
||||||
def node = it.asNode()
|
def node = it.asNode()
|
||||||
def builder = NodeBuilder.newInstance();
|
def builder = NodeBuilder.newInstance()
|
||||||
builder.current = node;
|
builder.current = node
|
||||||
builder.component(name: "FacetManager") {
|
builder.component(name: "FacetManager") {
|
||||||
facet(type: "android", name: "Android") {
|
facet(type: "android", name: "Android") {
|
||||||
configuration {
|
configuration {
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:inputType="text"
|
android:inputType="text"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:maxLength="15"
|
|
||||||
>
|
>
|
||||||
|
|
||||||
<requestFocus />
|
<requestFocus />
|
||||||
|
|||||||
15
android/res/values-ko/strings.xml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<string name="app_name">Mindustry</string>
|
||||||
|
<string-array name="donation_google_catalog_values">
|
||||||
|
<item>1 달러</item>
|
||||||
|
<item>2 달러</item>
|
||||||
|
<item>5 달러</item>
|
||||||
|
<item>10 달러</item>
|
||||||
|
<item>15 달러</item>
|
||||||
|
<item>25 달러</item>
|
||||||
|
<item>50 달러</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
</resources>
|
||||||
15
android/res/values-ru/strings.xml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<string name="app_name">Mindustry</string>
|
||||||
|
<string-array name="donation_google_catalog_values">
|
||||||
|
<item>1 Доллар</item>
|
||||||
|
<item>2 Доллара</item>
|
||||||
|
<item>5 Доллара</item>
|
||||||
|
<item>10 Долларов</item>
|
||||||
|
<item>15 Долларов</item>
|
||||||
|
<item>25 Долларов</item>
|
||||||
|
<item>50 Долларов</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
</resources>
|
||||||
@@ -12,7 +12,6 @@ import android.provider.Settings.Secure;
|
|||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
import com.badlogic.gdx.backends.android.AndroidApplication;
|
|
||||||
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
|
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
|
||||||
import com.badlogic.gdx.files.FileHandle;
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
import com.badlogic.gdx.utils.Base64Coder;
|
import com.badlogic.gdx.utils.Base64Coder;
|
||||||
@@ -25,8 +24,8 @@ import io.anuke.kryonet.KryoClient;
|
|||||||
import io.anuke.kryonet.KryoServer;
|
import io.anuke.kryonet.KryoServer;
|
||||||
import io.anuke.mindustry.core.Platform;
|
import io.anuke.mindustry.core.Platform;
|
||||||
import io.anuke.mindustry.core.ThreadHandler.ThreadProvider;
|
import io.anuke.mindustry.core.ThreadHandler.ThreadProvider;
|
||||||
|
import io.anuke.mindustry.game.Saves.SaveSlot;
|
||||||
import io.anuke.mindustry.io.SaveIO;
|
import io.anuke.mindustry.io.SaveIO;
|
||||||
import io.anuke.mindustry.io.Saves.SaveSlot;
|
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.ui.dialogs.FileChooser;
|
import io.anuke.mindustry.ui.dialogs.FileChooser;
|
||||||
import io.anuke.ucore.function.Consumer;
|
import io.anuke.ucore.function.Consumer;
|
||||||
@@ -48,27 +47,19 @@ import java.util.Locale;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class AndroidLauncher extends AndroidApplication{
|
public class AndroidLauncher extends PatchedAndroidApplication{
|
||||||
public static final int PERMISSION_REQUEST_CODE = 1;
|
public static final int PERMISSION_REQUEST_CODE = 1;
|
||||||
|
|
||||||
boolean doubleScaleTablets = true;
|
boolean doubleScaleTablets = true;
|
||||||
FileChooser chooser;
|
FileChooser chooser;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState){
|
protected void onCreate(Bundle savedInstanceState){
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
|
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
|
||||||
config.useImmersiveMode = true;
|
config.useImmersiveMode = true;
|
||||||
|
|
||||||
Platform.instance = new Platform(){
|
Platform.instance = new Platform(){
|
||||||
DateFormat format = SimpleDateFormat.getDateTimeInstance();
|
DateFormat format = SimpleDateFormat.getDateTimeInstance();
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasDiscord() {
|
|
||||||
return isPackageInstalled("com.discord");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String format(Date date){
|
public String format(Date date){
|
||||||
return format.format(date);
|
return format.format(date);
|
||||||
@@ -90,78 +81,64 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void openDonations() {
|
public void openDonations(){
|
||||||
showDonations();
|
showDonations();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ThreadProvider getThreadProvider() {
|
public ThreadProvider getThreadProvider(){
|
||||||
return new DefaultThreadImpl();
|
return new DefaultThreadImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDebug() {
|
public String getUUID(){
|
||||||
return false;
|
try{
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUUID() {
|
|
||||||
try {
|
|
||||||
String s = Secure.getString(getContext().getContentResolver(),
|
String s = Secure.getString(getContext().getContentResolver(),
|
||||||
Secure.ANDROID_ID);
|
Secure.ANDROID_ID);
|
||||||
|
|
||||||
int len = s.length();
|
int len = s.length();
|
||||||
byte[] data = new byte[len / 2];
|
byte[] data = new byte[len / 2];
|
||||||
for (int i = 0; i < len; i += 2) {
|
for(int i = 0; i < len; i += 2){
|
||||||
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
|
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
|
||||||
+ Character.digit(s.charAt(i + 1), 16));
|
+ Character.digit(s.charAt(i + 1), 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
String result = new String(Base64Coder.encode(data));
|
String result = new String(Base64Coder.encode(data));
|
||||||
|
|
||||||
if(result.equals("AAAAAAAAAOA=")) throw new RuntimeException("Bad UUID.");
|
if(result.equals("AAAAAAAAAOA=")) throw new RuntimeException("Bad UUID.");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}catch (Exception e){
|
}catch(Exception e){
|
||||||
return super.getUUID();
|
return super.getUUID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shareFile(FileHandle file){
|
public void shareFile(FileHandle file){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, String filetype) {
|
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, String filetype){
|
||||||
chooser = new FileChooser(text, file -> file.extension().equalsIgnoreCase(filetype), open, cons);
|
chooser = new FileChooser(text, file -> file.extension().equalsIgnoreCase(filetype), open, cons);
|
||||||
|
|
||||||
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
|
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
|
||||||
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)){
|
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)){
|
||||||
chooser.show();
|
chooser.show();
|
||||||
chooser = null;
|
chooser = null;
|
||||||
}else {
|
}else{
|
||||||
ArrayList<String> perms = new ArrayList<>();
|
ArrayList<String> perms = new ArrayList<>();
|
||||||
|
if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
|
||||||
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
|
||||||
perms.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
perms.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||||
}
|
}
|
||||||
|
if(checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
|
||||||
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
|
||||||
perms.add(Manifest.permission.READ_EXTERNAL_STORAGE);
|
perms.add(Manifest.permission.READ_EXTERNAL_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
requestPermissions(perms.toArray(new String[perms.size()]), PERMISSION_REQUEST_CODE);
|
requestPermissions(perms.toArray(new String[perms.size()]), PERMISSION_REQUEST_CODE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beginForceLandscape() {
|
public void beginForceLandscape(){
|
||||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void endForceLandscape() {
|
public void endForceLandscape(){
|
||||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
|
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,37 +147,30 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
try{
|
||||||
try {
|
|
||||||
ProviderInstaller.installIfNeeded(this);
|
ProviderInstaller.installIfNeeded(this);
|
||||||
} catch (GooglePlayServicesRepairableException e) {
|
}catch(GooglePlayServicesRepairableException e){
|
||||||
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
|
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
|
||||||
apiAvailability.getErrorDialog(this, e.getConnectionStatusCode(), 0).show();
|
apiAvailability.getErrorDialog(this, e.getConnectionStatusCode(), 0).show();
|
||||||
} catch (GooglePlayServicesNotAvailableException e) {
|
}catch(GooglePlayServicesNotAvailableException e){
|
||||||
Log.e("SecurityException", "Google Play Services not available.");
|
Log.e("SecurityException", "Google Play Services not available.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(doubleScaleTablets && isTablet(this.getContext())){
|
if(doubleScaleTablets && isTablet(this.getContext())){
|
||||||
Unit.dp.addition = 0.5f;
|
Unit.dp.addition = 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
config.hideStatusBar = true;
|
config.hideStatusBar = true;
|
||||||
|
|
||||||
Net.setClientProvider(new KryoClient());
|
Net.setClientProvider(new KryoClient());
|
||||||
Net.setServerProvider(new KryoServer());
|
Net.setServerProvider(new KryoServer());
|
||||||
|
|
||||||
initialize(new Mindustry(), config);
|
initialize(new Mindustry(), config);
|
||||||
|
|
||||||
checkFiles(getIntent());
|
checkFiles(getIntent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
|
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults){
|
||||||
if(requestCode == PERMISSION_REQUEST_CODE){
|
if(requestCode == PERMISSION_REQUEST_CODE){
|
||||||
for(int i : grantResults){
|
for(int i : grantResults){
|
||||||
if(i != PackageManager.PERMISSION_GRANTED) return;
|
if(i != PackageManager.PERMISSION_GRANTED) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(chooser != null){
|
if(chooser != null){
|
||||||
chooser.show();
|
chooser.show();
|
||||||
}
|
}
|
||||||
@@ -208,73 +178,65 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkFiles(Intent intent){
|
private void checkFiles(Intent intent){
|
||||||
try {
|
try{
|
||||||
Uri uri = intent.getData();
|
Uri uri = intent.getData();
|
||||||
if (uri != null) {
|
if(uri != null){
|
||||||
File myFile = null;
|
File myFile = null;
|
||||||
String scheme = uri.getScheme();
|
String scheme = uri.getScheme();
|
||||||
if (scheme.equals("file")) {
|
if(scheme.equals("file")){
|
||||||
String fileName = uri.getEncodedPath();
|
String fileName = uri.getEncodedPath();
|
||||||
myFile = new File(fileName);
|
myFile = new File(fileName);
|
||||||
} else if (!scheme.equals("content")) {
|
}else if(!scheme.equals("content")){
|
||||||
//error
|
//error
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean save = uri.getPath().endsWith(saveExtension);
|
boolean save = uri.getPath().endsWith(saveExtension);
|
||||||
boolean map = uri.getPath().endsWith(mapExtension);
|
boolean map = uri.getPath().endsWith(mapExtension);
|
||||||
|
|
||||||
InputStream inStream;
|
InputStream inStream;
|
||||||
if (myFile != null) inStream = new FileInputStream(myFile);
|
if(myFile != null) inStream = new FileInputStream(myFile);
|
||||||
else inStream = getContentResolver().openInputStream(uri);
|
else inStream = getContentResolver().openInputStream(uri);
|
||||||
|
|
||||||
Gdx.app.postRunnable(() -> {
|
Gdx.app.postRunnable(() -> {
|
||||||
|
|
||||||
if(save){ //open save
|
if(save){ //open save
|
||||||
System.out.println("Opening save.");
|
System.out.println("Opening save.");
|
||||||
FileHandle file = Gdx.files.local("temp-save." + saveExtension);
|
FileHandle file = Gdx.files.local("temp-save." + saveExtension);
|
||||||
file.write(inStream, false);
|
file.write(inStream, false);
|
||||||
|
|
||||||
if(SaveIO.isSaveValid(file)){
|
if(SaveIO.isSaveValid(file)){
|
||||||
try{
|
try{
|
||||||
SaveSlot slot = control.getSaves().importSave(file);
|
SaveSlot slot = control.saves.importSave(file);
|
||||||
ui.load.runLoadSave(slot);
|
ui.load.runLoadSave(slot);
|
||||||
}catch (IOException e){
|
}catch(IOException e){
|
||||||
ui.showError(Bundles.format("text.save.import.fail", Strings.parseException(e, false)));
|
ui.showError(Bundles.format("text.save.import.fail", Strings.parseException(e, false)));
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
ui.showError("$text.save.import.invalid");
|
ui.showError("$text.save.import.invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
}else if(map){ //open map
|
}else if(map){ //open map
|
||||||
Gdx.app.postRunnable(() -> {
|
Gdx.app.postRunnable(() -> {
|
||||||
System.out.println("Opening map.");
|
System.out.println("Opening map.");
|
||||||
if (!ui.editor.isShown()) {
|
if(!ui.editor.isShown()){
|
||||||
ui.editor.show();
|
ui.editor.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.editor.beginEditMap(inStream);
|
ui.editor.beginEditMap(inStream);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}catch(IOException e){
|
||||||
}catch (IOException e){
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPackageInstalled(String packagename) {
|
private boolean isPackageInstalled(String packagename){
|
||||||
try {
|
try{
|
||||||
getPackageManager().getPackageInfo(packagename, 0);
|
getPackageManager().getPackageInfo(packagename, 0);
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception e) {
|
}catch(Exception e){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTablet(Context context) {
|
private boolean isTablet(Context context){
|
||||||
TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
|
TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||||
return manager.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE;
|
return manager.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ public class AndroidTextFieldDialog{
|
|||||||
private TextPromptListener listener;
|
private TextPromptListener listener;
|
||||||
private boolean isBuild;
|
private boolean isBuild;
|
||||||
|
|
||||||
public AndroidTextFieldDialog() {
|
public AndroidTextFieldDialog(){
|
||||||
this.activity = (Activity)Gdx.app;
|
this.activity = (Activity) Gdx.app;
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidTextFieldDialog show() {
|
public AndroidTextFieldDialog show(){
|
||||||
|
|
||||||
activity.runOnUiThread(() -> {
|
activity.runOnUiThread(() -> {
|
||||||
AlertDialog dialog = builder.create();
|
AlertDialog dialog = builder.create();
|
||||||
@@ -36,7 +36,7 @@ public class AndroidTextFieldDialog{
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AndroidTextFieldDialog load() {
|
private AndroidTextFieldDialog load(){
|
||||||
|
|
||||||
activity.runOnUiThread(() -> {
|
activity.runOnUiThread(() -> {
|
||||||
|
|
||||||
@@ -56,19 +56,20 @@ public class AndroidTextFieldDialog{
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Wait till TextPrompt is built.
|
// Wait till TextPrompt is built.
|
||||||
while (!isBuild) {
|
while(!isBuild){
|
||||||
try {
|
try{
|
||||||
Thread.sleep(10);
|
Thread.sleep(10);
|
||||||
} catch (InterruptedException e) { }
|
}catch(InterruptedException ignored){
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getResourceId(String pVariableName, String pVariableType) {
|
public int getResourceId(String pVariableName, String pVariableType){
|
||||||
try {
|
try{
|
||||||
return activity.getResources().getIdentifier(pVariableName, pVariableType, activity.getPackageName());
|
return activity.getResources().getIdentifier(pVariableName, pVariableType, activity.getPackageName());
|
||||||
} catch (Exception e) {
|
}catch(Exception e){
|
||||||
Gdx.app.error("Android Dialogs", "Cannot find resouce with name: " + pVariableName
|
Gdx.app.error("Android Dialogs", "Cannot find resouce with name: " + pVariableName
|
||||||
+ " Did you copy the layouts to /res/layouts and /res/layouts_v14 ?");
|
+ " Did you copy the layouts to /res/layouts and /res/layouts_v14 ?");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -76,19 +77,19 @@ public class AndroidTextFieldDialog{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidTextFieldDialog setText(CharSequence value) {
|
public AndroidTextFieldDialog setText(CharSequence value){
|
||||||
userInput.append(value);
|
userInput.append(value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidTextFieldDialog setCancelButtonLabel(CharSequence label) {
|
public AndroidTextFieldDialog setCancelButtonLabel(CharSequence label){
|
||||||
builder.setNegativeButton(label, (dialog, id) -> dialog.cancel());
|
builder.setNegativeButton(label, (dialog, id) -> dialog.cancel());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidTextFieldDialog setConfirmButtonLabel(CharSequence label) {
|
public AndroidTextFieldDialog setConfirmButtonLabel(CharSequence label){
|
||||||
builder.setPositiveButton(label, (dialog, id) -> {
|
builder.setPositiveButton(label, (dialog, id) -> {
|
||||||
if (listener != null && !userInput.getText().toString().isEmpty()) {
|
if(listener != null && !userInput.getText().toString().isEmpty()){
|
||||||
listener.confirm(userInput.getText().toString());
|
listener.confirm(userInput.getText().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,18 +97,18 @@ public class AndroidTextFieldDialog{
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidTextFieldDialog setTextPromptListener(TextPromptListener listener) {
|
public AndroidTextFieldDialog setTextPromptListener(TextPromptListener listener){
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidTextFieldDialog setInputType(int type) {
|
public AndroidTextFieldDialog setInputType(int type){
|
||||||
userInput.setInputType(type);
|
userInput.setInputType(type);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidTextFieldDialog setMaxLength(int length) {
|
public AndroidTextFieldDialog setMaxLength(int length){
|
||||||
userInput.setFilters(new InputFilter[] { new InputFilter.LengthFilter(length) });
|
userInput.setFilters(new InputFilter[]{new InputFilter.LengthFilter(length)});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,9 @@ import android.support.v4.app.FragmentManager;
|
|||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v4.app.FragmentTransaction;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
|
||||||
import org.sufficientlysecure.donations.DonationsFragment;
|
import org.sufficientlysecure.donations.DonationsFragment;
|
||||||
|
|
||||||
public class DonationsActivity extends FragmentActivity {
|
public class DonationsActivity extends FragmentActivity{
|
||||||
DonationsFragment donationsFragment;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Google
|
* Google
|
||||||
*/
|
*/
|
||||||
@@ -21,13 +18,14 @@ public class DonationsActivity extends FragmentActivity {
|
|||||||
private static final String[] GOOGLE_CATALOG = new String[]{
|
private static final String[] GOOGLE_CATALOG = new String[]{
|
||||||
"mindustry.donation.1", "mindustry.donation.2", "mindustry.donation.5",
|
"mindustry.donation.1", "mindustry.donation.2", "mindustry.donation.5",
|
||||||
"mindustry.donation.10", "mindustry.donation.15",
|
"mindustry.donation.10", "mindustry.donation.15",
|
||||||
"mindustry.donation.25", "mindustry.donation.50" };
|
"mindustry.donation.25", "mindustry.donation.50"};
|
||||||
|
DonationsFragment donationsFragment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the activity is first created.
|
* Called when the activity is first created.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState){
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
setTheme(R.style.GdxTheme);
|
setTheme(R.style.GdxTheme);
|
||||||
@@ -35,7 +33,7 @@ public class DonationsActivity extends FragmentActivity {
|
|||||||
setContentView(R.layout.donations_activity);
|
setContentView(R.layout.donations_activity);
|
||||||
|
|
||||||
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
|
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
|
||||||
if (BuildConfig.DONATIONS_GOOGLE) {
|
if(BuildConfig.DONATIONS_GOOGLE){
|
||||||
donationsFragment = DonationsFragment.newInstance(BuildConfig.DEBUG, true, GOOGLE_PUBKEY, GOOGLE_CATALOG,
|
donationsFragment = DonationsFragment.newInstance(BuildConfig.DEBUG, true, GOOGLE_PUBKEY, GOOGLE_CATALOG,
|
||||||
getResources().getStringArray(R.array.donation_google_catalog_values), false, null, null,
|
getResources().getStringArray(R.array.donation_google_catalog_values), false, null, null,
|
||||||
null, false, null, null, false, null);
|
null, false, null, null, false, null);
|
||||||
@@ -48,30 +46,27 @@ public class DonationsActivity extends FragmentActivity {
|
|||||||
|
|
||||||
public void onStart(){
|
public void onStart(){
|
||||||
super.onStart();
|
super.onStart();
|
||||||
Button b = ((Button)findViewById(org.sufficientlysecure.donations.R.id.donations__google_android_market_donate_button));
|
Button b = findViewById(org.sufficientlysecure.donations.R.id.donations__google_android_market_donate_button);
|
||||||
b.setOnClickListener(new View.OnClickListener() {
|
b.setOnClickListener(view -> {
|
||||||
@Override public void onClick(View view) {
|
|
||||||
donationsFragment.donateGoogleOnClick(donationsFragment.getView());
|
donationsFragment.donateGoogleOnClick(donationsFragment.getView());
|
||||||
b.setEnabled(false);
|
b.setEnabled(false);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Needed for Google Play In-app Billing. It uses startIntentSenderForResult(). The result is not propagated to
|
* Needed for Google Play In-app Billing. It uses startIntentSenderForResult(). The result is not propagated to
|
||||||
* the Fragment like in startActivityForResult(). Thus we need to propagate manually to our Fragment.
|
* the Fragment like in startActivityForResult(). Thus we need to propagate manually to our Fragment.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
protected void onActivityResult(int requestCode, int resultCode, Intent data){
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
Button b = ((Button)findViewById(org.sufficientlysecure.donations.R.id.donations__google_android_market_donate_button));
|
Button b = findViewById(org.sufficientlysecure.donations.R.id.donations__google_android_market_donate_button);
|
||||||
b.setEnabled(true);
|
b.setEnabled(true);
|
||||||
|
|
||||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||||
Fragment fragment = fragmentManager.findFragmentByTag("donationsFragment");
|
Fragment fragment = fragmentManager.findFragmentByTag("donationsFragment");
|
||||||
if (fragment != null) {
|
if(fragment != null){
|
||||||
fragment.onActivityResult(requestCode, resultCode, data);
|
fragment.onActivityResult(requestCode, resultCode, data);
|
||||||
//TODO donation event, set settings?
|
//TODO donation event, set settings?
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package io.anuke.mindustry;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.backends.android.AndroidApplication;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
public class PatchedAndroidApplication extends AndroidApplication {
|
||||||
|
private final ExecutorService exec = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause () {
|
||||||
|
if(useImmersiveMode) {
|
||||||
|
exec.submit(() -> {
|
||||||
|
try {Thread.sleep(100);} catch (InterruptedException ignored) {}
|
||||||
|
graphics.onDrawFrame(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,10 +15,17 @@ public class TextFieldDialogListener extends ClickListener{
|
|||||||
private int type;
|
private int type;
|
||||||
private int max;
|
private int max;
|
||||||
|
|
||||||
|
//type - 0 is text, 1 is numbers, 2 is decimals
|
||||||
|
public TextFieldDialogListener(TextField field, int type, int max){
|
||||||
|
this.field = field;
|
||||||
|
this.type = type;
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
|
||||||
public static void add(TextField field, int type, int max){
|
public static void add(TextField field, int type, int max){
|
||||||
field.addListener(new TextFieldDialogListener(field, type, max));
|
field.addListener(new TextFieldDialogListener(field, type, max));
|
||||||
field.addListener(new InputListener(){
|
field.addListener(new InputListener(){
|
||||||
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
|
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){
|
||||||
Gdx.input.setOnscreenKeyboardVisible(false);
|
Gdx.input.setOnscreenKeyboardVisible(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -29,13 +36,6 @@ public class TextFieldDialogListener extends ClickListener{
|
|||||||
add(field, 0, 16);
|
add(field, 0, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
//type - 0 is text, 1 is numbers, 2 is decimals
|
|
||||||
public TextFieldDialogListener(TextField field, int type, int max){
|
|
||||||
this.field = field;
|
|
||||||
this.type = type;
|
|
||||||
this.max = max;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clicked(final InputEvent event, float x, float y){
|
public void clicked(final InputEvent event, float x, float y){
|
||||||
|
|
||||||
if(Gdx.app.getType() == ApplicationType.Desktop) return;
|
if(Gdx.app.getType() == ApplicationType.Desktop) return;
|
||||||
|
|||||||
@@ -5,74 +5,38 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
public class Annotations{
|
||||||
* Goal: To create a system to send events to the server from the client and vice versa, without creating a new packet type each time.<br>
|
|
||||||
* These events may optionally also trigger on the caller client/server as well.<br>
|
/** Marks a class as serializable.*/
|
||||||
*/
|
@Target(ElementType.TYPE)
|
||||||
public class Annotations {
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface Serialize{
|
||||||
|
|
||||||
/**Marks a method as invokable remotely across a server/client connection.*/
|
|
||||||
@Target(ElementType.METHOD)
|
|
||||||
@Retention(RetentionPolicy.CLASS)
|
|
||||||
public @interface Remote {
|
|
||||||
/**Specifies the locations from which this method can be invoked.*/
|
|
||||||
Loc targets() default Loc.server;
|
|
||||||
/**Specifies which methods are generated. Only affects server-to-client methods.*/
|
|
||||||
Variant variants() default Variant.all;
|
|
||||||
/**The local locations where this method is called locally, when invoked.*/
|
|
||||||
Loc called() default Loc.none;
|
|
||||||
/**Whether to forward this packet to all other clients upon recieval. Server only.*/
|
|
||||||
boolean forward() default false;
|
|
||||||
/**Whether the packet for this method is sent with UDP instead of TCP.
|
|
||||||
* UDP is faster, but is prone to packet loss and duplication.*/
|
|
||||||
boolean unreliable() default false;
|
|
||||||
/**The simple class name where this method is placed.*/
|
|
||||||
String in() default "Call";
|
|
||||||
/**Priority of this event.*/
|
|
||||||
PacketPriority priority() default PacketPriority.normal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Specifies that this method will be used to write classes of the type returned by {@link #value()}.<br>
|
public enum PacketPriority{
|
||||||
* This method must return void and have two parameters, the first being of type {@link java.nio.ByteBuffer} and the second
|
/** Gets put in a queue and processed if not connected. */
|
||||||
* being the type returned by {@link #value()}.*/
|
|
||||||
@Target(ElementType.METHOD)
|
|
||||||
@Retention(RetentionPolicy.CLASS)
|
|
||||||
public @interface WriteClass {
|
|
||||||
Class<?> value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**Specifies that this method will be used to read classes of the type returned by {@link #value()}. <br>
|
|
||||||
* This method must return the type returned by {@link #value()},
|
|
||||||
* and have one parameter, being of type {@link java.nio.ByteBuffer}.*/
|
|
||||||
@Target(ElementType.METHOD)
|
|
||||||
@Retention(RetentionPolicy.CLASS)
|
|
||||||
public @interface ReadClass {
|
|
||||||
Class<?> value();
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum PacketPriority {
|
|
||||||
/**Gets put in a queue and processed if not connected.*/
|
|
||||||
normal,
|
normal,
|
||||||
/**Gets handled immediately, regardless of connection status.*/
|
/** Gets handled immediately, regardless of connection status. */
|
||||||
high,
|
high,
|
||||||
/**Does not get handled unless client is connected.*/
|
/** Does not get handled unless client is connected. */
|
||||||
low
|
low
|
||||||
}
|
}
|
||||||
|
|
||||||
/**A set of two booleans, one specifying server and one specifying client.*/
|
/** A set of two booleans, one specifying server and one specifying client. */
|
||||||
public enum Loc {
|
public enum Loc{
|
||||||
/**Method can only be invoked on the client from the server.*/
|
/** Method can only be invoked on the client from the server. */
|
||||||
server(true, false),
|
server(true, false),
|
||||||
/**Method can only be invoked on the server from the client.*/
|
/** Method can only be invoked on the server from the client. */
|
||||||
client(false, true),
|
client(false, true),
|
||||||
/**Method can be invoked from anywhere*/
|
/** Method can be invoked from anywhere */
|
||||||
both(true, true),
|
both(true, true),
|
||||||
/**Neither server no client.*/
|
/** Neither server nor client. */
|
||||||
none(false, false);
|
none(false, false);
|
||||||
|
|
||||||
/**If true, this method can be invoked ON clients FROM servers.*/
|
/** If true, this method can be invoked ON clients FROM servers. */
|
||||||
public final boolean isServer;
|
public final boolean isServer;
|
||||||
/**If true, this method can be invoked ON servers FROM clients.*/
|
/** If true, this method can be invoked ON servers FROM clients. */
|
||||||
public final boolean isClient;
|
public final boolean isClient;
|
||||||
|
|
||||||
Loc(boolean server, boolean client){
|
Loc(boolean server, boolean client){
|
||||||
@@ -81,12 +45,12 @@ public class Annotations {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Variant {
|
public enum Variant{
|
||||||
/**Method can only be invoked targeting one player.*/
|
/** Method can only be invoked targeting one player. */
|
||||||
one(true, false),
|
one(true, false),
|
||||||
/**Method can only be invoked targeting all players.*/
|
/** Method can only be invoked targeting all players. */
|
||||||
all(false, true),
|
all(false, true),
|
||||||
/**Method targets both one player and all players.*/
|
/** Method targets both one player and all players. */
|
||||||
both(true, true);
|
both(true, true);
|
||||||
|
|
||||||
public final boolean isOne, isAll;
|
public final boolean isOne, isAll;
|
||||||
@@ -96,4 +60,52 @@ public class Annotations {
|
|||||||
this.isAll = isAll;
|
this.isAll = isAll;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Marks a method as invokable remotely across a server/client connection. */
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface Remote{
|
||||||
|
/** Specifies the locations from which this method can be invoked. */
|
||||||
|
Loc targets() default Loc.server;
|
||||||
|
|
||||||
|
/** Specifies which methods are generated. Only affects server-to-client methods. */
|
||||||
|
Variant variants() default Variant.all;
|
||||||
|
|
||||||
|
/** The local locations where this method is called locally, when invoked. */
|
||||||
|
Loc called() default Loc.none;
|
||||||
|
|
||||||
|
/** Whether to forward this packet to all other clients upon recieval. Client only. */
|
||||||
|
boolean forward() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the packet for this method is sent with UDP instead of TCP.
|
||||||
|
* UDP is faster, but is prone to packet loss and duplication.
|
||||||
|
*/
|
||||||
|
boolean unreliable() default false;
|
||||||
|
|
||||||
|
/** Priority of this event. */
|
||||||
|
PacketPriority priority() default PacketPriority.normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies that this method will be used to write classes of the type returned by {@link #value()}.<br>
|
||||||
|
* This method must return void and have two parameters, the first being of type {@link java.nio.ByteBuffer} and the second
|
||||||
|
* being the type returned by {@link #value()}.
|
||||||
|
*/
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface WriteClass{
|
||||||
|
Class<?> value();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies that this method will be used to read classes of the type returned by {@link #value()}. <br>
|
||||||
|
* This method must return the type returned by {@link #value()},
|
||||||
|
* and have one parameter, being of type {@link java.nio.ByteBuffer}.
|
||||||
|
*/
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface ReadClass{
|
||||||
|
Class<?> value();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ package io.anuke.annotations;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**Represents a class witha list method entries to include in it.*/
|
/** Represents a class witha list method entries to include in it. */
|
||||||
public class ClassEntry {
|
public class ClassEntry{
|
||||||
/**All methods in this generated class.*/
|
/** All methods in this generated class. */
|
||||||
public final ArrayList<MethodEntry> methods = new ArrayList<>();
|
public final ArrayList<MethodEntry> methods = new ArrayList<>();
|
||||||
/**Simple class name.*/
|
/** Simple class name. */
|
||||||
public final String name;
|
public final String name;
|
||||||
|
|
||||||
public ClassEntry(String name) {
|
public ClassEntry(String name){
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,16 @@ import javax.tools.Diagnostic.Kind;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**This class finds reader and writer methods annotated by the {@link io.anuke.annotations.Annotations.WriteClass}
|
/**
|
||||||
* and {@link io.anuke.annotations.Annotations.ReadClass} annotations.*/
|
* This class finds reader and writer methods annotated by the {@link io.anuke.annotations.Annotations.WriteClass}
|
||||||
public class IOFinder {
|
* and {@link io.anuke.annotations.Annotations.ReadClass} annotations.
|
||||||
|
*/
|
||||||
|
public class IOFinder{
|
||||||
|
|
||||||
/**Finds all class serializers for all types and returns them. Logs errors when necessary.
|
/**
|
||||||
* Maps fully qualified class names to their serializers.*/
|
* Finds all class serializers for all types and returns them. Logs errors when necessary.
|
||||||
|
* Maps fully qualified class names to their serializers.
|
||||||
|
*/
|
||||||
public HashMap<String, ClassSerializer> findSerializers(RoundEnvironment env){
|
public HashMap<String, ClassSerializer> findSerializers(RoundEnvironment env){
|
||||||
HashMap<String, ClassSerializer> result = new HashMap<>();
|
HashMap<String, ClassSerializer> result = new HashMap<>();
|
||||||
|
|
||||||
@@ -51,33 +55,33 @@ public class IOFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getValue(WriteClass write){
|
private String getValue(WriteClass write){
|
||||||
try {
|
try{
|
||||||
Class<?> type = write.value();
|
Class<?> type = write.value();
|
||||||
return type.getName();
|
return type.getName();
|
||||||
}catch (MirroredTypeException e){
|
}catch(MirroredTypeException e){
|
||||||
return e.getTypeMirror().toString();
|
return e.getTypeMirror().toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getValue(ReadClass read){
|
private String getValue(ReadClass read){
|
||||||
try {
|
try{
|
||||||
Class<?> type = read.value();
|
Class<?> type = read.value();
|
||||||
return type.getName();
|
return type.getName();
|
||||||
}catch (MirroredTypeException e){
|
}catch(MirroredTypeException e){
|
||||||
return e.getTypeMirror().toString();
|
return e.getTypeMirror().toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Information about read/write methods for a specific class type.*/
|
/** Information about read/write methods for a specific class type. */
|
||||||
public static class ClassSerializer{
|
public static class ClassSerializer{
|
||||||
/**Fully qualified method name of the reader.*/
|
/** Fully qualified method name of the reader. */
|
||||||
public final String readMethod;
|
public final String readMethod;
|
||||||
/**Fully qualified method name of the writer.*/
|
/** Fully qualified method name of the writer. */
|
||||||
public final String writeMethod;
|
public final String writeMethod;
|
||||||
/**Fully qualified class type name.*/
|
/** Fully qualified class type name. */
|
||||||
public final String classType;
|
public final String classType;
|
||||||
|
|
||||||
public ClassSerializer(String readMethod, String writeMethod, String classType) {
|
public ClassSerializer(String readMethod, String writeMethod, String classType){
|
||||||
this.readMethod = readMethod;
|
this.readMethod = readMethod;
|
||||||
this.writeMethod = writeMethod;
|
this.writeMethod = writeMethod;
|
||||||
this.classType = classType;
|
this.classType = classType;
|
||||||
|
|||||||
@@ -6,32 +6,34 @@ import io.anuke.annotations.Annotations.Variant;
|
|||||||
|
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
|
|
||||||
/**Class that repesents a remote method to be constructed and put into a class.*/
|
/** Class that repesents a remote method to be constructed and put into a class. */
|
||||||
public class MethodEntry {
|
public class MethodEntry{
|
||||||
/**Simple target class name.*/
|
/** Simple target class name. */
|
||||||
public final String className;
|
public final String className;
|
||||||
/**Fully qualified target method to call.*/
|
/** Fully qualified target method to call. */
|
||||||
public final String targetMethod;
|
public final String targetMethod;
|
||||||
/**Whether this method can be called on a client/server.*/
|
/** Whether this method can be called on a client/server. */
|
||||||
public final Loc where;
|
public final Loc where;
|
||||||
/**Whether an additional 'one' and 'all' method variant is generated. At least one of these must be true.
|
/**
|
||||||
* Only applicable to client (server-invoked) methods.*/
|
* Whether an additional 'one' and 'all' method variant is generated. At least one of these must be true.
|
||||||
|
* Only applicable to client (server-invoked) methods.
|
||||||
|
*/
|
||||||
public final Variant target;
|
public final Variant target;
|
||||||
/**Whether this method is called locally as well as remotely.*/
|
/** Whether this method is called locally as well as remotely. */
|
||||||
public final Loc local;
|
public final Loc local;
|
||||||
/**Whether this method is unreliable and uses UDP.*/
|
/** Whether this method is unreliable and uses UDP. */
|
||||||
public final boolean unreliable;
|
public final boolean unreliable;
|
||||||
/**Whether to forward this method call to all other clients when a client invokes it. Server only.*/
|
/** Whether to forward this method call to all other clients when a client invokes it. Server only. */
|
||||||
public final boolean forward;
|
public final boolean forward;
|
||||||
/**Unique method ID.*/
|
/** Unique method ID. */
|
||||||
public final int id;
|
public final int id;
|
||||||
/**The element method associated with this entry.*/
|
/** The element method associated with this entry. */
|
||||||
public final ExecutableElement element;
|
public final ExecutableElement element;
|
||||||
/**The assigned packet priority. Only used in clients.*/
|
/** The assigned packet priority. Only used in clients. */
|
||||||
public final PacketPriority priority;
|
public final PacketPriority priority;
|
||||||
|
|
||||||
public MethodEntry(String className, String targetMethod, Loc where, Variant target,
|
public MethodEntry(String className, String targetMethod, Loc where, Variant target,
|
||||||
Loc local, boolean unreliable, boolean forward, int id, ExecutableElement element, PacketPriority priority) {
|
Loc local, boolean unreliable, boolean forward, int id, ExecutableElement element, PacketPriority priority){
|
||||||
this.className = className;
|
this.className = className;
|
||||||
this.forward = forward;
|
this.forward = forward;
|
||||||
this.targetMethod = targetMethod;
|
this.targetMethod = targetMethod;
|
||||||
@@ -45,7 +47,7 @@ public class MethodEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode(){
|
||||||
return targetMethod.hashCode();
|
return targetMethod.hashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,25 +18,27 @@ import java.util.*;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
/**The annotation processor for generating remote method call code.*/
|
/** The annotation processor for generating remote method call code. */
|
||||||
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
||||||
@SupportedAnnotationTypes({
|
@SupportedAnnotationTypes({
|
||||||
"io.anuke.annotations.Annotations.Remote",
|
"io.anuke.annotations.Annotations.Remote",
|
||||||
"io.anuke.annotations.Annotations.WriteClass",
|
"io.anuke.annotations.Annotations.WriteClass",
|
||||||
"io.anuke.annotations.Annotations.ReadClass",
|
"io.anuke.annotations.Annotations.ReadClass",
|
||||||
})
|
})
|
||||||
public class RemoteMethodAnnotationProcessor extends AbstractProcessor {
|
public class RemoteMethodAnnotationProcessor extends AbstractProcessor{
|
||||||
/**Maximum size of each event packet.*/
|
/** Maximum size of each event packet. */
|
||||||
public static final int maxPacketSize = 4096;
|
public static final int maxPacketSize = 4096;
|
||||||
/**Name of the base package to put all the generated classes.*/
|
/** Name of the base package to put all the generated classes. */
|
||||||
private static final String packageName = "io.anuke.mindustry.gen";
|
private static final String packageName = "io.anuke.mindustry.gen";
|
||||||
|
|
||||||
/**Name of class that handles reading and invoking packets on the server.*/
|
/** Name of class that handles reading and invoking packets on the server. */
|
||||||
private static final String readServerName = "RemoteReadServer";
|
private static final String readServerName = "RemoteReadServer";
|
||||||
/**Name of class that handles reading and invoking packets on the client.*/
|
/** Name of class that handles reading and invoking packets on the client. */
|
||||||
private static final String readClientName = "RemoteReadClient";
|
private static final String readClientName = "RemoteReadClient";
|
||||||
|
/**Simple class name of generated class name.*/
|
||||||
|
private static final String callLocation = "Call";
|
||||||
|
|
||||||
/**Processing round number.*/
|
/** Processing round number. */
|
||||||
private int round;
|
private int round;
|
||||||
|
|
||||||
//class serializers
|
//class serializers
|
||||||
@@ -51,7 +53,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor {
|
|||||||
private ArrayList<ClassEntry> classes;
|
private ArrayList<ClassEntry> classes;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void init(ProcessingEnvironment processingEnv) {
|
public synchronized void init(ProcessingEnvironment processingEnv){
|
||||||
super.init(processingEnv);
|
super.init(processingEnv);
|
||||||
//put all relevant utils into utils class
|
//put all relevant utils into utils class
|
||||||
Utils.typeUtils = processingEnv.getTypeUtils();
|
Utils.typeUtils = processingEnv.getTypeUtils();
|
||||||
@@ -61,18 +63,17 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
|
||||||
if(round > 1) return false; //only process 2 rounds
|
if(round > 1) return false; //only process 2 rounds
|
||||||
|
|
||||||
round ++;
|
round++;
|
||||||
|
|
||||||
try {
|
try{
|
||||||
|
|
||||||
//round 1: find all annotations, generate *writers*
|
//round 1: find all annotations, generate *writers*
|
||||||
if(round == 1) {
|
if(round == 1){
|
||||||
//get serializers
|
//get serializers
|
||||||
serializers = new IOFinder().findSerializers(roundEnv);
|
serializers = new IOFinder().findSerializers(roundEnv);
|
||||||
|
|
||||||
//last method ID used
|
//last method ID used
|
||||||
int lastMethodID = 0;
|
int lastMethodID = 0;
|
||||||
//find all elements with the Remote annotation
|
//find all elements with the Remote annotation
|
||||||
@@ -88,29 +89,29 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor {
|
|||||||
orderedElements.sort(Comparator.comparing(Object::toString));
|
orderedElements.sort(Comparator.comparing(Object::toString));
|
||||||
|
|
||||||
//create methods
|
//create methods
|
||||||
for (Element element : orderedElements) {
|
for(Element element : orderedElements){
|
||||||
Remote annotation = element.getAnnotation(Remote.class);
|
Remote annotation = element.getAnnotation(Remote.class);
|
||||||
|
|
||||||
//check for static
|
//check for static
|
||||||
if (!element.getModifiers().contains(Modifier.STATIC) || !element.getModifiers().contains(Modifier.PUBLIC)) {
|
if(!element.getModifiers().contains(Modifier.STATIC) || !element.getModifiers().contains(Modifier.PUBLIC)){
|
||||||
Utils.messager.printMessage(Kind.ERROR, "All @Remote methods must be public and static: ", element);
|
Utils.messager.printMessage(Kind.ERROR, "All @Remote methods must be public and static: ", element);
|
||||||
}
|
}
|
||||||
|
|
||||||
//can't generate none methods
|
//can't generate none methods
|
||||||
if (annotation.targets() == Loc.none) {
|
if(annotation.targets() == Loc.none){
|
||||||
Utils.messager.printMessage(Kind.ERROR, "A @Remote method's targets() cannot be equal to 'none':", element);
|
Utils.messager.printMessage(Kind.ERROR, "A @Remote method's targets() cannot be equal to 'none':", element);
|
||||||
}
|
}
|
||||||
|
|
||||||
//get and create class entry if needed
|
//get and create class entry if needed
|
||||||
if (!classMap.containsKey(annotation.in())) {
|
if(!classMap.containsKey(callLocation)){
|
||||||
ClassEntry clas = new ClassEntry(annotation.in());
|
ClassEntry clas = new ClassEntry(callLocation);
|
||||||
classMap.put(annotation.in(), clas);
|
classMap.put(callLocation, clas);
|
||||||
classes.add(clas);
|
classes.add(clas);
|
||||||
|
|
||||||
Utils.messager.printMessage(Kind.NOTE, "Generating class '" + clas.name + "'.");
|
Utils.messager.printMessage(Kind.NOTE, "Generating class '" + clas.name + "'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassEntry entry = classMap.get(annotation.in());
|
ClassEntry entry = classMap.get(callLocation);
|
||||||
|
|
||||||
//create and add entry
|
//create and add entry
|
||||||
MethodEntry method = new MethodEntry(entry.name, Utils.getMethodName(element), annotation.targets(), annotation.variants(),
|
MethodEntry method = new MethodEntry(entry.name, Utils.getMethodName(element), annotation.targets(), annotation.variants(),
|
||||||
@@ -127,7 +128,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor {
|
|||||||
writegen.generateFor(classes, packageName);
|
writegen.generateFor(classes, packageName);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}else if(round == 2) { //round 2: generate all *readers*
|
}else if(round == 2){ //round 2: generate all *readers*
|
||||||
RemoteReadGenerator readgen = new RemoteReadGenerator(serializers);
|
RemoteReadGenerator readgen = new RemoteReadGenerator(serializers);
|
||||||
|
|
||||||
//generate server readers
|
//generate server readers
|
||||||
@@ -147,7 +148,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}catch (Exception e){
|
}catch(Exception e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,22 +14,25 @@ import java.nio.ByteBuffer;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**Generates code for reading remote invoke packets on the client and server.*/
|
/** Generates code for reading remote invoke packets on the client and server. */
|
||||||
public class RemoteReadGenerator {
|
public class RemoteReadGenerator{
|
||||||
private final HashMap<String, ClassSerializer> serializers;
|
private final HashMap<String, ClassSerializer> serializers;
|
||||||
|
|
||||||
/**Creates a read generator that uses the supplied serializer setup.*/
|
/** Creates a read generator that uses the supplied serializer setup. */
|
||||||
public RemoteReadGenerator(HashMap<String, ClassSerializer> serializers) {
|
public RemoteReadGenerator(HashMap<String, ClassSerializer> serializers){
|
||||||
this.serializers = serializers;
|
this.serializers = serializers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Generates a class for reading remote invoke packets.
|
/**
|
||||||
|
* Generates a class for reading remote invoke packets.
|
||||||
|
*
|
||||||
* @param entries List of methods to use/
|
* @param entries List of methods to use/
|
||||||
* @param className Simple target class name.
|
* @param className Simple target class name.
|
||||||
* @param packageName Full target package name.
|
* @param packageName Full target package name.
|
||||||
* @param needsPlayer Whether this read method requires a reference to the player sender.*/
|
* @param needsPlayer Whether this read method requires a reference to the player sender.
|
||||||
|
*/
|
||||||
public void generateFor(List<MethodEntry> entries, String className, String packageName, boolean needsPlayer)
|
public void generateFor(List<MethodEntry> entries, String className, String packageName, boolean needsPlayer)
|
||||||
throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException {
|
throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException{
|
||||||
|
|
||||||
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC);
|
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
@@ -69,10 +72,10 @@ public class RemoteReadGenerator {
|
|||||||
StringBuilder varResult = new StringBuilder();
|
StringBuilder varResult = new StringBuilder();
|
||||||
|
|
||||||
//go through each parameter
|
//go through each parameter
|
||||||
for(int i = 0; i < entry.element.getParameters().size(); i ++){
|
for(int i = 0; i < entry.element.getParameters().size(); i++){
|
||||||
VariableElement var = entry.element.getParameters().get(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
|
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
|
//full type name of parameter
|
||||||
String typeName = var.asType().toString();
|
String typeName = var.asType().toString();
|
||||||
//name of parameter
|
//name of parameter
|
||||||
@@ -81,17 +84,17 @@ public class RemoteReadGenerator {
|
|||||||
String capName = typeName.equals("byte") ? "" : Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
|
String capName = typeName.equals("byte") ? "" : Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
|
||||||
|
|
||||||
//write primitives automatically
|
//write primitives automatically
|
||||||
if (Utils.isPrimitive(typeName)) {
|
if(Utils.isPrimitive(typeName)){
|
||||||
if (typeName.equals("boolean")) {
|
if(typeName.equals("boolean")){
|
||||||
readBlock.addStatement("boolean " + varName + " = buffer.get() == 1");
|
readBlock.addStatement("boolean " + varName + " = buffer.get() == 1");
|
||||||
} else {
|
}else{
|
||||||
readBlock.addStatement(typeName + " " + varName + " = buffer.get" + capName + "()");
|
readBlock.addStatement(typeName + " " + varName + " = buffer.get" + capName + "()");
|
||||||
}
|
}
|
||||||
} else {
|
}else{
|
||||||
//else, try and find a serializer
|
//else, try and find a serializer
|
||||||
ClassSerializer ser = serializers.get(typeName);
|
ClassSerializer ser = serializers.get(typeName);
|
||||||
|
|
||||||
if (ser == null) { //make sure a serializer exists!
|
if(ser == null){ //make sure a serializer exists!
|
||||||
Utils.messager.printMessage(Kind.ERROR, "No @ReadClass method to read class type: '" + typeName + "'", var);
|
Utils.messager.printMessage(Kind.ERROR, "No @ReadClass method to read class type: '" + typeName + "'", var);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -121,7 +124,7 @@ public class RemoteReadGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readBlock.nextControlFlow("catch (java.lang.Exception e)");
|
readBlock.nextControlFlow("catch (java.lang.Exception e)");
|
||||||
readBlock.addStatement("throw new java.lang.RuntimeException(\"Failed to to read remote method '"+entry.element.getSimpleName() +"'!\", e)");
|
readBlock.addStatement("throw new java.lang.RuntimeException(\"Failed to to read remote method '" + entry.element.getSimpleName() + "'!\", e)");
|
||||||
readBlock.endControlFlow();
|
readBlock.endControlFlow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,17 +14,17 @@ import java.nio.ByteBuffer;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**Generates code for writing remote invoke packets on the client and server.*/
|
/** Generates code for writing remote invoke packets on the client and server. */
|
||||||
public class RemoteWriteGenerator {
|
public class RemoteWriteGenerator{
|
||||||
private final HashMap<String, ClassSerializer> serializers;
|
private final HashMap<String, ClassSerializer> serializers;
|
||||||
|
|
||||||
/**Creates a write generator that uses the supplied serializer setup.*/
|
/** Creates a write generator that uses the supplied serializer setup. */
|
||||||
public RemoteWriteGenerator(HashMap<String, ClassSerializer> serializers) {
|
public RemoteWriteGenerator(HashMap<String, ClassSerializer> serializers){
|
||||||
this.serializers = serializers;
|
this.serializers = serializers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Generates all classes in this list.*/
|
/** Generates all classes in this list. */
|
||||||
public void generateFor(List<ClassEntry> entries, String packageName) throws IOException {
|
public void generateFor(List<ClassEntry> entries, String packageName) throws IOException{
|
||||||
|
|
||||||
for(ClassEntry entry : entries){
|
for(ClassEntry entry : entries){
|
||||||
//create builder
|
//create builder
|
||||||
@@ -58,7 +58,7 @@ public class RemoteWriteGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Creates a specific variant for a method entry.*/
|
/** Creates a specific variant for a method entry. */
|
||||||
private void writeMethodVariant(TypeSpec.Builder classBuilder, MethodEntry methodEntry, boolean toAll, boolean forwarded){
|
private void writeMethodVariant(TypeSpec.Builder classBuilder, MethodEntry methodEntry, boolean toAll, boolean forwarded){
|
||||||
ExecutableElement elem = methodEntry.element;
|
ExecutableElement elem = methodEntry.element;
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ public class RemoteWriteGenerator {
|
|||||||
if(!forwarded && methodEntry.local != Loc.none){
|
if(!forwarded && methodEntry.local != Loc.none){
|
||||||
//add in local checks
|
//add in local checks
|
||||||
if(methodEntry.local != Loc.both){
|
if(methodEntry.local != Loc.both){
|
||||||
method.beginControlFlow("if("+getCheckString(methodEntry.local) + " || !io.anuke.mindustry.net.Net.active())");
|
method.beginControlFlow("if(" + getCheckString(methodEntry.local) + " || !io.anuke.mindustry.net.Net.active())");
|
||||||
}
|
}
|
||||||
|
|
||||||
//concatenate parameters
|
//concatenate parameters
|
||||||
@@ -109,16 +109,16 @@ public class RemoteWriteGenerator {
|
|||||||
//special case: calling local-only methods uses the local player
|
//special case: calling local-only methods uses the local player
|
||||||
if(index == 0 && methodEntry.where == Loc.client){
|
if(index == 0 && methodEntry.where == Loc.client){
|
||||||
results.append("io.anuke.mindustry.Vars.players[0]");
|
results.append("io.anuke.mindustry.Vars.players[0]");
|
||||||
}else {
|
}else{
|
||||||
results.append(var.getSimpleName());
|
results.append(var.getSimpleName());
|
||||||
}
|
}
|
||||||
if(index != elem.getParameters().size() - 1) results.append(", ");
|
if(index != elem.getParameters().size() - 1) results.append(", ");
|
||||||
index ++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//add the statement to call it
|
//add the statement to call it
|
||||||
method.addStatement("$N." + elem.getSimpleName() + "(" + results.toString() + ")",
|
method.addStatement("$N." + elem.getSimpleName() + "(" + results.toString() + ")",
|
||||||
((TypeElement)elem.getEnclosingElement()).getQualifiedName().toString());
|
((TypeElement) elem.getEnclosingElement()).getQualifiedName().toString());
|
||||||
|
|
||||||
if(methodEntry.local != Loc.both){
|
if(methodEntry.local != Loc.both){
|
||||||
method.endControlFlow();
|
method.endControlFlow();
|
||||||
@@ -126,10 +126,10 @@ public class RemoteWriteGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//start control flow to check if it's actually client/server so no netcode is called
|
//start control flow to check if it's actually client/server so no netcode is called
|
||||||
method.beginControlFlow("if("+getCheckString(methodEntry.where)+")");
|
method.beginControlFlow("if(" + getCheckString(methodEntry.where) + ")");
|
||||||
|
|
||||||
//add statement to create packet from pool
|
//add statement to create packet from pool
|
||||||
method.addStatement("$1N packet = $2N.obtain($1N.class)", "io.anuke.mindustry.net.Packets.InvokePacket", "com.badlogic.gdx.utils.Pools");
|
method.addStatement("$1N packet = $2N.obtain($1N.class, $1N::new)", "io.anuke.mindustry.net.Packets.InvokePacket", "io.anuke.ucore.util.Pooling");
|
||||||
//assign buffer
|
//assign buffer
|
||||||
method.addStatement("packet.writeBuffer = TEMP_BUFFER");
|
method.addStatement("packet.writeBuffer = TEMP_BUFFER");
|
||||||
//assign priority
|
//assign priority
|
||||||
@@ -139,7 +139,7 @@ public class RemoteWriteGenerator {
|
|||||||
//rewind buffer
|
//rewind buffer
|
||||||
method.addStatement("TEMP_BUFFER.position(0)");
|
method.addStatement("TEMP_BUFFER.position(0)");
|
||||||
|
|
||||||
for(int i = 0; i < elem.getParameters().size(); i ++){
|
for(int i = 0; i < elem.getParameters().size(); i++){
|
||||||
//first argument is skipped as it is always the player caller
|
//first argument is skipped as it is always the player caller
|
||||||
if((!methodEntry.where.isServer/* || methodEntry.mode == Loc.both*/) && i == 0){
|
if((!methodEntry.where.isServer/* || methodEntry.mode == Loc.both*/) && i == 0){
|
||||||
continue;
|
continue;
|
||||||
@@ -164,7 +164,7 @@ public class RemoteWriteGenerator {
|
|||||||
method.beginControlFlow("if(io.anuke.mindustry.net.Net.server())");
|
method.beginControlFlow("if(io.anuke.mindustry.net.Net.server())");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Utils.isPrimitive(typeName)) { //check if it's a primitive, and if so write it
|
if(Utils.isPrimitive(typeName)){ //check if it's a primitive, and if so write it
|
||||||
if(typeName.equals("boolean")){ //booleans are special
|
if(typeName.equals("boolean")){ //booleans are special
|
||||||
method.addStatement("TEMP_BUFFER.put(" + varName + " ? (byte)1 : 0)");
|
method.addStatement("TEMP_BUFFER.put(" + varName + " ? (byte)1 : 0)");
|
||||||
}else{
|
}else{
|
||||||
@@ -181,7 +181,7 @@ public class RemoteWriteGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//add statement for writing it
|
//add statement for writing it
|
||||||
method.addStatement(ser.writeMethod + "(TEMP_BUFFER, " + varName +")");
|
method.addStatement(ser.writeMethod + "(TEMP_BUFFER, " + varName + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(writePlayerSkipCheck){ //write end check
|
if(writePlayerSkipCheck){ //write end check
|
||||||
@@ -197,7 +197,7 @@ public class RemoteWriteGenerator {
|
|||||||
if(forwarded){ //forward packet
|
if(forwarded){ //forward packet
|
||||||
if(!methodEntry.local.isClient){ //if the client doesn't get it called locally, forward it back after validation
|
if(!methodEntry.local.isClient){ //if the client doesn't get it called locally, forward it back after validation
|
||||||
sendString = "send(";
|
sendString = "send(";
|
||||||
}else {
|
}else{
|
||||||
sendString = "sendExcept(exceptSenderID, ";
|
sendString = "sendExcept(exceptSenderID, ";
|
||||||
}
|
}
|
||||||
}else if(toAll){ //send to all players / to server
|
}else if(toAll){ //send to all players / to server
|
||||||
@@ -207,8 +207,8 @@ public class RemoteWriteGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//send the actual packet
|
//send the actual packet
|
||||||
method.addStatement("io.anuke.mindustry.net.Net." + sendString + "packet, "+
|
method.addStatement("io.anuke.mindustry.net.Net." + sendString + "packet, " +
|
||||||
(methodEntry.unreliable ? "io.anuke.mindustry.net.Net.SendMode.udp" : "io.anuke.mindustry.net.Net.SendMode.tcp")+")");
|
(methodEntry.unreliable ? "io.anuke.mindustry.net.Net.SendMode.udp" : "io.anuke.mindustry.net.Net.SendMode.tcp") + ")");
|
||||||
|
|
||||||
|
|
||||||
//end check for server/client
|
//end check for server/client
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
package io.anuke.annotations;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.*;
|
||||||
|
import io.anuke.annotations.Annotations.Serialize;
|
||||||
|
|
||||||
|
import javax.annotation.processing.*;
|
||||||
|
import javax.lang.model.SourceVersion;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
import javax.lang.model.element.TypeElement;
|
||||||
|
import javax.lang.model.element.VariableElement;
|
||||||
|
import javax.lang.model.util.ElementFilter;
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.DataOutput;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
||||||
|
@SupportedAnnotationTypes({
|
||||||
|
"io.anuke.annotations.Annotations.Serialize"
|
||||||
|
})
|
||||||
|
public class SerializeAnnotationProcessor extends AbstractProcessor{
|
||||||
|
/**Target class name.*/
|
||||||
|
private static final String className = "Serialization";
|
||||||
|
/** Name of the base package to put all the generated classes. */
|
||||||
|
private static final String packageName = "io.anuke.mindustry.gen";
|
||||||
|
|
||||||
|
private int round;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void init(ProcessingEnvironment processingEnv){
|
||||||
|
super.init(processingEnv);
|
||||||
|
//put all relevant utils into utils class
|
||||||
|
Utils.typeUtils = processingEnv.getTypeUtils();
|
||||||
|
Utils.elementUtils = processingEnv.getElementUtils();
|
||||||
|
Utils.filer = processingEnv.getFiler();
|
||||||
|
Utils.messager = processingEnv.getMessager();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
|
||||||
|
if(round++ != 0) return false; //only process 1 round
|
||||||
|
|
||||||
|
try{
|
||||||
|
Set<TypeElement> elements = ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(Serialize.class));
|
||||||
|
|
||||||
|
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC);
|
||||||
|
MethodSpec.Builder method = MethodSpec.methodBuilder("init").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
||||||
|
|
||||||
|
for(TypeElement elem : elements){
|
||||||
|
TypeName type = TypeName.get(elem.asType());
|
||||||
|
|
||||||
|
TypeSpec.Builder serializer = TypeSpec.anonymousClassBuilder("")
|
||||||
|
.addSuperinterface(ParameterizedTypeName.get(
|
||||||
|
ClassName.get(Class.forName("io.anuke.ucore.io.TypeSerializer")), type));
|
||||||
|
|
||||||
|
MethodSpec.Builder writeMethod = MethodSpec.methodBuilder("write")
|
||||||
|
.returns(void.class)
|
||||||
|
.addParameter(DataOutput.class, "stream")
|
||||||
|
.addParameter(type, "object")
|
||||||
|
.addAnnotation(Override.class)
|
||||||
|
.addException(IOException.class)
|
||||||
|
.addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
|
MethodSpec.Builder readMethod = MethodSpec.methodBuilder("read")
|
||||||
|
.returns(type)
|
||||||
|
.addParameter(DataInput.class, "stream")
|
||||||
|
.addAnnotation(Override.class)
|
||||||
|
.addException(IOException.class)
|
||||||
|
.addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
|
readMethod.addStatement("$L object = new $L()", type, type);
|
||||||
|
|
||||||
|
List<VariableElement> fields = ElementFilter.fieldsIn(Utils.elementUtils.getAllMembers(elem));
|
||||||
|
for(VariableElement field : fields){
|
||||||
|
if(field.getModifiers().contains(Modifier.STATIC) || field.getModifiers().contains(Modifier.TRANSIENT) || field.getModifiers().contains(Modifier.PRIVATE)) continue;
|
||||||
|
|
||||||
|
String name = field.getSimpleName().toString();
|
||||||
|
String typeName = Utils.typeUtils.erasure(field.asType()).toString().replace('$', '.');
|
||||||
|
String capName = Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
|
||||||
|
|
||||||
|
if(field.asType().getKind().isPrimitive()){
|
||||||
|
writeMethod.addStatement("stream.write" + capName + "(object." + name + ")");
|
||||||
|
readMethod.addStatement("object." + name + "= stream.read" + capName + "()");
|
||||||
|
}else{
|
||||||
|
writeMethod.addStatement("io.anuke.ucore.core.Settings.getSerializer(" + typeName+ ".class).write(stream, object." + name + ")");
|
||||||
|
readMethod.addStatement("object." + name + " = (" +typeName+")io.anuke.ucore.core.Settings.getSerializer(" + typeName+ ".class).read(stream)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readMethod.addStatement("return object");
|
||||||
|
|
||||||
|
serializer.addMethod(writeMethod.build());
|
||||||
|
serializer.addMethod(readMethod.build());
|
||||||
|
|
||||||
|
method.addStatement("io.anuke.ucore.core.Settings.setSerializer($N, $L)", Utils.elementUtils.getBinaryName(elem).toString().replace('$', '.') + ".class", serializer.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
classBuilder.addMethod(method.build());
|
||||||
|
|
||||||
|
//write result
|
||||||
|
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(Utils.filer);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}catch(Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,14 +7,14 @@ import javax.lang.model.element.TypeElement;
|
|||||||
import javax.lang.model.util.Elements;
|
import javax.lang.model.util.Elements;
|
||||||
import javax.lang.model.util.Types;
|
import javax.lang.model.util.Types;
|
||||||
|
|
||||||
public class Utils {
|
public class Utils{
|
||||||
public static Types typeUtils;
|
public static Types typeUtils;
|
||||||
public static Elements elementUtils;
|
public static Elements elementUtils;
|
||||||
public static Filer filer;
|
public static Filer filer;
|
||||||
public static Messager messager;
|
public static Messager messager;
|
||||||
|
|
||||||
public static String getMethodName(Element element){
|
public static String getMethodName(Element element){
|
||||||
return ((TypeElement)element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName();
|
return ((TypeElement) element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isPrimitive(String type){
|
public static boolean isPrimitive(String type){
|
||||||
|
|||||||
110
build.gradle
@@ -9,7 +9,7 @@ buildscript {
|
|||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.0'
|
classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.0'
|
||||||
classpath 'de.richsource.gradle.plugins:gwt-gradle-plugin:0.6'
|
classpath 'de.richsource.gradle.plugins:gwt-gradle-plugin:0.6'
|
||||||
classpath 'com.android.tools.build:gradle:3.1.0'
|
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||||
classpath "com.badlogicgames.gdx:gdx-tools:1.9.8"
|
classpath "com.badlogicgames.gdx:gdx-tools:1.9.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -22,12 +22,12 @@ allprojects {
|
|||||||
|
|
||||||
ext {
|
ext {
|
||||||
versionNumber = '4.0'
|
versionNumber = '4.0'
|
||||||
versionType = 'alpha'
|
versionModifier = 'alpha'
|
||||||
|
versionType = 'official'
|
||||||
appName = 'Mindustry'
|
appName = 'Mindustry'
|
||||||
gdxVersion = '1.9.8'
|
gdxVersion = '1.9.8'
|
||||||
roboVMVersion = '2.3.0'
|
roboVMVersion = '2.3.0'
|
||||||
aiVersion = '1.8.1'
|
uCoreVersion = 'd5f892dcf1773b0f6d47d2190d139cc6342ac75f'
|
||||||
uCoreVersion = 'e7a37cff68'
|
|
||||||
|
|
||||||
getVersionString = {
|
getVersionString = {
|
||||||
String buildVersion = getBuildVersion()
|
String buildVersion = getBuildVersion()
|
||||||
@@ -43,24 +43,34 @@ allprojects {
|
|||||||
return project.ext.mainClassName.substring(0, project.ext.mainClassName.indexOf("desktop") - 1)
|
return project.ext.mainClassName.substring(0, project.ext.mainClassName.indexOf("desktop") - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generateLocales = {
|
||||||
|
def output = 'en\n'
|
||||||
|
def bundles = new File(project(':core').projectDir, 'assets/bundles/')
|
||||||
|
bundles.listFiles().each { other ->
|
||||||
|
if(other.name == "bundle.properties") return
|
||||||
|
output += other.name.substring("bundle".length() + 1, other.name.lastIndexOf('.')) + "\n"
|
||||||
|
}
|
||||||
|
new File(project(':core').projectDir, 'assets/locales').text = output
|
||||||
|
}
|
||||||
|
|
||||||
writeVersion = {
|
writeVersion = {
|
||||||
def pfile = new File('core/assets/version.properties')
|
def pfile = new File(project(':core').projectDir, 'assets/version.properties')
|
||||||
def props = new Properties()
|
def props = new Properties()
|
||||||
|
|
||||||
try{
|
try{
|
||||||
pfile.createNewFile()
|
pfile.createNewFile()
|
||||||
}catch (Exception e){}
|
}catch (Exception ignored){}
|
||||||
|
|
||||||
if(pfile.exists()) {
|
if(pfile.exists()) {
|
||||||
|
|
||||||
props.load(new FileInputStream(pfile))
|
props.load(new FileInputStream(pfile))
|
||||||
|
|
||||||
String code = getBuildVersion()
|
String buildid = getBuildVersion()
|
||||||
|
|
||||||
props["name"] = appName
|
props["type"] = versionType
|
||||||
props["version"] = versionType
|
props["number"] = versionNumber
|
||||||
props["code"] = versionNumber
|
props["modifier"] = versionModifier
|
||||||
props["build"] = code
|
props["build"] = buildid
|
||||||
|
|
||||||
props.store(pfile.newWriter(), "Autogenerated file. Do not modify.")
|
props.store(pfile.newWriter(), "Autogenerated file. Do not modify.")
|
||||||
}
|
}
|
||||||
@@ -82,11 +92,12 @@ project(":desktop") {
|
|||||||
dependencies {
|
dependencies {
|
||||||
compile project(":core")
|
compile project(":core")
|
||||||
compile project(":kryonet")
|
compile project(":kryonet")
|
||||||
|
if(new File(projectDir.parent, '../debug').exists() && System.properties["release"] == null) compile project(":debug")
|
||||||
|
|
||||||
compile "com.badlogicgames.gdx:gdx-backend-lwjgl3:$gdxVersion"
|
compile "com.badlogicgames.gdx:gdx-backend-lwjgl3:$gdxVersion"
|
||||||
compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
|
compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
|
||||||
compile "com.badlogicgames.gdx:gdx-controllers-lwjgl3:$gdxVersion"
|
compile "com.badlogicgames.gdx:gdx-controllers-lwjgl3:$gdxVersion"
|
||||||
compile 'com.github.MinnDevelopment:java-discord-rpc:v2.0.0'
|
compile 'com.github.MinnDevelopment:java-discord-rpc:v2.0.0'
|
||||||
compile 'com.yuvimasory:orange-extensions:1.3.0'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +105,6 @@ project(":html") {
|
|||||||
apply plugin: "gwt"
|
apply plugin: "gwt"
|
||||||
apply plugin: "war"
|
apply plugin: "war"
|
||||||
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(":core")
|
compile project(":core")
|
||||||
compileOnly project(":annotations")
|
compileOnly project(":annotations")
|
||||||
@@ -102,24 +112,34 @@ project(":html") {
|
|||||||
compile "com.badlogicgames.gdx:gdx-backend-gwt:$gdxVersion"
|
compile "com.badlogicgames.gdx:gdx-backend-gwt:$gdxVersion"
|
||||||
compile "com.badlogicgames.gdx:gdx:$gdxVersion:sources"
|
compile "com.badlogicgames.gdx:gdx:$gdxVersion:sources"
|
||||||
compile "com.badlogicgames.gdx:gdx-backend-gwt:$gdxVersion:sources"
|
compile "com.badlogicgames.gdx:gdx-backend-gwt:$gdxVersion:sources"
|
||||||
compile "com.badlogicgames.gdx:gdx-ai:$aiVersion:sources"
|
|
||||||
|
|
||||||
compile "com.badlogicgames.gdx:gdx-controllers:$gdxVersion:sources"
|
compile "com.badlogicgames.gdx:gdx-controllers:$gdxVersion:sources"
|
||||||
compile "com.badlogicgames.gdx:gdx-controllers-gwt:$gdxVersion"
|
compile "com.badlogicgames.gdx:gdx-controllers-gwt:$gdxVersion"
|
||||||
compile "com.badlogicgames.gdx:gdx-controllers-gwt:$gdxVersion:sources"
|
compile "com.badlogicgames.gdx:gdx-controllers-gwt:$gdxVersion:sources"
|
||||||
compile "com.sksamuel.gwt:gwt-websockets:1.0.4"
|
|
||||||
compile "com.sksamuel.gwt:gwt-websockets:1.0.4:sources"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compileJava.options.compilerArgs = [
|
|
||||||
"-processor", "io.anuke.annotations.RemoteMethodAnnotationProcessor"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
project(":ios") {
|
project(":ios") {
|
||||||
apply plugin: "java"
|
apply plugin: "java"
|
||||||
apply plugin: "robovm"
|
apply plugin: "robovm"
|
||||||
|
|
||||||
|
task copyGen{
|
||||||
|
copy{
|
||||||
|
from ("core/build/classes/java/main/io/anuke/mindustry/gen/"){
|
||||||
|
include "**/*.java"
|
||||||
|
}
|
||||||
|
|
||||||
|
into "ios/src/io/anuke/mindustry/gen"
|
||||||
|
}
|
||||||
|
|
||||||
|
doFirst{
|
||||||
|
delete{
|
||||||
|
delete "ios/src/io/anuke/mindustry/gen/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
build.dependsOn(copyGen)
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(":core")
|
compile project(":core")
|
||||||
@@ -135,16 +155,16 @@ project(":ios") {
|
|||||||
project(":core") {
|
project(":core") {
|
||||||
apply plugin: "java"
|
apply plugin: "java"
|
||||||
|
|
||||||
|
task finish {
|
||||||
|
generateLocales()
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly project(":annotations")
|
compileOnly project(":annotations")
|
||||||
|
build.finalizedBy(finish)
|
||||||
|
|
||||||
boolean comp = System.properties["release"] == null || System.properties["release"] == "false"
|
def comp = System.properties["release"] == null || System.properties["release"] == "false"
|
||||||
|
if(!comp) println("Note: Compiling release build.")
|
||||||
if(!comp){
|
|
||||||
println("NOTICE: Compiling release build.")
|
|
||||||
}else{
|
|
||||||
println("Compiling DEBUG build.")
|
|
||||||
}
|
|
||||||
|
|
||||||
if(new File(projectDir.parent, '../uCore').exists() && comp){
|
if(new File(projectDir.parent, '../uCore').exists() && comp){
|
||||||
compile project(":uCore")
|
compile project(":uCore")
|
||||||
@@ -161,13 +181,19 @@ project(":core") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileJava.options.compilerArgs = [
|
compileJava.options.compilerArgs = [
|
||||||
"-processor", "io.anuke.annotations.RemoteMethodAnnotationProcessor"
|
"-processor", "io.anuke.annotations.RemoteMethodAnnotationProcessor,io.anuke.annotations.SerializeAnnotationProcessor"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
project(":server") {
|
project(":server") {
|
||||||
apply plugin: "java"
|
apply plugin: "java"
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
if(findProject(":android") != null){
|
||||||
|
compile.exclude module: android
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly project(":annotations")
|
compileOnly project(":annotations")
|
||||||
|
|
||||||
@@ -178,7 +204,24 @@ project(":server") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
project(":packer") {
|
project(":tests"){
|
||||||
|
apply plugin: "java"
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testImplementation project(":core")
|
||||||
|
testImplementation('org.junit.jupiter:junit-jupiter-api:5.1.0')
|
||||||
|
testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.1.0')
|
||||||
|
testImplementation "com.badlogicgames.gdx:gdx-backend-headless:$gdxVersion"
|
||||||
|
testImplementation "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
workingDir = new File("../core/assets")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project(":tools") {
|
||||||
apply plugin: "java"
|
apply plugin: "java"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -199,11 +242,8 @@ project(":kryonet") {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(":core")
|
compile project(":core")
|
||||||
compile 'com.github.crykn:kryonet:2.22.1'
|
compile "org.lz4:lz4-java:1.4.1"
|
||||||
compile "org.java-websocket:Java-WebSocket:1.3.7"
|
compile 'com.github.Anuken:kryonet:53b10247b1'
|
||||||
|
compile 'com.github.Anuken:WaifUPnP:05eb46bc577fd7674596946ba288c96c0cedd893'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.eclipse.doLast {
|
|
||||||
delete ".project"
|
|
||||||
}
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 59 KiB |
BIN
core/assets-raw/sprites/blocks/defense/force-projector-top.png
Normal file
|
After Width: | Height: | Size: 121 B |
BIN
core/assets-raw/sprites/blocks/defense/force-projector.png
Normal file
|
After Width: | Height: | Size: 312 B |
BIN
core/assets-raw/sprites/blocks/defense/mend-projector-top.png
Normal file
|
After Width: | Height: | Size: 111 B |
BIN
core/assets-raw/sprites/blocks/defense/mend-projector.png
Normal file
|
After Width: | Height: | Size: 217 B |
|
After Width: | Height: | Size: 111 B |
BIN
core/assets-raw/sprites/blocks/defense/overdrive-projector.png
Normal file
|
After Width: | Height: | Size: 215 B |
BIN
core/assets-raw/sprites/blocks/defense/shock-mine.png
Normal file
|
After Width: | Height: | Size: 123 B |
|
Before Width: | Height: | Size: 160 B After Width: | Height: | Size: 83 B |
|
Before Width: | Height: | Size: 177 B After Width: | Height: | Size: 93 B |
|
Before Width: | Height: | Size: 178 B After Width: | Height: | Size: 95 B |
|
Before Width: | Height: | Size: 227 B After Width: | Height: | Size: 119 B |
|
Before Width: | Height: | Size: 197 B |
|
After Width: | Height: | Size: 98 B |
|
After Width: | Height: | Size: 98 B |
|
After Width: | Height: | Size: 98 B |
|
After Width: | Height: | Size: 97 B |
|
After Width: | Height: | Size: 116 B |
|
After Width: | Height: | Size: 117 B |
|
After Width: | Height: | Size: 119 B |
|
After Width: | Height: | Size: 117 B |
|
After Width: | Height: | Size: 113 B |
|
After Width: | Height: | Size: 108 B |
|
After Width: | Height: | Size: 104 B |
|
After Width: | Height: | Size: 106 B |
|
After Width: | Height: | Size: 109 B |
|
After Width: | Height: | Size: 107 B |
|
After Width: | Height: | Size: 110 B |
|
After Width: | Height: | Size: 110 B |
|
After Width: | Height: | Size: 109 B |
|
After Width: | Height: | Size: 108 B |
|
After Width: | Height: | Size: 105 B |
|
After Width: | Height: | Size: 109 B |
|
After Width: | Height: | Size: 105 B |
|
After Width: | Height: | Size: 105 B |
|
After Width: | Height: | Size: 105 B |
|
After Width: | Height: | Size: 103 B |
|
After Width: | Height: | Size: 127 B |
|
After Width: | Height: | Size: 127 B |
|
After Width: | Height: | Size: 133 B |
|
After Width: | Height: | Size: 129 B |
|
After Width: | Height: | Size: 120 B |
|
After Width: | Height: | Size: 114 B |
|
After Width: | Height: | Size: 110 B |
|
After Width: | Height: | Size: 113 B |
|
After Width: | Height: | Size: 108 B |
|
After Width: | Height: | Size: 107 B |
|
After Width: | Height: | Size: 110 B |
|
After Width: | Height: | Size: 110 B |
|
After Width: | Height: | Size: 111 B |
|
After Width: | Height: | Size: 111 B |
|
After Width: | Height: | Size: 110 B |
|
After Width: | Height: | Size: 113 B |
BIN
core/assets-raw/sprites/blocks/distribution/distributor.png
Normal file
|
After Width: | Height: | Size: 163 B |
|
Before Width: | Height: | Size: 257 B After Width: | Height: | Size: 115 B |
|
Before Width: | Height: | Size: 682 B After Width: | Height: | Size: 782 B |
|
Before Width: | Height: | Size: 580 B After Width: | Height: | Size: 273 B |
|
Before Width: | Height: | Size: 296 B |
|
Before Width: | Height: | Size: 233 B After Width: | Height: | Size: 114 B |
|
Before Width: | Height: | Size: 179 B After Width: | Height: | Size: 124 B |
|
Before Width: | Height: | Size: 189 B After Width: | Height: | Size: 139 B |
|
Before Width: | Height: | Size: 172 B After Width: | Height: | Size: 120 B |
|
Before Width: | Height: | Size: 301 B After Width: | Height: | Size: 199 B |
|
Before Width: | Height: | Size: 226 B After Width: | Height: | Size: 113 B |
|
Before Width: | Height: | Size: 248 B After Width: | Height: | Size: 110 B |
|
Before Width: | Height: | Size: 234 B |
|
Before Width: | Height: | Size: 210 B |
|
Before Width: | Height: | Size: 346 B After Width: | Height: | Size: 216 B |
|
Before Width: | Height: | Size: 492 B After Width: | Height: | Size: 271 B |
|
Before Width: | Height: | Size: 219 B After Width: | Height: | Size: 119 B |
|
Before Width: | Height: | Size: 298 B After Width: | Height: | Size: 168 B |
|
Before Width: | Height: | Size: 289 B After Width: | Height: | Size: 155 B |
|
Before Width: | Height: | Size: 574 B After Width: | Height: | Size: 294 B |
|
Before Width: | Height: | Size: 174 B |
|
Before Width: | Height: | Size: 196 B |
|
Before Width: | Height: | Size: 233 B |