Compare commits
1992 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23c56974b2 | ||
|
|
a5ce57e56d | ||
|
|
7e2b3a6e2d | ||
|
|
234649bd68 | ||
|
|
d655f95b67 | ||
|
|
a3abad34e3 | ||
|
|
903a2c069e | ||
|
|
306a660e87 | ||
|
|
e624c42026 | ||
|
|
76ed066a95 | ||
|
|
24baa77c47 | ||
|
|
b06a9cbf16 | ||
|
|
c53bb52d94 | ||
|
|
f609ee77a4 | ||
|
|
d1b5b7eb3c | ||
|
|
2e8d6b56df | ||
|
|
b3d7515dcd | ||
|
|
1327a2bef4 | ||
|
|
757e0fbda0 | ||
|
|
b603409f74 | ||
|
|
50816deb9e | ||
|
|
d6447cb31a | ||
|
|
8901838c19 | ||
|
|
5c63ff889a | ||
|
|
3f1ed6d4a4 | ||
|
|
bbb9b3ef62 | ||
|
|
0e78751c6c | ||
|
|
7ce93c7f85 | ||
|
|
be229f441e | ||
|
|
30c45e6a43 | ||
|
|
f3921e3dcc | ||
|
|
48391219fd | ||
|
|
27e9b5aeb9 | ||
|
|
bab43859f5 | ||
|
|
1fd98fe07c | ||
|
|
4d6c8ade98 | ||
|
|
8234f31e83 | ||
|
|
e5ff429241 | ||
|
|
b58b6c7361 | ||
|
|
640a45ea66 | ||
|
|
5ce8e6339d | ||
|
|
fa9611e28c | ||
|
|
b5b75656d1 | ||
|
|
197b67f8c1 | ||
|
|
c95f0674b6 | ||
|
|
1c6fed8df8 | ||
|
|
3feb9e76f0 | ||
|
|
3d8fb1b6ca | ||
|
|
83d9bd7d81 | ||
|
|
5373011058 | ||
|
|
c0ca134c5d | ||
|
|
007a0da40a | ||
|
|
e6eb847d81 | ||
|
|
7c1d035977 | ||
|
|
260a6bac6d | ||
|
|
74cefb3ec9 | ||
|
|
88e3022db0 | ||
|
|
0e61d61dd2 | ||
|
|
aec4a07aec | ||
|
|
55b6abffd1 | ||
|
|
3e2fcfa30f | ||
|
|
3b5d6860d6 | ||
|
|
2260e6824c | ||
|
|
c5cb2d8683 | ||
|
|
5259969384 | ||
|
|
c03e3f56aa | ||
|
|
6787bbdc05 | ||
|
|
d9a067b4d2 | ||
|
|
ac88d84322 | ||
|
|
ef617b7fd2 | ||
|
|
905f1608de | ||
|
|
fdca6771fb | ||
|
|
66038b77c4 | ||
|
|
27565cfe1c | ||
|
|
b66c29e12c | ||
|
|
1f41a2e8c0 | ||
|
|
1439f9d14b | ||
|
|
b6912254c4 | ||
|
|
1b5a338e1e | ||
|
|
fe76490418 | ||
|
|
29b31daba7 | ||
|
|
15bb01fd22 | ||
|
|
93d1904978 | ||
|
|
010a1594fa | ||
|
|
1d191f1914 | ||
|
|
7b18389d45 | ||
|
|
7f874f87c4 | ||
|
|
27d9f965be | ||
|
|
0a3193f1d6 | ||
|
|
2a995efa2a | ||
|
|
f5fa737867 | ||
|
|
8a6b5668fa | ||
|
|
cbce04f70f | ||
|
|
e5674b1b1e | ||
|
|
50a94af0d1 | ||
|
|
9bdf27fe3e | ||
|
|
e267519c6d | ||
|
|
e4078b1c2f | ||
|
|
f87bd78674 | ||
|
|
c483ae2c23 | ||
|
|
09e34da880 | ||
|
|
9fb570f965 | ||
|
|
ad7692b110 | ||
|
|
ec447fa2c0 | ||
|
|
bc74208c8c | ||
|
|
631b0a7761 | ||
|
|
f447aeff3e | ||
|
|
12f1ee9537 | ||
|
|
68f00a8983 | ||
|
|
d77830ebf0 | ||
|
|
739c4f2de2 | ||
|
|
3127bb54b2 | ||
|
|
ee2b099799 | ||
|
|
be962d6e2e | ||
|
|
c7522ff89f | ||
|
|
af47e7662f | ||
|
|
ba1363895e | ||
|
|
07305aecf4 | ||
|
|
90247e3b27 | ||
|
|
686d922119 | ||
|
|
90aed50ca8 | ||
|
|
13a2319416 | ||
|
|
a6ee946024 | ||
|
|
d4166c4f1f | ||
|
|
ed02eadb76 | ||
|
|
c0c2d2da35 | ||
|
|
eac99d30f9 | ||
|
|
439c9c5599 | ||
|
|
0cc3bcb121 | ||
|
|
b3e7b9e65b | ||
|
|
6f6e9f4cc2 | ||
|
|
6de1920042 | ||
|
|
c1cc11c7cb | ||
|
|
f1772418f2 | ||
|
|
8e17571824 | ||
|
|
6e3162aec2 | ||
|
|
c9b37419c7 | ||
|
|
b1e39b1bcb | ||
|
|
899b2f6aac | ||
|
|
540a5f30cb | ||
|
|
f2cc56ddc8 | ||
|
|
e41b17543f | ||
|
|
d40cff0741 | ||
|
|
02a9e2cd57 | ||
|
|
1f543f6c18 | ||
|
|
d1094492bd | ||
|
|
7f1fdf035e | ||
|
|
44b0ef408f | ||
|
|
a575ad2d99 | ||
|
|
92aba83450 | ||
|
|
fba7f7592b | ||
|
|
3f0dd7264d | ||
|
|
b7ec90e7c0 | ||
|
|
89c007fcdb | ||
|
|
a5b27dc339 | ||
|
|
390367f253 | ||
|
|
7ea558a187 | ||
|
|
c3fbecf858 | ||
|
|
5ecfb7c51d | ||
|
|
bac8c20b0b | ||
|
|
480a9e38b4 | ||
|
|
97fc46cffe | ||
|
|
6a7d2303a4 | ||
|
|
5bf7401139 | ||
|
|
8a36b3e590 | ||
|
|
1c12740006 | ||
|
|
fa9deece91 | ||
|
|
0b6ef1c57c | ||
|
|
9735e18acf | ||
|
|
20eb7bc05b | ||
|
|
be74e954fa | ||
|
|
cc45e063cd | ||
|
|
f8a3db6b99 | ||
|
|
1461673168 | ||
|
|
71b55317c1 | ||
|
|
bce85ded79 | ||
|
|
58182fe040 | ||
|
|
6a23439fce | ||
|
|
c191dd8855 | ||
|
|
898867db8f | ||
|
|
ea9ebe26a3 | ||
|
|
8143b8d80a | ||
|
|
51e4b10437 | ||
|
|
a98dc0b31f | ||
|
|
da360f54e9 | ||
|
|
7239c2cf08 | ||
|
|
9fc42dec6a | ||
|
|
7b2b9b3988 | ||
|
|
174e4b8632 | ||
|
|
91569596d8 | ||
|
|
de6cde6ddd | ||
|
|
77911385e1 | ||
|
|
b207d05d4b | ||
|
|
6b7debbba7 | ||
|
|
d902878f63 | ||
|
|
668120577d | ||
|
|
02263f1eb7 | ||
|
|
3d18b7f4e3 | ||
|
|
521b4fb4d7 | ||
|
|
02ccdd2d67 | ||
|
|
fefef3bc47 | ||
|
|
2f19cab144 | ||
|
|
5e6465e8f3 | ||
|
|
a92d143788 | ||
|
|
d9aa4eb9c9 | ||
|
|
399b24ed8b | ||
|
|
0c1594d659 | ||
|
|
cee0a09a88 | ||
|
|
4b0c977e73 | ||
|
|
c1258b75d5 | ||
|
|
dac24e8bf1 | ||
|
|
90b8910935 | ||
|
|
92764c8389 | ||
|
|
315693251d | ||
|
|
ac21c620fe | ||
|
|
b128155615 | ||
|
|
a76da8e488 | ||
|
|
29e0d4f2c2 | ||
|
|
9224120f5b | ||
|
|
c1cd27b9da | ||
|
|
5d1e96cf50 | ||
|
|
1e7f28f309 | ||
|
|
b23d35797b | ||
|
|
43f7bd1cdb | ||
|
|
526f1106fb | ||
|
|
467d995aed | ||
|
|
e49ebecffa | ||
|
|
3b85dc27d7 | ||
|
|
d6bf6de924 | ||
|
|
28d2243abc | ||
|
|
a17dfb820e | ||
|
|
48d1c2038e | ||
|
|
52489ef777 | ||
|
|
c946b42360 | ||
|
|
b9ff4ba9c5 | ||
|
|
b86cdb52be | ||
|
|
dac2264ac7 | ||
|
|
562c41c288 | ||
|
|
6d20e354b1 | ||
|
|
cee0ddce56 | ||
|
|
1237b14b7a | ||
|
|
3498a34c56 | ||
|
|
6e4cac413b | ||
|
|
5df2a3e625 | ||
|
|
7251fa4a03 | ||
|
|
b827176bc4 | ||
|
|
bbe6c5017a | ||
|
|
e9f72180e6 | ||
|
|
8fcab2d637 | ||
|
|
9470f1f99f | ||
|
|
e81385a8e6 | ||
|
|
819835fbc0 | ||
|
|
55d6a617e7 | ||
|
|
d8cd07127c | ||
|
|
361eb6a7e2 | ||
|
|
7ebe84cc0e | ||
|
|
b551af6bcf | ||
|
|
f31b1ed8d0 | ||
|
|
3d5236dfd3 | ||
|
|
26acf7cbbc | ||
|
|
e96fcb3cb7 | ||
|
|
4ed888bde5 | ||
|
|
a814b799e0 | ||
|
|
ca864655d1 | ||
|
|
4d83221c76 | ||
|
|
fffdd1ca86 | ||
|
|
9efdb0af5d | ||
|
|
65de36ab41 | ||
|
|
cb6fe97a87 | ||
|
|
55c1d8043e | ||
|
|
92d6c7fb3b | ||
|
|
b0fc855b57 | ||
|
|
82ba151d81 | ||
|
|
50631807dd | ||
|
|
4c83aba918 | ||
|
|
47f5127bf8 | ||
|
|
47e5895a18 | ||
|
|
1007667f9a | ||
|
|
065a8e712c | ||
|
|
88dba65593 | ||
|
|
ec2593f3d5 | ||
|
|
00f7f57c46 | ||
|
|
623e3924ed | ||
|
|
14ac712214 | ||
|
|
0638b1f951 | ||
|
|
0b407c7c1f | ||
|
|
0bd122c570 | ||
|
|
7e0391a8a0 | ||
|
|
69c04ea90d | ||
|
|
7ec6e64c18 | ||
|
|
7ecf5aa26d | ||
|
|
9a48028508 | ||
|
|
2701bd3de2 | ||
|
|
0fe8836db4 | ||
|
|
91c1c004c7 | ||
|
|
2bb2964790 | ||
|
|
8dd4e9feb0 | ||
|
|
01bd8d5148 | ||
|
|
8234eec7fc | ||
|
|
d9bfe88ddf | ||
|
|
2526224820 | ||
|
|
78e92b1027 | ||
|
|
0cc5945331 | ||
|
|
97aca84b26 | ||
|
|
98844d752c | ||
|
|
91e5fa5409 | ||
|
|
b57fb47855 | ||
|
|
891c449e6b | ||
|
|
53e1cf55c4 | ||
|
|
af3c88e606 | ||
|
|
75606baf6a | ||
|
|
fa8a6d001a | ||
|
|
67e32ce880 | ||
|
|
44a86ef2e7 | ||
|
|
ffb2d6eeaa | ||
|
|
0cac9f379e | ||
|
|
4a8a7a9d8f | ||
|
|
05b2b18f69 | ||
|
|
73dd7ba21a | ||
|
|
1d95980066 | ||
|
|
c2f71e5788 | ||
|
|
f361ac27e0 | ||
|
|
ebceee0a5c | ||
|
|
765aa15473 | ||
|
|
e1f0564d0b | ||
|
|
af6ed6ea89 | ||
|
|
1de3217738 | ||
|
|
54dcf06722 | ||
|
|
9ba98ed4b4 | ||
|
|
1249eb3b00 | ||
|
|
fb511a4eef | ||
|
|
a8c4e9f567 | ||
|
|
0aabe9bbe0 | ||
|
|
799fc6029d | ||
|
|
3dd814f0b8 | ||
|
|
5b727ac6fd | ||
|
|
1c17c38e15 | ||
|
|
5b6ab30eb9 | ||
|
|
925b1e3057 | ||
|
|
8810cf037e | ||
|
|
25e04ca3e5 | ||
|
|
188171ec03 | ||
|
|
d85f6c72eb | ||
|
|
2b96d30255 | ||
|
|
bb3c80c055 | ||
|
|
7e8326a3af | ||
|
|
75ada3cca1 | ||
|
|
4f7d6fc018 | ||
|
|
c560de9c53 | ||
|
|
c4e8fef8d0 | ||
|
|
6ab24ccefd | ||
|
|
ea8dccdfb2 | ||
|
|
b28e7de1db | ||
|
|
f00510a508 | ||
|
|
15572cdd7a | ||
|
|
eb4a2a2da1 | ||
|
|
73d9348c83 | ||
|
|
d828b280af | ||
|
|
4efba475de | ||
|
|
6dca449b08 | ||
|
|
1d5a25ce75 | ||
|
|
1b7159647e | ||
|
|
f4e666bce8 | ||
|
|
4dc90d4074 | ||
|
|
2042dafb73 | ||
|
|
cb4c916ed7 | ||
|
|
da19c5ae19 | ||
|
|
4008d88f0b | ||
|
|
0fc246cfdc | ||
|
|
ac46b77380 | ||
|
|
76e21fbd19 | ||
|
|
1988958c4a | ||
|
|
5e5aadc4ac | ||
|
|
3fbeb33390 | ||
|
|
d08f9bf819 | ||
|
|
dce253e146 | ||
|
|
8411cc16f1 | ||
|
|
51af6eeec9 | ||
|
|
090e0f35dc | ||
|
|
33fdea7b7d | ||
|
|
a12211587c | ||
|
|
44912c0fa9 | ||
|
|
ee0b946ea6 | ||
|
|
5040eacda7 | ||
|
|
ec99daaefb | ||
|
|
176e4a3bb9 | ||
|
|
ac3106728f | ||
|
|
5dc78a24e0 | ||
|
|
7482e2a988 | ||
|
|
f4a838df98 | ||
|
|
54d37b63b3 | ||
|
|
75eed2926a | ||
|
|
03b5bc9449 | ||
|
|
55903576b6 | ||
|
|
d9ea17baca | ||
|
|
b11908f509 | ||
|
|
0d4e75fc42 | ||
|
|
3038862af5 | ||
|
|
f60afc39f1 | ||
|
|
8dd4839f53 | ||
|
|
8b83360fe5 | ||
|
|
b268e8ca58 | ||
|
|
7ecd8b3169 | ||
|
|
2466267b1c | ||
|
|
49f6b9bb05 | ||
|
|
10cacf71ae | ||
|
|
1589b8a72b | ||
|
|
e78948e548 | ||
|
|
b1da2faa04 | ||
|
|
3966ff6817 | ||
|
|
b1bf96bfff | ||
|
|
f97d1eedee | ||
|
|
a7c0f9e73c | ||
|
|
8c3c671dcd | ||
|
|
a2df243387 | ||
|
|
ef757f4563 | ||
|
|
5d3f48d0eb | ||
|
|
b3977d43b0 | ||
|
|
5a4ba149cf | ||
|
|
d658367be7 | ||
|
|
bb3b4d4415 | ||
|
|
e4cdf20030 | ||
|
|
caf5d37d98 | ||
|
|
acfd18ab7b | ||
|
|
2510b09201 | ||
|
|
658079fab6 | ||
|
|
a4ddf90ef5 | ||
|
|
ff990925f0 | ||
|
|
b12c25bc0b | ||
|
|
40edbe785c | ||
|
|
5ad2807958 | ||
|
|
a297d11023 | ||
|
|
01e3599c7d | ||
|
|
06b08c80c2 | ||
|
|
f39609d1ef | ||
|
|
99fafc47f2 | ||
|
|
b46a8263ba | ||
|
|
c3a073fbbf | ||
|
|
bc8f02666a | ||
|
|
c9316bd9fa | ||
|
|
6e88a665a0 | ||
|
|
f0f4c77d4f | ||
|
|
7cb2b75802 | ||
|
|
66c0c9baa2 | ||
|
|
9bf3074aee | ||
|
|
1e7aaac3d4 | ||
|
|
e127df3aed | ||
|
|
418f598d26 | ||
|
|
5d266174af | ||
|
|
c34bf78ab6 | ||
|
|
f840b007ed | ||
|
|
b672d79dd7 | ||
|
|
8c310e38ff | ||
|
|
b8d1f66653 | ||
|
|
a0459191d6 | ||
|
|
6263c11ce5 | ||
|
|
d292f954a6 | ||
|
|
63ed322d62 | ||
|
|
8729410cd8 | ||
|
|
881929c569 | ||
|
|
31f89df5b9 | ||
|
|
749b9f5b30 | ||
|
|
7d2b7197d6 | ||
|
|
7f9e32a74c | ||
|
|
6236819f67 | ||
|
|
45aa43e62e | ||
|
|
4951f1f0b7 | ||
|
|
2765b8d47c | ||
|
|
81265500a5 | ||
|
|
3251dde4a8 | ||
|
|
7cc94057a1 | ||
|
|
be530abd4b | ||
|
|
c6826a6c7e | ||
|
|
101a4c2f65 | ||
|
|
d7ea50f2ad | ||
|
|
578d5b7a71 | ||
|
|
5c73168c4d | ||
|
|
6c6640f6c6 | ||
|
|
10f3fbf87b | ||
|
|
1100803af4 | ||
|
|
c21a0a2516 | ||
|
|
44e150638d | ||
|
|
8360d60ee8 | ||
|
|
3bf2e18e85 | ||
|
|
78fb3fc22f | ||
|
|
7f811403df | ||
|
|
95f7fc1b3b | ||
|
|
42d7eb4e05 | ||
|
|
8980275f0a | ||
|
|
8f8117e94b | ||
|
|
d6d2e88b71 | ||
|
|
86ef6dc9d7 | ||
|
|
c3881b57de | ||
|
|
ef381cb970 | ||
|
|
b180462c45 | ||
|
|
a0bdeb2649 | ||
|
|
20077738d2 | ||
|
|
38e55ab541 | ||
|
|
da4f042fa4 | ||
|
|
17f86c5f77 | ||
|
|
1f6c2df476 | ||
|
|
6be58ecb8d | ||
|
|
961e2a2490 | ||
|
|
1c8fd4cc38 | ||
|
|
43a0b6486a | ||
|
|
f1cf8b2849 | ||
|
|
7bf299bcc0 | ||
|
|
f41212b4d7 | ||
|
|
38a2ae0db2 | ||
|
|
07b5999b13 | ||
|
|
58c39e14d6 | ||
|
|
7c0080ee65 | ||
|
|
8db4f88ecc | ||
|
|
0372ec7c9f | ||
|
|
a48efd971c | ||
|
|
c1283b856b | ||
|
|
d6af9a6671 | ||
|
|
72fc103e16 | ||
|
|
69f6154894 | ||
|
|
91d54dfad3 | ||
|
|
8c495a3f57 | ||
|
|
3892cf2283 | ||
|
|
c93431ecc6 | ||
|
|
c8f3e26f44 | ||
|
|
565bac1e2b | ||
|
|
7e306d476d | ||
|
|
dc30ac4069 | ||
|
|
9e0bd49f04 | ||
|
|
fbc79d5d6f | ||
|
|
b9ff9b7ee4 | ||
|
|
1b17944901 | ||
|
|
701aa840b3 | ||
|
|
b4594b2274 | ||
|
|
a4a3f6f8c5 | ||
|
|
988da3b8e9 | ||
|
|
769fc93940 | ||
|
|
4157e3c74d | ||
|
|
916a00b6ff | ||
|
|
43ca3ca210 | ||
|
|
93371b1cd0 | ||
|
|
973d907218 | ||
|
|
efaba522cd | ||
|
|
2ef0e33227 | ||
|
|
5cfd784501 | ||
|
|
5c9e005397 | ||
|
|
6b52c64b6f | ||
|
|
30f2fd0b7e | ||
|
|
c9da9754ef | ||
|
|
69dae20275 | ||
|
|
07b3991fdf | ||
|
|
4ef0143928 | ||
|
|
7a2a436a52 | ||
|
|
6547a38567 | ||
|
|
c398b89284 | ||
|
|
9521af7be5 | ||
|
|
c2d6076407 | ||
|
|
a074010eb7 | ||
|
|
f9ed74c15a | ||
|
|
4dec69fca7 | ||
|
|
c772e1fcc6 | ||
|
|
f0acfb3cf3 | ||
|
|
870f06218b | ||
|
|
6b3039dba2 | ||
|
|
b291c09b73 | ||
|
|
521e3c773f | ||
|
|
60ce8ca935 | ||
|
|
d02268d347 | ||
|
|
54e5d6a302 | ||
|
|
1bb621bbd5 | ||
|
|
b2b6ddb5b2 | ||
|
|
660abe188b | ||
|
|
49a43a4308 | ||
|
|
208105f21d | ||
|
|
a193351bd7 | ||
|
|
e3f40cd968 | ||
|
|
0c54417a11 | ||
|
|
4e3226ee3d | ||
|
|
22ff8e2b9b | ||
|
|
df7285a1f5 | ||
|
|
6d55285b62 | ||
|
|
4c0062e967 | ||
|
|
67cd8ccae4 | ||
|
|
42a63daf00 | ||
|
|
3d26e461c2 | ||
|
|
49736a37c9 | ||
|
|
874aa6cf4a | ||
|
|
0f6629718d | ||
|
|
b9de9e5a0c | ||
|
|
61b99f04e9 | ||
|
|
fd89911dd4 | ||
|
|
6a5900d745 | ||
|
|
a6593e3572 | ||
|
|
c25853dc3e | ||
|
|
16873c6086 | ||
|
|
23e1d0998a | ||
|
|
6e08b67817 | ||
|
|
7a60339c5d | ||
|
|
7f6026bd52 | ||
|
|
e0f1242ca7 | ||
|
|
bd95d81b40 | ||
|
|
d5b71e2773 | ||
|
|
c21b02b1ec | ||
|
|
c1cd84593d | ||
|
|
85d67db1ed | ||
|
|
fe0d3cfe22 | ||
|
|
1661905d9b | ||
|
|
06f2330295 | ||
|
|
ca1e43d79c | ||
|
|
43676b68bf | ||
|
|
752cccb588 | ||
|
|
3eca6b770e | ||
|
|
a1a72ee713 | ||
|
|
9dc49743e8 | ||
|
|
fb08a3638b | ||
|
|
3d353b414c | ||
|
|
f9b6b8e5b7 | ||
|
|
da577a0db2 | ||
|
|
fbd55a341e | ||
|
|
064a0545a8 | ||
|
|
a33ac30a01 | ||
|
|
6d7d4bcba1 | ||
|
|
b541cfcc75 | ||
|
|
6c52812a0d | ||
|
|
360494af50 | ||
|
|
b48e6d0e2f | ||
|
|
83d334582b | ||
|
|
250d982d99 | ||
|
|
982b7f33bc | ||
|
|
103ebc009d | ||
|
|
a0ef83fb62 | ||
|
|
682bfcc8e8 | ||
|
|
d31a530d6e | ||
|
|
f5f495b9b8 | ||
|
|
dad5b186db | ||
|
|
430eef02e2 | ||
|
|
0555e4dfa7 | ||
|
|
6188250605 | ||
|
|
064172e1f1 | ||
|
|
0752076bf2 | ||
|
|
a8d5198ca6 | ||
|
|
9cb4645b11 | ||
|
|
b81de5ebe4 | ||
|
|
d7e432f730 | ||
|
|
2eb27d156d | ||
|
|
d1485e3e65 | ||
|
|
21170634bd | ||
|
|
baa9f22a0b | ||
|
|
f39702e1cc | ||
|
|
b94f883f39 | ||
|
|
7c5f3762dd | ||
|
|
938ae6e80a | ||
|
|
2584197a02 | ||
|
|
2a81370c66 | ||
|
|
29e9d064df | ||
|
|
b0f69263c7 | ||
|
|
c15aec641a | ||
|
|
a9333baa78 | ||
|
|
26e70fa585 | ||
|
|
b95206cf87 | ||
|
|
2c982213b9 | ||
|
|
45488947ef | ||
|
|
56ffe5aea8 | ||
|
|
a6523630bf | ||
|
|
0da19d54bb | ||
|
|
8a5f19e4f9 | ||
|
|
14f975bde7 | ||
|
|
9b285e6b21 | ||
|
|
403597f860 | ||
|
|
add0d0cd86 | ||
|
|
685275237a | ||
|
|
8576d535bd | ||
|
|
7ff2e98420 | ||
|
|
843a8c3e56 | ||
|
|
3772b04c6b | ||
|
|
fb7633cb07 | ||
|
|
efa8d8a0d7 | ||
|
|
f4a7108382 | ||
|
|
d59aab1a7d | ||
|
|
ee3aedc75f | ||
|
|
cecb5cf4b4 | ||
|
|
0a7e40bd23 | ||
|
|
fd2deb0a82 | ||
|
|
5f6c71b9d3 | ||
|
|
3cf5adc278 | ||
|
|
e907c2045c | ||
|
|
5740c2b6d0 | ||
|
|
c2c0c3fd08 | ||
|
|
df4278a646 | ||
|
|
810a59f146 | ||
|
|
9ec23940b9 | ||
|
|
bf5dd7386e | ||
|
|
5f7e25b65e | ||
|
|
d58e3ac235 | ||
|
|
679aab18ee | ||
|
|
fb032eb763 | ||
|
|
0d6657a1e8 | ||
|
|
fceac4c1a1 | ||
|
|
b3f29f100d | ||
|
|
24071ed23b | ||
|
|
e1e9b28bf1 | ||
|
|
6386cae19a | ||
|
|
b12d3ae0ba | ||
|
|
bd274f804a | ||
|
|
63356e96ec | ||
|
|
80332e37d5 | ||
|
|
63717bdf51 | ||
|
|
313cadb763 | ||
|
|
0847b20401 | ||
|
|
7401c16ded | ||
|
|
0df4e26736 | ||
|
|
fdf7c88083 | ||
|
|
eabc5c15c7 | ||
|
|
bec394abbc | ||
|
|
96f41b0cf3 | ||
|
|
c12865eabc | ||
|
|
ecfac00c30 | ||
|
|
d90807b29c | ||
|
|
f4f5658fee | ||
|
|
62399d0f2b | ||
|
|
47ec565316 | ||
|
|
0f224c7780 | ||
|
|
946ac8eefb | ||
|
|
19cb144cdb | ||
|
|
b204074690 | ||
|
|
d5c758c18a | ||
|
|
843be42568 | ||
|
|
db2f61ec29 | ||
|
|
d095008e7c | ||
|
|
fc8e1d5b6d | ||
|
|
ba78eab30a | ||
|
|
7b7e803011 | ||
|
|
7dfd20d020 | ||
|
|
f0882d8d5e | ||
|
|
e3735ffa9c | ||
|
|
185e4334f6 | ||
|
|
58d8e22b40 | ||
|
|
47b06d0eac | ||
|
|
42c323365a | ||
|
|
9c69e3a1a0 | ||
|
|
af7b7ef2b1 | ||
|
|
4a8be42258 | ||
|
|
6f1a64db78 | ||
|
|
934db24d3b | ||
|
|
93ae73abb6 | ||
|
|
71ea9b3bd9 | ||
|
|
6517eaf62f | ||
|
|
a0f0640729 | ||
|
|
2082976783 | ||
|
|
25338ff1cf | ||
|
|
e41d2d66c5 | ||
|
|
ec4a5880b7 | ||
|
|
f419de0fad | ||
|
|
6bcc103cf7 | ||
|
|
08ac91359b | ||
|
|
63eee99aba | ||
|
|
2280ed6071 | ||
|
|
5a1c9ce785 | ||
|
|
2ee518c9fc | ||
|
|
15623fbe5c | ||
|
|
daefe6bc1f | ||
|
|
31708b9af7 | ||
|
|
fa2df57021 | ||
|
|
d38abe95f9 | ||
|
|
ae47f37b27 | ||
|
|
e88ff1a358 | ||
|
|
bce8a61390 | ||
|
|
2bfe0c30ec | ||
|
|
3c02234a3b | ||
|
|
de16c95dd6 | ||
|
|
5da0267df9 | ||
|
|
0aa313e37c | ||
|
|
a7ca632c09 | ||
|
|
d1de976dc4 | ||
|
|
2e42526e90 | ||
|
|
918c9492df | ||
|
|
6e162d91e5 | ||
|
|
1eaa1a05ac | ||
|
|
caea5c7df2 | ||
|
|
b789394efc | ||
|
|
89aec3ac51 | ||
|
|
405d6cf33f | ||
|
|
cecfe77e95 | ||
|
|
7001ad09cb | ||
|
|
b5660a50ca | ||
|
|
c8d59cea6d | ||
|
|
90b0650af9 | ||
|
|
d04ce2a750 | ||
|
|
3dfad51e93 | ||
|
|
dbe482d494 | ||
|
|
db77cfa3b5 | ||
|
|
ac14f43107 | ||
|
|
2a7da8c80e | ||
|
|
0a40991c75 | ||
|
|
9dffbde8c8 | ||
|
|
0968f0be59 | ||
|
|
baa0d5a951 | ||
|
|
5f79040faa | ||
|
|
126b54b981 | ||
|
|
9e105dbce5 | ||
|
|
5370874686 | ||
|
|
84693f5073 | ||
|
|
1823bc8f15 | ||
|
|
a7a31f6c35 | ||
|
|
b4573861a8 | ||
|
|
1f48daa4ed | ||
|
|
f365d8519b | ||
|
|
c74d2f8cf2 | ||
|
|
b48736e771 | ||
|
|
26f0a627d5 | ||
|
|
f55fb48ea7 | ||
|
|
9e96954eaa | ||
|
|
186ae4e2a2 | ||
|
|
fef4882c15 | ||
|
|
c8f2362b7e | ||
|
|
0869db6eb6 | ||
|
|
8237d901e4 | ||
|
|
f76b349d3f | ||
|
|
d7fcb65b4e | ||
|
|
8769b9bf0e | ||
|
|
dc8cb09013 | ||
|
|
348b379490 | ||
|
|
0601a2a90b | ||
|
|
bb7da46301 | ||
|
|
3b3a1dd496 | ||
|
|
e025f94200 | ||
|
|
27522ae494 | ||
|
|
2bd3bc0e13 | ||
|
|
d85a7338ea | ||
|
|
a47e300297 | ||
|
|
a76cb3cb1a | ||
|
|
ce9f515543 | ||
|
|
1e954dc2be | ||
|
|
e247b092dc | ||
|
|
732769524c | ||
|
|
917db20e76 | ||
|
|
2a9008f042 | ||
|
|
c5df9aa814 | ||
|
|
6648a9ff1a | ||
|
|
c66c3590b1 | ||
|
|
a7bdd6c856 | ||
|
|
6ae8247a02 | ||
|
|
2662228bec | ||
|
|
2b1bd90dfa | ||
|
|
61d212128a | ||
|
|
a51a8d7473 | ||
|
|
9fbe421905 | ||
|
|
778b61914a | ||
|
|
d0565420ef | ||
|
|
b346b9114a | ||
|
|
99518f4e1d | ||
|
|
6501071510 | ||
|
|
6dd9369066 | ||
|
|
5be5d11c8e | ||
|
|
8ea28e1ced | ||
|
|
87ab895253 | ||
|
|
43762e82a8 | ||
|
|
758b327639 | ||
|
|
bb9855e830 | ||
|
|
cac6041583 | ||
|
|
1f905790e7 | ||
|
|
427cf8e594 | ||
|
|
5c6a155d75 | ||
|
|
b9ccc528e9 | ||
|
|
4537c4ea57 | ||
|
|
af3423d94a | ||
|
|
5869b7d27e | ||
|
|
be50ededcd | ||
|
|
f7a7521120 | ||
|
|
5ca1d66755 | ||
|
|
36ce04e8f0 | ||
|
|
cd1918e337 | ||
|
|
269a92a723 | ||
|
|
06f3e8ca7a | ||
|
|
210971fedb | ||
|
|
66f7198c7c | ||
|
|
6c00b2a0ff | ||
|
|
42a6b0e369 | ||
|
|
68cfd1790a | ||
|
|
465a8af03e | ||
|
|
8993c1db04 | ||
|
|
9574f742e1 | ||
|
|
fb9670d0ad | ||
|
|
737e32e447 | ||
|
|
09d42773a6 | ||
|
|
b9b57f7908 | ||
|
|
409cc219f1 | ||
|
|
c479a3482d | ||
|
|
bf125c92d3 | ||
|
|
b4cecbc3b9 | ||
|
|
f940f96a14 | ||
|
|
f81529c005 | ||
|
|
182d8e2daf | ||
|
|
0f76aeba05 | ||
|
|
1e3a190d5a | ||
|
|
93fe794f63 | ||
|
|
890e84ab62 | ||
|
|
65e94850ca | ||
|
|
28fb6a7d2a | ||
|
|
0b4de1a4fa | ||
|
|
305c19496e | ||
|
|
685f915656 | ||
|
|
1ef546b578 | ||
|
|
50422aaac5 | ||
|
|
597d58e843 | ||
|
|
b3ff616af2 | ||
|
|
cf02a75846 | ||
|
|
fa665468d3 | ||
|
|
d9e05907af | ||
|
|
17b1eaf1b6 | ||
|
|
803f9e8eb6 | ||
|
|
733713c9a2 | ||
|
|
f112226178 | ||
|
|
95354f6d11 | ||
|
|
0e7c70fe3c | ||
|
|
d2d0be7759 | ||
|
|
c25ea81926 | ||
|
|
5bcaed54c6 | ||
|
|
45c2cd7ac3 | ||
|
|
6fff4ad8a1 | ||
|
|
3d98de34eb | ||
|
|
9b65151718 | ||
|
|
3c89ccf7c3 | ||
|
|
973dc5fe3e | ||
|
|
b786260f89 | ||
|
|
7f6dcbd75a | ||
|
|
0382d40dcc | ||
|
|
140e1fa53e | ||
|
|
34568f12d6 | ||
|
|
c7bfba7a23 | ||
|
|
5e7d9f8119 | ||
|
|
86b769bd27 | ||
|
|
789cc3cdb9 | ||
|
|
69d0751e65 | ||
|
|
68f1efdbdd | ||
|
|
ba788bac7a | ||
|
|
b314e38c0e | ||
|
|
bb6230966f | ||
|
|
e2d016f318 | ||
|
|
8273198c56 | ||
|
|
0c6b7aa934 | ||
|
|
b6c0e92c2c | ||
|
|
d984862c69 | ||
|
|
5b4a22e219 | ||
|
|
6a24a82345 | ||
|
|
23b2170c66 | ||
|
|
f6f0d6c1be | ||
|
|
3cc89156a7 | ||
|
|
8598b0a23a | ||
|
|
bd349803d3 | ||
|
|
0842c3f0a0 | ||
|
|
8a4824e72d | ||
|
|
e1dfb68cfd | ||
|
|
73b25c103c | ||
|
|
d988b4b5c9 | ||
|
|
30af729f93 | ||
|
|
8d0486d425 | ||
|
|
95ade7f32a | ||
|
|
9e7a97b780 | ||
|
|
b08eafc78e | ||
|
|
42252fa217 | ||
|
|
be5ba03142 | ||
|
|
35679925d2 | ||
|
|
780c4208bb | ||
|
|
b3590134ab | ||
|
|
d851a09944 | ||
|
|
5275599baf | ||
|
|
402fe88cf6 | ||
|
|
a89d2025e3 | ||
|
|
a7f86b2ba6 | ||
|
|
c5c8d646f7 | ||
|
|
fbc2d13435 | ||
|
|
ed795076f0 | ||
|
|
5119959b0f | ||
|
|
638343d25e | ||
|
|
55f0aa6d3b | ||
|
|
49c7984c8c | ||
|
|
92d265402b | ||
|
|
6a8d66c169 | ||
|
|
0d0450e3d1 | ||
|
|
bcadcb18bc | ||
|
|
da2a8aaf26 | ||
|
|
aaf7911735 | ||
|
|
a375dd3fc2 | ||
|
|
645e66fe71 | ||
|
|
ddb3afc255 | ||
|
|
5c4ce00dec | ||
|
|
a7c7295893 | ||
|
|
c1d4a4851f | ||
|
|
671162e700 | ||
|
|
6ccc555047 | ||
|
|
34d9193cd8 | ||
|
|
90f38fd135 | ||
|
|
39e3ae931c | ||
|
|
60684b4ef9 | ||
|
|
08af9aaa02 | ||
|
|
aae6d2038b | ||
|
|
732d90635f | ||
|
|
9292f62a20 | ||
|
|
1ae9d04f47 | ||
|
|
803b5328f5 | ||
|
|
56afe6a10b | ||
|
|
d636242b6f | ||
|
|
b2382ac429 | ||
|
|
de42cd6250 | ||
|
|
0e59a22cbe | ||
|
|
e8869c07fe | ||
|
|
3051598b92 | ||
|
|
d202c6ebdd | ||
|
|
e16aa5a74a | ||
|
|
7c06ba94c1 | ||
|
|
1acb5fc56c | ||
|
|
503b947fb7 | ||
|
|
65f63fd4d2 | ||
|
|
df08498d70 | ||
|
|
46bc2207ff | ||
|
|
d8ee862125 | ||
|
|
39b0051b73 | ||
|
|
f250008db3 | ||
|
|
76aa201a99 | ||
|
|
12d9479184 | ||
|
|
795bd84d06 | ||
|
|
598c7235b4 | ||
|
|
46d15e0aab | ||
|
|
8e0fa30439 | ||
|
|
88608b3f88 | ||
|
|
c980e72f52 | ||
|
|
807d7c2084 | ||
|
|
b683c3f8d5 | ||
|
|
c07c872ad5 | ||
|
|
4787a68a08 | ||
|
|
55effc54bb | ||
|
|
c225291790 | ||
|
|
14e79b50d2 | ||
|
|
61d9fd3d72 | ||
|
|
b562c30381 | ||
|
|
684b84310b | ||
|
|
1c9ad2266d | ||
|
|
ee288fbd3b | ||
|
|
196a79a10c | ||
|
|
42ba97f872 | ||
|
|
5b445c59c1 | ||
|
|
78f24b8840 | ||
|
|
f598ccb79b | ||
|
|
befae9a7c2 | ||
|
|
dc58626602 | ||
|
|
e8eecf8a1f | ||
|
|
aa19c80567 | ||
|
|
7030f69bc6 | ||
|
|
daa80955ac | ||
|
|
611115e55b | ||
|
|
371debceb7 | ||
|
|
31e2e05e30 | ||
|
|
1bc7454146 | ||
|
|
f1ff904b66 | ||
|
|
945be0c524 | ||
|
|
4edd024015 | ||
|
|
77c0163a79 | ||
|
|
0af1e549f8 | ||
|
|
8c6e8d8bcb | ||
|
|
c3ad3a9823 | ||
|
|
e63053f0f0 | ||
|
|
a9ece49c0d | ||
|
|
530ff9761b | ||
|
|
a12ff624e5 | ||
|
|
255edd94f8 | ||
|
|
dcbe4072dc | ||
|
|
3784251108 | ||
|
|
f290f688d0 | ||
|
|
b05a10b114 | ||
|
|
dafe629c1d | ||
|
|
12174bcdbf | ||
|
|
4254de01e4 | ||
|
|
7b3a5ad227 | ||
|
|
d9751dbc6d | ||
|
|
9a32b1a35a | ||
|
|
4ce15416fb | ||
|
|
4bb7d007f8 | ||
|
|
3a62bfa8ce | ||
|
|
7ffc170b76 | ||
|
|
a796fc1dce | ||
|
|
44f826cc14 | ||
|
|
23b431acae | ||
|
|
2b46659daf | ||
|
|
bdbc8ab6d2 | ||
|
|
d61da30c15 | ||
|
|
d110fe5ea3 | ||
|
|
d390484ea4 | ||
|
|
6938c69d97 | ||
|
|
4c85864260 | ||
|
|
1cefaf28db | ||
|
|
381df23bf2 | ||
|
|
6a0dc4c965 | ||
|
|
94651897b2 | ||
|
|
bc28dd392b | ||
|
|
9f20de427e | ||
|
|
b68e0a8562 | ||
|
|
898c07c4af | ||
|
|
603cb4295a | ||
|
|
931882fb6a | ||
|
|
b84ec4ff8e | ||
|
|
434a754c9a | ||
|
|
8c501fa10b | ||
|
|
a4987f864f | ||
|
|
3fd677b3e6 | ||
|
|
6d23963e98 | ||
|
|
759068b82a | ||
|
|
12f4d5a9a4 | ||
|
|
d54d8a25af | ||
|
|
b99dba808e | ||
|
|
89f3511082 | ||
|
|
a06f6f0b2d | ||
|
|
6e62936458 | ||
|
|
e64122bbbb | ||
|
|
8abe6c4270 | ||
|
|
04dc701c25 | ||
|
|
2dfa334ba6 | ||
|
|
b758b69243 | ||
|
|
c432639dfa | ||
|
|
ab49825d35 | ||
|
|
6a22d45320 | ||
|
|
fea5142955 | ||
|
|
4910afbc82 | ||
|
|
2990013b8e | ||
|
|
c3524794c6 | ||
|
|
fe9df51721 | ||
|
|
0663d8067a | ||
|
|
27ffefa0cd | ||
|
|
3c4c046e1f | ||
|
|
f6d8658ee2 | ||
|
|
7f3f1d7d76 | ||
|
|
43642ff546 | ||
|
|
911424b2e2 | ||
|
|
8e50228df2 | ||
|
|
9cca79adaa | ||
|
|
130eee35ec | ||
|
|
37c92302f0 | ||
|
|
709d3751d1 | ||
|
|
4545033f12 | ||
|
|
03d0849538 | ||
|
|
3ea2360290 | ||
|
|
a5b235d829 | ||
|
|
1514f9f7ec | ||
|
|
289c653574 | ||
|
|
a344c1a5d0 | ||
|
|
686c451ea6 | ||
|
|
c0ea4737fd | ||
|
|
c7d2be5a7f | ||
|
|
b09517066f | ||
|
|
07701f8c01 | ||
|
|
2cb9cfb097 | ||
|
|
11d2ed06cd | ||
|
|
c62a87e81a | ||
|
|
dabc891791 | ||
|
|
0adc2811bb | ||
|
|
d6412bf19c | ||
|
|
fce89d4db5 | ||
|
|
1fdd9dd124 | ||
|
|
f0d2f7b728 | ||
|
|
53d60e9cf6 | ||
|
|
bc658f9f45 | ||
|
|
95a1d84eb9 | ||
|
|
d7eb365446 | ||
|
|
8d5cd7b814 | ||
|
|
dcaf0dded5 | ||
|
|
21e446e6f0 | ||
|
|
aab97fefc8 | ||
|
|
bcec6261d1 | ||
|
|
cda3c3743b | ||
|
|
4f3cf9466e | ||
|
|
e5e325b25b | ||
|
|
739ce75154 | ||
|
|
d94427b4ee | ||
|
|
639738754a | ||
|
|
372b1311f7 | ||
|
|
2b9d618bd2 | ||
|
|
1fd22f6d10 | ||
|
|
a0c747407f | ||
|
|
2ca7f553bb | ||
|
|
128c3625e2 | ||
|
|
d51a8611c3 | ||
|
|
047652154e | ||
|
|
542555d721 | ||
|
|
6ea8a0f583 | ||
|
|
561e94617c | ||
|
|
5aa2860fa4 | ||
|
|
018ef5daf4 | ||
|
|
8a48a8bf3d | ||
|
|
5aec051d9b | ||
|
|
8b5adca750 | ||
|
|
98f012feb8 | ||
|
|
346ac88009 | ||
|
|
07074046e6 | ||
|
|
735187e78a | ||
|
|
4161698bb8 | ||
|
|
a4bd1dcc6d | ||
|
|
8876c673f7 | ||
|
|
40bb0ddf39 | ||
|
|
25178d0531 | ||
|
|
ea2adbd63b | ||
|
|
f10bdbf775 | ||
|
|
19649104a7 | ||
|
|
8280d11054 | ||
|
|
440226fecc | ||
|
|
c920902481 | ||
|
|
90505a8e19 | ||
|
|
23cb249c19 | ||
|
|
07a4b64b8a | ||
|
|
834c15a808 | ||
|
|
bdb1e29c85 | ||
|
|
becc23ca42 | ||
|
|
45d8188ba4 | ||
|
|
bd4f3c039c | ||
|
|
b399ed1ed6 | ||
|
|
c83ae5d34c | ||
|
|
ea753f2f83 | ||
|
|
85503a7a95 | ||
|
|
80a13237f4 | ||
|
|
f188fbb567 | ||
|
|
63d2d32fd8 | ||
|
|
de77d80dab | ||
|
|
5c00ced1e3 | ||
|
|
8eeb668945 | ||
|
|
53e7c03730 | ||
|
|
9af3cf7a13 | ||
|
|
50e8586dc2 | ||
|
|
dd68241d1f | ||
|
|
cb6920b8be | ||
|
|
dce8b8faa1 | ||
|
|
3e87fff9db | ||
|
|
b9aa8edf78 | ||
|
|
25f07e7bcb | ||
|
|
fed4d10ec6 | ||
|
|
fd62125862 | ||
|
|
069d572a97 | ||
|
|
f9129170a1 | ||
|
|
342523a7de | ||
|
|
969eb4c57f | ||
|
|
e7c3c3f199 | ||
|
|
5f27261cb1 | ||
|
|
b9d16d9fd9 | ||
|
|
ef42f022c7 | ||
|
|
33d9501dd2 | ||
|
|
c16c64b049 | ||
|
|
cc04537355 | ||
|
|
39f6bc30b7 | ||
|
|
9e9776971f | ||
|
|
85eb62110d | ||
|
|
9def4eaba4 | ||
|
|
941d2d0f39 | ||
|
|
35bd6a40c5 | ||
|
|
676ee8beda | ||
|
|
df63ce411d | ||
|
|
41754fc100 | ||
|
|
135b87fdb2 | ||
|
|
3101fc8056 | ||
|
|
64bacea3c7 | ||
|
|
1608bfd038 | ||
|
|
211be67e0e | ||
|
|
cdc8d2bfe4 | ||
|
|
c1e1e3c25b | ||
|
|
e75d1a51a6 | ||
|
|
c0e149f5f3 | ||
|
|
f8a24bc3a1 | ||
|
|
d99946df77 | ||
|
|
07835bb76d | ||
|
|
52a3e17ec5 | ||
|
|
ea1e137a00 | ||
|
|
3b340f7164 | ||
|
|
273f4590df | ||
|
|
8de0ca7d6e | ||
|
|
626a06ca00 | ||
|
|
c5859eb03a | ||
|
|
3397557737 | ||
|
|
a226cd390c | ||
|
|
d50092e9a2 | ||
|
|
2dbb099d79 | ||
|
|
864d6977ff | ||
|
|
5887169f90 | ||
|
|
289e8bb394 | ||
|
|
f4604f2207 | ||
|
|
6b55b64775 | ||
|
|
ec5c060574 | ||
|
|
b66c1c2649 | ||
|
|
d3c9689fff | ||
|
|
7bffc66b3d | ||
|
|
414b538e6b | ||
|
|
2ee99b3290 | ||
|
|
ae472fb03d | ||
|
|
58cbfa599a | ||
|
|
d4163f2d1c | ||
|
|
3ccf2ecc24 | ||
|
|
40ea1c865d | ||
|
|
1836cf9582 | ||
|
|
eef4137a59 | ||
|
|
ab0cb0c019 | ||
|
|
14de9d7f5f | ||
|
|
621fa7862c | ||
|
|
2504fd536b | ||
|
|
a4d49f5d17 | ||
|
|
2f3c098b50 | ||
|
|
f6bf229b0a | ||
|
|
3fd5f3f986 | ||
|
|
f905245b71 | ||
|
|
a6acd1bed2 | ||
|
|
8860dab37a | ||
|
|
1941b0fa8a | ||
|
|
dfcf11fb07 | ||
|
|
5fc8901e0b | ||
|
|
02fbc56137 | ||
|
|
0589290380 | ||
|
|
fa62336096 | ||
|
|
08f8323465 | ||
|
|
9b74b69950 | ||
|
|
46762ab0e1 | ||
|
|
8b7d75c5ba | ||
|
|
c7c638caa6 | ||
|
|
c875bb3f55 | ||
|
|
ceee1d36e6 | ||
|
|
9260cdee95 | ||
|
|
d97d971cf6 | ||
|
|
efc1d9040b | ||
|
|
30d8737f67 | ||
|
|
9e0af97cee | ||
|
|
838e12cc0a | ||
|
|
02394973b0 | ||
|
|
14c9050103 | ||
|
|
81af481d3a | ||
|
|
2e2c8ceab4 | ||
|
|
09e08a474b | ||
|
|
21946cafd1 | ||
|
|
32a182cd01 | ||
|
|
6041e238a6 | ||
|
|
5d4ca753a7 | ||
|
|
1b2e10d355 | ||
|
|
018fe5dea2 | ||
|
|
eeb88df5f6 | ||
|
|
cf186e0219 | ||
|
|
39266d23c8 | ||
|
|
cafd076f9c | ||
|
|
87ed405916 | ||
|
|
7091cad704 | ||
|
|
b68b3a1837 | ||
|
|
2aa05f989b | ||
|
|
cec5c24d69 | ||
|
|
c738dcb42e | ||
|
|
1bf5b19889 | ||
|
|
37240478b8 | ||
|
|
9e8dae8cd6 | ||
|
|
c6e4bf1fa4 | ||
|
|
71e8c088a6 | ||
|
|
989ee895e8 | ||
|
|
2538273402 | ||
|
|
18b68fefed | ||
|
|
362846bd68 | ||
|
|
6cf422eebf | ||
|
|
cf69fa1d7c | ||
|
|
fc4f8619f8 | ||
|
|
c5f93139bd | ||
|
|
9beb23b0e4 | ||
|
|
d154361e75 | ||
|
|
67d87f023b | ||
|
|
da7c393096 | ||
|
|
b3f936acb8 | ||
|
|
2ca62831e3 | ||
|
|
cb601b729e | ||
|
|
cc4e9c5ba1 | ||
|
|
a592144291 | ||
|
|
390b5e3b60 | ||
|
|
05cfe7a80a | ||
|
|
58e9e0c0de | ||
|
|
561198f517 | ||
|
|
16a1483f55 | ||
|
|
eeb8d5ef9c | ||
|
|
c5c63c24d5 | ||
|
|
32e32ecae2 | ||
|
|
280f3dd428 | ||
|
|
1acc6461e6 | ||
|
|
9864383300 | ||
|
|
41eb51a340 | ||
|
|
07ae854dec | ||
|
|
da99286826 | ||
|
|
79a095faa8 | ||
|
|
2f3a842f2e | ||
|
|
a05f4338c5 | ||
|
|
2693f9c176 | ||
|
|
15750b5eb0 | ||
|
|
361a540ed3 | ||
|
|
a83546bc9d | ||
|
|
e66a1a92c3 | ||
|
|
b599bafd5e | ||
|
|
589d4c92d1 | ||
|
|
b9b8a4a2f7 | ||
|
|
7df44ec060 | ||
|
|
83511368f6 | ||
|
|
c6bbdfdc9b | ||
|
|
713dbccf74 | ||
|
|
a1d4804fae | ||
|
|
a8f4df8030 | ||
|
|
256f805754 | ||
|
|
ea0358d570 | ||
|
|
42f227195c | ||
|
|
7d6e8fdcd1 | ||
|
|
7254204ae5 | ||
|
|
0cde4a9778 | ||
|
|
bfe701bd08 | ||
|
|
2a47c22607 | ||
|
|
5c28985ee6 | ||
|
|
424e58ff7d | ||
|
|
8a01b87c99 | ||
|
|
79c8548171 | ||
|
|
a234949b8c | ||
|
|
0eaf9bc9c6 | ||
|
|
305632c002 | ||
|
|
51226d6c88 | ||
|
|
73e53a7766 | ||
|
|
18e92f5abf | ||
|
|
a10235d6b0 | ||
|
|
95d603a035 | ||
|
|
32199ac307 | ||
|
|
25bc6ebaf0 | ||
|
|
9a0292268e | ||
|
|
91f9ce3098 | ||
|
|
c717084cb9 | ||
|
|
2af12a632a | ||
|
|
474ddcf989 | ||
|
|
d860977144 | ||
|
|
8093f69b6a | ||
|
|
a240c00ebf | ||
|
|
bc20967262 | ||
|
|
501253d13a | ||
|
|
603d8b16d0 | ||
|
|
9e811be477 | ||
|
|
e47dcd75ff | ||
|
|
f163601262 | ||
|
|
b1f32d241b | ||
|
|
3bb2b646db | ||
|
|
7dca6b2a30 | ||
|
|
758ace353e | ||
|
|
9c1730685c | ||
|
|
67a084a5e7 | ||
|
|
2395bc9308 | ||
|
|
00f3353976 | ||
|
|
aedd047c6f | ||
|
|
4ec85ae72b | ||
|
|
5ac8ae2a00 | ||
|
|
b4739e6036 | ||
|
|
dedb63e9b6 | ||
|
|
803538d5be | ||
|
|
1efbd9dcf2 | ||
|
|
0a2ff97eb0 | ||
|
|
2c3e473b0f | ||
|
|
2a74bb742b | ||
|
|
f7fcc0528e | ||
|
|
a241d6f5bb | ||
|
|
7b25b09c18 | ||
|
|
5fbe925429 | ||
|
|
18aa9fc15e | ||
|
|
83bc3e4e8d | ||
|
|
3b0bff1a9b | ||
|
|
a7b80f025c | ||
|
|
7227180707 | ||
|
|
85e4270536 | ||
|
|
54a2bf1ba8 | ||
|
|
0d2bef90f2 | ||
|
|
191d7fe1ef | ||
|
|
e17052a452 | ||
|
|
b3cd492a13 | ||
|
|
68c20ae728 | ||
|
|
4c9b034153 | ||
|
|
41510d4574 | ||
|
|
d611dd107a | ||
|
|
d0b2f63553 | ||
|
|
a26cd46a7e | ||
|
|
74e94e5344 | ||
|
|
5f49f23aa0 | ||
|
|
a7e86aeee8 | ||
|
|
1dcaa44e9b | ||
|
|
c1b225a3b0 | ||
|
|
e253f5b0bd | ||
|
|
8d784f616f | ||
|
|
19239a6890 | ||
|
|
77447c59f6 | ||
|
|
f1fd072400 | ||
|
|
b06d517084 | ||
|
|
e31061a546 | ||
|
|
dcb27eb9ba | ||
|
|
c90a206a3a | ||
|
|
9081f3ff03 | ||
|
|
084c90ba9f | ||
|
|
dd932c91b4 | ||
|
|
7de0da28cd | ||
|
|
81ffd3fd3c | ||
|
|
115e3a737b | ||
|
|
fc65812263 | ||
|
|
7ba7e14282 | ||
|
|
f22e1bdeb3 | ||
|
|
4740350ec5 | ||
|
|
60a2a53973 | ||
|
|
924532f600 | ||
|
|
e983fde30f | ||
|
|
65bf97bc03 | ||
|
|
075cfd6eb0 | ||
|
|
73f7681f59 | ||
|
|
48715d0311 | ||
|
|
cd99a0e1a7 | ||
|
|
f1c254d6db | ||
|
|
43ef64bb2f | ||
|
|
81bc6c6ce7 | ||
|
|
101744a710 | ||
|
|
b37ea872a8 | ||
|
|
e32e9df1ab | ||
|
|
3bdd6e04ca | ||
|
|
50c6b0b1bd | ||
|
|
cb4ecbd4b8 | ||
|
|
0573160b2f | ||
|
|
152a987c3a | ||
|
|
975221f4cc | ||
|
|
f966489298 | ||
|
|
e7ffb0214f | ||
|
|
51b03725a2 | ||
|
|
4fb74d1e39 | ||
|
|
7d5ceafff2 | ||
|
|
74b6bc5dd3 | ||
|
|
104fd78966 | ||
|
|
6b27d19057 | ||
|
|
6228b5353f | ||
|
|
2165a2af7d | ||
|
|
289cca3bf0 | ||
|
|
53a6297b59 | ||
|
|
ea3e16ee16 | ||
|
|
ad45bebbdc | ||
|
|
196a9dd77e | ||
|
|
148abaccd9 | ||
|
|
4813d6c8ff | ||
|
|
3563c929af | ||
|
|
d831fa7ba3 | ||
|
|
d673167477 | ||
|
|
d91ff744f2 | ||
|
|
d2a2311cce | ||
|
|
6cbc42d9de | ||
|
|
c7bc05f560 | ||
|
|
e9994794aa | ||
|
|
6bf031d0f5 | ||
|
|
436c76fd2f | ||
|
|
12d4aab48a | ||
|
|
0ed21a1d5f | ||
|
|
08488857da | ||
|
|
2c7ff64511 | ||
|
|
24f5921863 | ||
|
|
32ffacf8f6 | ||
|
|
928812142a | ||
|
|
164dd0c405 | ||
|
|
8caa9ed548 | ||
|
|
4f195b72d1 | ||
|
|
4b08cfd2b7 | ||
|
|
1e3326fb8a | ||
|
|
cd019ab329 | ||
|
|
7e781d9ff8 | ||
|
|
808615a77c | ||
|
|
06e94b1800 | ||
|
|
930c342fb6 | ||
|
|
25bbce2e10 | ||
|
|
9398ac5088 | ||
|
|
860efdc052 | ||
|
|
ade989aecb | ||
|
|
12380f54d2 | ||
|
|
876d193379 | ||
|
|
1dc4fd0800 | ||
|
|
0ff3c1ee78 | ||
|
|
863c7ae2bc | ||
|
|
7ae0192a09 | ||
|
|
12c4395508 | ||
|
|
7b144cbec6 | ||
|
|
1e0067d64b | ||
|
|
7655b65363 | ||
|
|
ae0b84cef0 | ||
|
|
a02c7989b4 | ||
|
|
60d28fb01b | ||
|
|
f8b554aff8 | ||
|
|
77f406e9b8 | ||
|
|
4358658889 | ||
|
|
73c0ebb75f | ||
|
|
4744465986 | ||
|
|
f931469132 | ||
|
|
afdb0aa8c2 | ||
|
|
73414d7c2a | ||
|
|
c1f025db52 | ||
|
|
087aef6b85 | ||
|
|
7ddcd93a57 | ||
|
|
caa25b811b | ||
|
|
5a60ab1d2a | ||
|
|
8a25d57c83 | ||
|
|
c5de6706e0 | ||
|
|
f50ee2ecf2 | ||
|
|
11fc494284 | ||
|
|
1c48c1a43e | ||
|
|
2e19504b65 | ||
|
|
5a0d079a78 | ||
|
|
e05f755a4e | ||
|
|
44bff5b7cf | ||
|
|
e2b9977ebc | ||
|
|
3e51abf6eb | ||
|
|
c1f765a467 | ||
|
|
e67667e4a3 | ||
|
|
14a97976cc | ||
|
|
2dfbbdfd5b | ||
|
|
4a3e00f822 | ||
|
|
39ee31d748 | ||
|
|
3ac50a3f3e | ||
|
|
6fb4c79f82 | ||
|
|
9c75133fc8 | ||
|
|
fd61add2e4 | ||
|
|
acd695a469 | ||
|
|
5036506547 | ||
|
|
b0becbad38 | ||
|
|
bcb87f8f76 | ||
|
|
ecb09c0f04 | ||
|
|
e7298702a1 | ||
|
|
b74cf71f40 | ||
|
|
2025c7c669 | ||
|
|
00249f62b6 | ||
|
|
9df875354a | ||
|
|
9bc340ba17 | ||
|
|
79c965bf8d | ||
|
|
e5e4884448 | ||
|
|
882076030d | ||
|
|
c02c00cdfb | ||
|
|
3eea0ea065 | ||
|
|
fbbec816e8 | ||
|
|
cf31293d7b | ||
|
|
aeae286273 | ||
|
|
2581353c5e | ||
|
|
087f8129b9 | ||
|
|
bac1648d4b | ||
|
|
f1aadd97a8 | ||
|
|
3858cdd4c5 | ||
|
|
182a8837be | ||
|
|
a31de609ce | ||
|
|
9ddd76d6cb | ||
|
|
c6fc103bff | ||
|
|
3ed5282e14 | ||
|
|
51cec64118 | ||
|
|
a2a9cffdee | ||
|
|
057f3aead7 | ||
|
|
4b36a6d5bd | ||
|
|
26c328ae34 | ||
|
|
7a01719816 | ||
|
|
f0857fa22d | ||
|
|
04f8282821 | ||
|
|
120d96c775 | ||
|
|
21bd7a75f0 | ||
|
|
dcf75222d9 | ||
|
|
1e53ea50b0 | ||
|
|
fdaac290ac | ||
|
|
a1fd621eb6 | ||
|
|
8b7f439ef5 | ||
|
|
3211b5da01 | ||
|
|
cfbe631e66 | ||
|
|
7f53328f52 | ||
|
|
9af93dc44d | ||
|
|
68b9bfe907 | ||
|
|
966fff70ed | ||
|
|
9788f9b981 | ||
|
|
6e4b02db5a | ||
|
|
2afb175560 | ||
|
|
4a40172782 | ||
|
|
baa0eb1149 | ||
|
|
6871db7155 | ||
|
|
a5e469e96c | ||
|
|
99d3e9ae7c | ||
|
|
97f342aceb | ||
|
|
1d1c73fd6f | ||
|
|
71f1fb5d66 | ||
|
|
65800a51c6 | ||
|
|
48c04bda8c | ||
|
|
afd31c2b42 | ||
|
|
53996d8a8d | ||
|
|
8b14219bab | ||
|
|
da2cc292c3 | ||
|
|
e215772f30 | ||
|
|
18d4efa315 | ||
|
|
6d68e10804 | ||
|
|
e71230755d | ||
|
|
7a8bd82f8e | ||
|
|
35c130c4ff | ||
|
|
e677538c53 | ||
|
|
8b4fcf99a6 | ||
|
|
03d0f54083 | ||
|
|
1f65ba185a | ||
|
|
024f2d62e2 | ||
|
|
7f56cdc1e9 | ||
|
|
abaa462645 | ||
|
|
ff74a212c5 | ||
|
|
a4d42ea22c | ||
|
|
c4d4dcb9db | ||
|
|
c4464e67fd | ||
|
|
09c57c32d6 | ||
|
|
e3621f44da | ||
|
|
ad248e2e20 | ||
|
|
47f075133f | ||
|
|
6fd0205495 | ||
|
|
47023af3d5 | ||
|
|
86d5842868 | ||
|
|
81990cf16c | ||
|
|
6c6861a97a | ||
|
|
0ad8408ba9 | ||
|
|
fbadb9f4aa | ||
|
|
4bb9a93ff9 | ||
|
|
ac3ab6971d | ||
|
|
66c81246b6 | ||
|
|
656c37372d | ||
|
|
b89078733e | ||
|
|
158241b8e2 | ||
|
|
2bd7c92b9e | ||
|
|
562fa07755 | ||
|
|
e9b066b866 | ||
|
|
3feca9bbf8 | ||
|
|
d89189debd | ||
|
|
ae7a8e1f65 | ||
|
|
c23e923ffb | ||
|
|
a2706a80b1 | ||
|
|
d2ab316072 | ||
|
|
f9bc4a30f0 | ||
|
|
d45d7f21b6 | ||
|
|
8e976c20a1 | ||
|
|
e23119e330 | ||
|
|
5169e197b6 | ||
|
|
ba1f59aa71 | ||
|
|
8814dbe29a | ||
|
|
f46be924b9 | ||
|
|
659bfea8cf | ||
|
|
c8455ddbc8 | ||
|
|
8a9c92227d | ||
|
|
4265d40024 | ||
|
|
861b3ac3f4 | ||
|
|
007a1bd1d2 | ||
|
|
b9841f9cfa | ||
|
|
33e818a757 | ||
|
|
d7e8a8e4f4 | ||
|
|
b66e03d2a8 | ||
|
|
908018b97c | ||
|
|
9abb08152b | ||
|
|
94dc220924 | ||
|
|
3d8e83850e | ||
|
|
eeae5149a1 | ||
|
|
f83b6728cf | ||
|
|
e3136e9e09 | ||
|
|
4147d8a512 | ||
|
|
8c7b688f78 | ||
|
|
ddecb2d831 | ||
|
|
99d1a2829f | ||
|
|
c0d250560a | ||
|
|
6fe5663f79 | ||
|
|
6a99a3922e | ||
|
|
502e8f78ce | ||
|
|
a11f6efe0a | ||
|
|
8172e69f8c | ||
|
|
65857d77c4 | ||
|
|
dfecfa3964 | ||
|
|
f6b1420103 | ||
|
|
84748afc55 | ||
|
|
eb0ea9030b | ||
|
|
da97aee8e4 | ||
|
|
05ccdfd51b | ||
|
|
a7b39e56bd | ||
|
|
012421afcb | ||
|
|
be50997f94 | ||
|
|
878f570472 | ||
|
|
36b9451e01 | ||
|
|
1d0cfd4435 | ||
|
|
006004fd70 | ||
|
|
a07e275e11 | ||
|
|
a942ed2cad | ||
|
|
88d2ec5be8 | ||
|
|
141cf518a2 | ||
|
|
f937cb30f0 | ||
|
|
f2f31120a0 | ||
|
|
63fa50d111 | ||
|
|
55932d03c9 | ||
|
|
93faf128b7 | ||
|
|
56b2cc2745 | ||
|
|
d2869b976d | ||
|
|
432b555f1b | ||
|
|
db1a2ddc64 | ||
|
|
88282a8c0b | ||
|
|
4674e5ad68 | ||
|
|
babe00245a | ||
|
|
ff578c8540 | ||
|
|
445126ea65 | ||
|
|
2683c74800 | ||
|
|
61197fe974 | ||
|
|
89d143af8f | ||
|
|
0f92f77b55 | ||
|
|
683211cb1f | ||
|
|
af83d08fb1 | ||
|
|
28765ef909 | ||
|
|
ad6e0bcd0f | ||
|
|
8edcebd3a6 | ||
|
|
6eb6870bb6 | ||
|
|
038fc72d7b | ||
|
|
2e3f7d8db2 | ||
|
|
883a2a9b59 | ||
|
|
9a289c83e6 | ||
|
|
6e970cb84d | ||
|
|
58a79d8631 | ||
|
|
26e93c2f06 | ||
|
|
2fe3fea7f4 | ||
|
|
2c4dcff72d | ||
|
|
f6595937f4 | ||
|
|
df1a102021 | ||
|
|
be0b13e27d | ||
|
|
27d6bf067e | ||
|
|
01e7397df5 | ||
|
|
b9dd6cc4b5 | ||
|
|
4f144c8f3d | ||
|
|
c0844304a6 | ||
|
|
b2f9b2ef77 | ||
|
|
47695f1f8c | ||
|
|
f044f30829 | ||
|
|
f7c4ea3e58 | ||
|
|
651d0f5162 | ||
|
|
e5856cf73b | ||
|
|
2dd95a62ca | ||
|
|
ae2dd5732a | ||
|
|
b20e0967fd | ||
|
|
899a12eddb | ||
|
|
c637ec15ff | ||
|
|
e6f1d194ae | ||
|
|
18ce4b6bde | ||
|
|
c2cb308081 | ||
|
|
bbf87df373 | ||
|
|
432a40c656 | ||
|
|
fbedc95ad9 | ||
|
|
f26e0b4609 | ||
|
|
f918cdeced | ||
|
|
6f3c771d73 | ||
|
|
49137d4f58 | ||
|
|
eebbf9bbf4 | ||
|
|
e45df98f26 | ||
|
|
b123b8b074 | ||
|
|
f7791a2bb2 | ||
|
|
ed765ad10a | ||
|
|
5f047603bf | ||
|
|
5c485eff04 | ||
|
|
0f2f8f2411 | ||
|
|
9bdf475049 | ||
|
|
35afc94d34 | ||
|
|
cf5e8c6463 | ||
|
|
6f25ba4541 | ||
|
|
c611ce9d58 | ||
|
|
c8980163e9 | ||
|
|
8fc84fad0a | ||
|
|
12c3b22b7c | ||
|
|
252817abb7 | ||
|
|
781fbb6255 | ||
|
|
add19ed7f1 | ||
|
|
c474b082cd | ||
|
|
3ae8065cf1 | ||
|
|
ecae603f50 | ||
|
|
0b3d4da92d | ||
|
|
6e8ba927dd | ||
|
|
9b55eeaa38 | ||
|
|
1a177ef239 | ||
|
|
207d95dbd8 | ||
|
|
78951113d6 | ||
|
|
58e5931b83 | ||
|
|
9891e971ea | ||
|
|
6b3dc669eb | ||
|
|
c6299c8f2c | ||
|
|
76fa8bef81 | ||
|
|
2ce30ece6c | ||
|
|
2b4401c753 | ||
|
|
4494503e6b | ||
|
|
2948738e33 | ||
|
|
095c65f36c | ||
|
|
7adf8cfdef | ||
|
|
2666b564c2 | ||
|
|
0ae627c56b | ||
|
|
81de3d2c7d | ||
|
|
57cd03c0c2 | ||
|
|
a629aeef75 | ||
|
|
b8e32304a3 | ||
|
|
e2d0ab5161 | ||
|
|
73040de839 | ||
|
|
097334726d | ||
|
|
6efcbe69a0 | ||
|
|
f6af699428 | ||
|
|
5a21387762 | ||
|
|
1f6d3dca0e | ||
|
|
0b0007502f | ||
|
|
59451fcc0b | ||
|
|
12b034d16b | ||
|
|
68dca82ab8 | ||
|
|
edbe50d8c4 | ||
|
|
644d54c3f1 | ||
|
|
f4a7f98b0b | ||
|
|
315bb483f2 | ||
|
|
d843f29e09 | ||
|
|
0807e1bd25 | ||
|
|
4aaaf3292e | ||
|
|
8c7d8abddd | ||
|
|
aa64dcfe27 | ||
|
|
f94c7e6105 | ||
|
|
7b0456a227 | ||
|
|
cad13b61bb | ||
|
|
4a238cff77 | ||
|
|
3f754116d8 | ||
|
|
13e378c7d3 | ||
|
|
e289f13d27 | ||
|
|
f0bfe24008 | ||
|
|
0ae6527584 | ||
|
|
10e4268dd5 | ||
|
|
317f40eecd | ||
|
|
ec32f65646 | ||
|
|
f1a455d7f1 | ||
|
|
481c5753e7 | ||
|
|
7f434fb625 | ||
|
|
5c31009495 | ||
|
|
549efa472a | ||
|
|
70b43ee31c | ||
|
|
2fcdae4c7e | ||
|
|
15311fa4ed | ||
|
|
0ce1164ffa | ||
|
|
12f51d477e | ||
|
|
00933f0e30 | ||
|
|
197118e16e | ||
|
|
b8cede1cf5 | ||
|
|
163bf15930 | ||
|
|
1bcfc69206 | ||
|
|
c3186b63ce | ||
|
|
8cd03c8a06 | ||
|
|
fd5f914845 | ||
|
|
07d23b4489 | ||
|
|
6f2dd3b708 | ||
|
|
c6c3357979 | ||
|
|
ed0809515e | ||
|
|
b46455642a | ||
|
|
9c1eca6d31 | ||
|
|
7726d94566 | ||
|
|
0383d3b8d7 | ||
|
|
830f67e001 | ||
|
|
296f195a7e | ||
|
|
f52fe3052e | ||
|
|
744d863fe9 | ||
|
|
0582382778 | ||
|
|
4cbd11a213 | ||
|
|
bf9207fe4e | ||
|
|
56351b427b | ||
|
|
4f5b737f7c | ||
|
|
20a511d940 | ||
|
|
d99f163cac | ||
|
|
899137fbf7 | ||
|
|
971b1542ba | ||
|
|
6b091b4d31 | ||
|
|
326f75cbda | ||
|
|
c250b1d24a | ||
|
|
5d62b1b318 | ||
|
|
e0cfbc7609 | ||
|
|
186a2aaa45 | ||
|
|
c307fc02cf | ||
|
|
c681cc5cf8 | ||
|
|
1e7c83f0c9 | ||
|
|
48daf12810 | ||
|
|
32d28a4070 | ||
|
|
8445c8e974 | ||
|
|
9e3870acbe | ||
|
|
78f146fbcf | ||
|
|
0c0573a7b1 | ||
|
|
aa6229be4b | ||
|
|
94cf054312 | ||
|
|
edfe58cb38 | ||
|
|
8798fa101a | ||
|
|
e6647484bd | ||
|
|
4b70b2fbcc | ||
|
|
7d9963d542 | ||
|
|
8952dd7f56 | ||
|
|
ccc1f6296c | ||
|
|
4c7259843c | ||
|
|
ddf2ce353f | ||
|
|
9f9e838a3a | ||
|
|
0f52fc1f4f | ||
|
|
71be99ad6d | ||
|
|
4b5d3ba4d8 | ||
|
|
b2ea1b7ca5 | ||
|
|
47f423540d | ||
|
|
a3871cca90 | ||
|
|
923b3eba96 | ||
|
|
cee9c8fa01 | ||
|
|
36edbbe2df | ||
|
|
8366dfcece | ||
|
|
4b7b07460a | ||
|
|
35c13d38a4 |
15
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -2,7 +2,7 @@
|
|||||||
name: Bug report
|
name: Bug report
|
||||||
about: Create a report to help fix an issue.
|
about: Create a report to help fix an issue.
|
||||||
title: ''
|
title: ''
|
||||||
labels: ''
|
labels: bug
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -13,4 +13,15 @@ assignees: ''
|
|||||||
|
|
||||||
**Issue**: *Explain your issue in detail.*
|
**Issue**: *Explain your issue in detail.*
|
||||||
|
|
||||||
**Steps to reproduce**: *How you happened across the issue, and what you were doing at the time.*
|
**Steps to reproduce**: *How you happened across the issue, and what exactly you did to make the bug happen.*
|
||||||
|
|
||||||
|
**Link(s) to mod(s) used**: *The mod repositories or zip files that are related to the issue, if applicable.*
|
||||||
|
|
||||||
|
**Save file**: *The save file you were playing on when the bug happened, if applicable.*
|
||||||
|
|
||||||
|
**Crash report**: *The contents of relevant crash report files. REQUIRED if you are reporting a crash.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Place an X (no spaces) between the brackets to confirm that you have read the line below.*
|
||||||
|
- [ ] **I have searched the closed and open issues to make sure that this problem has not already been reported.**
|
||||||
|
|||||||
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: Feature request
|
||||||
|
url: https://github.com/Anuken/Mindustry-Suggestions/issues/new/choose
|
||||||
|
about: Do not make a new issue for feature requests! Instead, post it in suggestions repository.
|
||||||
|
- name: Question
|
||||||
|
url: https://discord.com/invite/mindustry
|
||||||
|
about: Questions about the game should be asked in the Discord, not in the issue tracker.
|
||||||
11
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,11 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Do not make a new issue for feature requests! Instead, post in the suggestions
|
|
||||||
repository. See the README.
|
|
||||||
title: ''
|
|
||||||
labels: invalid
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Do not make a new issue for feature requests!** Instead, post it in suggestions repository: https://github.com/Anuken/Mindustry-Suggestions/issues/new/choose
|
|
||||||
23
.github/workflows/gradle.yml
vendored
@@ -3,15 +3,26 @@ name: Java CI
|
|||||||
on: [push]
|
on: [push]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
buildJava8:
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
- name: Set up JDK 1.8
|
- name: Set up JDK 8
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v1
|
||||||
with:
|
with:
|
||||||
java-version: 1.8
|
java-version: 8
|
||||||
#- name: Run unit tests with gradle
|
- name: Run unit tests with gradle and Java 8
|
||||||
# run: ./gradlew test
|
run: ./gradlew compileJava
|
||||||
|
|
||||||
|
buildJava14:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Set up JDK 14
|
||||||
|
uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: 14
|
||||||
|
- name: Run unit tests with gradle and Java 14
|
||||||
|
run: ./gradlew compileJava
|
||||||
|
|||||||
13
.gitignore
vendored
@@ -10,6 +10,7 @@ logs/
|
|||||||
/desktop/mindustry-saves/
|
/desktop/mindustry-saves/
|
||||||
/desktop/mindustry-maps/
|
/desktop/mindustry-maps/
|
||||||
/desktop/gifexport/
|
/desktop/gifexport/
|
||||||
|
/gifs/
|
||||||
/core/lib/
|
/core/lib/
|
||||||
/ios/assets/
|
/ios/assets/
|
||||||
/core/assets-raw/sprites/generated/
|
/core/assets-raw/sprites/generated/
|
||||||
@@ -18,6 +19,7 @@ logs/
|
|||||||
/annotations/out/
|
/annotations/out/
|
||||||
/net/build/
|
/net/build/
|
||||||
/tools/build/
|
/tools/build/
|
||||||
|
/core/build/
|
||||||
/tests/build/
|
/tests/build/
|
||||||
/server/build/
|
/server/build/
|
||||||
changelog
|
changelog
|
||||||
@@ -27,7 +29,6 @@ core/assets/saves/
|
|||||||
/core/assets/saves/
|
/core/assets/saves/
|
||||||
steam_appid.txt
|
steam_appid.txt
|
||||||
/test_files/
|
/test_files/
|
||||||
/annotations/build/
|
|
||||||
/android/assets/mindustry-maps/
|
/android/assets/mindustry-maps/
|
||||||
/android/assets/mindustry-saves/
|
/android/assets/mindustry-saves/
|
||||||
/core/assets/gifexport/
|
/core/assets/gifexport/
|
||||||
@@ -39,11 +40,9 @@ steam_appid.txt
|
|||||||
ios/robovm.properties
|
ios/robovm.properties
|
||||||
packr-out/
|
packr-out/
|
||||||
config/
|
config/
|
||||||
changelog
|
|
||||||
*.gif
|
*.gif
|
||||||
/core/assets/saves/
|
|
||||||
/out/
|
|
||||||
|
|
||||||
|
/core/assets/basepartnames
|
||||||
version.properties
|
version.properties
|
||||||
|
|
||||||
.attach_*
|
.attach_*
|
||||||
@@ -80,9 +79,11 @@ com_crashlytics_export_strings.xml
|
|||||||
/android/bin/
|
/android/bin/
|
||||||
/core/bin/
|
/core/bin/
|
||||||
/desktop/bin/
|
/desktop/bin/
|
||||||
/html/bin/
|
|
||||||
/ios/bin/
|
/ios/bin/
|
||||||
/ios-moe/bin/
|
/annotations/bin/
|
||||||
|
/server/bin/
|
||||||
|
/tests/bin/
|
||||||
|
/tools/bin/
|
||||||
*.tmp
|
*.tmp
|
||||||
*.bak
|
*.bak
|
||||||
*.swp
|
*.swp
|
||||||
|
|||||||
12
.travis.yml
@@ -1,10 +1,10 @@
|
|||||||
jdk:
|
jdk:
|
||||||
- openjdk8
|
- openjdk14
|
||||||
dist: trusty
|
dist: xenial
|
||||||
android:
|
android:
|
||||||
components:
|
components:
|
||||||
- android-29
|
- android-29
|
||||||
- build-tools-29.0.2
|
- build-tools-29.0.3
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds
|
- git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds
|
||||||
@@ -20,6 +20,12 @@ script:
|
|||||||
- "./gradlew test"
|
- "./gradlew test"
|
||||||
- "./gradlew desktop:dist -Pbuildversion=${TRAVIS_TAG:1}"
|
- "./gradlew desktop:dist -Pbuildversion=${TRAVIS_TAG:1}"
|
||||||
- "./gradlew server:dist -Pbuildversion=${TRAVIS_TAG:1}"
|
- "./gradlew server:dist -Pbuildversion=${TRAVIS_TAG:1}"
|
||||||
|
- "./gradlew core:javadoc"
|
||||||
|
- cd ../
|
||||||
|
- git clone --depth=1 https://github.com/MindustryGame/docs.git
|
||||||
|
- cp -a Mindustry/core/build/docs/javadoc/. docs/
|
||||||
|
- cd docs
|
||||||
|
- if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then git add .; git commit -m "Update ${TRAVIS_BUILD_NUMBER}"; git push https://Anuken:${GH_PUSH_TOKEN}@github.com/MindustryGame/docs; fi
|
||||||
deploy:
|
deploy:
|
||||||
- provider: releases
|
- provider: releases
|
||||||
skip_cleanup: true
|
skip_cleanup: true
|
||||||
|
|||||||
@@ -26,11 +26,12 @@ This means:
|
|||||||
- 4 spaces indentation
|
- 4 spaces indentation
|
||||||
- `camelCase`, **even for constants or enums**. Why? Because `SCREAMING_CASE` is ugly, annoying to type and does not achieve anything useful. Constants are *less* dangerous than variables, not more.
|
- `camelCase`, **even for constants or enums**. Why? Because `SCREAMING_CASE` is ugly, annoying to type and does not achieve anything useful. Constants are *less* dangerous than variables, not more.
|
||||||
- No underscores for anything. (Yes, I know `Bindings` violates this principle, but that's for legacy reasons and really should be cleaned up some day)
|
- No underscores for anything. (Yes, I know `Bindings` violates this principle, but that's for legacy reasons and really should be cleaned up some day)
|
||||||
|
- Do not use braceless `if/else` statements. `if(x) statement else statement2` should **never** be done. In very specific situations, having braceless if-statements on one line is allowed: `if(cond) return;` would be valid.
|
||||||
|
|
||||||
Import [this style file](.github/Mindustry-CodeStyle-IJ.xml) into IntelliJ to get correct formatting when developing Mindustry.
|
Import [this style file](.github/Mindustry-CodeStyle-IJ.xml) into IntelliJ to get correct formatting when developing Mindustry.
|
||||||
|
|
||||||
#### Do not use incompatible Java features (java.util.function, java.awt).
|
#### Do not use incompatible Java features (java.util.function, java.awt).
|
||||||
Android [does not support](https://developer.android.com/studio/write/java8-support#supported_features) many of Java 8's features, such as the packages `java.util.function`, `java.util.stream` or `forEach` in collections. Do not use these in your code.
|
Android and RoboVM (iOS) do not support many of Java 8's features, such as the packages `java.util.function`, `java.util.stream` or `forEach` in collections. Do not use these in your code.
|
||||||
If you need to use functional interfaces, use the ones in `arc.func`, which are more or less the same with different naming schemes.
|
If you need to use functional interfaces, use the ones in `arc.func`, which are more or less the same with different naming schemes.
|
||||||
|
|
||||||
The same applies to any class *outside* of the standard `java.[n]io` / `java.net` / `java.util` packages: Most of them are not supported.
|
The same applies to any class *outside* of the standard `java.[n]io` / `java.net` / `java.util` packages: Most of them are not supported.
|
||||||
@@ -39,20 +40,20 @@ In general, if you are using IntelliJ, you should be warned about platform incom
|
|||||||
|
|
||||||
|
|
||||||
#### Use `arc` collections and classes when possible.
|
#### Use `arc` collections and classes when possible.
|
||||||
Instead of using `java.util.List`, `java.util.HashMap`, and other standard Java collections, use `Array`, `ObjectMap` and other equivalents from `arc.struct`.
|
Instead of using `java.util.List`, `java.util.HashMap`, and other standard Java collections, use `Seq`, `ObjectMap` and other equivalents from `arc.struct`.
|
||||||
Why? Because that's what the rest of the codebase uses, and the standard collections have a lot of cruft and usability issues associated with them.
|
Why? Because that's what the rest of the codebase uses, and the standard collections have a lot of cruft and usability issues associated with them.
|
||||||
In the rare case that concurrency is required, you may use the standard Java classes for that purpose (e.g. `CopyOnWriteArrayList`).
|
In the rare case that concurrency is required, you may use the standard Java classes for that purpose (e.g. `CopyOnWriteArrayList`).
|
||||||
|
|
||||||
What you'll usually need to change:
|
What you'll usually need to change:
|
||||||
- `HashSet` -> `ObjectSet`
|
- `HashSet` -> `ObjectSet`
|
||||||
- `HashMap` -> `ObjectMap`
|
- `HashMap` -> `ObjectMap`
|
||||||
- `List` / `ArrayList` / `Stack` -> `Array`
|
- `List` / `ArrayList` / `Stack` -> `Seq`
|
||||||
- `java.util.Queue` -> `arc.struct.Queue`
|
- `java.util.Queue` -> `arc.struct.Queue`
|
||||||
- *Many others*
|
- *Many others*
|
||||||
|
|
||||||
|
|
||||||
#### Avoid boxed types (Integer, Boolean)
|
#### Avoid boxed types (Integer, Boolean)
|
||||||
Never create variables or collections with boxed types `Array<Integer>` or `ObjectMap<Integer, ...>`. Use the collections specialized for this task, e.g. `IntArray` and `IntMap`.
|
Never create variables or collections with boxed types `Seq<Integer>` or `ObjectMap<Integer, ...>`. Use the collections specialized for this task, e.g. `IntSeq` and `IntMap`.
|
||||||
|
|
||||||
|
|
||||||
#### Do not allocate anything if possible.
|
#### Do not allocate anything if possible.
|
||||||
@@ -67,3 +68,6 @@ If something needs to be encapsulated in the future, IntelliJ can handle it with
|
|||||||
|
|
||||||
#### Do not create methods unless necessary.
|
#### Do not create methods unless necessary.
|
||||||
Unless a block of code is very large or used in more than 1-2 places, don't split it up into a separate method. Making unnecessary methods only creates confusion, and may slightly decrease performance.
|
Unless a block of code is very large or used in more than 1-2 places, don't split it up into a separate method. Making unnecessary methods only creates confusion, and may slightly decrease performance.
|
||||||
|
|
||||||
|
## Other Notes
|
||||||
|
If you would like your name to appear in the game's credits, add it to the [list of contributors](https://github.com/Anuken/Mindustry/blob/master/core/assets/contributors) as part of your PR.
|
||||||
|
|||||||
10
README.md
@@ -7,6 +7,7 @@ A sandbox tower defense game written in Java.
|
|||||||
|
|
||||||
_[Trello Board](https://trello.com/b/aE2tcUwF/mindustry-40-plans)_
|
_[Trello Board](https://trello.com/b/aE2tcUwF/mindustry-40-plans)_
|
||||||
_[Wiki](https://mindustrygame.github.io/wiki)_
|
_[Wiki](https://mindustrygame.github.io/wiki)_
|
||||||
|
_[Javadoc](https://mindustrygame.github.io/docs/)_
|
||||||
|
|
||||||
### Contributing
|
### Contributing
|
||||||
|
|
||||||
@@ -14,10 +15,10 @@ See [CONTRIBUTING](CONTRIBUTING.md).
|
|||||||
|
|
||||||
### Building
|
### Building
|
||||||
|
|
||||||
Bleeding-edge live builds are generated automatically for every commit. You can see them [here](https://github.com/Anuken/MindustryBuilds/releases). Old builds might still be on [jenkins](https://jenkins.hellomouse.net/job/mindustry/).
|
Bleeding-edge builds are generated automatically for every commit. You can see them [here](https://github.com/Anuken/MindustryBuilds/releases).
|
||||||
|
|
||||||
If you'd rather compile on your own, follow these instructions.
|
If you'd rather compile on your own, follow these instructions.
|
||||||
First, make sure you have [JDK 8](https://adoptopenjdk.net/) installed. Open a terminal in the root directory, `cd` to the Mindustry folder and run the following commands:
|
First, make sure you have [JDK 14](https://adoptopenjdk.net/) installed. Open a terminal in the root directory, `cd` to the Mindustry folder and run the following commands:
|
||||||
|
|
||||||
#### Windows
|
#### Windows
|
||||||
|
|
||||||
@@ -38,9 +39,10 @@ Server builds are bundled with each released build (in Releases). If you'd rathe
|
|||||||
#### Android
|
#### Android
|
||||||
|
|
||||||
1. Install the Android SDK [here.](https://developer.android.com/studio#downloads) Make sure you're downloading the "Command line tools only", as Android Studio is not required.
|
1. Install the Android SDK [here.](https://developer.android.com/studio#downloads) Make sure you're downloading the "Command line tools only", as Android Studio is not required.
|
||||||
2. Create a file named `local.properties` inside the Mindustry directory, with its contents looking like this: `sdk.dir=<Path to Android SDK you just downloaded, without these bracket>`. For example, if you're on Windows and installed the tools to C:\\tools, your local.properties would contain `sdk.dir=C:\\tools` (*note the double backslashes are required instead of single ones!*).
|
2. Set the `ANDROID_HOME` environment variable to point to your unzipped Android SDK directory.
|
||||||
3. Run `gradlew android:assembleDebug` (or `./gradlew` if on linux/mac). This will create an unsigned APK in `android/build/outputs/apk`.
|
3. Run `gradlew android:assembleDebug` (or `./gradlew` if on linux/mac). This will create an unsigned APK in `android/build/outputs/apk`.
|
||||||
4. (Optional) To debug the application on a connected phone, do `gradlew android:installDebug android:run`. It is **highly recommended** to use IntelliJ for this instead, however.
|
|
||||||
|
To debug the application on a connected phone, run `gradlew android:installDebug android:run`.
|
||||||
|
|
||||||
##### Troubleshooting
|
##### Troubleshooting
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
android:appCategory="game"
|
android:appCategory="game"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/GdxTheme" android:fullBackupContent="@xml/backup_rules">
|
android:theme="@style/ArcTheme" android:fullBackupContent="@xml/backup_rules">
|
||||||
<meta-data android:name="android.max_aspect" android:value="2.1"/>
|
<meta-data android:name="android.max_aspect" android:value="2.1"/>
|
||||||
<activity
|
<activity
|
||||||
android:name="mindustry.android.AndroidLauncher"
|
android:name="mindustry.android.AndroidLauncher"
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ buildscript{
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
|
//IMPORTANT NOTICE: any version of the plugin after 3.4.1 will break builds
|
||||||
|
//it appears abstract methods don't get desugared properly (if at all)
|
||||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,9 +21,7 @@ configurations{ natives }
|
|||||||
repositories{
|
repositories{
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
jcenter()
|
jcenter()
|
||||||
maven{
|
maven{ url "https://maven.google.com" }
|
||||||
url "https://maven.google.com"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
@@ -29,16 +29,13 @@ dependencies{
|
|||||||
|
|
||||||
implementation arcModule("backends:backend-android")
|
implementation arcModule("backends:backend-android")
|
||||||
implementation 'com.jakewharton.android.repackaged:dalvik-dx:9.0.0_r3'
|
implementation 'com.jakewharton.android.repackaged:dalvik-dx:9.0.0_r3'
|
||||||
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi"
|
|
||||||
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a"
|
natives "com.github.Anuken.Arc:natives-android:${getArcHash()}"
|
||||||
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a"
|
natives "com.github.Anuken.Arc:natives-freetype-android:${getArcHash()}"
|
||||||
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86"
|
natives "com.github.Anuken.Arc:natives-box2d-android:${getArcHash()}"
|
||||||
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64"
|
|
||||||
natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-armeabi"
|
//android dependencies magically disappear during compilation, thanks gradle!
|
||||||
natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-armeabi-v7a"
|
if(new File(projectDir.parent, '../Arc').exists()) compileOnly fileTree(dir: '../../Arc/backends/backend-android/libs', include: ['*.jar'])
|
||||||
natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-arm64-v8a"
|
|
||||||
natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-x86"
|
|
||||||
natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-x86_64"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task deploy(type: Copy){
|
task deploy(type: Copy){
|
||||||
@@ -50,7 +47,7 @@ task deploy(type: Copy){
|
|||||||
}
|
}
|
||||||
|
|
||||||
android{
|
android{
|
||||||
buildToolsVersion '29.0.2'
|
buildToolsVersion '29.0.3'
|
||||||
compileSdkVersion 29
|
compileSdkVersion 29
|
||||||
sourceSets{
|
sourceSets{
|
||||||
main{
|
main{
|
||||||
@@ -119,25 +116,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-v7a/").mkdirs()
|
|
||||||
file("libs/arm64-v8a/").mkdirs()
|
|
||||||
file("libs/x86_64/").mkdirs()
|
|
||||||
file("libs/x86/").mkdirs()
|
|
||||||
|
|
||||||
configurations.natives.files.each{ jar ->
|
configurations.natives.files.each{ jar ->
|
||||||
def outputDir = null
|
copy{
|
||||||
if(jar.name.endsWith("natives-arm64-v8a.jar")) outputDir = file("libs/arm64-v8a")
|
from zipTree(jar)
|
||||||
if(jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a")
|
into file("libs/")
|
||||||
if(jar.name.endsWith("natives-armeabi.jar")) outputDir = file("libs/armeabi")
|
include "**"
|
||||||
if(jar.name.endsWith("natives-x86_64.jar")) outputDir = file("libs/x86_64")
|
|
||||||
if(jar.name.endsWith("natives-x86.jar")) outputDir = file("libs/x86")
|
|
||||||
if(outputDir != null){
|
|
||||||
copy{
|
|
||||||
from zipTree(jar)
|
|
||||||
into outputDir
|
|
||||||
include "*.so"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
# To enable ProGuard in your project, edit project.properties
|
|
||||||
# to define the proguard.config property as described in that file.
|
|
||||||
#
|
|
||||||
# Add project specific ProGuard rules here.
|
|
||||||
# By default, the flags in this file are appended to flags specified
|
|
||||||
# in ${sdk.dir}/tools/proguard/proguard-android.txt
|
|
||||||
# You can edit the include path and order by changing the ProGuard
|
|
||||||
# include property in project.properties.
|
|
||||||
#
|
|
||||||
# For more details, see
|
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
|
||||||
|
|
||||||
# Add any project specific keep options here:
|
|
||||||
|
|
||||||
# If your project uses WebView with JS, uncomment the following
|
|
||||||
# and specify the fully qualified class name to the JavaScript interface
|
|
||||||
# class:
|
|
||||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
|
||||||
# public *;
|
|
||||||
#}
|
|
||||||
|
|
||||||
-verbose
|
|
||||||
-verbose
|
|
||||||
-ignorewarnings
|
|
||||||
-keep class mindustry.game.Rules
|
|
||||||
-keep class mindustry.desktop.DesktopLauncher
|
|
||||||
-keepclasseswithmembers public class * {
|
|
||||||
public static void main(java.lang.String[]);
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# This file is automatically generated by Android Tools.
|
|
||||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
|
||||||
#
|
|
||||||
# This file must be checked in Version Control Systems.
|
|
||||||
#
|
|
||||||
# To customize properties used by the Ant build system edit
|
|
||||||
# "ant.properties", and override values to adapt the script to your
|
|
||||||
# project structure.
|
|
||||||
#
|
|
||||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
|
||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
|
||||||
# Project target.
|
|
||||||
target=android-19
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<style name="GdxTheme" parent="android:Theme.Material.NoActionBar">
|
<style name="ArcTheme" parent="android:Theme.Material.NoActionBar">
|
||||||
<item name="android:windowBackground">@android:color/transparent</item>
|
<item name="android:windowBackground">@android:color/transparent</item>
|
||||||
<item name="android:colorBackgroundCacheHint">@null</item>
|
<item name="android:colorBackgroundCacheHint">@null</item>
|
||||||
<item name="android:windowAnimationStyle">@android:style/Animation</item>
|
<item name="android:windowAnimationStyle">@android:style/Animation</item>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="GdxTheme" parent="android:Theme">
|
<style name="ArcTheme" parent="android:Theme">
|
||||||
<item name="android:windowBackground">@android:color/transparent</item>
|
<item name="android:windowBackground">@android:color/transparent</item>
|
||||||
<item name="android:colorBackgroundCacheHint">@null</item>
|
<item name="android:colorBackgroundCacheHint">@null</item>
|
||||||
<item name="android:windowAnimationStyle">@android:style/Animation</item>
|
<item name="android:windowAnimationStyle">@android:style/Animation</item>
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import mindustry.ui.dialogs.*;
|
|||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.System;
|
import java.lang.System;
|
||||||
|
import java.lang.Thread.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
@@ -37,6 +38,20 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState){
|
protected void onCreate(Bundle savedInstanceState){
|
||||||
|
UncaughtExceptionHandler handler = Thread.getDefaultUncaughtExceptionHandler();
|
||||||
|
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler((thread, error) -> {
|
||||||
|
CrashSender.log(error);
|
||||||
|
|
||||||
|
//try to forward exception to system handler
|
||||||
|
if(handler != null){
|
||||||
|
handler.uncaughtException(thread, error);
|
||||||
|
}else{
|
||||||
|
error.printStackTrace();
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
if(doubleScaleTablets && isTablet(this.getContext())){
|
if(doubleScaleTablets && isTablet(this.getContext())){
|
||||||
Scl.setAddition(0.5f);
|
Scl.setAddition(0.5f);
|
||||||
@@ -50,25 +65,7 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUUID(){
|
public rhino.Context getScriptContext(){
|
||||||
try{
|
|
||||||
String s = Secure.getString(getContext().getContentResolver(), Secure.ANDROID_ID);
|
|
||||||
int len = s.length();
|
|
||||||
byte[] data = new byte[len / 2];
|
|
||||||
for(int i = 0; i < len; i += 2){
|
|
||||||
data[i / 2] = (byte)((Character.digit(s.charAt(i), 16) << 4)
|
|
||||||
+ Character.digit(s.charAt(i + 1), 16));
|
|
||||||
}
|
|
||||||
String result = new String(Base64Coder.encode(data));
|
|
||||||
if(result.equals("AAAAAAAAAOA=")) throw new RuntimeException("Bad UUID.");
|
|
||||||
return result;
|
|
||||||
}catch(Exception e){
|
|
||||||
return super.getUUID();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public org.mozilla.javascript.Context getScriptContext(){
|
|
||||||
return AndroidRhinoContext.enter(getContext().getCacheDir());
|
return AndroidRhinoContext.enter(getContext().getCacheDir());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +108,7 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
});
|
});
|
||||||
}else if(VERSION.SDK_INT >= VERSION_CODES.M && !(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
|
}else if(VERSION.SDK_INT >= 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 = new FileChooser(open ? "$open" : "$save", file -> file.extension().equalsIgnoreCase(extension), open, file -> {
|
chooser = new FileChooser(open ? "@open" : "@save", file -> file.extension().equalsIgnoreCase(extension), open, file -> {
|
||||||
if(!open){
|
if(!open){
|
||||||
cons.get(file.parent().child(file.nameWithoutExtension() + "." + extension));
|
cons.get(file.parent().child(file.nameWithoutExtension() + "." + extension));
|
||||||
}else{
|
}else{
|
||||||
@@ -144,9 +141,8 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
|
|
||||||
}, new AndroidApplicationConfiguration(){{
|
}, new AndroidApplicationConfiguration(){{
|
||||||
useImmersiveMode = true;
|
useImmersiveMode = true;
|
||||||
depth = 0;
|
|
||||||
hideStatusBar = true;
|
hideStatusBar = true;
|
||||||
errorHandler = CrashSender::log;
|
stencil = 8;
|
||||||
}});
|
}});
|
||||||
checkFiles(getIntent());
|
checkFiles(getIntent());
|
||||||
|
|
||||||
@@ -220,10 +216,10 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
SaveSlot slot = control.saves.importSave(file);
|
SaveSlot slot = control.saves.importSave(file);
|
||||||
ui.load.runLoadSave(slot);
|
ui.load.runLoadSave(slot);
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
ui.showException("$save.import.fail", e);
|
ui.showException("@save.import.fail", e);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
ui.showErrorMessage("$save.import.invalid");
|
ui.showErrorMessage("@save.import.invalid");
|
||||||
}
|
}
|
||||||
}else if(map){ //open map
|
}else if(map){ //open map
|
||||||
Fi file = Core.files.local("temp-map." + mapExtension);
|
Fi file = Core.files.local("temp-map." + mapExtension);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import com.android.dx.dex.cf.*;
|
|||||||
import com.android.dx.dex.file.DexFile;
|
import com.android.dx.dex.file.DexFile;
|
||||||
import com.android.dx.merge.*;
|
import com.android.dx.merge.*;
|
||||||
import dalvik.system.*;
|
import dalvik.system.*;
|
||||||
import org.mozilla.javascript.*;
|
import rhino.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
@@ -41,6 +41,11 @@ public class AndroidRhinoContext{
|
|||||||
public Object getDynamicSecurityDomain(Object o){
|
public Object getDynamicSecurityDomain(Object o){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object callWithDomain(Object o, Context context, Callable callable, Scriptable scriptable, Scriptable scriptable1, Object[] objects){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AndroidContextFactory factory;
|
AndroidContextFactory factory;
|
||||||
@@ -121,7 +126,7 @@ public class AndroidRhinoContext{
|
|||||||
}
|
}
|
||||||
return loadClass(dex, name);
|
return loadClass(dex, name);
|
||||||
}catch(IOException | ClassNotFoundException e){
|
}catch(IOException | ClassNotFoundException e){
|
||||||
throw new FatalLoadingException(e);
|
throw new RuntimeException("Failed to define class", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,14 +156,6 @@ public class AndroidRhinoContext{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Might be thrown in any Rhino method that loads bytecode if the loading failed. */
|
|
||||||
public static class FatalLoadingException extends RuntimeException{
|
|
||||||
FatalLoadingException(Throwable t){
|
|
||||||
super("Failed to define class", t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class FileAndroidClassLoader extends BaseAndroidClassLoader{
|
static class FileAndroidClassLoader extends BaseAndroidClassLoader{
|
||||||
private static int instanceCounter = 0;
|
private static int instanceCounter = 0;
|
||||||
private final File dexFile;
|
private final File dexFile;
|
||||||
|
|||||||
@@ -1,6 +1,2 @@
|
|||||||
apply plugin: "java"
|
|
||||||
|
|
||||||
sourceCompatibility = 1.8
|
|
||||||
sourceSets.main.java.srcDirs = ["src/main/java/"]
|
sourceSets.main.java.srcDirs = ["src/main/java/"]
|
||||||
sourceSets.main.resources.srcDirs = ["src/main/resources/"]
|
sourceSets.main.resources.srcDirs = ["src/main/resources/"]
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,67 @@ import java.lang.annotation.*;
|
|||||||
public class Annotations{
|
public class Annotations{
|
||||||
//region entity interfaces
|
//region entity interfaces
|
||||||
|
|
||||||
|
/** Indicates that a method overrides other methods. */
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface Replace{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Indicates that a method should be final in all implementing classes. */
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface Final{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Indicates that a field will be interpolated when synced. */
|
||||||
|
@Target({ElementType.FIELD})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface SyncField{
|
||||||
|
/** If true, the field will be linearly interpolated. If false, it will be interpolated as an angle. */
|
||||||
|
boolean value();
|
||||||
|
/** If true, the field is clamped to 0-1. */
|
||||||
|
boolean clamped() default false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Indicates that a field will not be read from the server when syncing the local player state. */
|
||||||
|
@Target({ElementType.FIELD})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface SyncLocal{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Indicates that a component field is imported from other components. This means it doesn't actually exist. */
|
||||||
|
@Target({ElementType.FIELD})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface Import{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Indicates that a component field is read-only. */
|
||||||
|
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface ReadOnly{
|
||||||
|
}
|
||||||
|
|
||||||
/** Indicates multiple inheritance on a component type. */
|
/** Indicates multiple inheritance on a component type. */
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface Depends{
|
public @interface Component{
|
||||||
Class[] value();
|
/** Whether to generate a base class for this components.
|
||||||
|
* An entity cannot have two base classes, so only one component can have base be true. */
|
||||||
|
boolean base() default false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Indicates that a method is implemented by the annotation processor. */
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface InternalImpl{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Indicates priority of a method in an entity. Methods with higher priority are done last. */
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface MethodPriority{
|
||||||
|
float value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Indicates that a component def is present on all entities. */
|
/** Indicates that a component def is present on all entities. */
|
||||||
@@ -18,11 +74,30 @@ public class Annotations{
|
|||||||
public @interface BaseComponent{
|
public @interface BaseComponent{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Creates a group that only examines entities that have all the components listed. */
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface GroupDef{
|
||||||
|
Class[] value();
|
||||||
|
boolean collide() default false;
|
||||||
|
boolean spatial() default false;
|
||||||
|
boolean mapping() default false;
|
||||||
|
}
|
||||||
|
|
||||||
/** Indicates an entity definition. */
|
/** Indicates an entity definition. */
|
||||||
@Target(ElementType.TYPE)
|
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface EntityDef{
|
public @interface EntityDef{
|
||||||
|
/** List of component interfaces */
|
||||||
Class[] value();
|
Class[] value();
|
||||||
|
/** Whether the class is final */
|
||||||
|
boolean isFinal() default true;
|
||||||
|
/** If true, entities are recycled. */
|
||||||
|
boolean pooled() default false;
|
||||||
|
/** Whether to serialize (makes the serialize method return this value).
|
||||||
|
* If true, this entity is automatically put into save files.
|
||||||
|
* If false, no serialization code is generated at all. */
|
||||||
|
boolean serialize() default true;
|
||||||
|
/** Whether to generate IO code. This is for advanced usage only. */
|
||||||
|
boolean genio() default true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Indicates an internal interface for entity components. */
|
/** Indicates an internal interface for entity components. */
|
||||||
@@ -34,6 +109,32 @@ public class Annotations{
|
|||||||
//endregion
|
//endregion
|
||||||
//region misc. utility
|
//region misc. utility
|
||||||
|
|
||||||
|
/** Automatically loads block regions annotated with this. */
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface Load{
|
||||||
|
/**
|
||||||
|
* The region name to load. Variables can be used:
|
||||||
|
* "@" -> block name
|
||||||
|
* "$size" -> block size
|
||||||
|
* "#" "#1" "#2" -> index number, for arrays
|
||||||
|
* */
|
||||||
|
String value();
|
||||||
|
/** 1D Array length, if applicable. */
|
||||||
|
int length() default 1;
|
||||||
|
/** 2D array lengths. */
|
||||||
|
int[] lengths() default {};
|
||||||
|
/** Fallback string used to replace "@" (the block name) if the region isn't found. */
|
||||||
|
String fallback() default "error";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Registers a statement for auto serialization. */
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface RegisterStatement{
|
||||||
|
String value();
|
||||||
|
}
|
||||||
|
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface StyleDefaults{
|
public @interface StyleDefaults{
|
||||||
@@ -52,13 +153,6 @@ public class Annotations{
|
|||||||
public @interface OverrideCallSuper{
|
public @interface OverrideCallSuper{
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Marks a class as serializable. */
|
|
||||||
@Target(ElementType.TYPE)
|
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
|
||||||
public @interface Serialize{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
//region struct
|
//region struct
|
||||||
|
|
||||||
@@ -140,7 +234,7 @@ public class Annotations{
|
|||||||
/** The local locations where this method is called locally, when invoked. */
|
/** The local locations where this method is called locally, when invoked. */
|
||||||
Loc called() default Loc.none;
|
Loc called() default Loc.none;
|
||||||
|
|
||||||
/** Whether to forward this packet to all other clients upon recieval. Client only. */
|
/** Whether to forward this packet to all other clients upon receival. Client only. */
|
||||||
boolean forward() default false;
|
boolean forward() default false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -153,26 +247,9 @@ public class Annotations{
|
|||||||
PacketPriority priority() default PacketPriority.normal;
|
PacketPriority priority() default PacketPriority.normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Target(ElementType.TYPE)
|
||||||
* 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)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface WriteClass{
|
public @interface TypeIOHandler{
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|||||||
@@ -1,19 +1,28 @@
|
|||||||
package mindustry.annotations;
|
package mindustry.annotations;
|
||||||
|
|
||||||
|
import arc.files.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
|
import arc.util.Log;
|
||||||
|
import arc.util.Log.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import com.squareup.javapoet.*;
|
import com.squareup.javapoet.*;
|
||||||
import com.sun.source.util.*;
|
import com.sun.source.util.*;
|
||||||
|
import com.sun.tools.javac.model.*;
|
||||||
|
import com.sun.tools.javac.processing.*;
|
||||||
|
import com.sun.tools.javac.tree.*;
|
||||||
|
import com.sun.tools.javac.util.*;
|
||||||
import mindustry.annotations.util.*;
|
import mindustry.annotations.util.*;
|
||||||
|
|
||||||
import javax.annotation.processing.*;
|
import javax.annotation.processing.*;
|
||||||
import javax.lang.model.*;
|
import javax.lang.model.*;
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
|
import javax.lang.model.type.*;
|
||||||
import javax.lang.model.util.*;
|
import javax.lang.model.util.*;
|
||||||
import javax.tools.Diagnostic.*;
|
import javax.tools.Diagnostic.*;
|
||||||
import javax.tools.*;
|
import javax.tools.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
import java.util.List;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
||||||
@@ -22,14 +31,18 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
|||||||
public static final String packageName = "mindustry.gen";
|
public static final String packageName = "mindustry.gen";
|
||||||
|
|
||||||
public static Types typeu;
|
public static Types typeu;
|
||||||
public static Elements elementu;
|
public static JavacElements elementu;
|
||||||
public static Filer filer;
|
public static Filer filer;
|
||||||
public static Messager messager;
|
public static Messager messager;
|
||||||
public static Trees trees;
|
public static Trees trees;
|
||||||
|
public static TreeMaker maker;
|
||||||
|
|
||||||
protected int round;
|
protected int round;
|
||||||
protected int rounds = 1;
|
protected int rounds = 1;
|
||||||
protected RoundEnvironment env;
|
protected RoundEnvironment env;
|
||||||
|
protected Fi rootDirectory;
|
||||||
|
|
||||||
|
protected Context context;
|
||||||
|
|
||||||
public static String getMethodName(Element element){
|
public static String getMethodName(Element element){
|
||||||
return ((TypeElement)element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName();
|
return ((TypeElement)element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName();
|
||||||
@@ -40,16 +53,90 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
|||||||
|| type.equals("long") || type.equals("float") || type.equals("double") || type.equals("char");
|
|| type.equals("long") || type.equals("float") || type.equals("double") || type.equals("char");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean instanceOf(String type, String other){
|
||||||
|
TypeElement a = elementu.getTypeElement(type);
|
||||||
|
TypeElement b = elementu.getTypeElement(other);
|
||||||
|
return a != null && b != null && typeu.isSubtype(a.asType(), b.asType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getDefault(String value){
|
||||||
|
switch(value){
|
||||||
|
case "float":
|
||||||
|
case "double":
|
||||||
|
case "int":
|
||||||
|
case "long":
|
||||||
|
case "short":
|
||||||
|
case "char":
|
||||||
|
case "byte":
|
||||||
|
return "0";
|
||||||
|
case "boolean":
|
||||||
|
return "false";
|
||||||
|
default:
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//in bytes
|
||||||
|
public static int typeSize(String kind){
|
||||||
|
switch(kind){
|
||||||
|
case "boolean":
|
||||||
|
case "byte":
|
||||||
|
return 1;
|
||||||
|
case "short":
|
||||||
|
return 2;
|
||||||
|
case "float":
|
||||||
|
case "char":
|
||||||
|
case "int":
|
||||||
|
return 4;
|
||||||
|
case "long":
|
||||||
|
return 8;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Invalid primitive type: " + kind + "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String simpleName(String str){
|
||||||
|
return str.contains(".") ? str.substring(str.lastIndexOf('.') + 1) : str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TypeName tname(String pack, String simple){
|
||||||
|
return ClassName.get(pack, simple );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TypeName tname(String name){
|
||||||
|
if(!name.contains(".")) return ClassName.get(packageName, name);
|
||||||
|
|
||||||
|
String pack = name.substring(0, name.lastIndexOf("."));
|
||||||
|
String simple = name.substring(name.lastIndexOf(".") + 1);
|
||||||
|
return ClassName.get(pack, simple);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TypeName tname(Class<?> c){
|
||||||
|
return ClassName.get(c).box();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TypeVariableName getTVN(TypeParameterElement element) {
|
||||||
|
String name = element.getSimpleName().toString();
|
||||||
|
List<? extends TypeMirror> boundsMirrors = element.getBounds();
|
||||||
|
|
||||||
|
List<TypeName> boundsTypeNames = new ArrayList<>();
|
||||||
|
for (TypeMirror typeMirror : boundsMirrors) {
|
||||||
|
boundsTypeNames.add(TypeName.get(typeMirror));
|
||||||
|
}
|
||||||
|
|
||||||
|
return TypeVariableName.get(name, boundsTypeNames.toArray(new TypeName[0]));
|
||||||
|
}
|
||||||
|
|
||||||
public static void write(TypeSpec.Builder builder) throws Exception{
|
public static void write(TypeSpec.Builder builder) throws Exception{
|
||||||
write(builder, null);
|
write(builder, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void write(TypeSpec.Builder builder, Array<String> imports) throws Exception{
|
public static void write(TypeSpec.Builder builder, Seq<String> imports) throws Exception{
|
||||||
JavaFile file = JavaFile.builder(packageName, builder.build()).skipJavaLangImports(true).build();
|
JavaFile file = JavaFile.builder(packageName, builder.build()).skipJavaLangImports(true).build();
|
||||||
|
|
||||||
if(imports != null){
|
if(imports != null){
|
||||||
String rawSource = file.toString();
|
String rawSource = file.toString();
|
||||||
Array<String> result = new Array<>();
|
Seq<String> result = new Seq<>();
|
||||||
for (String s : rawSource.split("\n", -1)) {
|
for (String s : rawSource.split("\n", -1)) {
|
||||||
result.add(s);
|
result.add(s);
|
||||||
if (s.startsWith("package ")) {
|
if (s.startsWith("package ")) {
|
||||||
@@ -70,27 +157,31 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array<Stype> types(Class<? extends Annotation> type){
|
public Seq<Selement> elements(Class<? extends Annotation> type){
|
||||||
return Array.with(env.getElementsAnnotatedWith(type)).select(e -> e instanceof TypeElement)
|
return Seq.with(env.getElementsAnnotatedWith(type)).map(Selement::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Seq<Stype> types(Class<? extends Annotation> type){
|
||||||
|
return Seq.with(env.getElementsAnnotatedWith(type)).select(e -> e instanceof TypeElement)
|
||||||
.map(e -> new Stype((TypeElement)e));
|
.map(e -> new Stype((TypeElement)e));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array<Svar> fields(Class<? extends Annotation> type){
|
public Seq<Svar> fields(Class<? extends Annotation> type){
|
||||||
return Array.with(env.getElementsAnnotatedWith(type)).select(e -> e instanceof VariableElement)
|
return Seq.with(env.getElementsAnnotatedWith(type)).select(e -> e instanceof VariableElement)
|
||||||
.map(e -> new Svar((VariableElement)e));
|
.map(e -> new Svar((VariableElement)e));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array<Smethod> methods(Class<? extends Annotation> type){
|
public Seq<Smethod> methods(Class<? extends Annotation> type){
|
||||||
return Array.with(env.getElementsAnnotatedWith(type)).select(e -> e instanceof ExecutableElement)
|
return Seq.with(env.getElementsAnnotatedWith(type)).select(e -> e instanceof ExecutableElement)
|
||||||
.map(e -> new Smethod((ExecutableElement)e));
|
.map(e -> new Smethod((ExecutableElement)e));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void err(String message){
|
public static void err(String message){
|
||||||
messager.printMessage(Kind.ERROR, message);
|
messager.printMessage(Kind.ERROR, message);
|
||||||
Log.err("[CODEGEN ERROR] " +message);
|
Log.err("[CODEGEN ERROR] " +message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void err(String message, Element elem){
|
public static void err(String message, Element elem){
|
||||||
messager.printMessage(Kind.ERROR, message, elem);
|
messager.printMessage(Kind.ERROR, message, elem);
|
||||||
Log.err("[CODEGEN ERROR] " + message + ": " + elem);
|
Log.err("[CODEGEN ERROR] " + message + ": " + elem);
|
||||||
}
|
}
|
||||||
@@ -103,20 +194,41 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
|||||||
public synchronized void init(ProcessingEnvironment env){
|
public synchronized void init(ProcessingEnvironment env){
|
||||||
super.init(env);
|
super.init(env);
|
||||||
|
|
||||||
|
JavacProcessingEnvironment javacProcessingEnv = (JavacProcessingEnvironment)env;
|
||||||
|
|
||||||
trees = Trees.instance(env);
|
trees = Trees.instance(env);
|
||||||
typeu = env.getTypeUtils();
|
typeu = env.getTypeUtils();
|
||||||
elementu = env.getElementUtils();
|
elementu = javacProcessingEnv.getElementUtils();
|
||||||
filer = env.getFiler();
|
filer = env.getFiler();
|
||||||
messager = env.getMessager();
|
messager = env.getMessager();
|
||||||
|
context = ((JavacProcessingEnvironment)env).getContext();
|
||||||
|
maker = TreeMaker.instance(javacProcessingEnv.getContext());
|
||||||
|
|
||||||
|
Log.setLogLevel(LogLevel.info);
|
||||||
|
|
||||||
|
if(System.getProperty("debug") != null){
|
||||||
|
Log.setLogLevel(LogLevel.debug);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
|
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
|
||||||
if(round++ >= rounds) return false; //only process 1 round
|
if(round++ >= rounds) return false; //only process 1 round
|
||||||
|
if(rootDirectory == null){
|
||||||
|
try{
|
||||||
|
String path = Fi.get(filer.getResource(StandardLocation.CLASS_OUTPUT, "no", "no")
|
||||||
|
.toUri().toURL().toString().substring(OS.isWindows ? 6 : "file:".length()))
|
||||||
|
.parent().parent().parent().parent().parent().parent().parent().toString().replace("%20", " ");
|
||||||
|
rootDirectory = Fi.get(path);
|
||||||
|
}catch(IOException e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.env = roundEnv;
|
this.env = roundEnv;
|
||||||
try{
|
try{
|
||||||
process(roundEnv);
|
process(roundEnv);
|
||||||
}catch(Exception e){
|
}catch(Throwable e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,346 @@
|
|||||||
|
package mindustry.annotations.entity;
|
||||||
|
|
||||||
|
import arc.files.*;
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import arc.util.serialization.*;
|
||||||
|
import com.squareup.javapoet.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.annotations.*;
|
||||||
|
import mindustry.annotations.util.*;
|
||||||
|
import mindustry.annotations.util.TypeIOResolver.*;
|
||||||
|
|
||||||
|
import javax.lang.model.element.*;
|
||||||
|
|
||||||
|
import static mindustry.annotations.BaseProcessor.instanceOf;
|
||||||
|
|
||||||
|
public class EntityIO{
|
||||||
|
final static Json json = new Json();
|
||||||
|
//suffixes for sync fields
|
||||||
|
final static String targetSuf = "_TARGET_", lastSuf = "_LAST_";
|
||||||
|
//replacements after refactoring
|
||||||
|
final static StringMap replacements = StringMap.of("mindustry.entities.units.BuildRequest", "mindustry.entities.units.BuildPlan");
|
||||||
|
|
||||||
|
final ClassSerializer serializer;
|
||||||
|
final String name;
|
||||||
|
final TypeSpec.Builder type;
|
||||||
|
final Fi directory;
|
||||||
|
final Seq<Revision> revisions = new Seq<>();
|
||||||
|
|
||||||
|
boolean write;
|
||||||
|
MethodSpec.Builder method;
|
||||||
|
ObjectSet<String> presentFields = new ObjectSet<>();
|
||||||
|
|
||||||
|
EntityIO(String name, TypeSpec.Builder type, Seq<FieldSpec> typeFields, ClassSerializer serializer, Fi directory){
|
||||||
|
this.directory = directory;
|
||||||
|
this.type = type;
|
||||||
|
this.serializer = serializer;
|
||||||
|
this.name = name;
|
||||||
|
|
||||||
|
directory.mkdirs();
|
||||||
|
|
||||||
|
//load old revisions
|
||||||
|
for(Fi fi : directory.list()){
|
||||||
|
revisions.add(json.fromJson(Revision.class, fi));
|
||||||
|
}
|
||||||
|
|
||||||
|
//next revision to be used
|
||||||
|
int nextRevision = revisions.isEmpty() ? 0 : revisions.max(r -> r.version).version + 1;
|
||||||
|
|
||||||
|
//resolve preferred field order based on fields that fit
|
||||||
|
Seq<FieldSpec> fields = typeFields.select(spec ->
|
||||||
|
!spec.hasModifier(Modifier.TRANSIENT) &&
|
||||||
|
!spec.hasModifier(Modifier.STATIC) &&
|
||||||
|
!spec.hasModifier(Modifier.FINAL)/* &&
|
||||||
|
(spec.type.isPrimitive() || serializer.has(spec.type.toString()))*/);
|
||||||
|
|
||||||
|
//sort to keep order
|
||||||
|
fields.sortComparing(f -> f.name);
|
||||||
|
|
||||||
|
//keep track of fields present in the entity
|
||||||
|
presentFields.addAll(fields.map(f -> f.name));
|
||||||
|
|
||||||
|
//add new revision if it doesn't match or there are no revisions
|
||||||
|
if(revisions.isEmpty() || !revisions.peek().equal(fields)){
|
||||||
|
revisions.add(new Revision(nextRevision,
|
||||||
|
fields.map(f -> new RevisionField(f.name, f.type.toString(),
|
||||||
|
f.type.isPrimitive() ? BaseProcessor.typeSize(f.type.toString()) : -1))));
|
||||||
|
//write revision
|
||||||
|
directory.child(nextRevision + ".json").writeString(json.toJson(revisions.peek()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(MethodSpec.Builder method, boolean write) throws Exception{
|
||||||
|
this.method = method;
|
||||||
|
this.write = write;
|
||||||
|
|
||||||
|
//subclasses *have* to call this method
|
||||||
|
method.addAnnotation(CallSuper.class);
|
||||||
|
|
||||||
|
if(write){
|
||||||
|
//write short revision
|
||||||
|
st("write.s($L)", revisions.peek().version);
|
||||||
|
//write uses most recent revision
|
||||||
|
for(RevisionField field : revisions.peek().fields){
|
||||||
|
io(field.type, "this." + field.name);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
//read revision
|
||||||
|
st("short REV = read.s()");
|
||||||
|
|
||||||
|
for(int i = 0; i < revisions.size; i++){
|
||||||
|
//check for the right revision
|
||||||
|
Revision rev = revisions.get(i);
|
||||||
|
if(i == 0){
|
||||||
|
cont("if(REV == $L)", rev.version);
|
||||||
|
}else{
|
||||||
|
ncont("else if(REV == $L)", rev.version);
|
||||||
|
}
|
||||||
|
|
||||||
|
//add code for reading revision
|
||||||
|
for(RevisionField field : rev.fields){
|
||||||
|
//if the field doesn't exist, the result will be an empty string, it won't get assigned
|
||||||
|
io(field.type, presentFields.contains(field.name) ? "this." + field.name + " = " : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//throw exception on illegal revisions
|
||||||
|
ncont("else");
|
||||||
|
st("throw new IllegalArgumentException(\"Unknown revision '\" + REV + \"' for entity type '" + name + "'\")");
|
||||||
|
econt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeSync(MethodSpec.Builder method, boolean write, Seq<Svar> syncFields, Seq<Svar> allFields) throws Exception{
|
||||||
|
this.method = method;
|
||||||
|
this.write = write;
|
||||||
|
|
||||||
|
if(write){
|
||||||
|
//write uses most recent revision
|
||||||
|
for(RevisionField field : revisions.peek().fields){
|
||||||
|
io(field.type, "this." + field.name);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Revision rev = revisions.peek();
|
||||||
|
|
||||||
|
//base read code
|
||||||
|
st("if(lastUpdated != 0) updateSpacing = $T.timeSinceMillis(lastUpdated)", Time.class);
|
||||||
|
st("lastUpdated = $T.millis()", Time.class);
|
||||||
|
st("boolean islocal = isLocal()");
|
||||||
|
|
||||||
|
//add code for reading revision
|
||||||
|
for(RevisionField field : rev.fields){
|
||||||
|
Svar var = allFields.find(s -> s.name().equals(field.name));
|
||||||
|
boolean sf = var.has(SyncField.class), sl = var.has(SyncLocal.class);
|
||||||
|
|
||||||
|
if(sl) cont("if(!islocal)");
|
||||||
|
|
||||||
|
if(sf){
|
||||||
|
st(field.name + lastSuf + " = this." + field.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
io(field.type, "this." + (sf ? field.name + targetSuf : field.name) + " = ");
|
||||||
|
|
||||||
|
if(sl){
|
||||||
|
ncont("else" );
|
||||||
|
|
||||||
|
io(field.type, "");
|
||||||
|
|
||||||
|
//just assign the two values so jumping does not occur on de-possession
|
||||||
|
if(sf){
|
||||||
|
st(field.name + lastSuf + " = this." + field.name);
|
||||||
|
st(field.name + targetSuf + " = this." + field.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
econt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
st("afterSync()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeSyncManual(MethodSpec.Builder method, boolean write, Seq<Svar> syncFields) throws Exception{
|
||||||
|
this.method = method;
|
||||||
|
this.write = write;
|
||||||
|
|
||||||
|
if(write){
|
||||||
|
for(Svar field : syncFields){
|
||||||
|
st("buffer.put(this.$L)", field.name());
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
//base read code
|
||||||
|
st("if(lastUpdated != 0) updateSpacing = $T.timeSinceMillis(lastUpdated)", Time.class);
|
||||||
|
st("lastUpdated = $T.millis()", Time.class);
|
||||||
|
|
||||||
|
//just read the field
|
||||||
|
for(Svar field : syncFields){
|
||||||
|
//last
|
||||||
|
st("this.$L = this.$L", field.name() + lastSuf, field.name());
|
||||||
|
//assign target
|
||||||
|
st("this.$L = buffer.get()", field.name() + targetSuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeInterpolate(MethodSpec.Builder method, Seq<Svar> fields) throws Exception{
|
||||||
|
this.method = method;
|
||||||
|
|
||||||
|
cont("if(lastUpdated != 0 && updateSpacing != 0)");
|
||||||
|
|
||||||
|
//base calculations
|
||||||
|
st("float timeSinceUpdate = Time.timeSinceMillis(lastUpdated)");
|
||||||
|
st("float alpha = Math.min(timeSinceUpdate / updateSpacing, 2f)");
|
||||||
|
|
||||||
|
//write interpolated data, using slerp / lerp
|
||||||
|
for(Svar field : fields){
|
||||||
|
String name = field.name(), targetName = name + targetSuf, lastName = name + lastSuf;
|
||||||
|
st("$L = $L($T.$L($L, $L, alpha))", name, field.annotation(SyncField.class).clamped() ? "arc.math.Mathf.clamp" : "", Mathf.class, field.annotation(SyncField.class).value() ? "lerp" : "slerp", lastName, targetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
ncont("else if(lastUpdated != 0)"); //check if no meaningful data has arrived yet
|
||||||
|
|
||||||
|
//write values directly to targets
|
||||||
|
for(Svar field : fields){
|
||||||
|
String name = field.name(), targetName = name + targetSuf;
|
||||||
|
st("$L = $L", name, targetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
econt();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void io(String type, String field) throws Exception{
|
||||||
|
type = type.replace("mindustry.gen.", "");
|
||||||
|
type = replacements.get(type, type);
|
||||||
|
|
||||||
|
if(BaseProcessor.isPrimitive(type)){
|
||||||
|
s(type.equals("boolean") ? "bool" : type.charAt(0) + "", field);
|
||||||
|
}else if(instanceOf(type, "mindustry.ctype.Content")){
|
||||||
|
if(write){
|
||||||
|
s("s", field + ".id");
|
||||||
|
}else{
|
||||||
|
st(field + "mindustry.Vars.content.getByID(mindustry.ctype.ContentType.$L, read.s())", BaseProcessor.simpleName(type).toLowerCase().replace("type", ""));
|
||||||
|
}
|
||||||
|
}else if(serializer.writers.containsKey(type) && write){
|
||||||
|
st("$L(write, $L)", serializer.writers.get(type), field);
|
||||||
|
}else if(serializer.mutatorReaders.containsKey(type) && !write && !field.replace(" = ", "").contains(" ") && !field.isEmpty()){
|
||||||
|
st("$L$L(read, $L)", field, serializer.mutatorReaders.get(type), field.replace(" = ", ""));
|
||||||
|
}else if(serializer.readers.containsKey(type) && !write){
|
||||||
|
st("$L$L(read)", field, serializer.readers.get(type));
|
||||||
|
}else if(type.endsWith("[]")){ //it's a 1D array
|
||||||
|
String rawType = type.substring(0, type.length() - 2);
|
||||||
|
|
||||||
|
if(write){
|
||||||
|
s("i", field + ".length");
|
||||||
|
cont("for(int INDEX = 0; INDEX < $L.length; INDEX ++)", field);
|
||||||
|
io(rawType, field + "[INDEX]");
|
||||||
|
}else{
|
||||||
|
String fieldName = field.replace(" = ", "").replace("this.", "");
|
||||||
|
String lenf = fieldName + "_LENGTH";
|
||||||
|
s("i", "int " + lenf + " = ");
|
||||||
|
if(!field.isEmpty()){
|
||||||
|
st("$Lnew $L[$L]", field, type.replace("[]", ""), lenf);
|
||||||
|
}
|
||||||
|
cont("for(int INDEX = 0; INDEX < $L; INDEX ++)", lenf);
|
||||||
|
io(rawType, field.replace(" = ", "[INDEX] = "));
|
||||||
|
}
|
||||||
|
|
||||||
|
econt();
|
||||||
|
}else if(type.startsWith("arc.struct") && type.contains("<")){ //it's some type of data structure
|
||||||
|
String struct = type.substring(0, type.indexOf("<"));
|
||||||
|
String generic = type.substring(type.indexOf("<") + 1, type.indexOf(">"));
|
||||||
|
|
||||||
|
if(struct.equals("arc.struct.Queue") || struct.equals("arc.struct.Seq")){
|
||||||
|
if(write){
|
||||||
|
s("i", field + ".size");
|
||||||
|
cont("for(int INDEX = 0; INDEX < $L.size; INDEX ++)", field);
|
||||||
|
io(generic, field + ".get(INDEX)");
|
||||||
|
}else{
|
||||||
|
String fieldName = field.replace(" = ", "").replace("this.", "");
|
||||||
|
String lenf = fieldName + "_LENGTH";
|
||||||
|
s("i", "int " + lenf + " = ");
|
||||||
|
if(!field.isEmpty()){
|
||||||
|
st("$L.clear()", field.replace(" = ", ""));
|
||||||
|
}
|
||||||
|
cont("for(int INDEX = 0; INDEX < $L; INDEX ++)", lenf);
|
||||||
|
io(generic, field.replace(" = ", "_ITEM = ").replace("this.", generic + " "));
|
||||||
|
if(!field.isEmpty()){
|
||||||
|
String temp = field.replace(" = ", "_ITEM").replace("this.", "");
|
||||||
|
st("if($L != null) $L.add($L)", temp, field.replace(" = ", ""), temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
econt();
|
||||||
|
}else{
|
||||||
|
Log.warn("Missing serialization code for collection '@' in '@'", type, name);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Log.warn("Missing serialization code for type '@' in '@'", type, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cont(String text, Object... fmt){
|
||||||
|
method.beginControlFlow(text, fmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void econt(){
|
||||||
|
method.endControlFlow();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ncont(String text, Object... fmt){
|
||||||
|
method.nextControlFlow(text, fmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void st(String text, Object... args){
|
||||||
|
method.addStatement(text, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void s(String type, String field){
|
||||||
|
if(write){
|
||||||
|
method.addStatement("write.$L($L)", type, field);
|
||||||
|
}else{
|
||||||
|
method.addStatement("$Lread.$L()", field, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Revision{
|
||||||
|
int version;
|
||||||
|
Seq<RevisionField> fields;
|
||||||
|
|
||||||
|
Revision(int version, Seq<RevisionField> fields){
|
||||||
|
this.version = version;
|
||||||
|
this.fields = fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
Revision(){}
|
||||||
|
|
||||||
|
/** @return whether these two revisions are compatible */
|
||||||
|
boolean equal(Seq<FieldSpec> specs){
|
||||||
|
if(fields.size != specs.size) return false;
|
||||||
|
|
||||||
|
for(int i = 0; i < fields.size; i++){
|
||||||
|
RevisionField field = fields.get(i);
|
||||||
|
FieldSpec spec = specs.get(i);
|
||||||
|
//TODO when making fields, their primitive size may be overwritten by an annotation; check for that
|
||||||
|
if(!(field.type.equals(spec.type.toString()) && (!spec.type.isPrimitive() || BaseProcessor.typeSize(spec.type.toString()) == field.size))){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RevisionField{
|
||||||
|
String name, type;
|
||||||
|
int size; //in bytes
|
||||||
|
|
||||||
|
RevisionField(String name, String type, int size){
|
||||||
|
this.name = name;
|
||||||
|
this.size = size;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
RevisionField(){}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,946 @@
|
|||||||
|
package mindustry.annotations.entity;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
|
import arc.files.*;
|
||||||
|
import arc.func.*;
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.util.ArcAnnotate.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import arc.util.io.*;
|
||||||
|
import arc.util.pooling.Pool.*;
|
||||||
|
import arc.util.pooling.*;
|
||||||
|
import com.squareup.javapoet.*;
|
||||||
|
import com.squareup.javapoet.TypeSpec.*;
|
||||||
|
import com.sun.source.tree.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.annotations.*;
|
||||||
|
import mindustry.annotations.util.*;
|
||||||
|
import mindustry.annotations.util.TypeIOResolver.*;
|
||||||
|
|
||||||
|
import javax.annotation.processing.*;
|
||||||
|
import javax.lang.model.element.*;
|
||||||
|
import javax.lang.model.type.*;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@SupportedAnnotationTypes({
|
||||||
|
"mindustry.annotations.Annotations.EntityDef",
|
||||||
|
"mindustry.annotations.Annotations.GroupDef",
|
||||||
|
"mindustry.annotations.Annotations.EntityInterface",
|
||||||
|
"mindustry.annotations.Annotations.BaseComponent",
|
||||||
|
"mindustry.annotations.Annotations.TypeIOHandler"
|
||||||
|
})
|
||||||
|
public class EntityProcess extends BaseProcessor{
|
||||||
|
Seq<EntityDefinition> definitions = new Seq<>();
|
||||||
|
Seq<GroupDefinition> groupDefs = new Seq<>();
|
||||||
|
Seq<Stype> baseComponents;
|
||||||
|
ObjectMap<String, Stype> componentNames = new ObjectMap<>();
|
||||||
|
ObjectMap<Stype, Seq<Stype>> componentDependencies = new ObjectMap<>();
|
||||||
|
ObjectMap<Selement, Seq<Stype>> defComponents = new ObjectMap<>();
|
||||||
|
ObjectMap<String, String> varInitializers = new ObjectMap<>();
|
||||||
|
ObjectMap<String, String> methodBlocks = new ObjectMap<>();
|
||||||
|
ObjectMap<Stype, ObjectSet<Stype>> baseClassDeps = new ObjectMap<>();
|
||||||
|
ObjectSet<String> imports = new ObjectSet<>();
|
||||||
|
Seq<Selement> allGroups = new Seq<>();
|
||||||
|
Seq<Selement> allDefs = new Seq<>();
|
||||||
|
Seq<Stype> allInterfaces = new Seq<>();
|
||||||
|
Seq<TypeSpec.Builder> baseClasses = new Seq<>();
|
||||||
|
ClassSerializer serializer;
|
||||||
|
|
||||||
|
{
|
||||||
|
rounds = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(RoundEnvironment env) throws Exception{
|
||||||
|
allGroups.addAll(elements(GroupDef.class));
|
||||||
|
allDefs.addAll(elements(EntityDef.class));
|
||||||
|
allInterfaces.addAll(types(EntityInterface.class));
|
||||||
|
|
||||||
|
//round 1: generate component interfaces
|
||||||
|
if(round == 1){
|
||||||
|
serializer = TypeIOResolver.resolve(this);
|
||||||
|
baseComponents = types(BaseComponent.class);
|
||||||
|
Seq<Stype> allComponents = types(Component.class);
|
||||||
|
|
||||||
|
//store code
|
||||||
|
for(Stype component : allComponents){
|
||||||
|
for(Svar f : component.fields()){
|
||||||
|
VariableTree tree = f.tree();
|
||||||
|
|
||||||
|
//add initializer if it exists
|
||||||
|
if(tree.getInitializer() != null){
|
||||||
|
String init = tree.getInitializer().toString();
|
||||||
|
varInitializers.put(f.descString(), init);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Smethod elem : component.methods()){
|
||||||
|
if(elem.is(Modifier.ABSTRACT) || elem.is(Modifier.NATIVE)) continue;
|
||||||
|
//get all statements in the method, store them
|
||||||
|
methodBlocks.put(elem.descString(), elem.tree().getBody().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//store components
|
||||||
|
for(Stype type : allComponents){
|
||||||
|
componentNames.put(type.name(), type);
|
||||||
|
}
|
||||||
|
|
||||||
|
//add component imports
|
||||||
|
for(Stype comp : allComponents){
|
||||||
|
imports.addAll(getImports(comp.e));
|
||||||
|
}
|
||||||
|
|
||||||
|
//create component interfaces
|
||||||
|
for(Stype component : allComponents){
|
||||||
|
TypeSpec.Builder inter = TypeSpec.interfaceBuilder(interfaceName(component))
|
||||||
|
.addModifiers(Modifier.PUBLIC).addAnnotation(EntityInterface.class);
|
||||||
|
|
||||||
|
inter.addJavadoc("Interface for {@link $L}", component.fullName());
|
||||||
|
|
||||||
|
//implement extra interfaces these components may have, e.g. position
|
||||||
|
for(Stype extraInterface : component.interfaces().select(i -> !isCompInterface(i))){
|
||||||
|
//javapoet completely chokes on this if I add `addSuperInterface` or create the type name with TypeName.get
|
||||||
|
inter.superinterfaces.add(tname(extraInterface.fullName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
//implement super interfaces
|
||||||
|
Seq<Stype> depends = getDependencies(component);
|
||||||
|
for(Stype type : depends){
|
||||||
|
inter.addSuperinterface(ClassName.get(packageName, interfaceName(type)));
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectSet<String> signatures = new ObjectSet<>();
|
||||||
|
|
||||||
|
//add utility methods to interface
|
||||||
|
for(Smethod method : component.methods()){
|
||||||
|
//skip private methods, those are for internal use.
|
||||||
|
if(method.isAny(Modifier.PRIVATE, Modifier.STATIC)) continue;
|
||||||
|
|
||||||
|
//keep track of signatures used to prevent dupes
|
||||||
|
signatures.add(method.e.toString());
|
||||||
|
|
||||||
|
inter.addMethod(MethodSpec.methodBuilder(method.name())
|
||||||
|
.addJavadoc(method.doc() == null ? "" : method.doc())
|
||||||
|
.addExceptions(method.thrownt())
|
||||||
|
.addTypeVariables(method.typeVariables().map(TypeVariableName::get))
|
||||||
|
.returns(method.ret().toString().equals("void") ? TypeName.VOID : method.retn())
|
||||||
|
.addParameters(method.params().map(v -> ParameterSpec.builder(v.tname(), v.name())
|
||||||
|
.build())).addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Svar field : component.fields().select(e -> !e.is(Modifier.STATIC) && !e.is(Modifier.PRIVATE) && !e.has(Import.class))){
|
||||||
|
String cname = field.name();
|
||||||
|
|
||||||
|
//getter
|
||||||
|
if(!signatures.contains(cname + "()")){
|
||||||
|
inter.addMethod(MethodSpec.methodBuilder(cname).addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC)
|
||||||
|
.addAnnotations(Seq.with(field.annotations()).select(a -> a.toString().contains("Null")).map(AnnotationSpec::get))
|
||||||
|
.addJavadoc(field.doc() == null ? "" : field.doc())
|
||||||
|
.returns(field.tname()).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
//setter
|
||||||
|
if(!field.is(Modifier.FINAL) && !signatures.contains(cname + "(" + field.mirror().toString() + ")") &&
|
||||||
|
!field.annotations().contains(f -> f.toString().equals("@mindustry.annotations.Annotations.ReadOnly"))){
|
||||||
|
inter.addMethod(MethodSpec.methodBuilder(cname).addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC)
|
||||||
|
.addJavadoc(field.doc() == null ? "" : field.doc())
|
||||||
|
.addParameter(ParameterSpec.builder(field.tname(), field.name())
|
||||||
|
.addAnnotations(Seq.with(field.annotations())
|
||||||
|
.select(a -> a.toString().contains("Null")).map(AnnotationSpec::get)).build()).build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write(inter);
|
||||||
|
|
||||||
|
//generate base class if necessary
|
||||||
|
//SPECIAL CASE: components with EntityDefs don't get a base class! the generated class becomes the base class itself
|
||||||
|
if(component.annotation(Component.class).base()){
|
||||||
|
|
||||||
|
Seq<Stype> deps = depends.copy().and(component);
|
||||||
|
baseClassDeps.get(component, ObjectSet::new).addAll(deps);
|
||||||
|
|
||||||
|
//do not generate base classes when the component will generate one itself
|
||||||
|
if(!component.has(EntityDef.class)){
|
||||||
|
TypeSpec.Builder base = TypeSpec.classBuilder(baseName(component)).addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT);
|
||||||
|
|
||||||
|
//go through all the fields.
|
||||||
|
for(Stype type : deps){
|
||||||
|
//add public fields
|
||||||
|
for(Svar field : type.fields().select(e -> !e.is(Modifier.STATIC) && !e.is(Modifier.PRIVATE) && !e.has(Import.class) && !e.has(ReadOnly.class))){
|
||||||
|
FieldSpec.Builder builder = FieldSpec.builder(field.tname(),field.name(), Modifier.PUBLIC);
|
||||||
|
|
||||||
|
//keep transience
|
||||||
|
if(field.is(Modifier.TRANSIENT)) builder.addModifiers(Modifier.TRANSIENT);
|
||||||
|
//keep all annotations
|
||||||
|
builder.addAnnotations(field.annotations().map(AnnotationSpec::get));
|
||||||
|
|
||||||
|
//add initializer if it exists
|
||||||
|
if(varInitializers.containsKey(field.descString())){
|
||||||
|
builder.initializer(varInitializers.get(field.descString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
base.addField(builder.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//add interfaces
|
||||||
|
for(Stype type : deps){
|
||||||
|
base.addSuperinterface(tname(packageName, interfaceName(type)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//add to queue to be written later
|
||||||
|
baseClasses.add(base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//LOGGING
|
||||||
|
|
||||||
|
Log.debug("&gGenerating interface for " + component.name());
|
||||||
|
|
||||||
|
for(TypeName tn : inter.superinterfaces){
|
||||||
|
Log.debug("&g> &lbimplements @", simpleName(tn.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
//log methods generated
|
||||||
|
for(MethodSpec spec : inter.methodSpecs){
|
||||||
|
Log.debug("&g> > &c@ @(@)", simpleName(spec.returnType.toString()), spec.name, Seq.with(spec.parameters).toString(", ", p -> simpleName(p.type.toString()) + " " + p.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.debug("");
|
||||||
|
}
|
||||||
|
|
||||||
|
}else if(round == 2){ //round 2: get component classes and generate interfaces for them
|
||||||
|
|
||||||
|
//parse groups
|
||||||
|
//this needs to be done before the entity interfaces are generated, as the entity classes need to know which groups to add themselves to
|
||||||
|
for(Selement<?> group : allGroups){
|
||||||
|
GroupDef an = group.annotation(GroupDef.class);
|
||||||
|
Seq<Stype> types = types(an, GroupDef::value).map(stype -> {
|
||||||
|
Stype result = interfaceToComp(stype);
|
||||||
|
if(result == null) throw new IllegalArgumentException("Interface " + stype + " does not have an associated component!");
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
//representative component type
|
||||||
|
Stype repr = types.first();
|
||||||
|
String groupType = repr.annotation(Component.class).base() ? baseName(repr) : interfaceName(repr);
|
||||||
|
|
||||||
|
boolean collides = an.collide();
|
||||||
|
groupDefs.add(new GroupDefinition(group.name().startsWith("g") ? group.name().substring(1) : group.name(),
|
||||||
|
ClassName.bestGuess(packageName + "." + groupType), types, an.spatial(), an.mapping(), collides));
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectMap<String, Selement> usedNames = new ObjectMap<>();
|
||||||
|
ObjectMap<Selement, ObjectSet<String>> extraNames = new ObjectMap<>();
|
||||||
|
|
||||||
|
//look at each definition
|
||||||
|
for(Selement<?> type : allDefs){
|
||||||
|
EntityDef ann = type.annotation(EntityDef.class);
|
||||||
|
boolean isFinal = ann.isFinal();
|
||||||
|
|
||||||
|
//all component classes (not interfaces)
|
||||||
|
Seq<Stype> components = allComponents(type);
|
||||||
|
Seq<GroupDefinition> groups = groupDefs.select(g -> (!g.components.isEmpty() && !g.components.contains(s -> !components.contains(s))) || g.manualInclusions.contains(type));
|
||||||
|
ObjectMap<String, Seq<Smethod>> methods = new ObjectMap<>();
|
||||||
|
ObjectMap<FieldSpec, Svar> specVariables = new ObjectMap<>();
|
||||||
|
ObjectSet<String> usedFields = new ObjectSet<>();
|
||||||
|
|
||||||
|
//make sure there's less than 2 base classes
|
||||||
|
Seq<Stype> baseClasses = components.select(s -> s.annotation(Component.class).base());
|
||||||
|
if(baseClasses.size > 2){
|
||||||
|
err("No entity may have more than 2 base classes. Base classes: " + baseClasses, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
//get base class type name for extension
|
||||||
|
Stype baseClassType = baseClasses.any() ? baseClasses.first() : null;
|
||||||
|
@Nullable TypeName baseClass = baseClasses.any() ? tname(packageName + "." + baseName(baseClassType)) : null;
|
||||||
|
//whether the main class is the base itself
|
||||||
|
boolean typeIsBase = baseClassType != null && type.has(Component.class) && type.annotation(Component.class).base();
|
||||||
|
|
||||||
|
if(type.isType() && (!type.name().endsWith("Def") && !type.name().endsWith("Comp"))){
|
||||||
|
err("All entity def names must end with 'Def'/'Comp'", type.e);
|
||||||
|
}
|
||||||
|
|
||||||
|
String name = type.isType() ?
|
||||||
|
type.name().replace("Def", "").replace("Comp", "") :
|
||||||
|
createName(type);
|
||||||
|
|
||||||
|
//check for type name conflicts
|
||||||
|
if(!typeIsBase && baseClass != null && name.equals(baseName(baseClassType))){
|
||||||
|
name += "Entity";
|
||||||
|
}
|
||||||
|
|
||||||
|
//skip double classes
|
||||||
|
if(usedNames.containsKey(name)){
|
||||||
|
extraNames.get(usedNames.get(name), ObjectSet::new).add(type.name());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
usedNames.put(name, type);
|
||||||
|
extraNames.get(type, ObjectSet::new).add(name);
|
||||||
|
if(!type.isType()){
|
||||||
|
extraNames.get(type, ObjectSet::new).add(type.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeSpec.Builder builder = TypeSpec.classBuilder(name).addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
|
//add serialize() boolean
|
||||||
|
builder.addMethod(MethodSpec.methodBuilder("serialize").addModifiers(Modifier.PUBLIC).returns(boolean.class).addStatement("return " + ann.serialize()).build());
|
||||||
|
|
||||||
|
//all SyncField fields
|
||||||
|
Seq<Svar> syncedFields = new Seq<>();
|
||||||
|
Seq<Svar> allFields = new Seq<>();
|
||||||
|
Seq<FieldSpec> allFieldSpecs = new Seq<>();
|
||||||
|
|
||||||
|
boolean isSync = components.contains(s -> s.name().contains("Sync"));
|
||||||
|
|
||||||
|
//add all components
|
||||||
|
for(Stype comp : components){
|
||||||
|
//whether this component's fields are defined in the base class
|
||||||
|
boolean isShadowed = baseClass != null && !typeIsBase && baseClassDeps.get(baseClassType).contains(comp);
|
||||||
|
|
||||||
|
//write fields to the class; ignoring transient/imported ones
|
||||||
|
Seq<Svar> fields = comp.fields().select(f -> !f.has(Import.class));
|
||||||
|
for(Svar f : fields){
|
||||||
|
if(!usedFields.add(f.name())){
|
||||||
|
err("Field '" + f.name() + "' of component '" + comp.name() + "' redefines a field in entity '" + type.name() + "'");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldSpec.Builder fbuilder = FieldSpec.builder(f.tname(), f.name());
|
||||||
|
//keep statics/finals
|
||||||
|
if(f.is(Modifier.STATIC)){
|
||||||
|
fbuilder.addModifiers(Modifier.STATIC);
|
||||||
|
if(f.is(Modifier.FINAL)) fbuilder.addModifiers(Modifier.FINAL);
|
||||||
|
}
|
||||||
|
//add transient modifier for serialization
|
||||||
|
if(f.is(Modifier.TRANSIENT)){
|
||||||
|
fbuilder.addModifiers(Modifier.TRANSIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
//add initializer if it exists
|
||||||
|
if(varInitializers.containsKey(f.descString())){
|
||||||
|
fbuilder.initializer(varInitializers.get(f.descString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
fbuilder.addModifiers(f.has(ReadOnly.class) ? Modifier.PROTECTED : Modifier.PUBLIC);
|
||||||
|
fbuilder.addAnnotations(f.annotations().map(AnnotationSpec::get));
|
||||||
|
FieldSpec spec = fbuilder.build();
|
||||||
|
|
||||||
|
//whether this field would be added to the superclass
|
||||||
|
boolean isVisible = !f.is(Modifier.STATIC) && !f.is(Modifier.PRIVATE) && !f.has(ReadOnly.class);
|
||||||
|
|
||||||
|
//add the field only if it isn't visible or it wasn't implemented by the base class
|
||||||
|
if(!isShadowed || !isVisible){
|
||||||
|
builder.addField(spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
specVariables.put(spec, f);
|
||||||
|
|
||||||
|
allFieldSpecs.add(spec);
|
||||||
|
allFields.add(f);
|
||||||
|
|
||||||
|
//add extra sync fields
|
||||||
|
if(f.has(SyncField.class) && isSync){
|
||||||
|
if(!f.tname().toString().equals("float")) err("All SyncFields must be of type float", f);
|
||||||
|
|
||||||
|
syncedFields.add(f);
|
||||||
|
|
||||||
|
//a synced field has 3 values:
|
||||||
|
//- target state
|
||||||
|
//- last state
|
||||||
|
//- current state (the field itself, will be written to)
|
||||||
|
|
||||||
|
//target
|
||||||
|
builder.addField(FieldSpec.builder(float.class, f.name() + EntityIO.targetSuf).addModifiers(Modifier.TRANSIENT, Modifier.PRIVATE).build());
|
||||||
|
|
||||||
|
//last
|
||||||
|
builder.addField(FieldSpec.builder(float.class, f.name() + EntityIO.lastSuf).addModifiers(Modifier.TRANSIENT, Modifier.PRIVATE).build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//get all methods from components
|
||||||
|
for(Smethod elem : comp.methods()){
|
||||||
|
methods.get(elem.toString(), Seq::new).add(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syncedFields.sortComparing(Selement::name);
|
||||||
|
|
||||||
|
//override toString method
|
||||||
|
builder.addMethod(MethodSpec.methodBuilder("toString")
|
||||||
|
.addAnnotation(Override.class)
|
||||||
|
.returns(String.class)
|
||||||
|
.addModifiers(Modifier.PUBLIC)
|
||||||
|
.addStatement("return $S + $L", name + "#", "id").build());
|
||||||
|
|
||||||
|
EntityIO io = new EntityIO(type.name(), builder, allFieldSpecs, serializer, rootDirectory.child("annotations/src/main/resources/revisions").child(name));
|
||||||
|
//entities with no sync comp and no serialization gen no code
|
||||||
|
boolean hasIO = ann.genio() && (components.contains(s -> s.name().contains("Sync")) || ann.serialize());
|
||||||
|
|
||||||
|
//add all methods from components
|
||||||
|
for(ObjectMap.Entry<String, Seq<Smethod>> entry : methods){
|
||||||
|
if(entry.value.contains(m -> m.has(Replace.class))){
|
||||||
|
//check replacements
|
||||||
|
if(entry.value.count(m -> m.has(Replace.class)) > 1){
|
||||||
|
err("Type " + type + " has multiple components replacing method " + entry.key + ".");
|
||||||
|
}
|
||||||
|
Smethod base = entry.value.find(m -> m.has(Replace.class));
|
||||||
|
entry.value.clear();
|
||||||
|
entry.value.add(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
//check multi return
|
||||||
|
if(entry.value.count(m -> !m.isAny(Modifier.NATIVE, Modifier.ABSTRACT) && !m.isVoid()) > 1){
|
||||||
|
err("Type " + type + " has multiple components implementing non-void method " + entry.key + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.value.sort(Structs.comps(Structs.comparingFloat(m -> m.has(MethodPriority.class) ? m.annotation(MethodPriority.class).value() : 0), Structs.comparing(Selement::name)));
|
||||||
|
|
||||||
|
//representative method
|
||||||
|
Smethod first = entry.value.first();
|
||||||
|
|
||||||
|
//skip internal impl
|
||||||
|
if(first.has(InternalImpl.class)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//build method using same params/returns
|
||||||
|
MethodSpec.Builder mbuilder = MethodSpec.methodBuilder(first.name()).addModifiers(first.is(Modifier.PRIVATE) ? Modifier.PRIVATE : Modifier.PUBLIC);
|
||||||
|
//if(isFinal || entry.value.contains(s -> s.has(Final.class))) mbuilder.addModifiers(Modifier.FINAL);
|
||||||
|
if(entry.value.contains(s -> s.has(CallSuper.class))) mbuilder.addAnnotation(CallSuper.class); //add callSuper here if necessary
|
||||||
|
if(first.is(Modifier.STATIC)) mbuilder.addModifiers(Modifier.STATIC);
|
||||||
|
mbuilder.addTypeVariables(first.typeVariables().map(TypeVariableName::get));
|
||||||
|
mbuilder.returns(first.retn());
|
||||||
|
mbuilder.addExceptions(first.thrownt());
|
||||||
|
|
||||||
|
for(Svar var : first.params()){
|
||||||
|
mbuilder.addParameter(var.tname(), var.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
//only write the block if it's a void method with several entries
|
||||||
|
boolean writeBlock = first.ret().toString().equals("void") && entry.value.size > 1;
|
||||||
|
|
||||||
|
if((entry.value.first().is(Modifier.ABSTRACT) || entry.value.first().is(Modifier.NATIVE)) && entry.value.size == 1 && !entry.value.first().has(InternalImpl.class)){
|
||||||
|
err(entry.value.first().up().getSimpleName() + "#" + entry.value.first() + " is an abstract method and must be implemented in some component", type);
|
||||||
|
}
|
||||||
|
|
||||||
|
//SPECIAL CASE: inject group add/remove code
|
||||||
|
if(first.name().equals("add") || first.name().equals("remove")){
|
||||||
|
mbuilder.addStatement("if(added == $L) return", first.name().equals("add"));
|
||||||
|
|
||||||
|
for(GroupDefinition def : groups){
|
||||||
|
//remove/add from each group, assume imported
|
||||||
|
mbuilder.addStatement("Groups.$L.$L(this)", def.name, first.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hasIO){
|
||||||
|
//SPECIAL CASE: I/O code
|
||||||
|
//note that serialization is generated even for non-serializing entities for manual usage
|
||||||
|
if((first.name().equals("read") || first.name().equals("write"))){
|
||||||
|
io.write(mbuilder, first.name().equals("write"));
|
||||||
|
}
|
||||||
|
|
||||||
|
//SPECIAL CASE: sync I/O code
|
||||||
|
if((first.name().equals("readSync") || first.name().equals("writeSync"))){
|
||||||
|
io.writeSync(mbuilder, first.name().equals("writeSync"), syncedFields, allFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
//SPECIAL CASE: sync I/O code for writing to/from a manual buffer
|
||||||
|
if((first.name().equals("readSyncManual") || first.name().equals("writeSyncManual"))){
|
||||||
|
io.writeSyncManual(mbuilder, first.name().equals("writeSyncManual"), syncedFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
//SPECIAL CASE: interpolate method implementation
|
||||||
|
if(first.name().equals("interpolate")){
|
||||||
|
io.writeInterpolate(mbuilder, syncedFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
//SPECIAL CASE: method to snap to target position after being read for the first time
|
||||||
|
if(first.name().equals("snapSync")){
|
||||||
|
mbuilder.addStatement("updateSpacing = 16");
|
||||||
|
mbuilder.addStatement("lastUpdated = $T.millis()", Time.class);
|
||||||
|
for(Svar field : syncedFields){
|
||||||
|
//reset last+current state to target position
|
||||||
|
mbuilder.addStatement("$L = $L", field.name() + EntityIO.lastSuf, field.name() + EntityIO.targetSuf);
|
||||||
|
mbuilder.addStatement("$L = $L", field.name(), field.name() + EntityIO.targetSuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//SPECIAL CASE: method to snap to current position so interpolation doesn't go wild
|
||||||
|
if(first.name().equals("snapInterpolation")){
|
||||||
|
mbuilder.addStatement("updateSpacing = 16");
|
||||||
|
mbuilder.addStatement("lastUpdated = $T.millis()", Time.class);
|
||||||
|
for(Svar field : syncedFields){
|
||||||
|
//reset last+current state to target position
|
||||||
|
mbuilder.addStatement("$L = $L", field.name() + EntityIO.lastSuf, field.name());
|
||||||
|
mbuilder.addStatement("$L = $L", field.name() + EntityIO.targetSuf, field.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Smethod elem : entry.value){
|
||||||
|
String descStr = elem.descString();
|
||||||
|
|
||||||
|
if(elem.is(Modifier.ABSTRACT) || elem.is(Modifier.NATIVE) || !methodBlocks.containsKey(descStr)) continue;
|
||||||
|
|
||||||
|
//get all statements in the method, copy them over
|
||||||
|
String str = methodBlocks.get(descStr);
|
||||||
|
//name for code blocks in the methods
|
||||||
|
String blockName = elem.up().getSimpleName().toString().toLowerCase().replace("comp", "");
|
||||||
|
|
||||||
|
//skip empty blocks
|
||||||
|
if(str.replace("{", "").replace("\n", "").replace("}", "").replace("\t", "").replace(" ", "").isEmpty()){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//wrap scope to prevent variable leakage
|
||||||
|
if(writeBlock){
|
||||||
|
//replace return; with block break
|
||||||
|
str = str.replace("return;", "break " + blockName + ";");
|
||||||
|
mbuilder.addCode(blockName + ": {\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//trim block
|
||||||
|
str = str.substring(2, str.length() - 1);
|
||||||
|
|
||||||
|
//make sure to remove braces here
|
||||||
|
mbuilder.addCode(str);
|
||||||
|
|
||||||
|
//end scope
|
||||||
|
if(writeBlock) mbuilder.addCode("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//add free code to remove methods - always at the end
|
||||||
|
//this only gets called next frame.
|
||||||
|
if(first.name().equals("remove") && ann.pooled()){
|
||||||
|
mbuilder.addStatement("$T.app.post(() -> $T.free(this))", Core.class, Pools.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.addMethod(mbuilder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
//add pool reset method and implement Poolable
|
||||||
|
if(ann.pooled()){
|
||||||
|
builder.addSuperinterface(Poolable.class);
|
||||||
|
//implement reset()
|
||||||
|
MethodSpec.Builder resetBuilder = MethodSpec.methodBuilder("reset").addModifiers(Modifier.PUBLIC);
|
||||||
|
for(FieldSpec spec : allFieldSpecs){
|
||||||
|
@Nullable Svar variable = specVariables.get(spec);
|
||||||
|
if(variable != null && variable.isAny(Modifier.STATIC, Modifier.FINAL)) continue;
|
||||||
|
String desc = variable.descString();
|
||||||
|
|
||||||
|
if(spec.type.isPrimitive()){
|
||||||
|
//set to primitive default
|
||||||
|
resetBuilder.addStatement("$L = $L", spec.name, variable != null && varInitializers.containsKey(desc) ? varInitializers.get(desc) : getDefault(spec.type.toString()));
|
||||||
|
}else{
|
||||||
|
//set to default null
|
||||||
|
if(!varInitializers.containsKey(desc)){
|
||||||
|
resetBuilder.addStatement("$L = null", spec.name);
|
||||||
|
} //else... TODO reset if poolable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.addMethod(resetBuilder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
//make constructor private
|
||||||
|
builder.addMethod(MethodSpec.constructorBuilder().addModifiers(Modifier.PROTECTED).build());
|
||||||
|
|
||||||
|
//add create() method
|
||||||
|
builder.addMethod(MethodSpec.methodBuilder("create").addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||||
|
.returns(tname(packageName + "." + name))
|
||||||
|
.addStatement(ann.pooled() ? "return Pools.obtain($L.class, " +name +"::new)" : "return new $L()", name).build());
|
||||||
|
|
||||||
|
definitions.add(new EntityDefinition(packageName + "." + name, builder, type, typeIsBase ? null : baseClass, components, groups, allFieldSpecs));
|
||||||
|
}
|
||||||
|
|
||||||
|
//generate groups
|
||||||
|
TypeSpec.Builder groupsBuilder = TypeSpec.classBuilder("Groups").addModifiers(Modifier.PUBLIC);
|
||||||
|
MethodSpec.Builder groupInit = MethodSpec.methodBuilder("init").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
||||||
|
for(GroupDefinition group : groupDefs){
|
||||||
|
//class names for interface/group
|
||||||
|
ClassName itype = group.baseType;
|
||||||
|
ClassName groupc = ClassName.bestGuess("mindustry.entities.EntityGroup");
|
||||||
|
|
||||||
|
//add field...
|
||||||
|
groupsBuilder.addField(ParameterizedTypeName.get(
|
||||||
|
ClassName.bestGuess("mindustry.entities.EntityGroup"), itype), group.name, Modifier.PUBLIC, Modifier.STATIC);
|
||||||
|
|
||||||
|
groupInit.addStatement("$L = new $T<>($L.class, $L, $L)", group.name, groupc, itype, group.spatial, group.mapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
//write the groups
|
||||||
|
groupsBuilder.addMethod(groupInit.build());
|
||||||
|
|
||||||
|
MethodSpec.Builder groupClear = MethodSpec.methodBuilder("clear").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
||||||
|
for(GroupDefinition group : groupDefs){
|
||||||
|
groupClear.addStatement("$L.clear()", group.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
//write clear
|
||||||
|
groupsBuilder.addMethod(groupClear.build());
|
||||||
|
|
||||||
|
//add method for resizing all necessary groups
|
||||||
|
MethodSpec.Builder groupResize = MethodSpec.methodBuilder("resize")
|
||||||
|
.addParameter(TypeName.FLOAT, "x").addParameter(TypeName.FLOAT, "y").addParameter(TypeName.FLOAT, "w").addParameter(TypeName.FLOAT, "h")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
||||||
|
|
||||||
|
MethodSpec.Builder groupUpdate = MethodSpec.methodBuilder("update")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
||||||
|
|
||||||
|
//method resize
|
||||||
|
for(GroupDefinition group : groupDefs){
|
||||||
|
if(group.spatial){
|
||||||
|
groupResize.addStatement("$L.resize(x, y, w, h)", group.name);
|
||||||
|
groupUpdate.addStatement("$L.updatePhysics()", group.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
groupUpdate.addStatement("all.update()");
|
||||||
|
|
||||||
|
for(GroupDefinition group : groupDefs){
|
||||||
|
if(group.collides){
|
||||||
|
groupUpdate.addStatement("$L.collide()", group.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
groupsBuilder.addMethod(groupResize.build());
|
||||||
|
groupsBuilder.addMethod(groupUpdate.build());
|
||||||
|
|
||||||
|
write(groupsBuilder);
|
||||||
|
|
||||||
|
//load map of sync IDs
|
||||||
|
StringMap map = new StringMap();
|
||||||
|
Fi idProps = rootDirectory.child("annotations/src/main/resources/classids.properties");
|
||||||
|
if(!idProps.exists()) idProps.writeString("");
|
||||||
|
PropertiesUtils.load(map, idProps.reader());
|
||||||
|
//next ID to be used in generation
|
||||||
|
Integer max = map.values().toSeq().map(Integer::parseInt).max(i -> i);
|
||||||
|
int maxID = max == null ? 0 : max + 1;
|
||||||
|
|
||||||
|
//assign IDs
|
||||||
|
definitions.sort(Structs.comparing(t -> t.naming.toString()));
|
||||||
|
for(EntityDefinition def : definitions){
|
||||||
|
String name = def.naming.fullName();
|
||||||
|
if(map.containsKey(name)){
|
||||||
|
def.classID = map.getInt(name);
|
||||||
|
}else{
|
||||||
|
def.classID = maxID++;
|
||||||
|
map.put(name, def.classID + "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OrderedMap<String, String> res = new OrderedMap<>();
|
||||||
|
res.putAll(map);
|
||||||
|
res.orderedKeys().sort();
|
||||||
|
|
||||||
|
//write assigned IDs
|
||||||
|
PropertiesUtils.store(res, idProps.writer(false), "Maps entity names to IDs. Autogenerated.");
|
||||||
|
|
||||||
|
//build mapping class for sync IDs
|
||||||
|
TypeSpec.Builder idBuilder = TypeSpec.classBuilder("EntityMapping").addModifiers(Modifier.PUBLIC)
|
||||||
|
.addField(FieldSpec.builder(TypeName.get(Prov[].class), "idMap", Modifier.PUBLIC, Modifier.STATIC).initializer("new Prov[256]").build())
|
||||||
|
.addField(FieldSpec.builder(ParameterizedTypeName.get(ClassName.get(ObjectMap.class),
|
||||||
|
tname(String.class), tname(Prov.class)),
|
||||||
|
"nameMap", Modifier.PUBLIC, Modifier.STATIC).initializer("new ObjectMap<>()").build())
|
||||||
|
.addMethod(MethodSpec.methodBuilder("map").addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||||
|
.returns(TypeName.get(Prov.class)).addParameter(int.class, "id").addStatement("return idMap[id]").build())
|
||||||
|
.addMethod(MethodSpec.methodBuilder("map").addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||||
|
.returns(TypeName.get(Prov.class)).addParameter(String.class, "name").addStatement("return nameMap.get(name)").build());
|
||||||
|
|
||||||
|
CodeBlock.Builder idStore = CodeBlock.builder();
|
||||||
|
|
||||||
|
//store the mappings
|
||||||
|
for(EntityDefinition def : definitions){
|
||||||
|
//store mapping
|
||||||
|
idStore.addStatement("idMap[$L] = $L::new", def.classID, def.name);
|
||||||
|
extraNames.get(def.naming).each(extra -> {
|
||||||
|
idStore.addStatement("nameMap.put($S, $L::new)", extra, def.name);
|
||||||
|
if(!Strings.camelToKebab(extra).equals(extra)){
|
||||||
|
idStore.addStatement("nameMap.put($S, $L::new)", Strings.camelToKebab(extra), def.name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//return mapping
|
||||||
|
def.builder.addMethod(MethodSpec.methodBuilder("classId").addAnnotation(Override.class)
|
||||||
|
.returns(int.class).addModifiers(Modifier.PUBLIC).addStatement("return " + def.classID).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
idBuilder.addStaticBlock(idStore.build());
|
||||||
|
|
||||||
|
write(idBuilder);
|
||||||
|
}else{
|
||||||
|
//round 3: generate actual classes and implement interfaces
|
||||||
|
|
||||||
|
//write base classes
|
||||||
|
for(TypeSpec.Builder b : baseClasses){
|
||||||
|
write(b, imports.asArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
//implement each definition
|
||||||
|
for(EntityDefinition def : definitions){
|
||||||
|
|
||||||
|
ObjectSet<String> methodNames = def.components.flatMap(type -> type.methods().map(Smethod::simpleString)).<String>as().asSet();
|
||||||
|
|
||||||
|
//add base class extension if it exists
|
||||||
|
if(def.extend != null){
|
||||||
|
def.builder.superclass(def.extend);
|
||||||
|
}
|
||||||
|
|
||||||
|
//get interface for each component
|
||||||
|
for(Stype comp : def.components){
|
||||||
|
|
||||||
|
//implement the interface
|
||||||
|
Stype inter = allInterfaces.find(i -> i.name().equals(interfaceName(comp)));
|
||||||
|
if(inter == null){
|
||||||
|
err("Failed to generate interface for", comp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
def.builder.addSuperinterface(inter.tname());
|
||||||
|
|
||||||
|
//generate getter/setter for each method
|
||||||
|
for(Smethod method : inter.methods()){
|
||||||
|
String var = method.name();
|
||||||
|
FieldSpec field = Seq.with(def.fieldSpecs).find(f -> f.name.equals(var));
|
||||||
|
//make sure it's a real variable AND that the component doesn't already implement it somewhere with custom logic
|
||||||
|
if(field == null || methodNames.contains(method.simpleString())) continue;
|
||||||
|
|
||||||
|
//getter
|
||||||
|
if(!method.isVoid()){
|
||||||
|
def.builder.addMethod(MethodSpec.overriding(method.e).addStatement("return " + var).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
//setter
|
||||||
|
if(method.isVoid() && !Seq.with(field.annotations).contains(f -> f.type.toString().equals("@mindustry.annotations.Annotations.ReadOnly"))){
|
||||||
|
def.builder.addMethod(MethodSpec.overriding(method.e).addStatement("this." + var + " = " + var).build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write(def.builder, imports.asArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
//store nulls
|
||||||
|
TypeSpec.Builder nullsBuilder = TypeSpec.classBuilder("Nulls").addModifiers(Modifier.PUBLIC).addModifiers(Modifier.FINAL);
|
||||||
|
|
||||||
|
//create mock types of all components
|
||||||
|
for(Stype interf : allInterfaces){
|
||||||
|
//indirect interfaces to implement methods for
|
||||||
|
Seq<Stype> dependencies = interf.allInterfaces().and(interf);
|
||||||
|
Seq<Smethod> methods = dependencies.flatMap(Stype::methods);
|
||||||
|
methods.sortComparing(Object::toString);
|
||||||
|
|
||||||
|
//optionally add superclass
|
||||||
|
Stype superclass = dependencies.map(this::interfaceToComp).find(s -> s != null && s.annotation(Component.class).base());
|
||||||
|
//use the base type when the interface being emulated has a base
|
||||||
|
TypeName type = superclass != null && interfaceToComp(interf).annotation(Component.class).base() ? tname(baseName(superclass)) : interf.tname();
|
||||||
|
|
||||||
|
//used method signatures
|
||||||
|
ObjectSet<String> signatures = new ObjectSet<>();
|
||||||
|
|
||||||
|
//create null builder
|
||||||
|
String baseName = interf.name().substring(0, interf.name().length() - 1);
|
||||||
|
String className = "Null" + baseName;
|
||||||
|
TypeSpec.Builder nullBuilder = TypeSpec.classBuilder(className)
|
||||||
|
.addModifiers(Modifier.FINAL);
|
||||||
|
|
||||||
|
nullBuilder.addSuperinterface(interf.tname());
|
||||||
|
if(superclass != null) nullBuilder.superclass(tname(baseName(superclass)));
|
||||||
|
|
||||||
|
for(Smethod method : methods){
|
||||||
|
String signature = method.toString();
|
||||||
|
if(signatures.contains(signature)) continue;
|
||||||
|
|
||||||
|
Stype compType = interfaceToComp(method.type());
|
||||||
|
MethodSpec.Builder builder = MethodSpec.overriding(method.e).addModifiers(Modifier.PUBLIC, Modifier.FINAL);
|
||||||
|
builder.addAnnotation(OverrideCallSuper.class); //just in case
|
||||||
|
|
||||||
|
if(!method.isVoid()){
|
||||||
|
if(method.name().equals("isNull")){
|
||||||
|
builder.addStatement("return true");
|
||||||
|
}else if(method.name().equals("id")){
|
||||||
|
builder.addStatement("return -1");
|
||||||
|
}else{
|
||||||
|
Svar variable = compType == null || method.params().size > 0 ? null : compType.fields().find(v -> v.name().equals(method.name()));
|
||||||
|
String desc = variable == null ? null : variable.descString();
|
||||||
|
if(variable == null || !varInitializers.containsKey(desc)){
|
||||||
|
builder.addStatement("return " + getDefault(method.ret().toString()));
|
||||||
|
}else{
|
||||||
|
String init = varInitializers.get(desc);
|
||||||
|
builder.addStatement("return " + (init.equals("{}") ? "new " + variable.mirror().toString() : "") + init);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nullBuilder.addMethod(builder.build());
|
||||||
|
|
||||||
|
signatures.add(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
nullsBuilder.addField(FieldSpec.builder(type, Strings.camelize(baseName)).initializer("new " + className + "()").addModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.PUBLIC).build());
|
||||||
|
|
||||||
|
write(nullBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
write(nullsBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Seq<String> getImports(Element elem){
|
||||||
|
return Seq.with(trees.getPath(elem).getCompilationUnit().getImports()).map(Object::toString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return interface for a component type */
|
||||||
|
String interfaceName(Stype comp){
|
||||||
|
String suffix = "Comp";
|
||||||
|
if(!comp.name().endsWith(suffix)) err("All components must have names that end with 'Comp'", comp.e);
|
||||||
|
|
||||||
|
//example: BlockComp -> IBlock
|
||||||
|
return comp.name().substring(0, comp.name().length() - suffix.length()) + "c";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return base class name for a component type */
|
||||||
|
String baseName(Stype comp){
|
||||||
|
String suffix = "Comp";
|
||||||
|
if(!comp.name().endsWith(suffix)) err("All components must have names that end with 'Comp'", comp.e);
|
||||||
|
|
||||||
|
return comp.name().substring(0, comp.name().length() - suffix.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable Stype interfaceToComp(Stype type){
|
||||||
|
//example: IBlock -> BlockComp
|
||||||
|
String name = type.name().substring(0, type.name().length() - 1) + "Comp";
|
||||||
|
return componentNames.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return all components that a entity def has */
|
||||||
|
Seq<Stype> allComponents(Selement<?> type){
|
||||||
|
if(!defComponents.containsKey(type)){
|
||||||
|
//get base defs
|
||||||
|
Seq<Stype> interfaces = types(type.annotation(EntityDef.class), EntityDef::value);
|
||||||
|
Seq<Stype> components = new Seq<>();
|
||||||
|
for(Stype i : interfaces){
|
||||||
|
Stype comp = interfaceToComp(i);
|
||||||
|
if(comp != null){
|
||||||
|
components.add(comp);
|
||||||
|
}else{
|
||||||
|
throw new IllegalArgumentException("Type '" + i + "' is not a component interface!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectSet<Stype> out = new ObjectSet<>();
|
||||||
|
for(Stype comp : components){
|
||||||
|
//get dependencies for each def, add them
|
||||||
|
out.add(comp);
|
||||||
|
out.addAll(getDependencies(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
defComponents.put(type, out.asArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
return defComponents.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
Seq<Stype> getDependencies(Stype component){
|
||||||
|
if(!componentDependencies.containsKey(component)){
|
||||||
|
ObjectSet<Stype> out = new ObjectSet<>();
|
||||||
|
//add base component interfaces
|
||||||
|
out.addAll(component.interfaces().select(this::isCompInterface).map(this::interfaceToComp));
|
||||||
|
//remove self interface
|
||||||
|
out.remove(component);
|
||||||
|
|
||||||
|
//out now contains the base dependencies; finish constructing the tree
|
||||||
|
ObjectSet<Stype> result = new ObjectSet<>();
|
||||||
|
for(Stype type : out){
|
||||||
|
result.add(type);
|
||||||
|
result.addAll(getDependencies(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(component.annotation(BaseComponent.class) == null){
|
||||||
|
result.addAll(baseComponents);
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove it again just in case
|
||||||
|
out.remove(component);
|
||||||
|
componentDependencies.put(component, result.asArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
return componentDependencies.get(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isCompInterface(Stype type){
|
||||||
|
return interfaceToComp(type) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String createName(Selement<?> elem){
|
||||||
|
Seq<Stype> comps = types(elem.annotation(EntityDef.class), EntityDef::value).map(this::interfaceToComp);;
|
||||||
|
comps.sortComparing(Selement::name);
|
||||||
|
return comps.toString("", s -> s.name().replace("Comp", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
<T extends Annotation> Seq<Stype> types(T t, Cons<T> consumer){
|
||||||
|
try{
|
||||||
|
consumer.get(t);
|
||||||
|
}catch(MirroredTypesException e){
|
||||||
|
return Seq.with(e.getTypeMirrors()).map(Stype::of);
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Missing types.");
|
||||||
|
}
|
||||||
|
|
||||||
|
class GroupDefinition{
|
||||||
|
final String name;
|
||||||
|
final ClassName baseType;
|
||||||
|
final Seq<Stype> components;
|
||||||
|
final boolean spatial, mapping, collides;
|
||||||
|
final ObjectSet<Selement> manualInclusions = new ObjectSet<>();
|
||||||
|
|
||||||
|
public GroupDefinition(String name, ClassName bestType, Seq<Stype> components, boolean spatial, boolean mapping, boolean collides){
|
||||||
|
this.baseType = bestType;
|
||||||
|
this.components = components;
|
||||||
|
this.name = name;
|
||||||
|
this.spatial = spatial;
|
||||||
|
this.mapping = mapping;
|
||||||
|
this.collides = collides;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EntityDefinition{
|
||||||
|
final Seq<GroupDefinition> groups;
|
||||||
|
final Seq<Stype> components;
|
||||||
|
final Seq<FieldSpec> fieldSpecs;
|
||||||
|
final TypeSpec.Builder builder;
|
||||||
|
final Selement naming;
|
||||||
|
final String name;
|
||||||
|
final @Nullable TypeName extend;
|
||||||
|
int classID;
|
||||||
|
|
||||||
|
public EntityDefinition(String name, Builder builder, Selement naming, TypeName extend, Seq<Stype> components, Seq<GroupDefinition> groups, Seq<FieldSpec> fieldSpec){
|
||||||
|
this.builder = builder;
|
||||||
|
this.name = name;
|
||||||
|
this.naming = naming;
|
||||||
|
this.groups = groups;
|
||||||
|
this.components = components;
|
||||||
|
this.extend = extend;
|
||||||
|
this.fieldSpecs = fieldSpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return "Definition{" +
|
||||||
|
"groups=" + groups +
|
||||||
|
"components=" + components +
|
||||||
|
", base=" + naming +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,29 +5,21 @@ import arc.scene.style.*;
|
|||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.serialization.*;
|
import arc.util.serialization.*;
|
||||||
import com.squareup.javapoet.*;
|
import com.squareup.javapoet.*;
|
||||||
import mindustry.annotations.*;
|
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.annotations.*;
|
||||||
|
|
||||||
import javax.annotation.processing.*;
|
import javax.annotation.processing.*;
|
||||||
import javax.lang.model.*;
|
import javax.lang.model.*;
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
import javax.tools.Diagnostic.*;
|
|
||||||
import javax.tools.*;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@SupportedAnnotationTypes("mindustry.annotations.Annotations.StyleDefaults")
|
@SupportedAnnotationTypes("mindustry.annotations.Annotations.StyleDefaults")
|
||||||
public class AssetsProcess extends BaseProcessor{
|
public class AssetsProcess extends BaseProcessor{
|
||||||
private String path;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(RoundEnvironment env) throws Exception{
|
public void process(RoundEnvironment env) throws Exception{
|
||||||
path = Fi.get(BaseProcessor.filer.createResource(StandardLocation.CLASS_OUTPUT, "no", "no")
|
processSounds("Sounds", rootDirectory + "/core/assets/sounds", "arc.audio.Sound");
|
||||||
.toUri().toURL().toString().substring(System.getProperty("os.name").contains("Windows") ? 6 : "file:".length()))
|
processSounds("Musics", rootDirectory + "/core/assets/music", "arc.audio.Music");
|
||||||
.parent().parent().parent().parent().parent().parent().toString();
|
|
||||||
path = path.replace("%20", " ");
|
|
||||||
|
|
||||||
processSounds("Sounds", path + "/assets/sounds", "arc.audio.Sound");
|
|
||||||
processSounds("Musics", path + "/assets/music", "arc.audio.Music");
|
|
||||||
processUI(env.getElementsAnnotatedWith(StyleDefaults.class));
|
processUI(env.getElementsAnnotatedWith(StyleDefaults.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,8 +30,8 @@ public class AssetsProcess extends BaseProcessor{
|
|||||||
MethodSpec.Builder load = MethodSpec.methodBuilder("load").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
MethodSpec.Builder load = MethodSpec.methodBuilder("load").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
||||||
MethodSpec.Builder loadStyles = MethodSpec.methodBuilder("loadStyles").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
MethodSpec.Builder loadStyles = MethodSpec.methodBuilder("loadStyles").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
||||||
MethodSpec.Builder icload = MethodSpec.methodBuilder("load").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
MethodSpec.Builder icload = MethodSpec.methodBuilder("load").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
||||||
String resources = path + "/assets-raw/sprites/ui";
|
String resources = rootDirectory + "/core/assets-raw/sprites/ui";
|
||||||
Jval icons = Jval.read(Fi.get(path + "/assets-raw/fontgen/config.json").readString());
|
Jval icons = Jval.read(Fi.get(rootDirectory + "/core/assets-raw/fontgen/config.json").readString());
|
||||||
|
|
||||||
ictype.addField(FieldSpec.builder(ParameterizedTypeName.get(ObjectMap.class, String.class, TextureRegionDrawable.class),
|
ictype.addField(FieldSpec.builder(ParameterizedTypeName.get(ObjectMap.class, String.class, TextureRegionDrawable.class),
|
||||||
"icons", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).initializer("new ObjectMap<>()").build());
|
"icons", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).initializer("new ObjectMap<>()").build());
|
||||||
@@ -77,7 +69,7 @@ public class AssetsProcess extends BaseProcessor{
|
|||||||
});
|
});
|
||||||
|
|
||||||
for(Element elem : elements){
|
for(Element elem : elements){
|
||||||
Array.with(((TypeElement)elem).getEnclosedElements()).each(e -> e.getKind() == ElementKind.FIELD, field -> {
|
Seq.with(((TypeElement)elem).getEnclosedElements()).each(e -> e.getKind() == ElementKind.FIELD, field -> {
|
||||||
String fname = field.getSimpleName().toString();
|
String fname = field.getSimpleName().toString();
|
||||||
if(fname.startsWith("default")){
|
if(fname.startsWith("default")){
|
||||||
loadStyles.addStatement("arc.Core.scene.addStyle(" + field.asType().toString() + ".class, mindustry.ui.Styles." + fname + ")");
|
loadStyles.addStatement("arc.Core.scene.addStyle(" + field.asType().toString() + ".class, mindustry.ui.Styles." + fname + ")");
|
||||||
@@ -105,7 +97,7 @@ public class AssetsProcess extends BaseProcessor{
|
|||||||
String name = p.nameWithoutExtension();
|
String name = p.nameWithoutExtension();
|
||||||
|
|
||||||
if(names.contains(name)){
|
if(names.contains(name)){
|
||||||
BaseProcessor.messager.printMessage(Kind.ERROR, "Duplicate file name: " + p.toString() + "!");
|
BaseProcessor.err("Duplicate file name: " + p.toString() + "!");
|
||||||
}else{
|
}else{
|
||||||
names.add(name);
|
names.add(name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,9 +68,9 @@ public class CallSuperProcess extends AbstractProcessor{
|
|||||||
}
|
}
|
||||||
|
|
||||||
static class CodeAnalyzerTreeScanner extends TreePathScanner<Object, Trees>{
|
static class CodeAnalyzerTreeScanner extends TreePathScanner<Object, Trees>{
|
||||||
private String methodName;
|
String methodName;
|
||||||
private MethodTree method;
|
MethodTree method;
|
||||||
private boolean callSuperUsed;
|
boolean callSuperUsed;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitClass(ClassTree classTree, Trees trees){
|
public Object visitClass(ClassTree classTree, Trees trees){
|
||||||
@@ -83,6 +83,9 @@ public class CallSuperProcess extends AbstractProcessor{
|
|||||||
|
|
||||||
if(extendTree instanceof JCIdent){
|
if(extendTree instanceof JCIdent){
|
||||||
JCIdent tree = (JCIdent)extendTree;
|
JCIdent tree = (JCIdent)extendTree;
|
||||||
|
|
||||||
|
if(tree == null || tree.sym == null) return super.visitClass(classTree, trees);
|
||||||
|
|
||||||
com.sun.tools.javac.code.Scope members = tree.sym.members();
|
com.sun.tools.javac.code.Scope members = tree.sym.members();
|
||||||
|
|
||||||
if(checkScope(members))
|
if(checkScope(members))
|
||||||
|
|||||||
@@ -1,115 +0,0 @@
|
|||||||
package mindustry.annotations.impl;
|
|
||||||
|
|
||||||
import arc.util.serialization.*;
|
|
||||||
import com.squareup.javapoet.*;
|
|
||||||
import mindustry.annotations.Annotations.*;
|
|
||||||
import mindustry.annotations.*;
|
|
||||||
import mindustry.annotations.remote.*;
|
|
||||||
|
|
||||||
import javax.annotation.processing.*;
|
|
||||||
import javax.lang.model.element.Modifier;
|
|
||||||
import javax.lang.model.element.*;
|
|
||||||
import javax.lang.model.util.*;
|
|
||||||
import javax.tools.*;
|
|
||||||
import java.io.*;
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.zip.*;
|
|
||||||
|
|
||||||
@SupportedAnnotationTypes("mindustry.annotations.Annotations.Serialize")
|
|
||||||
public class SerializeProcess extends BaseProcessor{
|
|
||||||
/** Target class name. */
|
|
||||||
private static final String className = "Serialization";
|
|
||||||
/** Name of the base package to put all the generated classes. */
|
|
||||||
private static final String data = "eJy1WHtzEzkS/xb3t3bqrmpm8c464RFggK28uHMdBC5mSV2tKUrWyLbIvE6jcRK8/ib7YffXkmyPExvM1ZIC29Nq9fPXrdb87Y+Ki0s+lixXRdrURt/EqRw240TlVakN41rEP7YfRiqT9S1SU9xiyrmZrFMguRFmndYYlW2g1FIrnqnP3KiyWK2vDBSllpvoqtxELaSJD7U4k+atLqcqlXob11uEQpqWc5/4lK9JtYSMF+NYy1Em2w7ZpeIOs/Xos6pAFhmva9YrPmFfqWdVM8yUYLWBn4JNS5UypcJodu4l19KEzqK+DwgstzI6LLjSykgddFh4XBb1/rNNjnTY0Y2RR81oJPWLKKw6bBixn16wmRqFFVMFNBdCliMGEQU0ul3RbO2RCfbcKmlxVMkQgn/7wLSsm8z0UrAU8opZavdDAjNIx5t+rOrDItVwDVKt92IPvPZnPCr1Gc9lGHDHEpd1fNSoLA2ipG+0Ksb2SWo29N9Oy9paGCUvlcxSGDOi7xpMYi8eS2PJNdahJ7QPjoM99ZwR2Wh/Evu7m0qGEXv+3Mt3kY5m5IvXH/OqkkW62hMWTZZFUTIX3IhJ+G6iyys+zCRDEOfzuQ8SfdXtCD3+kNgIPPvlBavF9nhUC7j2pTEwqf57X4pGS8RnuV/o7ftFWRhZmPjYfZ/LusymAE1rO+cbtqMOh5ToIo0XonwWD6sKkLV1uWbEF5xYM+LaYNtraSZlysa0iXOK44lEsLVM3UoYgLRifzOkemHCEbBnLGJVTMtLCVSiDyApHgM+v88R1CUAwuDw7OT8Te/kY+9kiSvGVVoQrN1jdCuhSwvr0VJYyzS3CaUndGcdLCvXtMXh7Z13E+Gd055ivdP1wj/v89LsWqUtq2HegpHM7iyldKx/UXILttgdJQTCc+QmnPB6Ei44TOlkhlEUoYFcG2ocdWiRGyWtKreUZC6zWrJFhV+g9ZRXKBXaVAHwaEPcyLGyqJ+Frud4FzJVSFCxUV5LEQZXOXqfqAH1FMcDQ5DYr78iVXENpJkwYAEswtY8jOK6GdbOzMDxZLIYmwmMRjeuMi4Au0GBxATBYk8CIzNUj9R1SKoj9ow9ZL//bu1Y7gfx/v6SaspX5ZXUx7xGQ7D45eiVYSC1LpGzJZ/8X8OzujcugELLHHTvd7vd/W73p+4D+nhIH93uI/o4wP/H+P+kJWAlmrWo29Tj3M1kugMjiiYy1Ipsx+lh15hnh3rc5MDe6bWQFdVvGAw5dVotTaMLRnBAilyQknlnh6yd9Pr/PjnvvT+1WXNn1FmTDwHsr2RvnfcvzOLeg2/O4s7h/rZsURLYX5WFlxi5GM1dyAH9joWWqLB3Mq/oMQwwKowvKWTxdFgH1A4zeWEnBDa68kfPihaSKJyLV7GdIigfhpXDTxeve8jMVAnS809pXHMKB8GVKvJxbuqnA/zFg4EuSzMYCJVP9wdBhGTdY1aGKLOekTmV/Zq4+BSo+U8j9Q37yBw7YwyC+5ImHfYjG+kyZ2gk9/c/HiGURyXXKUR75pelZqdcTEgqKcDsstLlWC5qoVVl4lMxKRdscRtnnk9eK8NwSPnHMzpSBnSYIRoiKymLyRbQC6eCwvzzz2fI+7jEb4oltfnDIZpvY+Rb7rDsUb8V0nZfCv+N9AC/heXH3wTlrdXxvfBd7gpw2KUVhqKtKJ8vAl5gcEDA+zc1JW9s5/VKanMTBg3uBDGtQ8qwLDPJC8aLG3CP0IOlnfFUYZgCpZvg61nrFPJRBfnePTfQtU60FdtvoWL3rBExWXhcpnA5Yv+4K+mDnRWixFmAi41MhqjIyy2DIJL7A1gj1DFLlR3YaHBxFynucRMGxygveDzWPD/hhg8GAczpYQIY2xP6X/LaH9KvAbFRrHGKl3lfyjT8SsRa7nRYt8Oe+D8c9gS8H2ATIK5qg2k5mtFTfolPmp39CMu1vjXA0gzByARPtzNFtCkPe10feOJuDReQGSWkTEwUzWkX/f/2d/E49LaDNYhPDt/BP9vGWlLnc0TajGlY3FHBwcEBVnaPo48cdLQi94V5fxWiu+MVCWl54KnzFkaJA/hKHQP5RwPYbFV9501hVC5bVUeFMt8ER4K/w6G9hd64DkcNrKoIdieLhfA7Qo/it7RghTbY5U+51aJL3iZbvjlbtuXeSdf3xPZXfbgLbIrNXUD/n9CyHn8ZW5ZlDVx3QLMfLebAprE3ENu+an8pjZdXIoQf6+6Yo4DTE+4Hp3mF1KwC7pTv4oXjjBKvdnX5D2lIePSAsovWVQjKsmfGtXTNuqoxS7vo6/Z6zad0ALci4n66S077pGjrTKXVuUMgqAznQzID+Q/f45Cml1r24hUl9NKh98ZlyG8d4l4ZTx0bLW9nIphvX23sdc8qDkWcl0MqrF+YhUC0x56yrl8lswRO9qzUC/6F04jV+TFuRkILH377jHAJeldXpTgWW8x286sSFtAyovGeZw2VnxfrdJMxKeKuPsuNNdVa98W1zUXLRyexihY9kVV+ph2Cgn/+5ZpH3mLwaA14u3Vte1m27Buvx3aq8Vdjr5GcWgxli9t7NEOsaU4GYrwmR9jcXOrlNOjjgG0xT3GRR0Ph+tD77dXToo3ZwoIMibAeL/W71wYztwA9e3v7Dx+j43QfPX6w//DJwavEWV24sYjeaywt2GAf1rxhJOz+Hsb4CQ5Rv3Np4tLCSTKHBKlHmIftm8lqEXs7TblhsmbLxoOU/gkCfcbF";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(RoundEnvironment env) throws Exception{
|
|
||||||
Set<TypeElement> elements = ElementFilter.typesIn(env.getElementsAnnotatedWith(Serialize.class));
|
|
||||||
|
|
||||||
JavaFileObject obj = filer.createSourceFile(packageName + ".Injector");
|
|
||||||
OutputStream stream = obj.openOutputStream();
|
|
||||||
stream.write(new DataInputStream(new InflaterInputStream(new ByteArrayInputStream(Base64Coder.decode(data)))).readUTF().replace("debug", "gen").getBytes());
|
|
||||||
stream.close();
|
|
||||||
|
|
||||||
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC);
|
|
||||||
classBuilder.addStaticBlock(CodeBlock.of("Injector.ii();"));
|
|
||||||
classBuilder.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "\"unchecked\"").build());
|
|
||||||
classBuilder.addJavadoc(RemoteProcess.autogenWarning);
|
|
||||||
|
|
||||||
MethodSpec.Builder method = MethodSpec.methodBuilder("init").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
|
||||||
|
|
||||||
for(TypeElement elem : elements){
|
|
||||||
TypeName type = TypeName.get(elem.asType());
|
|
||||||
String simpleTypeName = type.toString().substring(type.toString().lastIndexOf('.') + 1);
|
|
||||||
|
|
||||||
TypeSpec.Builder serializer = TypeSpec.anonymousClassBuilder("")
|
|
||||||
.addSuperinterface(ParameterizedTypeName.get(
|
|
||||||
ClassName.bestGuess("arc.Settings.TypeSerializer"), type));
|
|
||||||
|
|
||||||
MethodSpec.Builder writeMethod = MethodSpec.methodBuilder("write")
|
|
||||||
.returns(void.class)
|
|
||||||
.addParameter(DataOutput.class, "stream")
|
|
||||||
.addParameter(type, "object")
|
|
||||||
.addException(IOException.class)
|
|
||||||
.addModifiers(Modifier.PUBLIC);
|
|
||||||
|
|
||||||
MethodSpec.Builder readMethod = MethodSpec.methodBuilder("read")
|
|
||||||
.returns(type)
|
|
||||||
.addParameter(DataInput.class, "stream")
|
|
||||||
.addException(IOException.class)
|
|
||||||
.addModifiers(Modifier.PUBLIC);
|
|
||||||
|
|
||||||
readMethod.addStatement("$L object = new $L()", type, type);
|
|
||||||
|
|
||||||
List<VariableElement> fields = ElementFilter.fieldsIn(BaseProcessor.elementu.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 = BaseProcessor.typeu.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("arc.Core.settings.getSerializer(" + typeName + ".class).write(stream, object." + name + ")");
|
|
||||||
readMethod.addStatement("object." + name + " = (" + typeName + ")arc.Core.settings.getSerializer(" + typeName + ".class).read(stream)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
readMethod.addStatement("return object");
|
|
||||||
|
|
||||||
serializer.addMethod(writeMethod.build());
|
|
||||||
serializer.addMethod(readMethod.build());
|
|
||||||
|
|
||||||
method.addStatement("arc.Core.settings.setSerializer($N, $L)", BaseProcessor.elementu.getBinaryName(elem).toString().replace('$', '.') + ".class", serializer.build());
|
|
||||||
|
|
||||||
name(writeMethod, "write" + simpleTypeName);
|
|
||||||
name(readMethod, "read" + simpleTypeName);
|
|
||||||
|
|
||||||
writeMethod.addModifiers(Modifier.STATIC);
|
|
||||||
readMethod.addModifiers(Modifier.STATIC);
|
|
||||||
|
|
||||||
classBuilder.addMethod(writeMethod.build());
|
|
||||||
classBuilder.addMethod(readMethod.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
classBuilder.addMethod(method.build());
|
|
||||||
|
|
||||||
//write result
|
|
||||||
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(BaseProcessor.filer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void name(MethodSpec.Builder builder, String name){
|
|
||||||
try{
|
|
||||||
Field field = builder.getClass().getDeclaredField("name");
|
|
||||||
field.setAccessible(true);
|
|
||||||
field.set(builder, name);
|
|
||||||
}catch(Exception e){
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +1,14 @@
|
|||||||
package mindustry.annotations.impl;
|
package mindustry.annotations.impl;
|
||||||
|
|
||||||
|
import arc.struct.*;
|
||||||
import com.squareup.javapoet.*;
|
import com.squareup.javapoet.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.annotations.*;
|
import mindustry.annotations.*;
|
||||||
import mindustry.annotations.Annotations.Struct;
|
import mindustry.annotations.util.*;
|
||||||
import mindustry.annotations.Annotations.StructField;
|
|
||||||
|
|
||||||
import javax.annotation.processing.*;
|
import javax.annotation.processing.*;
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
import javax.lang.model.type.TypeKind;
|
import javax.lang.model.type.*;
|
||||||
import javax.lang.model.util.ElementFilter;
|
|
||||||
import javax.tools.Diagnostic.Kind;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates ""value types"" classes that are packed into integer primitives of the most aproppriate size.
|
* Generates ""value types"" classes that are packed into integer primitives of the most aproppriate size.
|
||||||
@@ -24,28 +21,28 @@ public class StructProcess extends BaseProcessor{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(RoundEnvironment env) throws Exception{
|
public void process(RoundEnvironment env) throws Exception{
|
||||||
Set<TypeElement> elements = ElementFilter.typesIn(env.getElementsAnnotatedWith(Struct.class));
|
Seq<Stype> elements = types(Struct.class);
|
||||||
|
|
||||||
for(TypeElement elem : elements){
|
for(Stype elem : elements){
|
||||||
|
|
||||||
if(!elem.getSimpleName().toString().endsWith("Struct")){
|
if(!elem.name().endsWith("Struct")){
|
||||||
BaseProcessor.messager.printMessage(Kind.ERROR, "All classes annotated with @Struct must have their class names end in 'Struct'.", elem);
|
err("All classes annotated with @Struct must have their class names end in 'Struct'.", elem);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String structName = elem.getSimpleName().toString().substring(0, elem.getSimpleName().toString().length() - "Struct".length());
|
String structName = elem.name().substring(0, elem.name().length() - "Struct".length());
|
||||||
String structParam = structName.toLowerCase();
|
String structParam = structName.toLowerCase();
|
||||||
|
|
||||||
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(structName)
|
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(structName)
|
||||||
.addModifiers(Modifier.FINAL, Modifier.PUBLIC);
|
.addModifiers(Modifier.FINAL, Modifier.PUBLIC);
|
||||||
|
|
||||||
try{
|
try{
|
||||||
List<VariableElement> variables = ElementFilter.fieldsIn(elem.getEnclosedElements());
|
Seq<Svar> variables = elem.fields();
|
||||||
int structSize = variables.stream().mapToInt(StructProcess::varSize).sum();
|
int structSize = variables.mapInt(StructProcess::varSize).sum();
|
||||||
int structTotalSize = (structSize <= 8 ? 8 : structSize <= 16 ? 16 : structSize <= 32 ? 32 : 64);
|
int structTotalSize = (structSize <= 8 ? 8 : structSize <= 16 ? 16 : structSize <= 32 ? 32 : 64);
|
||||||
|
|
||||||
if(variables.size() == 0){
|
if(variables.size == 0){
|
||||||
BaseProcessor.messager.printMessage(Kind.ERROR, "making a struct with no fields is utterly pointles.", elem);
|
err("making a struct with no fields is utterly pointles.", elem);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,21 +59,21 @@ public class StructProcess extends BaseProcessor{
|
|||||||
doc.append("Bits used: ").append(structSize).append(" / ").append(structTotalSize).append("\n");
|
doc.append("Bits used: ").append(structSize).append(" / ").append(structTotalSize).append("\n");
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
for(VariableElement var : variables){
|
for(Svar var : variables){
|
||||||
int size = varSize(var);
|
int size = varSize(var);
|
||||||
TypeName varType = TypeName.get(var.asType());
|
TypeName varType = var.tname();
|
||||||
String varName = var.getSimpleName().toString();
|
String varName = var.name();
|
||||||
|
|
||||||
//add val param to constructor
|
//add val param to constructor
|
||||||
constructor.addParameter(varType, varName);
|
constructor.addParameter(varType, varName);
|
||||||
|
|
||||||
//[get] field(structType) : fieldType
|
//[get] field(structType) : fieldType
|
||||||
MethodSpec.Builder getter = MethodSpec.methodBuilder(var.getSimpleName().toString())
|
MethodSpec.Builder getter = MethodSpec.methodBuilder(var.name().toString())
|
||||||
.addModifiers(Modifier.STATIC, Modifier.PUBLIC)
|
.addModifiers(Modifier.STATIC, Modifier.PUBLIC)
|
||||||
.returns(varType)
|
.returns(varType)
|
||||||
.addParameter(structType, structParam);
|
.addParameter(structType, structParam);
|
||||||
//[set] field(structType, fieldType) : structType
|
//[set] field(structType, fieldType) : structType
|
||||||
MethodSpec.Builder setter = MethodSpec.methodBuilder(var.getSimpleName().toString())
|
MethodSpec.Builder setter = MethodSpec.methodBuilder(var.name().toString())
|
||||||
.addModifiers(Modifier.STATIC, Modifier.PUBLIC)
|
.addModifiers(Modifier.STATIC, Modifier.PUBLIC)
|
||||||
.returns(structType)
|
.returns(structType)
|
||||||
.addParameter(structType, structParam).addParameter(varType, "value");
|
.addParameter(structType, structParam).addParameter(varType, "value");
|
||||||
@@ -133,7 +130,7 @@ public class StructProcess extends BaseProcessor{
|
|||||||
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(BaseProcessor.filer);
|
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(BaseProcessor.filer);
|
||||||
}catch(IllegalArgumentException e){
|
}catch(IllegalArgumentException e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
BaseProcessor.messager.printMessage(Kind.ERROR, e.getMessage(), elem);
|
err(e.getMessage(), elem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,21 +151,21 @@ public class StructProcess extends BaseProcessor{
|
|||||||
return "0b" + builder.reverse().toString() + "L";
|
return "0b" + builder.reverse().toString() + "L";
|
||||||
}
|
}
|
||||||
|
|
||||||
static int varSize(VariableElement var) throws IllegalArgumentException{
|
static int varSize(Svar var) throws IllegalArgumentException{
|
||||||
if(!var.asType().getKind().isPrimitive()){
|
if(!var.mirror().getKind().isPrimitive()){
|
||||||
throw new IllegalArgumentException("All struct fields must be primitives: " + var);
|
throw new IllegalArgumentException("All struct fields must be primitives: " + var);
|
||||||
}
|
}
|
||||||
|
|
||||||
StructField an = var.getAnnotation(StructField.class);
|
StructField an = var.annotation(StructField.class);
|
||||||
if(var.asType().getKind() == TypeKind.BOOLEAN && an != null && an.value() != 1){
|
if(var.mirror().getKind() == TypeKind.BOOLEAN && an != null && an.value() != 1){
|
||||||
throw new IllegalArgumentException("Booleans can only be one bit long... why would you do this?");
|
throw new IllegalArgumentException("Booleans can only be one bit long... why would you do this?");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(var.asType().getKind() == TypeKind.FLOAT && an != null && an.value() != 32){
|
if(var.mirror().getKind() == TypeKind.FLOAT && an != null && an.value() != 32){
|
||||||
throw new IllegalArgumentException("Float size can't be changed. Very sad.");
|
throw new IllegalArgumentException("Float size can't be changed. Very sad.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return an == null ? typeSize(var.asType().getKind()) : an.value();
|
return an == null ? typeSize(var.mirror().getKind()) : an.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Class<?> typeForSize(int size) throws IllegalArgumentException{
|
static Class<?> typeForSize(int size) throws IllegalArgumentException{
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
package mindustry.annotations.misc;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
|
import arc.graphics.g2d.*;
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.struct.ObjectMap.*;
|
||||||
|
import com.squareup.javapoet.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.annotations.*;
|
||||||
|
import mindustry.annotations.util.*;
|
||||||
|
|
||||||
|
import javax.annotation.processing.*;
|
||||||
|
import javax.lang.model.element.*;
|
||||||
|
|
||||||
|
@SupportedAnnotationTypes("mindustry.annotations.Annotations.Load")
|
||||||
|
public class LoadRegionProcessor extends BaseProcessor{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(RoundEnvironment env) throws Exception{
|
||||||
|
TypeSpec.Builder regionClass = TypeSpec.classBuilder("ContentRegions")
|
||||||
|
.addModifiers(Modifier.PUBLIC);
|
||||||
|
MethodSpec.Builder method = MethodSpec.methodBuilder("loadRegions")
|
||||||
|
.addParameter(tname("mindustry.ctype.MappableContent"), "content")
|
||||||
|
.addModifiers(Modifier.STATIC, Modifier.PUBLIC);
|
||||||
|
|
||||||
|
ObjectMap<Stype, Seq<Svar>> fieldMap = new ObjectMap<>();
|
||||||
|
|
||||||
|
for(Svar field : fields(Load.class)){
|
||||||
|
if(!field.is(Modifier.PUBLIC)){
|
||||||
|
err("@LoadRegion field must be public", field);
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldMap.get(field.enclosingType(), Seq::new).add(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Entry<Stype, Seq<Svar>> entry : fieldMap){
|
||||||
|
method.beginControlFlow("if(content instanceof $T)", entry.key.tname());
|
||||||
|
|
||||||
|
for(Svar field : entry.value){
|
||||||
|
Load an = field.annotation(Load.class);
|
||||||
|
//get # of array dimensions
|
||||||
|
int dims = count(field.mirror().toString(), "[]");
|
||||||
|
boolean doFallback = !an.fallback().equals("error");
|
||||||
|
String fallbackString = doFallback ? ", " + parse(an.fallback()) : "";
|
||||||
|
|
||||||
|
//not an array
|
||||||
|
if(dims == 0){
|
||||||
|
method.addStatement("(($T)content).$L = $T.atlas.find($L$L)", entry.key.tname(), field.name(), Core.class, parse(an.value()), fallbackString);
|
||||||
|
}else{
|
||||||
|
//is an array, create length string
|
||||||
|
int[] lengths = an.lengths();
|
||||||
|
if(lengths.length == 0) lengths = new int[]{an.length()};
|
||||||
|
|
||||||
|
if(dims != lengths.length){
|
||||||
|
err("Length dimensions must match array dimensions: " + dims + " != " + lengths.length, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder lengthString = new StringBuilder();
|
||||||
|
for(int value : lengths) lengthString.append("[").append(value).append("]");
|
||||||
|
|
||||||
|
method.addStatement("(($T)content).$L = new $T$L", entry.key.tname(), field.name(), TextureRegion.class, lengthString.toString());
|
||||||
|
|
||||||
|
for(int i = 0; i < dims; i++){
|
||||||
|
method.beginControlFlow("for(int INDEX$L = 0; INDEX$L < $L; INDEX$L ++)", i, i, lengths[i], i);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder indexString = new StringBuilder();
|
||||||
|
for(int i = 0; i < dims; i++){
|
||||||
|
indexString.append("[INDEX").append(i).append("]");
|
||||||
|
}
|
||||||
|
|
||||||
|
method.addStatement("(($T)content).$L$L = $T.atlas.find($L$L)", entry.key.tname(), field.name(), indexString.toString(), Core.class, parse(an.value()), fallbackString);
|
||||||
|
|
||||||
|
for(int i = 0; i < dims; i++){
|
||||||
|
method.endControlFlow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
method.endControlFlow();
|
||||||
|
}
|
||||||
|
|
||||||
|
regionClass.addMethod(method.build());
|
||||||
|
|
||||||
|
write(regionClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int count(String str, String substring){
|
||||||
|
int lastIndex = 0;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
while(lastIndex != -1){
|
||||||
|
|
||||||
|
lastIndex = str.indexOf(substring, lastIndex);
|
||||||
|
|
||||||
|
if(lastIndex != -1){
|
||||||
|
count ++;
|
||||||
|
lastIndex += substring.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String parse(String value){
|
||||||
|
value = '"' + value + '"';
|
||||||
|
value = value.replace("@size", "\" + ((mindustry.world.Block)content).size + \"");
|
||||||
|
value = value.replace("@", "\" + content.name + \"");
|
||||||
|
value = value.replace("#1", "\" + INDEX0 + \"");
|
||||||
|
value = value.replace("#2", "\" + INDEX1 + \"");
|
||||||
|
value = value.replace("#", "\" + INDEX0 + \"");
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
package mindustry.annotations.misc;
|
||||||
|
|
||||||
|
import arc.func.*;
|
||||||
|
import arc.struct.*;
|
||||||
|
import com.squareup.javapoet.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.annotations.*;
|
||||||
|
import mindustry.annotations.util.*;
|
||||||
|
|
||||||
|
import javax.annotation.processing.*;
|
||||||
|
import javax.lang.model.element.*;
|
||||||
|
|
||||||
|
@SupportedAnnotationTypes("mindustry.annotations.Annotations.RegisterStatement")
|
||||||
|
public class LogicStatementProcessor extends BaseProcessor{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(RoundEnvironment env) throws Exception{
|
||||||
|
TypeSpec.Builder type = TypeSpec.classBuilder("LogicIO")
|
||||||
|
.addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
|
MethodSpec.Builder writer = MethodSpec.methodBuilder("write")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||||
|
.addParameter(Object.class, "obj")
|
||||||
|
.addParameter(StringBuilder.class, "out");
|
||||||
|
|
||||||
|
MethodSpec.Builder reader = MethodSpec.methodBuilder("read")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||||
|
.returns(tname("mindustry.logic.LStatement"))
|
||||||
|
.addParameter(String[].class, "tokens");
|
||||||
|
|
||||||
|
Seq<Stype> types = types(RegisterStatement.class);
|
||||||
|
|
||||||
|
type.addField(FieldSpec.builder(
|
||||||
|
ParameterizedTypeName.get(
|
||||||
|
ClassName.get(Seq.class),
|
||||||
|
ParameterizedTypeName.get(ClassName.get(Prov.class),
|
||||||
|
tname("mindustry.logic.LStatement"))), "allStatements", Modifier.PUBLIC, Modifier.STATIC)
|
||||||
|
.initializer("Seq.with(" + types.toString(", ", t -> "" + t.toString() + "::new") + ")").build());
|
||||||
|
|
||||||
|
boolean beganWrite = false, beganRead = false;
|
||||||
|
|
||||||
|
for(Stype c : types){
|
||||||
|
String name = c.annotation(RegisterStatement.class).value();
|
||||||
|
|
||||||
|
if(beganWrite){
|
||||||
|
writer.nextControlFlow("else if(obj instanceof $T)", c.mirror());
|
||||||
|
}else{
|
||||||
|
writer.beginControlFlow("if(obj instanceof $T)", c.mirror());
|
||||||
|
beganWrite = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//write the name & individual fields
|
||||||
|
writer.addStatement("out.append($S)", name);
|
||||||
|
|
||||||
|
Seq<Svar> fields = c.fields();
|
||||||
|
|
||||||
|
String readSt = "if(tokens[0].equals($S))";
|
||||||
|
if(beganRead){
|
||||||
|
reader.nextControlFlow("else " + readSt, name);
|
||||||
|
}else{
|
||||||
|
reader.beginControlFlow(readSt, name);
|
||||||
|
beganRead = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.addStatement("$T result = new $T()", c.mirror(), c.mirror());
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
for(Svar field : fields){
|
||||||
|
if(field.is(Modifier.TRANSIENT)) continue;
|
||||||
|
|
||||||
|
writer.addStatement("out.append(\" \")");
|
||||||
|
writer.addStatement("out.append((($T)obj).$L$L)", c.mirror(), field.name(),
|
||||||
|
Seq.with(typeu.directSupertypes(field.mirror())).contains(t -> t.toString().contains("java.lang.Enum")) ? ".name()" :
|
||||||
|
"");
|
||||||
|
|
||||||
|
//reading primitives, strings and enums is supported; nothing else is
|
||||||
|
reader.addStatement("if(tokens.length > $L) result.$L = $L(tokens[$L])",
|
||||||
|
index + 1,
|
||||||
|
field.name(),
|
||||||
|
field.mirror().toString().equals("java.lang.String") ?
|
||||||
|
"" : (field.tname().isPrimitive() ? field.tname().box().toString() :
|
||||||
|
field.mirror().toString()) + ".valueOf", //if it's not a string, it must have a valueOf method
|
||||||
|
index + 1
|
||||||
|
);
|
||||||
|
|
||||||
|
index ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.addStatement("result.afterRead()");
|
||||||
|
reader.addStatement("return result");
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.endControlFlow();
|
||||||
|
writer.endControlFlow();
|
||||||
|
|
||||||
|
reader.addStatement("return null");
|
||||||
|
|
||||||
|
type.addMethod(writer.build());
|
||||||
|
type.addMethod(reader.build());
|
||||||
|
|
||||||
|
write(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
package mindustry.annotations.remote;
|
|
||||||
|
|
||||||
import mindustry.annotations.*;
|
|
||||||
import mindustry.annotations.Annotations.ReadClass;
|
|
||||||
import mindustry.annotations.Annotations.WriteClass;
|
|
||||||
|
|
||||||
import javax.annotation.processing.RoundEnvironment;
|
|
||||||
import javax.lang.model.element.Element;
|
|
||||||
import javax.lang.model.type.MirroredTypeException;
|
|
||||||
import javax.tools.Diagnostic.Kind;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class finds reader and writer methods annotated by the {@link WriteClass}
|
|
||||||
* and {@link 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.
|
|
||||||
*/
|
|
||||||
public HashMap<String, ClassSerializer> findSerializers(RoundEnvironment env){
|
|
||||||
HashMap<String, ClassSerializer> result = new HashMap<>();
|
|
||||||
|
|
||||||
//get methods with the types
|
|
||||||
Set<? extends Element> writers = env.getElementsAnnotatedWith(WriteClass.class);
|
|
||||||
Set<? extends Element> readers = env.getElementsAnnotatedWith(ReadClass.class);
|
|
||||||
|
|
||||||
//look for writers first
|
|
||||||
for(Element writer : writers){
|
|
||||||
WriteClass writean = writer.getAnnotation(WriteClass.class);
|
|
||||||
String typeName = getValue(writean);
|
|
||||||
|
|
||||||
//make sure there's only one read method
|
|
||||||
if(readers.stream().filter(elem -> getValue(elem.getAnnotation(ReadClass.class)).equals(typeName)).count() > 1){
|
|
||||||
BaseProcessor.messager.printMessage(Kind.ERROR, "Multiple writer methods for type '" + typeName + "'", writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
//make sure there's only one write method
|
|
||||||
long count = readers.stream().filter(elem -> getValue(elem.getAnnotation(ReadClass.class)).equals(typeName)).count();
|
|
||||||
if(count == 0){
|
|
||||||
BaseProcessor.messager.printMessage(Kind.ERROR, "Writer method does not have an accompanying reader: ", writer);
|
|
||||||
}else if(count > 1){
|
|
||||||
BaseProcessor.messager.printMessage(Kind.ERROR, "Writer method has multiple reader for type: ", writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
Element reader = readers.stream().filter(elem -> getValue(elem.getAnnotation(ReadClass.class)).equals(typeName)).findFirst().get();
|
|
||||||
|
|
||||||
//add to result list
|
|
||||||
result.put(typeName, new ClassSerializer(BaseProcessor.getMethodName(reader), BaseProcessor.getMethodName(writer), typeName));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getValue(WriteClass write){
|
|
||||||
try{
|
|
||||||
Class<?> type = write.value();
|
|
||||||
return type.getName();
|
|
||||||
}catch(MirroredTypeException e){
|
|
||||||
return e.getTypeMirror().toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getValue(ReadClass read){
|
|
||||||
try{
|
|
||||||
Class<?> type = read.value();
|
|
||||||
return type.getName();
|
|
||||||
}catch(MirroredTypeException e){
|
|
||||||
return e.getTypeMirror().toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Information about read/write methods for a specific class type. */
|
|
||||||
public static class ClassSerializer{
|
|
||||||
/** Fully qualified method name of the reader. */
|
|
||||||
public final String readMethod;
|
|
||||||
/** Fully qualified method name of the writer. */
|
|
||||||
public final String writeMethod;
|
|
||||||
/** Fully qualified class type name. */
|
|
||||||
public final String classType;
|
|
||||||
|
|
||||||
public ClassSerializer(String readMethod, String writeMethod, String classType){
|
|
||||||
this.readMethod = readMethod;
|
|
||||||
this.writeMethod = writeMethod;
|
|
||||||
this.classType = classType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +1,21 @@
|
|||||||
package mindustry.annotations.remote;
|
package mindustry.annotations.remote;
|
||||||
|
|
||||||
|
import arc.struct.*;
|
||||||
import com.squareup.javapoet.*;
|
import com.squareup.javapoet.*;
|
||||||
import mindustry.annotations.*;
|
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.annotations.remote.IOFinder.*;
|
import mindustry.annotations.*;
|
||||||
|
import mindustry.annotations.util.*;
|
||||||
|
import mindustry.annotations.util.TypeIOResolver.*;
|
||||||
|
|
||||||
import javax.annotation.processing.*;
|
import javax.annotation.processing.*;
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
import javax.tools.Diagnostic.*;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.*;
|
|
||||||
|
|
||||||
|
|
||||||
/** The annotation processor for generating remote method call code. */
|
/** The annotation processor for generating remote method call code. */
|
||||||
@SupportedAnnotationTypes({
|
@SupportedAnnotationTypes({
|
||||||
"mindustry.annotations.Annotations.Remote",
|
"mindustry.annotations.Annotations.Remote",
|
||||||
"mindustry.annotations.Annotations.WriteClass",
|
"mindustry.annotations.Annotations.TypeIOHandler"
|
||||||
"mindustry.annotations.Annotations.ReadClass",
|
|
||||||
})
|
})
|
||||||
public class RemoteProcess extends BaseProcessor{
|
public class RemoteProcess extends BaseProcessor{
|
||||||
/** Maximum size of each event packet. */
|
/** Maximum size of each event packet. */
|
||||||
@@ -32,15 +31,15 @@ public class RemoteProcess extends BaseProcessor{
|
|||||||
private static final String callLocation = "Call";
|
private static final String callLocation = "Call";
|
||||||
|
|
||||||
//class serializers
|
//class serializers
|
||||||
private HashMap<String, ClassSerializer> serializers;
|
private ClassSerializer serializer;
|
||||||
//all elements with the Remote annotation
|
//all elements with the Remote annotation
|
||||||
private Set<? extends Element> elements;
|
private Seq<Smethod> elements;
|
||||||
//map of all classes to generate by name
|
//map of all classes to generate by name
|
||||||
private HashMap<String, ClassEntry> classMap;
|
private HashMap<String, ClassEntry> classMap;
|
||||||
//list of all method entries
|
//list of all method entries
|
||||||
private ArrayList<MethodEntry> methods;
|
private Seq<MethodEntry> methods;
|
||||||
//list of all method entries
|
//list of all method entries
|
||||||
private ArrayList<ClassEntry> classes;
|
private Seq<ClassEntry> classes;
|
||||||
|
|
||||||
{
|
{
|
||||||
rounds = 2;
|
rounds = 2;
|
||||||
@@ -51,33 +50,33 @@ public class RemoteProcess extends BaseProcessor{
|
|||||||
//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);
|
serializer = TypeIOResolver.resolve(this);
|
||||||
//last method ID used
|
//last method ID used
|
||||||
int lastMethodID = 0;
|
int lastMethodID = 0;
|
||||||
//find all elements with the Remote annotation
|
//find all elements with the Remote annotation
|
||||||
elements = roundEnv.getElementsAnnotatedWith(Remote.class);
|
elements = methods(Remote.class);
|
||||||
//map of all classes to generate by name
|
//map of all classes to generate by name
|
||||||
classMap = new HashMap<>();
|
classMap = new HashMap<>();
|
||||||
//list of all method entries
|
//list of all method entries
|
||||||
methods = new ArrayList<>();
|
methods = new Seq<>();
|
||||||
//list of all method entries
|
//list of all method entries
|
||||||
classes = new ArrayList<>();
|
classes = new Seq<>();
|
||||||
|
|
||||||
List<Element> orderedElements = new ArrayList<>(elements);
|
Seq<Smethod> orderedElements = elements.copy();
|
||||||
orderedElements.sort(Comparator.comparing(Object::toString));
|
orderedElements.sortComparing(Object::toString);
|
||||||
|
|
||||||
//create methods
|
//create methods
|
||||||
for(Element element : orderedElements){
|
for(Smethod element : orderedElements){
|
||||||
Remote annotation = element.getAnnotation(Remote.class);
|
Remote annotation = element.annotation(Remote.class);
|
||||||
|
|
||||||
//check for static
|
//check for static
|
||||||
if(!element.getModifiers().contains(Modifier.STATIC) || !element.getModifiers().contains(Modifier.PUBLIC)){
|
if(!element.is(Modifier.STATIC) || !element.is(Modifier.PUBLIC)){
|
||||||
BaseProcessor.messager.printMessage(Kind.ERROR, "All @Remote methods must be public and static: ", element);
|
err("All @Remote methods must be public and static: ", element);
|
||||||
}
|
}
|
||||||
|
|
||||||
//can't generate none methods
|
//can't generate none methods
|
||||||
if(annotation.targets() == Loc.none){
|
if(annotation.targets() == Loc.none){
|
||||||
BaseProcessor.messager.printMessage(Kind.ERROR, "A @Remote method's targets() cannot be equal to 'none':", element);
|
err("A @Remote method's targets() cannot be equal to 'none':", element);
|
||||||
}
|
}
|
||||||
|
|
||||||
//get and create class entry if needed
|
//get and create class entry if needed
|
||||||
@@ -90,31 +89,31 @@ public class RemoteProcess extends BaseProcessor{
|
|||||||
ClassEntry entry = classMap.get(callLocation);
|
ClassEntry entry = classMap.get(callLocation);
|
||||||
|
|
||||||
//create and add entry
|
//create and add entry
|
||||||
MethodEntry method = new MethodEntry(entry.name, BaseProcessor.getMethodName(element), annotation.targets(), annotation.variants(),
|
MethodEntry method = new MethodEntry(entry.name, BaseProcessor.getMethodName(element.e), annotation.targets(), annotation.variants(),
|
||||||
annotation.called(), annotation.unreliable(), annotation.forward(), lastMethodID++, (ExecutableElement)element, annotation.priority());
|
annotation.called(), annotation.unreliable(), annotation.forward(), lastMethodID++, element.e, annotation.priority());
|
||||||
|
|
||||||
entry.methods.add(method);
|
entry.methods.add(method);
|
||||||
methods.add(method);
|
methods.add(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
//create read/write generators
|
//create read/write generators
|
||||||
RemoteWriteGenerator writegen = new RemoteWriteGenerator(serializers);
|
RemoteWriteGenerator writegen = new RemoteWriteGenerator(serializer);
|
||||||
|
|
||||||
//generate the methods to invoke (write)
|
//generate the methods to invoke (write)
|
||||||
writegen.generateFor(classes, packageName);
|
writegen.generateFor(classes, packageName);
|
||||||
}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(serializer);
|
||||||
|
|
||||||
//generate server readers
|
//generate server readers
|
||||||
readgen.generateFor(methods.stream().filter(method -> method.where.isClient).collect(Collectors.toList()), readServerName, packageName, true);
|
readgen.generateFor(methods.select(method -> method.where.isClient), readServerName, packageName, true);
|
||||||
//generate client readers
|
//generate client readers
|
||||||
readgen.generateFor(methods.stream().filter(method -> method.where.isServer).collect(Collectors.toList()), readClientName, packageName, false);
|
readgen.generateFor(methods.select(method -> method.where.isServer), readClientName, packageName, false);
|
||||||
|
|
||||||
//create class for storing unique method hash
|
//create class for storing unique method hash
|
||||||
TypeSpec.Builder hashBuilder = TypeSpec.classBuilder("MethodHash").addModifiers(Modifier.PUBLIC);
|
TypeSpec.Builder hashBuilder = TypeSpec.classBuilder("MethodHash").addModifiers(Modifier.PUBLIC);
|
||||||
hashBuilder.addJavadoc(autogenWarning);
|
hashBuilder.addJavadoc(autogenWarning);
|
||||||
hashBuilder.addField(FieldSpec.builder(int.class, "HASH", Modifier.STATIC, Modifier.PUBLIC, Modifier.FINAL)
|
hashBuilder.addField(FieldSpec.builder(int.class, "HASH", Modifier.STATIC, Modifier.PUBLIC, Modifier.FINAL)
|
||||||
.initializer("$1L", Objects.hash(methods)).build());
|
.initializer("$1L", Arrays.hashCode(methods.map(m -> m.element).toArray())).build());
|
||||||
|
|
||||||
//build and write resulting hash class
|
//build and write resulting hash class
|
||||||
TypeSpec spec = hashBuilder.build();
|
TypeSpec spec = hashBuilder.build();
|
||||||
|
|||||||
@@ -1,24 +1,19 @@
|
|||||||
package mindustry.annotations.remote;
|
package mindustry.annotations.remote;
|
||||||
|
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.util.io.*;
|
||||||
import com.squareup.javapoet.*;
|
import com.squareup.javapoet.*;
|
||||||
import mindustry.annotations.*;
|
import mindustry.annotations.*;
|
||||||
import mindustry.annotations.remote.IOFinder.ClassSerializer;
|
import mindustry.annotations.util.TypeIOResolver.*;
|
||||||
|
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
import javax.tools.Diagnostic.Kind;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.HashMap;
|
|
||||||
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 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(ClassSerializer serializers){
|
||||||
this.serializers = serializers;
|
this.serializers = serializers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,8 +24,7 @@ public class RemoteReadGenerator{
|
|||||||
* @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(Seq<MethodEntry> entries, String className, String packageName, boolean needsPlayer) throws Exception{
|
||||||
throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException{
|
|
||||||
|
|
||||||
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC);
|
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC);
|
||||||
classBuilder.addJavadoc(RemoteProcess.autogenWarning);
|
classBuilder.addJavadoc(RemoteProcess.autogenWarning);
|
||||||
@@ -38,19 +32,13 @@ public class RemoteReadGenerator{
|
|||||||
//create main method builder
|
//create main method builder
|
||||||
MethodSpec.Builder readMethod = MethodSpec.methodBuilder("readPacket")
|
MethodSpec.Builder readMethod = MethodSpec.methodBuilder("readPacket")
|
||||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||||
.addParameter(ByteBuffer.class, "buffer") //buffer to read form
|
.addParameter(Reads.class, "read") //buffer to read form
|
||||||
.addParameter(int.class, "id") //ID of method type to read
|
.addParameter(int.class, "id") //ID of method type to read
|
||||||
.returns(void.class);
|
.returns(void.class);
|
||||||
|
|
||||||
if(needsPlayer){
|
if(needsPlayer){
|
||||||
//since the player type isn't loaded yet, creating a type def is necessary
|
|
||||||
//this requires reflection since the TypeName constructor is private for some reason
|
|
||||||
Constructor<TypeName> cons = TypeName.class.getDeclaredConstructor(String.class);
|
|
||||||
cons.setAccessible(true);
|
|
||||||
|
|
||||||
TypeName playerType = cons.newInstance("mindustry.entities.type.Player");
|
|
||||||
//add player parameter
|
//add player parameter
|
||||||
readMethod.addParameter(playerType, "player");
|
readMethod.addParameter(ClassName.get(packageName, "Player"), "player");
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeBlock.Builder readBlock = CodeBlock.builder(); //start building block of code inside read method
|
CodeBlock.Builder readBlock = CodeBlock.builder(); //start building block of code inside read method
|
||||||
@@ -80,26 +68,22 @@ public class RemoteReadGenerator{
|
|||||||
//name of parameter
|
//name of parameter
|
||||||
String varName = var.getSimpleName().toString();
|
String varName = var.getSimpleName().toString();
|
||||||
//captialized version of type name for reading primitives
|
//captialized version of type name for reading primitives
|
||||||
String capName = typeName.equals("byte") ? "" : Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
|
String pname = typeName.equals("boolean") ? "bool" : typeName.charAt(0) + "";
|
||||||
|
|
||||||
//write primitives automatically
|
//write primitives automatically
|
||||||
if(BaseProcessor.isPrimitive(typeName)){
|
if(BaseProcessor.isPrimitive(typeName)){
|
||||||
if(typeName.equals("boolean")){
|
readBlock.addStatement("$L $L = read.$L()", typeName, varName, pname);
|
||||||
readBlock.addStatement("boolean " + varName + " = buffer.get() == 1");
|
|
||||||
}else{
|
|
||||||
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);
|
String ser = serializers.readers.get(typeName.replace("mindustry.gen.", ""), SerializerResolver.locate(entry.element, var.asType(), false));
|
||||||
|
|
||||||
if(ser == null){ //make sure a serializer exists!
|
if(ser == null){ //make sure a serializer exists!
|
||||||
BaseProcessor.messager.printMessage(Kind.ERROR, "No @ReadClass method to read class type: '" + typeName + "'", var);
|
BaseProcessor.err("No read method to read class type '" + typeName + "' in method " + entry.targetMethod + "; " + serializers.readers, var);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//add statement for reading it
|
//add statement for reading it
|
||||||
readBlock.addStatement(typeName + " " + varName + " = " + ser.readMethod + "(buffer)");
|
readBlock.addStatement(typeName + " " + varName + " = " + ser + "(read)");
|
||||||
}
|
}
|
||||||
|
|
||||||
//append variable name to string builder
|
//append variable name to string builder
|
||||||
|
|||||||
@@ -1,28 +1,26 @@
|
|||||||
package mindustry.annotations.remote;
|
package mindustry.annotations.remote;
|
||||||
|
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.util.io.*;
|
||||||
import com.squareup.javapoet.*;
|
import com.squareup.javapoet.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.annotations.*;
|
import mindustry.annotations.*;
|
||||||
import mindustry.annotations.Annotations.Loc;
|
import mindustry.annotations.util.TypeIOResolver.*;
|
||||||
import mindustry.annotations.remote.IOFinder.ClassSerializer;
|
|
||||||
|
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
import javax.tools.Diagnostic.Kind;
|
import java.io.*;
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.HashMap;
|
|
||||||
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 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(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(Seq<ClassEntry> entries, String packageName) throws IOException{
|
||||||
|
|
||||||
for(ClassEntry entry : entries){
|
for(ClassEntry entry : entries){
|
||||||
//create builder
|
//create builder
|
||||||
@@ -30,8 +28,12 @@ public class RemoteWriteGenerator{
|
|||||||
classBuilder.addJavadoc(RemoteProcess.autogenWarning);
|
classBuilder.addJavadoc(RemoteProcess.autogenWarning);
|
||||||
|
|
||||||
//add temporary write buffer
|
//add temporary write buffer
|
||||||
classBuilder.addField(FieldSpec.builder(ByteBuffer.class, "TEMP_BUFFER", Modifier.STATIC, Modifier.PRIVATE, Modifier.FINAL)
|
classBuilder.addField(FieldSpec.builder(ReusableByteOutStream.class, "OUT", Modifier.STATIC, Modifier.PRIVATE, Modifier.FINAL)
|
||||||
.initializer("ByteBuffer.allocate($1L)", RemoteProcess.maxPacketSize).build());
|
.initializer("new ReusableByteOutStream($L)", RemoteProcess.maxPacketSize).build());
|
||||||
|
|
||||||
|
//add writer for that buffer
|
||||||
|
classBuilder.addField(FieldSpec.builder(Writes.class, "WRITE", Modifier.STATIC, Modifier.PRIVATE, Modifier.FINAL)
|
||||||
|
.initializer("new Writes(new $T(OUT))", DataOutputStream.class).build());
|
||||||
|
|
||||||
//go through each method entry in this class
|
//go through each method entry in this class
|
||||||
for(MethodEntry methodEntry : entry.methods){
|
for(MethodEntry methodEntry : entry.methods){
|
||||||
@@ -63,7 +65,7 @@ public class RemoteWriteGenerator{
|
|||||||
|
|
||||||
//create builder
|
//create builder
|
||||||
MethodSpec.Builder method = MethodSpec.methodBuilder(elem.getSimpleName().toString() + (forwarded ? "__forward" : "")) //add except suffix when forwarding
|
MethodSpec.Builder method = MethodSpec.methodBuilder(elem.getSimpleName().toString() + (forwarded ? "__forward" : "")) //add except suffix when forwarding
|
||||||
.addModifiers(Modifier.STATIC, Modifier.SYNCHRONIZED)
|
.addModifiers(Modifier.STATIC)
|
||||||
.returns(void.class);
|
.returns(void.class);
|
||||||
|
|
||||||
//forwarded methods aren't intended for use, and are not public
|
//forwarded methods aren't intended for use, and are not public
|
||||||
@@ -74,12 +76,12 @@ public class RemoteWriteGenerator{
|
|||||||
//validate client methods to make sure
|
//validate client methods to make sure
|
||||||
if(methodEntry.where.isClient){
|
if(methodEntry.where.isClient){
|
||||||
if(elem.getParameters().isEmpty()){
|
if(elem.getParameters().isEmpty()){
|
||||||
BaseProcessor.messager.printMessage(Kind.ERROR, "Client invoke methods must have a first parameter of type Player.", elem);
|
BaseProcessor.err("Client invoke methods must have a first parameter of type Player", elem);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!elem.getParameters().get(0).asType().toString().equals("mindustry.entities.type.Player")){
|
if(!elem.getParameters().get(0).asType().toString().contains("Player")){
|
||||||
BaseProcessor.messager.printMessage(Kind.ERROR, "Client invoke methods should have a first parameter of type Player.", elem);
|
BaseProcessor.err("Client invoke methods should have a first parameter of type Player", elem);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,14 +131,14 @@ public class RemoteWriteGenerator{
|
|||||||
|
|
||||||
//add statement to create packet from pool
|
//add statement to create packet from pool
|
||||||
method.addStatement("$1N packet = $2N.obtain($1N.class, $1N::new)", "mindustry.net.Packets.InvokePacket", "arc.util.pooling.Pools");
|
method.addStatement("$1N packet = $2N.obtain($1N.class, $1N::new)", "mindustry.net.Packets.InvokePacket", "arc.util.pooling.Pools");
|
||||||
//assign buffer
|
|
||||||
method.addStatement("packet.writeBuffer = TEMP_BUFFER");
|
|
||||||
//assign priority
|
//assign priority
|
||||||
method.addStatement("packet.priority = (byte)" + methodEntry.priority.ordinal());
|
method.addStatement("packet.priority = (byte)" + methodEntry.priority.ordinal());
|
||||||
//assign method ID
|
//assign method ID
|
||||||
method.addStatement("packet.type = (byte)" + methodEntry.id);
|
method.addStatement("packet.type = (byte)" + methodEntry.id);
|
||||||
//rewind buffer
|
//reset stream
|
||||||
method.addStatement("TEMP_BUFFER.position(0)");
|
method.addStatement("OUT.reset()");
|
||||||
|
|
||||||
|
method.addTypeVariables(Seq.with(elem.getTypeParameters()).map(BaseProcessor::getTVN));
|
||||||
|
|
||||||
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
|
||||||
@@ -146,8 +148,12 @@ public class RemoteWriteGenerator{
|
|||||||
|
|
||||||
VariableElement var = elem.getParameters().get(i);
|
VariableElement var = elem.getParameters().get(i);
|
||||||
|
|
||||||
//add parameter to method
|
try{
|
||||||
method.addParameter(TypeName.get(var.asType()), var.getSimpleName().toString());
|
//add parameter to method
|
||||||
|
method.addParameter(TypeName.get(var.asType()), var.getSimpleName().toString());
|
||||||
|
}catch(Throwable t){
|
||||||
|
throw new RuntimeException("Error parsing method " + methodEntry.targetMethod);
|
||||||
|
}
|
||||||
|
|
||||||
//name of parameter
|
//name of parameter
|
||||||
String varName = var.getSimpleName().toString();
|
String varName = var.getSimpleName().toString();
|
||||||
@@ -164,23 +170,18 @@ public class RemoteWriteGenerator{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(BaseProcessor.isPrimitive(typeName)){ //check if it's a primitive, and if so write it
|
if(BaseProcessor.isPrimitive(typeName)){ //check if it's a primitive, and if so write it
|
||||||
if(typeName.equals("boolean")){ //booleans are special
|
method.addStatement("WRITE.$L($L)", typeName.equals("boolean") ? "bool" : typeName.charAt(0) + "", varName);
|
||||||
method.addStatement("TEMP_BUFFER.put(" + varName + " ? (byte)1 : 0)");
|
|
||||||
}else{
|
|
||||||
method.addStatement("TEMP_BUFFER.put" +
|
|
||||||
capName + "(" + varName + ")");
|
|
||||||
}
|
|
||||||
}else{
|
}else{
|
||||||
//else, try and find a serializer
|
//else, try and find a serializer
|
||||||
ClassSerializer ser = serializers.get(typeName);
|
String ser = serializers.writers.get(typeName.replace("mindustry.gen.", ""), SerializerResolver.locate(elem, var.asType(), true));
|
||||||
|
|
||||||
if(ser == null){ //make sure a serializer exists!
|
if(ser == null){ //make sure a serializer exists!
|
||||||
BaseProcessor.messager.printMessage(Kind.ERROR, "No @WriteClass method to write class type: '" + typeName + "'", var);
|
BaseProcessor.err("No @WriteClass method to write class type: '" + typeName + "'", var);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//add statement for writing it
|
//add statement for writing it
|
||||||
method.addStatement(ser.writeMethod + "(TEMP_BUFFER, " + varName + ")");
|
method.addStatement(ser + "(WRITE, " + varName + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(writePlayerSkipCheck){ //write end check
|
if(writePlayerSkipCheck){ //write end check
|
||||||
@@ -188,8 +189,10 @@ public class RemoteWriteGenerator{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//assign packet bytes
|
||||||
|
method.addStatement("packet.bytes = OUT.getBytes()");
|
||||||
//assign packet length
|
//assign packet length
|
||||||
method.addStatement("packet.writeLength = TEMP_BUFFER.position()");
|
method.addStatement("packet.length = OUT.size()");
|
||||||
|
|
||||||
String sendString;
|
String sendString;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package mindustry.annotations.remote;
|
||||||
|
|
||||||
|
import arc.struct.*;
|
||||||
|
|
||||||
|
import javax.lang.model.element.*;
|
||||||
|
import javax.lang.model.type.*;
|
||||||
|
|
||||||
|
public class SerializerResolver{
|
||||||
|
|
||||||
|
public static String locate(ExecutableElement elem, TypeMirror mirror, boolean write){
|
||||||
|
//generic type
|
||||||
|
if((mirror.toString().equals("T") && Seq.with(elem.getTypeParameters().get(0).getBounds()).contains(SerializerResolver::isEntity)) ||
|
||||||
|
isEntity(mirror)){
|
||||||
|
return write ? "mindustry.io.TypeIO.writeEntity" : "mindustry.io.TypeIO.readEntity";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isEntity(TypeMirror mirror){
|
||||||
|
return !mirror.toString().contains(".") || mirror.toString().startsWith("mindustry.gen.") && !mirror.toString().startsWith("byte");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,262 @@
|
|||||||
|
package mindustry.annotations.util;
|
||||||
|
|
||||||
|
import arc.func.*;
|
||||||
|
import com.sun.tools.javac.code.*;
|
||||||
|
import com.sun.tools.javac.code.Attribute.Array;
|
||||||
|
import com.sun.tools.javac.code.Attribute.Enum;
|
||||||
|
import com.sun.tools.javac.code.Attribute.Error;
|
||||||
|
import com.sun.tools.javac.code.Attribute.Visitor;
|
||||||
|
import com.sun.tools.javac.code.Attribute.*;
|
||||||
|
import com.sun.tools.javac.code.Type;
|
||||||
|
import com.sun.tools.javac.code.Symbol.*;
|
||||||
|
import com.sun.tools.javac.code.Type.ArrayType;
|
||||||
|
import com.sun.tools.javac.util.List;
|
||||||
|
import com.sun.tools.javac.util.Name;
|
||||||
|
import com.sun.tools.javac.util.*;
|
||||||
|
import sun.reflect.annotation.*;
|
||||||
|
|
||||||
|
import javax.lang.model.element.*;
|
||||||
|
import javax.lang.model.type.*;
|
||||||
|
import java.lang.Class;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.Map.*;
|
||||||
|
|
||||||
|
//replaces the standard Java AnnotationProxyMaker with one that doesn't crash
|
||||||
|
//thanks, oracle.
|
||||||
|
@SuppressWarnings({"sunapi", "unchecked"})
|
||||||
|
public class AnnotationProxyMaker{
|
||||||
|
private final Compound anno;
|
||||||
|
private final Class<? extends Annotation> annoType;
|
||||||
|
|
||||||
|
private AnnotationProxyMaker(Compound var1, Class<? extends Annotation> var2){
|
||||||
|
this.anno = var1;
|
||||||
|
this.annoType = var2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <A extends Annotation> A generateAnnotation(Compound var0, Class<A> var1){
|
||||||
|
AnnotationProxyMaker var2 = new AnnotationProxyMaker(var0, var1);
|
||||||
|
return (A)var1.cast(var2.generateAnnotation());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Annotation generateAnnotation(){
|
||||||
|
return AnnotationParser.annotationForMap(this.annoType, this.getAllReflectedValues());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> getAllReflectedValues(){
|
||||||
|
LinkedHashMap var1 = new LinkedHashMap();
|
||||||
|
Iterator var2 = this.getAllValues().entrySet().iterator();
|
||||||
|
|
||||||
|
while(var2.hasNext()){
|
||||||
|
Entry var3 = (Entry)var2.next();
|
||||||
|
MethodSymbol var4 = (MethodSymbol)var3.getKey();
|
||||||
|
Object var5 = this.generateValue(var4, (Attribute)var3.getValue());
|
||||||
|
if(var5 != null){
|
||||||
|
var1.put(var4.name.toString(), var5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return var1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<MethodSymbol, Attribute> getAllValues(){
|
||||||
|
LinkedHashMap map = new LinkedHashMap();
|
||||||
|
ClassSymbol cl = (ClassSymbol)this.anno.type.tsym;
|
||||||
|
|
||||||
|
//try to use Java 8 API for this if possible
|
||||||
|
try{
|
||||||
|
Class entryClass = Class.forName("com.sun.tools.javac.code.Scope$Entry");
|
||||||
|
Object members = cl.members();
|
||||||
|
Field field = members.getClass().getField("elems");
|
||||||
|
Object elems = field.get(members);
|
||||||
|
Field siblingField = entryClass.getField("sibling");
|
||||||
|
Field symField = entryClass.getField("sym");
|
||||||
|
for(Object currEntry = elems; currEntry != null; currEntry = siblingField.get(currEntry)){
|
||||||
|
handleSymbol((Symbol)symField.get(currEntry), map);
|
||||||
|
}
|
||||||
|
|
||||||
|
}catch(Throwable e){
|
||||||
|
//otherwise try other API
|
||||||
|
|
||||||
|
try{
|
||||||
|
Class lookupClass = Class.forName("com.sun.tools.javac.code.Scope$LookupKind");
|
||||||
|
Field nonRecField = lookupClass.getField("NON_RECURSIVE");
|
||||||
|
Object nonRec = nonRecField.get(null);
|
||||||
|
Scope scope = cl.members();
|
||||||
|
Method getSyms = scope.getClass().getMethod("getSymbols", lookupClass);
|
||||||
|
Iterable<Symbol> it = (Iterable<Symbol>)getSyms.invoke(scope, nonRec);
|
||||||
|
Iterator<Symbol> i = it.iterator();
|
||||||
|
while(i.hasNext()){
|
||||||
|
handleSymbol(i.next(), map);
|
||||||
|
}
|
||||||
|
|
||||||
|
}catch(Throwable death){
|
||||||
|
//I tried
|
||||||
|
throw new RuntimeException(death);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Pair var7 : this.anno.values){
|
||||||
|
map.put(var7.fst, var7.snd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleSymbol(Symbol sym, LinkedHashMap map){
|
||||||
|
|
||||||
|
if(sym.getKind() == ElementKind.METHOD){
|
||||||
|
MethodSymbol var4 = (MethodSymbol)sym;
|
||||||
|
Attribute var5 = var4.getDefaultValue();
|
||||||
|
if(var5 != null){
|
||||||
|
map.put(var4, var5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object generateValue(MethodSymbol var1, Attribute var2){
|
||||||
|
AnnotationProxyMaker.ValueVisitor var3 = new AnnotationProxyMaker.ValueVisitor(var1);
|
||||||
|
return var3.getValue(var2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ValueVisitor implements Visitor{
|
||||||
|
private MethodSymbol meth;
|
||||||
|
private Class<?> returnClass;
|
||||||
|
private Object value;
|
||||||
|
|
||||||
|
ValueVisitor(MethodSymbol var2){
|
||||||
|
this.meth = var2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object getValue(Attribute var1){
|
||||||
|
Method var2;
|
||||||
|
try{
|
||||||
|
var2 = AnnotationProxyMaker.this.annoType.getMethod(this.meth.name.toString());
|
||||||
|
}catch(NoSuchMethodException var4){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.returnClass = var2.getReturnType();
|
||||||
|
var1.accept(this);
|
||||||
|
if(!(this.value instanceof ExceptionProxy) && !AnnotationType.invocationHandlerReturnType(this.returnClass).isInstance(this.value)){
|
||||||
|
this.typeMismatch(var2, var1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitConstant(Constant var1){
|
||||||
|
this.value = var1.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitClass(com.sun.tools.javac.code.Attribute.Class var1){
|
||||||
|
this.value = mirrorProxy(var1.classType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitArray(Array var1){
|
||||||
|
Name var2 = ((ArrayType)var1.type).elemtype.tsym.getQualifiedName();
|
||||||
|
int var6;
|
||||||
|
if(var2.equals(var2.table.names.java_lang_Class)){
|
||||||
|
ListBuffer var14 = new ListBuffer();
|
||||||
|
Attribute[] var15 = var1.values;
|
||||||
|
int var16 = var15.length;
|
||||||
|
|
||||||
|
for(var6 = 0; var6 < var16; ++var6){
|
||||||
|
Attribute var7 = var15[var6];
|
||||||
|
Type var8 = var7 instanceof UnresolvedClass ? ((UnresolvedClass)var7).classType : ((com.sun.tools.javac.code.Attribute.Class)var7).classType;
|
||||||
|
var14.append(var8);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.value = mirrorProxy(var14.toList());
|
||||||
|
}else{
|
||||||
|
int var3 = var1.values.length;
|
||||||
|
Class var4 = this.returnClass;
|
||||||
|
this.returnClass = this.returnClass.getComponentType();
|
||||||
|
|
||||||
|
try{
|
||||||
|
Object var5 = java.lang.reflect.Array.newInstance(this.returnClass, var3);
|
||||||
|
|
||||||
|
for(var6 = 0; var6 < var3; ++var6){
|
||||||
|
var1.values[var6].accept(this);
|
||||||
|
if(this.value == null || this.value instanceof ExceptionProxy){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try{
|
||||||
|
java.lang.reflect.Array.set(var5, var6, this.value);
|
||||||
|
}catch(IllegalArgumentException var12){
|
||||||
|
this.value = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.value = var5;
|
||||||
|
}finally{
|
||||||
|
this.returnClass = var4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitEnum(Enum var1){
|
||||||
|
if(this.returnClass.isEnum()){
|
||||||
|
String var2 = var1.value.toString();
|
||||||
|
|
||||||
|
try{
|
||||||
|
this.value = java.lang.Enum.valueOf((Class)this.returnClass, var2);
|
||||||
|
}catch(IllegalArgumentException var4){
|
||||||
|
this.value = proxify(() -> new EnumConstantNotPresentException((Class)this.returnClass, var2));
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
this.value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitCompound(Compound var1){
|
||||||
|
try{
|
||||||
|
Class var2 = this.returnClass.asSubclass(Annotation.class);
|
||||||
|
this.value = AnnotationProxyMaker.generateAnnotation(var1, var2);
|
||||||
|
}catch(ClassCastException var3){
|
||||||
|
this.value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitError(Error var1){
|
||||||
|
if(var1 instanceof UnresolvedClass){
|
||||||
|
this.value = mirrorProxy(((UnresolvedClass)var1).classType);
|
||||||
|
}else{
|
||||||
|
this.value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void typeMismatch(Method var1, final Attribute var2){
|
||||||
|
this.value = proxify(() -> new AnnotationTypeMismatchException(var1, var2.type.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object mirrorProxy(Type t){
|
||||||
|
return proxify(() -> new MirroredTypeException(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object mirrorProxy(List<Type> t){
|
||||||
|
return proxify(() -> new MirroredTypesException(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T extends Throwable> Object proxify(Prov<T> prov){
|
||||||
|
try{
|
||||||
|
|
||||||
|
return new ExceptionProxy(){
|
||||||
|
@Override
|
||||||
|
protected RuntimeException generateException(){
|
||||||
|
return (RuntimeException)prov.get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}catch(Throwable t){
|
||||||
|
throw new RuntimeException(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,16 @@
|
|||||||
package mindustry.annotations.util;
|
package mindustry.annotations.util;
|
||||||
|
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.util.ArcAnnotate.*;
|
||||||
import com.squareup.javapoet.*;
|
import com.squareup.javapoet.*;
|
||||||
|
import com.sun.tools.javac.code.Attribute.*;
|
||||||
import mindustry.annotations.*;
|
import mindustry.annotations.*;
|
||||||
|
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
import javax.lang.model.type.*;
|
import javax.lang.model.type.*;
|
||||||
|
import java.lang.Class;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
|
||||||
public class Selement<T extends Element>{
|
public class Selement<T extends Element>{
|
||||||
public final T e;
|
public final T e;
|
||||||
@@ -13,6 +19,61 @@ public class Selement<T extends Element>{
|
|||||||
this.e = e;
|
this.e = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @Nullable String doc(){
|
||||||
|
return BaseProcessor.elementu.getDocComment(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Seq<Selement<?>> enclosed(){
|
||||||
|
return Seq.with(e.getEnclosedElements()).map(Selement::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String fullName(){
|
||||||
|
return e.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stype asType(){
|
||||||
|
return new Stype((TypeElement)e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Svar asVar(){
|
||||||
|
return new Svar((VariableElement)e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Smethod asMethod(){
|
||||||
|
return new Smethod((ExecutableElement)e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isVar(){
|
||||||
|
return e instanceof VariableElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isType(){
|
||||||
|
return e instanceof TypeElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMethod(){
|
||||||
|
return e instanceof ExecutableElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Seq<? extends AnnotationMirror> annotations(){
|
||||||
|
return Seq.with(e.getAnnotationMirrors());
|
||||||
|
}
|
||||||
|
|
||||||
|
public <A extends Annotation> A annotation(Class<A> annotation){
|
||||||
|
try{
|
||||||
|
Method m = com.sun.tools.javac.code.AnnoConstruct.class.getDeclaredMethod("getAttribute", Class.class);
|
||||||
|
m.setAccessible(true);
|
||||||
|
Compound compound = (Compound)m.invoke(e, annotation);
|
||||||
|
return compound == null ? null : AnnotationProxyMaker.generateAnnotation(compound, annotation);
|
||||||
|
}catch(Exception e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <A extends Annotation> boolean has(Class<A> annotation){
|
||||||
|
return annotation(annotation) != null;
|
||||||
|
}
|
||||||
|
|
||||||
public Element up(){
|
public Element up(){
|
||||||
return e.getEnclosingElement();
|
return e.getEnclosingElement();
|
||||||
}
|
}
|
||||||
@@ -45,6 +106,6 @@ public class Selement<T extends Element>{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o){
|
public boolean equals(Object o){
|
||||||
return o != null && o.getClass() == getClass() && ((Selement)o).e.equals(e);
|
return o != null && o.getClass() == getClass() && e.equals(((Selement)o).e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,24 +14,43 @@ public class Smethod extends Selement<ExecutableElement>{
|
|||||||
super(executableElement);
|
super(executableElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAny(Modifier... mod){
|
||||||
|
for(Modifier m : mod){
|
||||||
|
if(is(m)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String descString(){
|
||||||
|
return up().asType().toString() + "#" + super.toString().replace("mindustry.gen.", "");
|
||||||
|
}
|
||||||
|
|
||||||
public boolean is(Modifier mod){
|
public boolean is(Modifier mod){
|
||||||
return e.getModifiers().contains(mod);
|
return e.getModifiers().contains(mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array<TypeMirror> thrown(){
|
public Stype type(){
|
||||||
return Array.with(e.getThrownTypes()).as(TypeMirror.class);
|
return new Stype((TypeElement)up());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array<TypeName> thrownt(){
|
public Seq<TypeMirror> thrown(){
|
||||||
return Array.with(e.getThrownTypes()).map(TypeName::get);
|
return Seq.with(e.getThrownTypes()).as();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array<TypeParameterElement> typeVariables(){
|
public Seq<TypeName> thrownt(){
|
||||||
return Array.with(e.getTypeParameters()).as(TypeParameterElement.class);
|
return Seq.with(e.getThrownTypes()).map(TypeName::get);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array<Svar> params(){
|
public Seq<TypeParameterElement> typeVariables(){
|
||||||
return Array.with(e.getParameters()).map(Svar::new);
|
return Seq.with(e.getTypeParameters()).as();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Seq<Svar> params(){
|
||||||
|
return Seq.with(e.getParameters()).map(Svar::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isVoid(){
|
||||||
|
return ret().toString().equals("void");
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeMirror ret(){
|
public TypeMirror ret(){
|
||||||
@@ -45,4 +64,8 @@ public class Smethod extends Selement<ExecutableElement>{
|
|||||||
public MethodTree tree(){
|
public MethodTree tree(){
|
||||||
return BaseProcessor.trees.getTree(e);
|
return BaseProcessor.trees.getTree(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String simpleString(){
|
||||||
|
return name() + "(" + params().toString(", ", p -> BaseProcessor.simpleName(p.mirror().toString())) + ")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import mindustry.annotations.*;
|
|||||||
|
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
import javax.lang.model.type.*;
|
import javax.lang.model.type.*;
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
public class Stype extends Selement<TypeElement>{
|
public class Stype extends Selement<TypeElement>{
|
||||||
|
|
||||||
@@ -17,39 +16,41 @@ public class Stype extends Selement<TypeElement>{
|
|||||||
return new Stype((TypeElement)BaseProcessor.typeu.asElement(mirror));
|
return new Stype((TypeElement)BaseProcessor.typeu.asElement(mirror));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array<Stype> interfaces(){
|
public String fullName(){
|
||||||
return Array.with(e.getInterfaces()).map(Stype::of);
|
return mirror().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array<Stype> superclasses(){
|
public Seq<Stype> interfaces(){
|
||||||
Array<Stype> out = new Array<>();
|
return Seq.with(e.getInterfaces()).map(Stype::of);
|
||||||
Stype sup = superclass();
|
}
|
||||||
while(!sup.name().equals("Object")){
|
|
||||||
out.add(sup);
|
public Seq<Stype> allInterfaces(){
|
||||||
sup = sup.superclass();
|
return interfaces().flatMap(s -> s.allInterfaces().and(s)).distinct();
|
||||||
}
|
}
|
||||||
return out;
|
|
||||||
|
public Seq<Stype> superclasses(){
|
||||||
|
return Seq.with(BaseProcessor.typeu.directSupertypes(mirror())).map(Stype::of);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Seq<Stype> allSuperclasses(){
|
||||||
|
return superclasses().flatMap(s -> s.allSuperclasses().and(s)).distinct();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stype superclass(){
|
public Stype superclass(){
|
||||||
return new Stype((TypeElement)BaseProcessor.typeu.asElement(BaseProcessor.typeu.directSupertypes(mirror()).get(0)));
|
return new Stype((TypeElement)BaseProcessor.typeu.asElement(BaseProcessor.typeu.directSupertypes(mirror()).get(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public <A extends Annotation> A annotation(Class<A> annotation){
|
public Seq<Svar> fields(){
|
||||||
return e.getAnnotation(annotation);
|
return Seq.with(e.getEnclosedElements()).select(e -> e instanceof VariableElement).map(e -> new Svar((VariableElement)e));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array<Svar> fields(){
|
public Seq<Smethod> methods(){
|
||||||
return Array.with(e.getEnclosedElements()).select(e -> e instanceof VariableElement).map(e -> new Svar((VariableElement)e));
|
return Seq.with(e.getEnclosedElements()).select(e -> e instanceof ExecutableElement
|
||||||
}
|
|
||||||
|
|
||||||
public Array<Smethod> methods(){
|
|
||||||
return Array.with(e.getEnclosedElements()).select(e -> e instanceof ExecutableElement
|
|
||||||
&& !e.getSimpleName().toString().contains("<")).map(e -> new Smethod((ExecutableElement)e));
|
&& !e.getSimpleName().toString().contains("<")).map(e -> new Smethod((ExecutableElement)e));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array<Smethod> constructors(){
|
public Seq<Smethod> constructors(){
|
||||||
return Array.with(e.getEnclosedElements()).select(e -> e instanceof ExecutableElement
|
return Seq.with(e.getEnclosedElements()).select(e -> e instanceof ExecutableElement
|
||||||
&& e.getSimpleName().toString().contains("<")).map(e -> new Smethod((ExecutableElement)e));
|
&& e.getSimpleName().toString().contains("<")).map(e -> new Smethod((ExecutableElement)e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package mindustry.annotations.util;
|
package mindustry.annotations.util;
|
||||||
|
|
||||||
import com.sun.source.tree.*;
|
import com.sun.source.tree.*;
|
||||||
|
import com.sun.tools.javac.tree.JCTree.*;
|
||||||
import mindustry.annotations.*;
|
import mindustry.annotations.*;
|
||||||
|
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
@@ -11,6 +12,25 @@ public class Svar extends Selement<VariableElement>{
|
|||||||
super(e);
|
super(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String descString(){
|
||||||
|
return up().asType().toString() + "#" + super.toString().replace("mindustry.gen.", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public JCVariableDecl jtree(){
|
||||||
|
return (JCVariableDecl)BaseProcessor.elementu.getTree(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stype enclosingType(){
|
||||||
|
return new Stype((TypeElement)up());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAny(Modifier... mods){
|
||||||
|
for(Modifier m : mods){
|
||||||
|
if(is(m)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean is(Modifier mod){
|
public boolean is(Modifier mod){
|
||||||
return e.getModifiers().contains(mod);
|
return e.getModifiers().contains(mod);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package mindustry.annotations.util;
|
||||||
|
|
||||||
|
import arc.struct.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.annotations.*;
|
||||||
|
|
||||||
|
import javax.lang.model.element.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class finds reader and writer methods.
|
||||||
|
*/
|
||||||
|
public class TypeIOResolver{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds all class serializers for all types and returns them. Logs errors when necessary.
|
||||||
|
* Maps fully qualified class names to their serializers.
|
||||||
|
*/
|
||||||
|
public static ClassSerializer resolve(BaseProcessor processor){
|
||||||
|
ClassSerializer out = new ClassSerializer(new ObjectMap<>(), new ObjectMap<>(), new ObjectMap<>());
|
||||||
|
for(Stype type : processor.types(TypeIOHandler.class)){
|
||||||
|
//look at all TypeIOHandler methods
|
||||||
|
Seq<Smethod> methods = type.methods();
|
||||||
|
for(Smethod meth : methods){
|
||||||
|
if(meth.is(Modifier.PUBLIC) && meth.is(Modifier.STATIC)){
|
||||||
|
Seq<Svar> params = meth.params();
|
||||||
|
//2 params, second one is type, first is writer
|
||||||
|
if(params.size == 2 && params.first().tname().toString().equals("arc.util.io.Writes")){
|
||||||
|
out.writers.put(fix(params.get(1).tname().toString()), type.fullName() + "." + meth.name());
|
||||||
|
}else if(params.size == 1 && params.first().tname().toString().equals("arc.util.io.Reads") && !meth.isVoid()){
|
||||||
|
//1 param, one is reader, returns type
|
||||||
|
out.readers.put(fix(meth.retn().toString()), type.fullName() + "." + meth.name());
|
||||||
|
}else if(params.size == 2 && params.first().tname().toString().equals("arc.util.io.Reads") && !meth.isVoid() && meth.ret().equals(meth.params().get(1).mirror())){
|
||||||
|
//2 params, one is reader, other is type, returns type - these are made to reduce garbage allocated
|
||||||
|
out.mutatorReaders.put(fix(meth.retn().toString()), type.fullName() + "." + meth.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** makes sure type names don't contain 'gen' */
|
||||||
|
private static String fix(String str){
|
||||||
|
return str.replace("mindustry.gen", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Information about read/write methods for class types. */
|
||||||
|
public static class ClassSerializer{
|
||||||
|
public final ObjectMap<String, String> writers, readers, mutatorReaders;
|
||||||
|
|
||||||
|
public ClassSerializer(ObjectMap<String, String> writers, ObjectMap<String, String> readers, ObjectMap<String, String> mutatorReaders){
|
||||||
|
this.writers = writers;
|
||||||
|
this.readers = readers;
|
||||||
|
this.mutatorReaders = mutatorReaders;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
annotations/src/main/resources/classids.properties
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#Maps entity names to IDs. Autogenerated.
|
||||||
|
|
||||||
|
alpha=0
|
||||||
|
atrax=1
|
||||||
|
block=2
|
||||||
|
flare=3
|
||||||
|
mace=4
|
||||||
|
mega=5
|
||||||
|
mindustry.entities.comp.BuildingComp=6
|
||||||
|
mindustry.entities.comp.BulletComp=7
|
||||||
|
mindustry.entities.comp.DecalComp=8
|
||||||
|
mindustry.entities.comp.EffectStateComp=9
|
||||||
|
mindustry.entities.comp.FireComp=10
|
||||||
|
mindustry.entities.comp.LaunchCoreComp=11
|
||||||
|
mindustry.entities.comp.PlayerComp=12
|
||||||
|
mindustry.entities.comp.PuddleComp=13
|
||||||
|
mindustry.type.Weather.WeatherStateComp=14
|
||||||
|
mindustry.world.blocks.campaign.LaunchPad.LaunchPayloadComp=15
|
||||||
|
mindustry.world.blocks.defense.ForceProjector.ForceDrawComp=22
|
||||||
|
mono=16
|
||||||
|
nova=17
|
||||||
|
poly=18
|
||||||
|
pulsar=19
|
||||||
|
risso=20
|
||||||
|
spiroct=21
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:payloads,type:arc.struct.Seq<mindustry.world.blocks.payloads.Payload>,size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
1
annotations/src/main/resources/revisions/Building/0.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:cons,type:mindustry.world.modules.ConsumeModule,size:-1},{name:health,type:float,size:4},{name:items,type:mindustry.world.modules.ItemModule,size:-1},{name:liquids,type:mindustry.world.modules.LiquidModule,size:-1},{name:power,type:mindustry.world.modules.PowerModule,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
1
annotations/src/main/resources/revisions/Bullet/0.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:fdata,type:float,size:4},{name:lifetime,type:float,size:4},{name:owner,type:mindustry.gen.Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
1
annotations/src/main/resources/revisions/Decal/0.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:color,type:arc.graphics.Color,size:-1},{name:lifetime,type:float,size:4},{name:region,type:arc.graphics.g2d.TextureRegion,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:mindustry.gen.Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{version:1,fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{version:2,fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:mindustry.gen.Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{version:3,fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{version:4,fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{version:5,fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
1
annotations/src/main/resources/revisions/Fire/0.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:baseFlammability,type:float,size:4},{name:block,type:mindustry.world.Block,size:-1},{name:lifetime,type:float,size:4},{name:puddleFlammability,type:float,size:4},{name:tile,type:mindustry.world.Tile,size:-1},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
1
annotations/src/main/resources/revisions/Fire/1.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:1,fields:[{name:lifetime,type:float,size:4},{name:tile,type:mindustry.world.Tile,size:-1},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:block,type:mindustry.world.Block,size:-1},{name:lifetime,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:lifetime,type:float,size:4},{name:stacks,type:arc.struct.Seq<mindustry.type.ItemStack>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
1
annotations/src/main/resources/revisions/LegsUnit/0.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
1
annotations/src/main/resources/revisions/MechUnit/0.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
1
annotations/src/main/resources/revisions/Player/0.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:admin,type:boolean,size:1},{name:boosting,type:boolean,size:1},{name:color,type:arc.graphics.Color,size:-1},{name:mouseX,type:float,size:4},{name:mouseY,type:float,size:4},{name:name,type:java.lang.String,size:-1},{name:shooting,type:boolean,size:1},{name:team,type:mindustry.game.Team,size:-1},{name:typing,type:boolean,size:1},{name:unit,type:Unit,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
1
annotations/src/main/resources/revisions/Puddle/0.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:amount,type:float,size:4},{name:generation,type:int,size:4},{name:liquid,type:mindustry.type.Liquid,size:-1},{name:tile,type:mindustry.world.Tile,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:intensity,type:float,size:4},{name:life,type:float,size:4},{name:opacity,type:float,size:4},{name:weather,type:mindustry.type.Weather,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{version:1,fields:[{name:effectTimer,type:float,size:4},{name:intensity,type:float,size:4},{name:life,type:float,size:4},{name:opacity,type:float,size:4},{name:weather,type:mindustry.type.Weather,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{version:2,fields:[{name:effectTimer,type:float,size:4},{name:intensity,type:float,size:4},{name:life,type:float,size:4},{name:opacity,type:float,size:4},{name:weather,type:mindustry.type.Weather,size:-1},{name:windVector,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
133
build.gradle
@@ -25,18 +25,18 @@ buildscript{
|
|||||||
}
|
}
|
||||||
|
|
||||||
allprojects{
|
allprojects{
|
||||||
version = 'release'
|
|
||||||
apply plugin: 'maven'
|
apply plugin: 'maven'
|
||||||
|
|
||||||
|
version = 'release'
|
||||||
group = 'com.github.Anuken'
|
group = 'com.github.Anuken'
|
||||||
|
|
||||||
ext{
|
ext{
|
||||||
versionNumber = '5'
|
versionNumber = '6'
|
||||||
if(!project.hasProperty("versionModifier")) versionModifier = 'release'
|
if(!project.hasProperty("versionModifier")) versionModifier = 'alpha'
|
||||||
if(!project.hasProperty("versionType")) versionType = 'official'
|
if(!project.hasProperty("versionType")) versionType = 'official'
|
||||||
appName = 'Mindustry'
|
appName = 'Mindustry'
|
||||||
gdxVersion = '1.9.10'
|
|
||||||
roboVMVersion = '2.3.8'
|
|
||||||
steamworksVersion = '891ed912791e01fe9ee6237a6497e5212b85c256'
|
steamworksVersion = '891ed912791e01fe9ee6237a6497e5212b85c256'
|
||||||
|
rhinoVersion = '8437435dab9993769d72739608580d40c5343285'
|
||||||
|
|
||||||
loadVersionProps = {
|
loadVersionProps = {
|
||||||
return new Properties().with{p -> p.load(file('../core/assets/version.properties').newReader()); return p }
|
return new Properties().with{p -> p.load(file('../core/assets/version.properties').newReader()); return p }
|
||||||
@@ -107,6 +107,7 @@ allprojects{
|
|||||||
output += other.name.substring("bundle".length() + 1, other.name.lastIndexOf('.')) + "\n"
|
output += other.name.substring("bundle".length() + 1, other.name.lastIndexOf('.')) + "\n"
|
||||||
}
|
}
|
||||||
new File(project(':core').projectDir, 'assets/locales').text = output
|
new File(project(':core').projectDir, 'assets/locales').text = output
|
||||||
|
new File(project(':core').projectDir, 'assets/basepartnames').text = new File(project(':core').projectDir, 'assets/baseparts/').list().join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
writeVersion = {
|
writeVersion = {
|
||||||
@@ -146,6 +147,20 @@ allprojects{
|
|||||||
|
|
||||||
processorFile.text = text.toString().replace(".java", "").replace("/", ".").replace("\\", ".")
|
processorFile.text = text.toString().replace(".java", "").replace("/", ".").replace("\\", ".")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writePlugins = {
|
||||||
|
new File(rootDir, "annotations/src/main/resources/META-INF/services/").mkdirs()
|
||||||
|
def processorFile = new File(rootDir, "annotations/src/main/resources/META-INF/services/com.sun.source.util.Plugin")
|
||||||
|
def text = new StringBuilder()
|
||||||
|
def files = new File(rootDir, "annotations/src/main/java")
|
||||||
|
files.eachFileRecurse(groovy.io.FileType.FILES){ file ->
|
||||||
|
if(file.name.endsWith(".java") && (file.text.contains(" implements Plugin"))){
|
||||||
|
text.append(file.path.substring(files.path.length() + 1)).append("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processorFile.text = text.toString().replace(".java", "").replace("/", ".").replace("\\", ".")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories{
|
repositories{
|
||||||
@@ -157,24 +172,44 @@ allprojects{
|
|||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(Javadoc).all{ enabled = false }
|
tasks.withType(JavaCompile){
|
||||||
|
sourceCompatibility = 1.8
|
||||||
|
targetCompatibility = 1.8
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
options.compilerArgs += ["-Xlint:deprecation"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//compile with java 8 compatibility for everything except the annotati project
|
||||||
|
configure(subprojects - project(":annotations")){
|
||||||
|
tasks.withType(JavaCompile){
|
||||||
|
if(JavaVersion.current() != JavaVersion.VERSION_1_8){
|
||||||
|
options.compilerArgs.addAll(['--release', '8'])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(Javadoc){
|
||||||
|
options.addStringOption('Xdoclint:none', '-quiet')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
project(":desktop"){
|
project(":desktop"){
|
||||||
apply plugin: "java"
|
apply plugin: "java"
|
||||||
|
|
||||||
|
compileJava.options.fork = true
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
compile project(":core")
|
implementation project(":core")
|
||||||
|
implementation arcModule("natives:natives-box2d-desktop")
|
||||||
|
implementation arcModule("natives:natives-desktop")
|
||||||
|
implementation arcModule("natives:natives-freetype-desktop")
|
||||||
|
implementation 'com.github.MinnDevelopment:java-discord-rpc:v2.0.1'
|
||||||
|
|
||||||
if(debugged()) compile project(":debug")
|
if(debugged()) implementation project(":debug")
|
||||||
|
|
||||||
compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
|
implementation "com.github.Anuken:steamworks4j:$steamworksVersion"
|
||||||
compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop"
|
|
||||||
|
|
||||||
compile "com.github.Anuken:steamworks4j:$steamworksVersion"
|
implementation arcModule("backends:backend-sdl")
|
||||||
|
|
||||||
compile arcModule("backends:backend-sdl")
|
|
||||||
compile 'com.github.MinnDevelopment:java-discord-rpc:v2.0.1'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,26 +235,26 @@ project(":ios"){
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
compile project(":core")
|
implementation project(":core")
|
||||||
|
|
||||||
|
implementation arcModule("natives:natives-ios")
|
||||||
|
implementation arcModule("natives:natives-freetype-ios")
|
||||||
|
implementation arcModule("natives:natives-box2d-ios")
|
||||||
|
implementation arcModule("backends:backend-robovm")
|
||||||
|
|
||||||
compileOnly project(":annotations")
|
compileOnly project(":annotations")
|
||||||
|
|
||||||
compile arcModule("backends:backend-robovm")
|
|
||||||
|
|
||||||
compile "com.mobidevelop.robovm:robovm-rt:$roboVMVersion"
|
|
||||||
compile "com.mobidevelop.robovm:robovm-cocoatouch:$roboVMVersion"
|
|
||||||
compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-ios"
|
|
||||||
compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-ios"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
project(":core"){
|
project(":core"){
|
||||||
apply plugin: "java"
|
apply plugin: "java-library"
|
||||||
|
|
||||||
task preGen{
|
task preGen{
|
||||||
outputs.upToDateWhen{ false }
|
outputs.upToDateWhen{ false }
|
||||||
generateLocales()
|
generateLocales()
|
||||||
writeVersion()
|
writeVersion()
|
||||||
writeProcessors()
|
writeProcessors()
|
||||||
|
writePlugins()
|
||||||
}
|
}
|
||||||
|
|
||||||
task copyChangelog{
|
task copyChangelog{
|
||||||
@@ -232,11 +267,11 @@ project(":core"){
|
|||||||
|
|
||||||
def androidLogList = loglines.findAll{ line -> !line.endsWith("]") || line.endsWith("[Mobile]") || line.endsWith("[Android]")}
|
def androidLogList = loglines.findAll{ line -> !line.endsWith("]") || line.endsWith("[Mobile]") || line.endsWith("[Android]")}
|
||||||
def result = ""
|
def result = ""
|
||||||
androidLogList.forEach({line ->
|
androidLogList.forEach{line ->
|
||||||
if(result.length() + line.length() + 1 < maxLength){
|
if(result.length() + line.length() + 1 < maxLength){
|
||||||
result += line + "\n"
|
result += line + "\n"
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
def changelogs = file("../fastlane/metadata/android/en-US/changelogs/")
|
def changelogs = file("../fastlane/metadata/android/en-US/changelogs/")
|
||||||
new File(changelogs, buildVersion + ".txt").text = (result)
|
new File(changelogs, buildVersion + ".txt").text = (result)
|
||||||
new File(changelogs, androidVersion + ".txt").text = (result)
|
new File(changelogs, androidVersion + ".txt").text = (result)
|
||||||
@@ -246,12 +281,15 @@ project(":core"){
|
|||||||
dependencies{
|
dependencies{
|
||||||
compileJava.dependsOn(preGen)
|
compileJava.dependsOn(preGen)
|
||||||
|
|
||||||
compile "org.lz4:lz4-java:1.4.1"
|
api "org.lz4:lz4-java:1.4.1"
|
||||||
compile arcModule("arc-core")
|
api arcModule("arc-core")
|
||||||
compile arcModule("extensions:freetype")
|
api arcModule("extensions:freetype")
|
||||||
compile arcModule("extensions:arcnet")
|
api arcModule("extensions:box2d")
|
||||||
compile "org.mozilla:rhino:1.7.11"
|
api arcModule("extensions:g3d")
|
||||||
if(localArc() && debugged()) compile arcModule("extensions:recorder")
|
api arcModule("extensions:fx")
|
||||||
|
api arcModule("extensions:arcnet")
|
||||||
|
api "com.github.Anuken:rhino:$rhinoVersion"
|
||||||
|
if(localArc() && debugged()) api arcModule("extensions:recorder")
|
||||||
|
|
||||||
compileOnly project(":annotations")
|
compileOnly project(":annotations")
|
||||||
annotationProcessor project(":annotations")
|
annotationProcessor project(":annotations")
|
||||||
@@ -262,8 +300,9 @@ project(":server"){
|
|||||||
apply plugin: "java"
|
apply plugin: "java"
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
compile project(":core")
|
implementation project(":core")
|
||||||
compile arcModule("backends:backend-headless")
|
implementation arcModule("natives:natives-box2d-desktop")
|
||||||
|
implementation arcModule("backends:backend-headless")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,13 +313,18 @@ project(":tests"){
|
|||||||
testImplementation project(":core")
|
testImplementation project(":core")
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-params:5.3.1"
|
testImplementation "org.junit.jupiter:junit-jupiter-params:5.3.1"
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api:5.3.1"
|
testImplementation "org.junit.jupiter:junit-jupiter-api:5.3.1"
|
||||||
|
testImplementation arcModule("backends:backend-headless")
|
||||||
|
testImplementation arcModule("natives:natives-box2d-desktop")
|
||||||
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.3.1"
|
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.3.1"
|
||||||
compile arcModule("backends:backend-headless")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test{
|
test{
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
workingDir = new File("../core/assets")
|
workingDir = new File("../core/assets")
|
||||||
|
testLogging {
|
||||||
|
exceptionFormat = 'full'
|
||||||
|
showStandardStreams = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,30 +332,29 @@ project(":tools"){
|
|||||||
apply plugin: "java"
|
apply plugin: "java"
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
compile project(":core")
|
implementation project(":core")
|
||||||
|
|
||||||
compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
|
implementation arcModule("natives:natives-desktop")
|
||||||
compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop"
|
implementation arcModule("natives:natives-freetype-desktop")
|
||||||
compile "org.reflections:reflections:0.9.12"
|
implementation arcModule("natives:natives-box2d-desktop")
|
||||||
|
implementation arcModule("backends:backend-headless")
|
||||||
compile arcModule("backends:backend-sdl")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
project(":annotations"){
|
project(":annotations"){
|
||||||
apply plugin: "java"
|
apply plugin: "java-library"
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
compile 'com.squareup:javapoet:1.12.1'
|
implementation 'com.squareup:javapoet:1.12.1'
|
||||||
compile "com.github.Anuken.Arc:arc-core:$arcHash"
|
implementation "com.github.Anuken.Arc:arc-core:$arcHash"
|
||||||
compile files("${System.getProperty('java.home')}/../lib/tools.jar")
|
implementation files("${System.getProperty('java.home')}/../lib/tools.jar")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task deployAll{
|
task deployAll{
|
||||||
task cleanDeployOutput{
|
task cleanDeployOutput{
|
||||||
doFirst{
|
doFirst{
|
||||||
if("${getBuildVersion()}" == "custom build" || "${getBuildVersion()}" == "") throw new IllegalArgumentException("----\n\nSET A BUILD NUMBER FIRST!\n\n----")
|
if(getBuildVersion() == "custom build" || getBuildVersion() == "") throw new IllegalArgumentException("----\n\nSET A BUILD NUMBER FIRST!\n\n----")
|
||||||
if(!project.hasProperty("release")) throw new IllegalArgumentException("----\n\nSET THE RELEASE PROJECT PROPERTY FIRST!\n\n----")
|
if(!project.hasProperty("release")) throw new IllegalArgumentException("----\n\nSET THE RELEASE PROJECT PROPERTY FIRST!\n\n----")
|
||||||
|
|
||||||
delete{
|
delete{
|
||||||
|
|||||||
@@ -886,20 +886,6 @@
|
|||||||
"command-retreat"
|
"command-retreat"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"uid": "1bc31b80669cb5edc2ee5d1370554bc9",
|
|
||||||
"css": "players",
|
|
||||||
"code": 59483,
|
|
||||||
"src": "custom_icons",
|
|
||||||
"selected": true,
|
|
||||||
"svg": {
|
|
||||||
"path": "M370.1 55.1Q401.6 23.6 448.8 7.9 496.1-7.9 543.3 7.9 590.6 23.6 622 55.1 653.5 86.6 685 118.1 716.5 149.6 732.3 196.9 748 244.1 732.3 291.3 716.5 338.6 685 370.1 653.5 401.6 653.5 433.1 653.5 464.6 685 496.1 716.5 527.6 748 559.1 779.5 590.6 811 622 842.5 653.5 874 685 905.5 716.5 937 748 968.5 779.5 984.3 826.8 1000 874 984.3 921.3 968.5 968.5 921.3 984.3 874 1000 811 1000 748 1000 685 1000 622 1000 559.1 1000 496.1 1000 433.1 1000 370.1 1000 307.1 1000 244.1 1000 181.1 1000 118.1 1000 70.9 984.3 23.6 968.5 7.9 921.3-7.9 874 7.9 826.8 23.6 779.5 55.1 748 86.6 716.5 118.1 685 149.6 653.5 181.1 622 212.6 590.6 244.1 559.1 275.6 527.6 307.1 496.1 338.6 464.6 338.6 433.1 338.6 401.6 307.1 370.1 275.6 338.6 259.8 291.3 244.1 244.1 259.8 196.9 275.6 149.6 307.1 118.1 338.6 86.6 370.1 55.1",
|
|
||||||
"width": 992
|
|
||||||
},
|
|
||||||
"search": [
|
|
||||||
"players"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"uid": "2073dbd997e5d8e1ffc1322d13ba5585",
|
"uid": "2073dbd997e5d8e1ffc1322d13ba5585",
|
||||||
"css": "chat",
|
"css": "chat",
|
||||||
@@ -919,6 +905,34 @@
|
|||||||
"css": "zoom",
|
"css": "zoom",
|
||||||
"code": 59415,
|
"code": 59415,
|
||||||
"src": "fontawesome"
|
"src": "fontawesome"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uid": "1bc31b80669cb5edc2ee5d1370554bc9",
|
||||||
|
"css": "players",
|
||||||
|
"code": 59483,
|
||||||
|
"src": "custom_icons",
|
||||||
|
"selected": true,
|
||||||
|
"svg": {
|
||||||
|
"path": "M370.1 55.1Q401.6 23.6 448.8 7.9 496.1-7.9 543.3 7.9 590.6 23.6 622 55.1 653.5 86.6 685 118.1 716.5 149.6 732.3 196.9 748 244.1 732.3 291.3 716.5 338.6 685 370.1 653.5 401.6 653.5 433.1 653.5 464.6 685 496.1 716.5 527.6 748 559.1 779.5 590.6 811 622 842.5 653.5 874 685 905.5 716.5 937 748 968.5 779.5 984.3 826.8 1000 874 984.3 921.3 968.5 968.5 921.3 984.3 874 1000 811 1000 748 1000 685 1000 622 1000 559.1 1000 496.1 1000 433.1 1000 370.1 1000 307.1 1000 244.1 1000 181.1 1000 118.1 1000 70.9 984.3 23.6 968.5 7.9 921.3-7.9 874 7.9 826.8 23.6 779.5 55.1 748 86.6 716.5 118.1 685 149.6 653.5 181.1 622 212.6 590.6 244.1 559.1 275.6 527.6 307.1 496.1 338.6 464.6 338.6 433.1 338.6 401.6 307.1 370.1 275.6 338.6 259.8 291.3 244.1 244.1 259.8 196.9 275.6 149.6 307.1 118.1 338.6 86.6 370.1 55.1",
|
||||||
|
"width": 992
|
||||||
|
},
|
||||||
|
"search": [
|
||||||
|
"players"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uid": "dd1e5d774d1ced68cb7c439d8ed102f5",
|
||||||
|
"css": "logic",
|
||||||
|
"code": 59420,
|
||||||
|
"src": "custom_icons",
|
||||||
|
"selected": true,
|
||||||
|
"svg": {
|
||||||
|
"path": "M375 0L250 125H125V250L0 375 125 500 0 625 125 750V875H250L375 1000 500 875 625 1000 750 875H875V750L1000 625 875 500 1000 375 875 250V125H750L625 0 500 125ZM250 250H750V750H250ZM375 375V625H625V375Z",
|
||||||
|
"width": 1000
|
||||||
|
},
|
||||||
|
"search": [
|
||||||
|
"logic"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
67
core/assets-raw/fontgen/icons/logic.svg
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
sodipodi:docname="logic.svg"
|
||||||
|
inkscape:version="1.0 (9f2f71dc58, 2020-08-02)"
|
||||||
|
id="svg8"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 128 128">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
units="px"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-height="1316"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:cy="325.95853"
|
||||||
|
inkscape:cx="195.60221"
|
||||||
|
inkscape:zoom="1.28"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
borderopacity="1.0"
|
||||||
|
bordercolor="#666666"
|
||||||
|
pagecolor="#000000"
|
||||||
|
id="base">
|
||||||
|
<inkscape:grid
|
||||||
|
empspacing="5"
|
||||||
|
spacingy="4.2333332"
|
||||||
|
spacingx="4.2333332"
|
||||||
|
id="grid10"
|
||||||
|
type="xygrid"
|
||||||
|
originx="0"
|
||||||
|
originy="0" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
inkscape:label="Layer 1">
|
||||||
|
<path
|
||||||
|
id="path19"
|
||||||
|
style="fill:#ffffff;stroke-width:3.77953;stroke-miterlimit:4;stroke-dasharray:none"
|
||||||
|
d="M 48,0 32,16 H 16 V 32 L 0,48 16,64 0,80 16,96 v 16 h 16 l 16,16 16,-16 16,16 16,-16 h 16 V 96 L 128,80 112,64 128,48 112,32 V 16 H 96 L 80,0 64,16 Z M 32,32 H 96 V 96 H 32 Z M 48,48 V 80 H 80 V 48 Z" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
BIN
core/assets-raw/fonts/Arturito Slab_v2.ttf
Executable file
BIN
core/assets-raw/sprites/blocks/campaign/core-silo.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
BIN
core/assets-raw/sprites/blocks/campaign/launch-pad-light.png
Normal file
|
After Width: | Height: | Size: 186 B |
BIN
core/assets-raw/sprites/blocks/campaign/launch-pad.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
core/assets-raw/sprites/blocks/campaign/launchpod.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
core/assets-raw/sprites/blocks/defense/overdrive-dome-top.png
Normal file
|
After Width: | Height: | Size: 516 B |
BIN
core/assets-raw/sprites/blocks/defense/overdrive-dome.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
core/assets-raw/sprites/blocks/defense/parallax.png
Normal file
|
After Width: | Height: | Size: 758 B |
BIN
core/assets-raw/sprites/blocks/defense/segment.png
Normal file
|
After Width: | Height: | Size: 794 B |
BIN
core/assets-raw/sprites/blocks/distribution/block-loader.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
core/assets-raw/sprites/blocks/distribution/block-unloader.png
Normal file
|
After Width: | Height: | Size: 895 B |
|
After Width: | Height: | Size: 178 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
BIN
core/assets-raw/sprites/blocks/distribution/cross.png
Normal file
|
After Width: | Height: | Size: 170 B |
|
Before Width: | Height: | Size: 852 B After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 503 B |
|
After Width: | Height: | Size: 926 B |
|
After Width: | Height: | Size: 513 B |
BIN
core/assets-raw/sprites/blocks/distribution/payload-conveyor.png
Normal file
|
After Width: | Height: | Size: 412 B |
|
After Width: | Height: | Size: 129 B |