mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 19:45:05 +08:00
Compare commits
1525 Commits
continuous
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48bdd4238e | ||
|
|
fd2b7e9197 | ||
|
|
0e42e5b9e3 | ||
|
|
65750f0cf3 | ||
|
|
6469b0a5f5 | ||
|
|
4f98187e9a | ||
|
|
74c19a1557 | ||
|
|
cfebee6ea8 | ||
|
|
bd0d6644e0 | ||
|
|
f41450127a | ||
|
|
70897af362 | ||
|
|
f1d7101ad8 | ||
|
|
ac9d960eef | ||
|
|
0c471aecb1 | ||
|
|
72d0d70587 | ||
|
|
bec526a77e | ||
|
|
4d1119391a | ||
|
|
1dd622fcbb | ||
|
|
af4b64983a | ||
|
|
e751092555 | ||
|
|
ce06b1d3d7 | ||
|
|
a834f4996f | ||
|
|
fdcf267fe3 | ||
|
|
7f2ebd1b5e | ||
|
|
68b2d9f269 | ||
|
|
3f1eed9f59 | ||
|
|
0637dbaab1 | ||
|
|
85388e97c1 | ||
|
|
de961eb45e | ||
|
|
3d60770b84 | ||
|
|
93c5853356 | ||
|
|
98e587285b | ||
|
|
2aa13c8347 | ||
|
|
53344771fd | ||
|
|
2373743920 | ||
|
|
90a3497afe | ||
|
|
339aebb08c | ||
|
|
b4afe390d6 | ||
|
|
ca0c5f929a | ||
|
|
48cc526c7e | ||
|
|
3d30dc8d02 | ||
|
|
75adb2e686 | ||
|
|
45787a87b3 | ||
|
|
0a85734ae7 | ||
|
|
b28c1186b2 | ||
|
|
5007f8488c | ||
|
|
f7062498c2 | ||
|
|
964744d330 | ||
|
|
f5d635b67b | ||
|
|
d0112a98b5 | ||
|
|
614b9113ad | ||
|
|
e14cd758ad | ||
|
|
de1361d99d | ||
|
|
e731775f70 | ||
|
|
342d61b283 | ||
|
|
b030cdb4e3 | ||
|
|
18a973d4f2 | ||
|
|
51fa7d2611 | ||
|
|
6b6d3b3770 | ||
|
|
fd5e3fbbb9 | ||
|
|
6247bbc629 | ||
|
|
0181e640c9 | ||
|
|
26230596ba | ||
|
|
884e052d98 | ||
|
|
5516180ed8 | ||
|
|
6d00aef398 | ||
|
|
2d52dae69c | ||
|
|
eb64ffcec9 | ||
|
|
7eba5a994d | ||
|
|
c39d2e243a | ||
|
|
3661af921e | ||
|
|
4581755f9b | ||
|
|
593b0f295a | ||
|
|
7c23b6473c | ||
|
|
960a3a1483 | ||
|
|
485d4324f8 | ||
|
|
881788c0c9 | ||
|
|
73cf55b958 | ||
|
|
b7c2c476a8 | ||
|
|
fa152bef20 | ||
|
|
770054daaf | ||
|
|
2ad5066271 | ||
|
|
99acd64203 | ||
|
|
86154f81aa | ||
|
|
e982b7911f | ||
|
|
4e138ee795 | ||
|
|
8e5d0a6425 | ||
|
|
33901afa57 | ||
|
|
8fce7dc78e | ||
|
|
d618b817ca | ||
|
|
914be8dbd7 | ||
|
|
9e67a90b25 | ||
|
|
44e67c987b | ||
|
|
3c6c90c1e7 | ||
|
|
3e8bd16d2b | ||
|
|
fb964b8686 | ||
|
|
38ef16b08b | ||
|
|
1f5c97964b | ||
|
|
4798cd6d1e | ||
|
|
df4194ca57 | ||
|
|
888599677e | ||
|
|
22da42b121 | ||
|
|
5ad8bc3ba4 | ||
|
|
0154ffa060 | ||
|
|
cb3f5a74a8 | ||
|
|
b3c7dbe3e4 | ||
|
|
6b24b263ab | ||
|
|
75b69fbf85 | ||
|
|
23b410ccb0 | ||
|
|
bf6a9cb0e7 | ||
|
|
689e29bc42 | ||
|
|
b316af13d6 | ||
|
|
e7f939c87b | ||
|
|
b94446161e | ||
|
|
567cf44111 | ||
|
|
9244bdc7db | ||
|
|
0db2597d1e | ||
|
|
744d5d1141 | ||
|
|
778315da5f | ||
|
|
1acda22ad4 | ||
|
|
4cb1f69475 | ||
|
|
f1806cbf2e | ||
|
|
a4beb7d493 | ||
|
|
880ae0fe7c | ||
|
|
cd3cc7e696 | ||
|
|
9e9a9847fc | ||
|
|
cb5f5baa2b | ||
|
|
edef41fb71 | ||
|
|
6bfa5ce600 | ||
|
|
d1f70bfe2c | ||
|
|
a56f512dc3 | ||
|
|
7c88fd0a17 | ||
|
|
bec23c6d57 | ||
|
|
81197b1aa4 | ||
|
|
8205e22465 | ||
|
|
8407af17f4 | ||
|
|
22fef6fa36 | ||
|
|
88f91d3959 | ||
|
|
b63abe1cf2 | ||
|
|
cd3dc78d4d | ||
|
|
ddf5a01dfc | ||
|
|
10e8790311 | ||
|
|
f04a26901c | ||
|
|
b9f4f1eba4 | ||
|
|
8b0d49f036 | ||
|
|
e94a2c900f | ||
|
|
bfb84a7ac4 | ||
|
|
fa272d9d93 | ||
|
|
87f0217588 | ||
|
|
c4f71f1a44 | ||
|
|
af332eb8ac | ||
|
|
ac6dc2c2d3 | ||
|
|
a29b6772b9 | ||
|
|
3691f02359 | ||
|
|
622d88eeba | ||
|
|
56c19c4f5a | ||
|
|
c5471fe6fd | ||
|
|
046b1da8a8 | ||
|
|
8fd5a5af96 | ||
|
|
229f1560b0 | ||
|
|
8f7f311f60 | ||
|
|
721c8043f1 | ||
|
|
31a86d8af2 | ||
|
|
ac7617990a | ||
|
|
0813d2c7ce | ||
|
|
0ceb0d9e11 | ||
|
|
30db748dcb | ||
|
|
399d549d0c | ||
|
|
77fb2d0eb2 | ||
|
|
ea88bb88b2 | ||
|
|
190e4a5e8a | ||
|
|
823dc3d46f | ||
|
|
779cb2f721 | ||
|
|
88c42d50f2 | ||
|
|
a749bb8ef1 | ||
|
|
723cd8e26c | ||
|
|
a6592e7776 | ||
|
|
4342689e73 | ||
|
|
8a2a7d1180 | ||
|
|
199e226758 | ||
|
|
16ed6cbdcb | ||
|
|
b51d1a4e2e | ||
|
|
534adc9630 | ||
|
|
d15949d2e8 | ||
|
|
43609bc77c | ||
|
|
3917e096ea | ||
|
|
d1a571201b | ||
|
|
8a8cdd2927 | ||
|
|
3ef4acecb5 | ||
|
|
e8c1fc958f | ||
|
|
08bc4ccec4 | ||
|
|
6ae62e3bb1 | ||
|
|
397f2f208a | ||
|
|
8bebf698ef | ||
|
|
6a2a2c33ee | ||
|
|
0adda483c5 | ||
|
|
d8eb918cea | ||
|
|
96b95db7c8 | ||
|
|
b1915106b0 | ||
|
|
0d2a8488ae | ||
|
|
a52c8aa291 | ||
|
|
fbbafb45a3 | ||
|
|
659adca473 | ||
|
|
38e8a581b6 | ||
|
|
06e476e8c8 | ||
|
|
f529f06ea1 | ||
|
|
159ded433d | ||
|
|
c3b6422ad0 | ||
|
|
41b78c26ef | ||
|
|
ca93c5b666 | ||
|
|
80f8b778a9 | ||
|
|
8c5db5f980 | ||
|
|
3756361cfe | ||
|
|
5f3e167799 | ||
|
|
b7ed779f71 | ||
|
|
fa6f564c12 | ||
|
|
ad457f717b | ||
|
|
f95ce7f52d | ||
|
|
ec73f23e4a | ||
|
|
2972d7c309 | ||
|
|
4d003bc13f | ||
|
|
4cb11861e4 | ||
|
|
addd50467e | ||
|
|
6cd2dbf178 | ||
|
|
f079e63737 | ||
|
|
d807041aa5 | ||
|
|
6153d7f168 | ||
|
|
e37feece4d | ||
|
|
6cf11cb6cf | ||
|
|
bb4e64ea58 | ||
|
|
9ed55776a9 | ||
|
|
b45bc9af67 | ||
|
|
2227e487c0 | ||
|
|
1f49ce599f | ||
|
|
8af995cc28 | ||
|
|
b39d660189 | ||
|
|
9608da5bf9 | ||
|
|
d3adcf3185 | ||
|
|
40c051fb6b | ||
|
|
015f1ba8c0 | ||
|
|
c3de4a5c3b | ||
|
|
09210e4316 | ||
|
|
93b382f174 | ||
|
|
42cf51c6aa | ||
|
|
f7bc258c2f | ||
|
|
9e1908fc6f | ||
|
|
6bdb3f6ea1 | ||
|
|
2fe94bceb6 | ||
|
|
371639f0dc | ||
|
|
f88d424ecd | ||
|
|
c2ca80c889 | ||
|
|
0313e19674 | ||
|
|
281d4359d0 | ||
|
|
7b02c37fa7 | ||
|
|
2ea0b0d60c | ||
|
|
d879e028cf | ||
|
|
3e7e81e078 | ||
|
|
cc53d59532 | ||
|
|
319dea1f7d | ||
|
|
48047c05b7 | ||
|
|
85b0273911 | ||
|
|
eb72b6baee | ||
|
|
422addcbb6 | ||
|
|
4a58be2aa0 | ||
|
|
562b54839c | ||
|
|
639eaa9416 | ||
|
|
6c6cb65b30 | ||
|
|
8ea8437e19 | ||
|
|
2656eb1aeb | ||
|
|
fa1e92b127 | ||
|
|
cff8ee13e6 | ||
|
|
3956e3863e | ||
|
|
9600218757 | ||
|
|
2db7cb0d64 | ||
|
|
267a70d621 | ||
|
|
667bedab82 | ||
|
|
49990a0859 | ||
|
|
f7c4cd9398 | ||
|
|
cd4f4d5ad4 | ||
|
|
fe429fe213 | ||
|
|
0a24ca3fe2 | ||
|
|
8c93a0d247 | ||
|
|
5c75dda864 | ||
|
|
55bdded6a4 | ||
|
|
25b2c0f7e3 | ||
|
|
ed522852cf | ||
|
|
224e42d345 | ||
|
|
128a1f59a9 | ||
|
|
40ffde0439 | ||
|
|
ec5578a437 | ||
|
|
1cf40a2d17 | ||
|
|
958ea0ac1d | ||
|
|
a9fdae28b2 | ||
|
|
3d9eb869b0 | ||
|
|
8162c6d42f | ||
|
|
48a9f17222 | ||
|
|
e381d04094 | ||
|
|
0e79326571 | ||
|
|
f7eb8cd913 | ||
|
|
a15c1f99b2 | ||
|
|
ba2191172d | ||
|
|
6ab2c9dbbf | ||
|
|
7da460d4b1 | ||
|
|
ffe7b1f4a1 | ||
|
|
6a1f502d25 | ||
|
|
434359ea01 | ||
|
|
ae2ad6ddf2 | ||
|
|
ec11683dc5 | ||
|
|
47318b0c14 | ||
|
|
60d6214ad7 | ||
|
|
a3e26a21a7 | ||
|
|
d0f3a6f74b | ||
|
|
fee236a050 | ||
|
|
e3e4bcc015 | ||
|
|
2d546ccbf7 | ||
|
|
b41804bb5b | ||
|
|
47a04df189 | ||
|
|
2efedaf46c | ||
|
|
49e43c830b | ||
|
|
763e101208 | ||
|
|
e39a62b1fd | ||
|
|
da76abda75 | ||
|
|
829d7d0a7e | ||
|
|
9f6372b305 | ||
|
|
12edd782c6 | ||
|
|
0b59fa9416 | ||
|
|
cc0f12ed26 | ||
|
|
f42553d0e1 | ||
|
|
e7564420c9 | ||
|
|
e81a0ded11 | ||
|
|
a32c702dbd | ||
|
|
23a5ed71de | ||
|
|
245dc97cfb | ||
|
|
ece204c30f | ||
|
|
1bd59096fd | ||
|
|
0b02c2c6a7 | ||
|
|
6a61a499e9 | ||
|
|
6b1c283082 | ||
|
|
5402a9611e | ||
|
|
43e06ccd45 | ||
|
|
f52c825bf5 | ||
|
|
bf8b709372 | ||
|
|
fdf82e5270 | ||
|
|
0224a1b66b | ||
|
|
505ad6d69b | ||
|
|
5bcd573821 | ||
|
|
c5a291d9c7 | ||
|
|
232a8c1148 | ||
|
|
663f6eaf5c | ||
|
|
9d3210259c | ||
|
|
4ec6c2f7cf | ||
|
|
8452bec877 | ||
|
|
0d4296e0e1 | ||
|
|
2b85da3bc9 | ||
|
|
17f194b9a3 | ||
|
|
ff47fbaedc | ||
|
|
87c88f7463 | ||
|
|
60fd5f7ab8 | ||
|
|
5ceab059dc | ||
|
|
67c898f9ad | ||
|
|
d903187eea | ||
|
|
653f0841e4 | ||
|
|
10bfadb556 | ||
|
|
0b2cc066dd | ||
|
|
60ab13d216 | ||
|
|
f90c658567 | ||
|
|
0c54895877 | ||
|
|
4eb54328f8 | ||
|
|
b1189db9c5 | ||
|
|
869578f1ba | ||
|
|
3320f776ce | ||
|
|
1d64635783 | ||
|
|
bbb076c0d4 | ||
|
|
fe2a4d0428 | ||
|
|
6bdc1941e6 | ||
|
|
9188905145 | ||
|
|
3f2fbb10d8 | ||
|
|
9c97235fe8 | ||
|
|
70a13b47db | ||
|
|
18afaf0eaf | ||
|
|
8b8c3d8116 | ||
|
|
514fc9fe43 | ||
|
|
5d8923d69c | ||
|
|
5db880af57 | ||
|
|
c05db9ce58 | ||
|
|
04079abe00 | ||
|
|
8054b69f73 | ||
|
|
b5ee777466 | ||
|
|
96f3061709 | ||
|
|
420c5a4ff3 | ||
|
|
e8f6476e8c | ||
|
|
65ec35b732 | ||
|
|
8d731b5d15 | ||
|
|
38c0dc4551 | ||
|
|
4d8cb0469f | ||
|
|
62cb8f5ba6 | ||
|
|
97c75d96d5 | ||
|
|
f5ae806b31 | ||
|
|
482dc3a5a5 | ||
|
|
a8539ac004 | ||
|
|
9970c56218 | ||
|
|
480218412a | ||
|
|
6ae09d2866 | ||
|
|
609680b328 | ||
|
|
ccbe370c8e | ||
|
|
9706e47643 | ||
|
|
d98361f782 | ||
|
|
ba7c789ec9 | ||
|
|
d128997d40 | ||
|
|
61342547ce | ||
|
|
c1a5f173b8 | ||
|
|
f5c5b7b2c8 | ||
|
|
057b47555d | ||
|
|
43299f6747 | ||
|
|
03bf6cb719 | ||
|
|
3a1bb12830 | ||
|
|
5efa68757e | ||
|
|
afaf5bf3ea | ||
|
|
50c805826f | ||
|
|
35ae9f4a64 | ||
|
|
d7d96c02a2 | ||
|
|
dd03723144 | ||
|
|
26f07196ea | ||
|
|
8c291fdfe3 | ||
|
|
d1e118f07c | ||
|
|
6c531c14e6 | ||
|
|
433213c915 | ||
|
|
ab0c0b18c2 | ||
|
|
29fd5f9fbe | ||
|
|
882d8afc93 | ||
|
|
e11635d15c | ||
|
|
5d79d93aac | ||
|
|
7ccf651fd0 | ||
|
|
67af41cce8 | ||
|
|
e2c96e62e1 | ||
|
|
2ecae442fc | ||
|
|
a1060b0eb5 | ||
|
|
ddd8de888f | ||
|
|
a758dffbc1 | ||
|
|
87775faeca | ||
|
|
ef0fc46ed8 | ||
|
|
138b4fa247 | ||
|
|
47d1f3459c | ||
|
|
4712aae834 | ||
|
|
2900ee1cde | ||
|
|
c6c4178dd2 | ||
|
|
a3ce0e6b1b | ||
|
|
0b1ad3b7f0 | ||
|
|
37fb46f092 | ||
|
|
bc8bf9a9fb | ||
|
|
9e28c98911 | ||
|
|
0a1269d52d | ||
|
|
2e5bc31c9e | ||
|
|
1b335fd945 | ||
|
|
0c8b2d007a | ||
|
|
9ee1b32e2d | ||
|
|
953ad98a16 | ||
|
|
1357057bd8 | ||
|
|
35c9323de6 | ||
|
|
13a0afef06 | ||
|
|
c7ad8e4bf6 | ||
|
|
f1754bdd5f | ||
|
|
c462a1c500 | ||
|
|
0bba184994 | ||
|
|
178602ea1f | ||
|
|
2eb8f88a20 | ||
|
|
96d11df06c | ||
|
|
950d210ec5 | ||
|
|
55c1bddac5 | ||
|
|
ac50c762d7 | ||
|
|
5c2ab150b3 | ||
|
|
0870536405 | ||
|
|
b47ede477a | ||
|
|
eef5cc17b3 | ||
|
|
ad2191333d | ||
|
|
a85cac497d | ||
|
|
e0c69d7df5 | ||
|
|
ff3d91ceb4 | ||
|
|
5777431577 | ||
|
|
cd86f80203 | ||
|
|
8c885d3f37 | ||
|
|
dddb46a6d0 | ||
|
|
6b0f378c5b | ||
|
|
9dd7f37d42 | ||
|
|
9f10fb6472 | ||
|
|
64dbccb9bd | ||
|
|
9a432a5a13 | ||
|
|
842e494fa6 | ||
|
|
7fc9ee154a | ||
|
|
5f84010c2a | ||
|
|
3dcd6cb80b | ||
|
|
79e94bf766 | ||
|
|
3de370f3d5 | ||
|
|
c84d2f4624 | ||
|
|
380a9f7a6f | ||
|
|
a6c7b67d0d | ||
|
|
c13c1f2577 | ||
|
|
151405618f | ||
|
|
70e11cc309 | ||
|
|
7619824d80 | ||
|
|
f3d181b5ee | ||
|
|
55055a70f0 | ||
|
|
22d3ba674e | ||
|
|
ac487a2133 | ||
|
|
4da3a14adc | ||
|
|
69ec810ed0 | ||
|
|
2df01316ce | ||
|
|
3a67aefee2 | ||
|
|
d114dffcb4 | ||
|
|
7bb5d9a67a | ||
|
|
a6b1e57ae1 | ||
|
|
c70c13eb5c | ||
|
|
d905ea354e | ||
|
|
99cec81894 | ||
|
|
5d5bccf1bb | ||
|
|
6fcf0a77af | ||
|
|
e7477c0abf | ||
|
|
85540855c3 | ||
|
|
2dc220b42f | ||
|
|
2d6cadbf1b | ||
|
|
340871e03a | ||
|
|
e222a74960 | ||
|
|
ab499d5095 | ||
|
|
a5f7027229 | ||
|
|
bf5cf897e2 | ||
|
|
d33c1af549 | ||
|
|
677464d04d | ||
|
|
d2d6ed8bd4 | ||
|
|
bd2a44dbdd | ||
|
|
e9ee4beb9f | ||
|
|
3b3f057f6f | ||
|
|
a9dec51e59 | ||
|
|
257312ad7c | ||
|
|
6ee8a2dfa7 | ||
|
|
75c5e9cfa7 | ||
|
|
1a94f2b585 | ||
|
|
f0b4c42c68 | ||
|
|
9be061735f | ||
|
|
6bfa525080 | ||
|
|
8fcaf18897 | ||
|
|
f558cde266 | ||
|
|
b508a33f5d | ||
|
|
b4db99006b | ||
|
|
8994f079a5 | ||
|
|
b2d184cfa5 | ||
|
|
92dc92379f | ||
|
|
2a6862ceb9 | ||
|
|
4c569e1d5f | ||
|
|
4420ffd49e | ||
|
|
fb7f57cf6a | ||
|
|
8be3bdac5d | ||
|
|
2785376bd3 | ||
|
|
d6e77e531d | ||
|
|
add509bf9e | ||
|
|
e686b1410d | ||
|
|
2c23a1e0a0 | ||
|
|
47eb9e8c8f | ||
|
|
712b354421 | ||
|
|
18ef4922de | ||
|
|
274f9d5846 | ||
|
|
f6fa085fe4 | ||
|
|
9ab0f04ba5 | ||
|
|
fb7854f1ef | ||
|
|
1086c31503 | ||
|
|
3a47248a09 | ||
|
|
71a333261b | ||
|
|
5ea2e295c1 | ||
|
|
1fc7547a53 | ||
|
|
a7d63649f8 | ||
|
|
2f26fcdc2a | ||
|
|
107d4cdd61 | ||
|
|
52f9aad4d0 | ||
|
|
7bb5175084 | ||
|
|
dd570b616b | ||
|
|
943a30af04 | ||
|
|
eabed60e56 | ||
|
|
f793413a79 | ||
|
|
f4a3b8571d | ||
|
|
da6586b847 | ||
|
|
4a5f34089d | ||
|
|
90da9659d1 | ||
|
|
2e30acf611 | ||
|
|
5554d13f7f | ||
|
|
a5ef33b302 | ||
|
|
9a2588f7eb | ||
|
|
cac5852e68 | ||
|
|
d52d50e283 | ||
|
|
6911da8581 | ||
|
|
e70f9a67b8 | ||
|
|
e4bc767644 | ||
|
|
97ab977f58 | ||
|
|
173aa7333a | ||
|
|
058aca0ce3 | ||
|
|
8ab693f3fe | ||
|
|
2396b2d4db | ||
|
|
6120c0daec | ||
|
|
790f9bde54 | ||
|
|
7a469fb481 | ||
|
|
d4a2011a59 | ||
|
|
9165832caf | ||
|
|
d274a5c13c | ||
|
|
e6bd15c68b | ||
|
|
38bef99f98 | ||
|
|
95ff9e7165 | ||
|
|
2fddbdddee | ||
|
|
465e812ed9 | ||
|
|
3b1fb79a85 | ||
|
|
0f8f35b415 | ||
|
|
a133b1c2a9 | ||
|
|
fa74acb5f0 | ||
|
|
836b4c358f | ||
|
|
982e32d108 | ||
|
|
024a335505 | ||
|
|
963cbf61e4 | ||
|
|
6d98d2c7c3 | ||
|
|
64726f13e1 | ||
|
|
85dfaaa2c2 | ||
|
|
42a915b04a | ||
|
|
42a8aa6c66 | ||
|
|
56464d3291 | ||
|
|
aed96ee753 | ||
|
|
a937320c65 | ||
|
|
71b2232995 | ||
|
|
a2d9730c60 | ||
|
|
a81a0cb059 | ||
|
|
5af9511505 | ||
|
|
14ae9b312d | ||
|
|
2d3e5c2e0b | ||
|
|
17950fec3e | ||
|
|
2009140da8 | ||
|
|
2a394eee62 | ||
|
|
09a7585643 | ||
|
|
a09084ceba | ||
|
|
147e5dceff | ||
|
|
3510afd30b | ||
|
|
d3586c2143 | ||
|
|
56ba2325c1 | ||
|
|
b77a4ed3a1 | ||
|
|
9b86c3127a | ||
|
|
0da7ffe45f | ||
|
|
30b78d9559 | ||
|
|
c16abc0b85 | ||
|
|
708c691cdb | ||
|
|
31c20ac4d8 | ||
|
|
1458014a29 | ||
|
|
4de1241713 | ||
|
|
1c84a5c8ad | ||
|
|
6728b843f7 | ||
|
|
1b55104d51 | ||
|
|
55d78b0197 | ||
|
|
c3c277f03b | ||
|
|
76978bfd47 | ||
|
|
6ff3231dab | ||
|
|
64716e6b42 | ||
|
|
a1191eb4ab | ||
|
|
ccb687e552 | ||
|
|
075dbbd08b | ||
|
|
24266c64ef | ||
|
|
f19430447a | ||
|
|
166bed732e | ||
|
|
02cb12e4b4 | ||
|
|
159467ad44 | ||
|
|
2a006086c5 | ||
|
|
e0dc1eec93 | ||
|
|
ab130ee92c | ||
|
|
dabbe09918 | ||
|
|
296a7ac11d | ||
|
|
6bbf08893e | ||
|
|
f8b958738a | ||
|
|
1b4427f13f | ||
|
|
e55577fd26 | ||
|
|
c42960ec2a | ||
|
|
c033d4b65c | ||
|
|
dc6f03b4e4 | ||
|
|
b6967a432a | ||
|
|
7d0467863c | ||
|
|
a0b72d3995 | ||
|
|
5fe4b867f3 | ||
|
|
40af058406 | ||
|
|
b4376a6a8c | ||
|
|
457422c679 | ||
|
|
080eba948f | ||
|
|
eff86defd9 | ||
|
|
fcb463d400 | ||
|
|
efee8149e2 | ||
|
|
bc32f37fce | ||
|
|
58bfa247a4 | ||
|
|
59b9b31604 | ||
|
|
844af709c0 | ||
|
|
bb6e2d6885 | ||
|
|
6243dc7913 | ||
|
|
45c4362ae6 | ||
|
|
a0230b7e00 | ||
|
|
768755c31a | ||
|
|
3088c7f198 | ||
|
|
c8469071bf | ||
|
|
115fc301b5 | ||
|
|
bc449b8e95 | ||
|
|
74bbc0fe7e | ||
|
|
c73fa3d7a6 | ||
|
|
5694610478 | ||
|
|
ec107dfba5 | ||
|
|
64aa476330 | ||
|
|
42f6719e8d | ||
|
|
244b9dc02b | ||
|
|
fe3644a417 | ||
|
|
e18b61e041 | ||
|
|
d054782693 | ||
|
|
d56e53a347 | ||
|
|
3503c721ac | ||
|
|
0fab5f07d0 | ||
|
|
b0d12f8bf9 | ||
|
|
9fe58aaabc | ||
|
|
03c8ea14cc | ||
|
|
260edc2a08 | ||
|
|
b41591a527 | ||
|
|
4e9481451b | ||
|
|
95b48da37d | ||
|
|
1b36785177 | ||
|
|
8bc76e3d58 | ||
|
|
1a5e2b907d | ||
|
|
3717e5c2e0 | ||
|
|
33a1416199 | ||
|
|
ff4221fbe7 | ||
|
|
486bca82e8 | ||
|
|
611d07fc16 | ||
|
|
f7e12586cf | ||
|
|
f62aa051c8 | ||
|
|
2b6b898102 | ||
|
|
1dd0444531 | ||
|
|
ba9eb01c1f | ||
|
|
73a8144e75 | ||
|
|
6aef422de6 | ||
|
|
5f4b8b60cb | ||
|
|
3256236ba2 | ||
|
|
b102727320 | ||
|
|
3434005e66 | ||
|
|
b3026a7991 | ||
|
|
0a051832a8 | ||
|
|
2dbafbda02 | ||
|
|
240b6fb6f2 | ||
|
|
4163d3655a | ||
|
|
2c7bf49fc9 | ||
|
|
739592e50d | ||
|
|
393e31e509 | ||
|
|
a1dceacc8f | ||
|
|
cf26c87872 | ||
|
|
21195b3491 | ||
|
|
3f66f6a6a5 | ||
|
|
daae4f2f80 | ||
|
|
4e2708c1ac | ||
|
|
d57d8e0d5d | ||
|
|
9577a6af21 | ||
|
|
107a6aed01 | ||
|
|
2c2045d413 | ||
|
|
30fe471d2b | ||
|
|
5ab6979633 | ||
|
|
ec5e9cb6e3 | ||
|
|
f4b4546197 | ||
|
|
f047749e61 | ||
|
|
87840ce91d | ||
|
|
bf31e9f634 | ||
|
|
f86d84daed | ||
|
|
41ed920d35 | ||
|
|
df23ddb545 | ||
|
|
767556ccad | ||
|
|
f9dab2ad19 | ||
|
|
66cb3a6120 | ||
|
|
7672a370da | ||
|
|
870e47ed03 | ||
|
|
32d4bdb80f | ||
|
|
929dfd2c71 | ||
|
|
f437af6451 | ||
|
|
413a0fb2e5 | ||
|
|
793adadb06 | ||
|
|
999b43b89f | ||
|
|
bd60c88c7d | ||
|
|
23b9a2eddf | ||
|
|
0b57d97c8c | ||
|
|
6255293dd4 | ||
|
|
04136d95a3 | ||
|
|
40aa29e42a | ||
|
|
a709f30da9 | ||
|
|
0796c14e79 | ||
|
|
a9c0a4be23 | ||
|
|
3e1209d3a4 | ||
|
|
caf14c1b7c | ||
|
|
27f7d2c8d2 | ||
|
|
8ee430eda2 | ||
|
|
484e4cb225 | ||
|
|
b080ad9954 | ||
|
|
f6625d9188 | ||
|
|
1eb2816bc4 | ||
|
|
077be5aaf3 | ||
|
|
d59875f114 | ||
|
|
e89191ed39 | ||
|
|
ea21438637 | ||
|
|
0d2e8333e8 | ||
|
|
338399e622 | ||
|
|
27cab8aad5 | ||
|
|
1545a49b4c | ||
|
|
3ca15250e8 | ||
|
|
6cbac51731 | ||
|
|
e310c666b1 | ||
|
|
677b0170aa | ||
|
|
9150b770e4 | ||
|
|
2ad6511c31 | ||
|
|
0848f28d83 | ||
|
|
5d9bc950ce | ||
|
|
714da79395 | ||
|
|
823fe9ebbd | ||
|
|
4bf72b5383 | ||
|
|
51945f002b | ||
|
|
bcca9387de | ||
|
|
b8417fa46d | ||
|
|
85b0699288 | ||
|
|
6c03fb0226 | ||
|
|
a084dea07c | ||
|
|
2e0fc3e4c1 | ||
|
|
24f4d410ce | ||
|
|
052e0445ab | ||
|
|
758c908d5a | ||
|
|
3917c2589d | ||
|
|
f4a77308ec | ||
|
|
103b9724f9 | ||
|
|
75a315ecf0 | ||
|
|
63b3b9ef6d | ||
|
|
a6c2cfe89b | ||
|
|
5120657386 | ||
|
|
e754de46d1 | ||
|
|
5d718aa0d6 | ||
|
|
55fcbc8880 | ||
|
|
e19aa001b2 | ||
|
|
b447ea9c18 | ||
|
|
13274655d4 | ||
|
|
3723ac60ef | ||
|
|
da578f47f1 | ||
|
|
433e7de686 | ||
|
|
e18e9ae2ea | ||
|
|
27d5123a61 | ||
|
|
89b9f9ffe2 | ||
|
|
a17b8aaa13 | ||
|
|
e210969612 | ||
|
|
1208356b92 | ||
|
|
d7cd74fe2f | ||
|
|
31b63e9939 | ||
|
|
b99c2c2df1 | ||
|
|
94d3eff9ce | ||
|
|
b78e9961c6 | ||
|
|
b0704ca5d6 | ||
|
|
31c0934108 | ||
|
|
37083c8aef | ||
|
|
af23b0c67b | ||
|
|
a9e83fb9cf | ||
|
|
51126e1691 | ||
|
|
dd410a2de5 | ||
|
|
7ccb0b5c02 | ||
|
|
7f3e62e456 | ||
|
|
fcfc29d7ea | ||
|
|
2f3429a144 | ||
|
|
20782693f4 | ||
|
|
0cfb354374 | ||
|
|
9be5b7c6c9 | ||
|
|
e7653d2ea6 | ||
|
|
1494887e29 | ||
|
|
42dab2b1a5 | ||
|
|
36a0c1fb17 | ||
|
|
60c6767337 | ||
|
|
75451cc7fa | ||
|
|
db10035d9d | ||
|
|
67df4861ce | ||
|
|
4ad3e52407 | ||
|
|
b5b2e322c2 | ||
|
|
2e39432e04 | ||
|
|
75e0eb8f7d | ||
|
|
4d7309b77d | ||
|
|
384cc8541e | ||
|
|
63bd4faa22 | ||
|
|
acba3e8c7b | ||
|
|
a4ec54551a | ||
|
|
155e766276 | ||
|
|
59ef64c821 | ||
|
|
9feaee3e28 | ||
|
|
5fd30876ab | ||
|
|
8d1288373d | ||
|
|
f487cf0763 | ||
|
|
bea0f46d31 | ||
|
|
a55282f2c8 | ||
|
|
09764c65ae | ||
|
|
6f29e2ea12 | ||
|
|
2ed18ddded | ||
|
|
9f45a1e8cb | ||
|
|
2e5fcd45bd | ||
|
|
2c8cf356f9 | ||
|
|
8b6243d872 | ||
|
|
8082d2092f | ||
|
|
c2840ce608 | ||
|
|
addd2f76ef | ||
|
|
d6c715c5c3 | ||
|
|
1e84082d81 | ||
|
|
8602bd4e9e | ||
|
|
ac0e9b633d | ||
|
|
d683f32a34 | ||
|
|
b92b13158b | ||
|
|
dea0c2ce43 | ||
|
|
0ec21fa424 | ||
|
|
0258055c1d | ||
|
|
9280d47766 | ||
|
|
63d6c2f1fd | ||
|
|
ad3ca3b304 | ||
|
|
1564dc4e8e | ||
|
|
7dbaf87cd4 | ||
|
|
5b0aed5035 | ||
|
|
72f3fc9578 | ||
|
|
00a0959e45 | ||
|
|
f587f6ecd6 | ||
|
|
2906ab7cd5 | ||
|
|
2b30141bcc | ||
|
|
7bcce219ed | ||
|
|
5a7ea67a0e | ||
|
|
c04631dad5 | ||
|
|
aca292da94 | ||
|
|
f1b4b01029 | ||
|
|
5d737987bb | ||
|
|
f84dafb7fe | ||
|
|
dc6397e607 | ||
|
|
a1f8416336 | ||
|
|
02f1a92a1b | ||
|
|
d5d3c6868e | ||
|
|
b9028879fb | ||
|
|
59411a214a | ||
|
|
b69649c50e | ||
|
|
dc13474729 | ||
|
|
7674964cc8 | ||
|
|
a8f3701e92 | ||
|
|
ad3157e940 | ||
|
|
332f81553a | ||
|
|
c22c227108 | ||
|
|
e72b89a88b | ||
|
|
3369cca3e6 | ||
|
|
906e6ece0b | ||
|
|
4179464de1 | ||
|
|
fe0661fde9 | ||
|
|
76cd263c83 | ||
|
|
fa4c023961 | ||
|
|
e18d0976ef | ||
|
|
ae23528e04 | ||
|
|
bee36ae6a8 | ||
|
|
397dbcad51 | ||
|
|
4eb42bf73a | ||
|
|
eb830889f9 | ||
|
|
98ba50c974 | ||
|
|
a692857fe8 | ||
|
|
4fa711bfd3 | ||
|
|
8d9d9fd682 | ||
|
|
949c9e278b | ||
|
|
74babbfe01 | ||
|
|
e260228e90 | ||
|
|
a0d0aac9da | ||
|
|
6755c8ef7f | ||
|
|
b7d97bc21b | ||
|
|
24a56795aa | ||
|
|
2fd2d749dc | ||
|
|
84e158da79 | ||
|
|
31edf71985 | ||
|
|
4f25b03c9c | ||
|
|
3da70aa4f7 | ||
|
|
74dd990f2f | ||
|
|
1aab248fa4 | ||
|
|
8582c505e9 | ||
|
|
57cb127d73 | ||
|
|
af9a759e9a | ||
|
|
c7b1f28590 | ||
|
|
37c84ad909 | ||
|
|
face262d32 | ||
|
|
c9716b87be | ||
|
|
5ec762b69c | ||
|
|
688fc87f48 | ||
|
|
0aaf624cd7 | ||
|
|
64403a5cd8 | ||
|
|
5efac59e8f | ||
|
|
2eae8a02e5 | ||
|
|
0cfc3966c5 | ||
|
|
a56fe98dc5 | ||
|
|
586a03d431 | ||
|
|
c175a1b949 | ||
|
|
3937520d3e | ||
|
|
4309604eca | ||
|
|
4360676f96 | ||
|
|
6ad205a619 | ||
|
|
24632c0e69 | ||
|
|
6d2d7a9d6d | ||
|
|
7e76089b76 | ||
|
|
73cbe46ecb | ||
|
|
385c557a60 | ||
|
|
6058828a33 | ||
|
|
cd11dd138e | ||
|
|
5b93c0651e | ||
|
|
63026564c2 | ||
|
|
f415ac379d | ||
|
|
7b62f5af21 | ||
|
|
bfef1cf301 | ||
|
|
0f02f3472e | ||
|
|
2f8ab7174b | ||
|
|
1b5e416988 | ||
|
|
03105e096d | ||
|
|
3d19551172 | ||
|
|
811de8d4e7 | ||
|
|
0d1d899d7c | ||
|
|
72e3313c30 | ||
|
|
b48d965111 | ||
|
|
08d2309986 | ||
|
|
cc0bf4bc43 | ||
|
|
fbb5301075 | ||
|
|
47433059b5 | ||
|
|
5aaa34dc7e | ||
|
|
f68aa134a1 | ||
|
|
8577f3bd79 | ||
|
|
8e441e2b96 | ||
|
|
2b0a4f552b | ||
|
|
aa3af3bf67 | ||
|
|
31573ccbeb | ||
|
|
9c086c503a | ||
|
|
27b2fb55c2 | ||
|
|
69081da566 | ||
|
|
2d04a3faa9 | ||
|
|
300e65e200 | ||
|
|
09a88e4cbc | ||
|
|
ffa411b874 | ||
|
|
cc25bb91bd | ||
|
|
a3e10ef9ac | ||
|
|
1c1cab6e30 | ||
|
|
88873cad9d | ||
|
|
48fe23b483 | ||
|
|
76f3b31eb4 | ||
|
|
ea4929c7e7 | ||
|
|
00d5b652c1 | ||
|
|
df311e861d | ||
|
|
e7a6988811 | ||
|
|
9c72a2ed05 | ||
|
|
ea085ae8d7 | ||
|
|
4cf28bb6b8 | ||
|
|
4e58654c10 | ||
|
|
57847a7dd3 | ||
|
|
a1af4dba99 | ||
|
|
96432c6ca9 | ||
|
|
268f4a8ec2 | ||
|
|
a80e3e3022 | ||
|
|
8e517beff8 | ||
|
|
108dc1243f | ||
|
|
3b3d82e097 | ||
|
|
94bdf0238a | ||
|
|
41fc8e1672 | ||
|
|
4d7018bfde | ||
|
|
0637008eec | ||
|
|
c658fe782d | ||
|
|
94ec3df282 | ||
|
|
90fa1c1fef | ||
|
|
78e36a2eab | ||
|
|
88df5e4631 | ||
|
|
124bedcc59 | ||
|
|
92423c8108 | ||
|
|
d7389e4511 | ||
|
|
b923b3d6b6 | ||
|
|
b7b468ba14 | ||
|
|
20f95b2104 | ||
|
|
c5900d761f | ||
|
|
a09abe4bcf | ||
|
|
85641c3e1d | ||
|
|
57ce27dfe7 | ||
|
|
2eb6fbbc42 | ||
|
|
37a4c921a6 | ||
|
|
6432a9f68d | ||
|
|
25608759e5 | ||
|
|
0213d3be89 | ||
|
|
8ec0283c06 | ||
|
|
bd17310bad | ||
|
|
67a296d304 | ||
|
|
2f4f36d407 | ||
|
|
828ede1e3a | ||
|
|
1c02cfb443 | ||
|
|
5885a6ccd4 | ||
|
|
be71073e93 | ||
|
|
dcd92e8a57 | ||
|
|
a1e8f0e1df | ||
|
|
d23797a244 | ||
|
|
0c5d9a8146 | ||
|
|
51b53e0f2c | ||
|
|
691fbe8615 | ||
|
|
c25ebc4adc | ||
|
|
b8b44ff3e3 | ||
|
|
16c91c4046 | ||
|
|
8dbe38ebfe | ||
|
|
a62975fe1f | ||
|
|
00ff0ced07 | ||
|
|
b0099a2c5d | ||
|
|
f0bd91fba7 | ||
|
|
2168912095 | ||
|
|
efc472cf84 | ||
|
|
1018169842 | ||
|
|
06359502e1 | ||
|
|
0949e89c11 | ||
|
|
c1da6335e4 | ||
|
|
4e07206c98 | ||
|
|
426b088e16 | ||
|
|
0e3b544534 | ||
|
|
45b51451ab | ||
|
|
9313824a5f | ||
|
|
6f5e809507 | ||
|
|
7c44e6451a | ||
|
|
27ca283446 | ||
|
|
4647feaf35 | ||
|
|
67c8527e2b | ||
|
|
3b6365a048 | ||
|
|
d216265519 | ||
|
|
ba38146726 | ||
|
|
17ce269513 | ||
|
|
8fcb6ca128 | ||
|
|
58cd129055 | ||
|
|
236586eed5 | ||
|
|
f51e6ab1e2 | ||
|
|
fbcf7758bf | ||
|
|
99454bac95 | ||
|
|
a4745e06fc | ||
|
|
9613276658 | ||
|
|
b3777bd7c0 | ||
|
|
fa43690519 | ||
|
|
aaba1b6db9 | ||
|
|
5368a7f56b | ||
|
|
6d9056c74c | ||
|
|
ea60581142 | ||
|
|
139972e5c8 | ||
|
|
24dd05dd36 | ||
|
|
b028a18d16 | ||
|
|
e2faa06de2 | ||
|
|
3b5e5462b4 | ||
|
|
323e314714 | ||
|
|
7867a53895 | ||
|
|
2e2fca08a3 | ||
|
|
770c72d0c5 | ||
|
|
66eacf4839 | ||
|
|
af63c6fd5b | ||
|
|
9c9f98623a | ||
|
|
4bfd57037b | ||
|
|
58deff4184 | ||
|
|
ec8393eccb | ||
|
|
dd1607f261 | ||
|
|
4138aaf19f | ||
|
|
de21d49463 | ||
|
|
b58214bc26 | ||
|
|
a95b345e33 | ||
|
|
9d94f5973b | ||
|
|
ceba3e90c6 | ||
|
|
a38603ebe1 | ||
|
|
a9bb69cd32 | ||
|
|
1a0700aafe | ||
|
|
690275a0de | ||
|
|
b98df4df07 | ||
|
|
fa91f6d279 | ||
|
|
3a4d5beabd | ||
|
|
ed66e84f71 | ||
|
|
d97cd43174 | ||
|
|
fae4e066e9 | ||
|
|
9c3ed99de2 | ||
|
|
b0a4b00eb0 | ||
|
|
bf245a5439 | ||
|
|
ac3d861df7 | ||
|
|
2e9b4bf07c | ||
|
|
f3ec856995 | ||
|
|
4aa0439be4 | ||
|
|
41ba97d426 | ||
|
|
e759bf819a | ||
|
|
e45165a958 | ||
|
|
f7a298e8b7 | ||
|
|
3fb08631c4 | ||
|
|
54166f6be4 | ||
|
|
abf3e99896 | ||
|
|
da3c921ea8 | ||
|
|
19bae91be1 | ||
|
|
58f8f87e61 | ||
|
|
4209dd9529 | ||
|
|
a207140613 | ||
|
|
34b12cdf8c | ||
|
|
7bdc2664d4 | ||
|
|
8de7adae11 | ||
|
|
006c301564 | ||
|
|
e917d13ce3 | ||
|
|
f8f8e5c743 | ||
|
|
6f16759f6c | ||
|
|
05ff89f1a3 | ||
|
|
6e3365a412 | ||
|
|
1e8888b2a4 | ||
|
|
a5a6dfb0df | ||
|
|
c9febff75f | ||
|
|
a5a51792dc | ||
|
|
df1dbbdd09 | ||
|
|
8d26578c33 | ||
|
|
27c1257d97 | ||
|
|
da85d25a02 | ||
|
|
667d410b9f | ||
|
|
d00b27d447 | ||
|
|
5784a2116f | ||
|
|
016be4ab0f | ||
|
|
3cda974475 | ||
|
|
78f8a7279a | ||
|
|
f1813fed8a | ||
|
|
adae21a549 | ||
|
|
456e391c75 | ||
|
|
ebba9effb7 | ||
|
|
12e6b7a9ab | ||
|
|
172d3f9e88 | ||
|
|
e471a9d586 | ||
|
|
9a78494be9 | ||
|
|
438d574714 | ||
|
|
dff2f20dbb | ||
|
|
1e3e1c574d | ||
|
|
b2d221e3df | ||
|
|
e8d0a3a5b6 | ||
|
|
6a3541f6d9 | ||
|
|
98898f852e | ||
|
|
5a2b0b1514 | ||
|
|
e76774ebe3 | ||
|
|
2e11e1cd30 | ||
|
|
77e209f5ed | ||
|
|
2c73f5a0fa | ||
|
|
d35d54afa4 | ||
|
|
2e42e30f1c | ||
|
|
6f5ccd4239 | ||
|
|
f44451e0f1 | ||
|
|
4fc4454a74 | ||
|
|
100f89b0e7 | ||
|
|
2916a1020e | ||
|
|
3192fd851d | ||
|
|
ce2e4767ad | ||
|
|
8133cd9d01 | ||
|
|
e75f120cf7 | ||
|
|
774ee7cf38 | ||
|
|
f6f2aede91 | ||
|
|
063dc599b9 | ||
|
|
0a35d46131 | ||
|
|
ad5147a53f | ||
|
|
c02a3167ca | ||
|
|
7dde5b83b1 | ||
|
|
7a10caf3df | ||
|
|
7db489df98 | ||
|
|
d2b0860577 | ||
|
|
0af71adf39 | ||
|
|
4697cda8b0 | ||
|
|
df0a0f2a64 | ||
|
|
106b193511 | ||
|
|
1195c1b96b | ||
|
|
e48b54d461 | ||
|
|
1c4c10e97e | ||
|
|
c4d3e4af20 | ||
|
|
d19f81fef1 | ||
|
|
e55c292c81 | ||
|
|
249bbf991a | ||
|
|
a7a1a2457c | ||
|
|
cc211aa82e | ||
|
|
530d68e43a | ||
|
|
276afa836b | ||
|
|
1fde2ba0dd | ||
|
|
c52453ea1a | ||
|
|
cd1c47245a | ||
|
|
4ccca49099 | ||
|
|
38ec856198 | ||
|
|
9b2c616baa | ||
|
|
e5c3122ba7 | ||
|
|
64b30c4bd6 | ||
|
|
2ddcaf37b4 | ||
|
|
072781f21f | ||
|
|
379266732e | ||
|
|
1333895aa6 | ||
|
|
fa1d58020b | ||
|
|
f1aa3d2832 | ||
|
|
dab20204ce | ||
|
|
87a536ffc0 | ||
|
|
77327d2c21 | ||
|
|
491d537384 | ||
|
|
8a599ee8e9 | ||
|
|
6f27a141a5 | ||
|
|
12115e1dd1 | ||
|
|
9e515756af | ||
|
|
e5268bcf3f | ||
|
|
0c16521ff4 | ||
|
|
9575c9a9b5 | ||
|
|
ff81e98bc2 | ||
|
|
b708774bcd | ||
|
|
7bcaa0db87 | ||
|
|
f4538c2eec | ||
|
|
19c8340b5c | ||
|
|
0735d551ff | ||
|
|
57f3f03236 | ||
|
|
848b1f8ae6 | ||
|
|
aba773d1c0 | ||
|
|
3903f06abb | ||
|
|
e365040659 | ||
|
|
0211b8720f | ||
|
|
2c8b1ee753 | ||
|
|
71f1aa6a2d | ||
|
|
3736938bea | ||
|
|
69b11fcf38 | ||
|
|
fe5b7dc7cf | ||
|
|
5b0ee9679c | ||
|
|
441beea431 | ||
|
|
46a9d3fac6 | ||
|
|
aeee1419a2 | ||
|
|
126433c42c | ||
|
|
11a29ac213 | ||
|
|
e33ceda57a | ||
|
|
cd81aa82ea | ||
|
|
76cac2a352 | ||
|
|
285c11522d | ||
|
|
bc1d9fed7f | ||
|
|
80a1f6c4c8 | ||
|
|
156171d77a | ||
|
|
cc21b87045 | ||
|
|
19de6ce5ff | ||
|
|
4f1bc7d68a | ||
|
|
5ef65c1d5b | ||
|
|
9a98aeb958 | ||
|
|
6ebca5c330 | ||
|
|
0cffe3afe9 | ||
|
|
726eab44d9 | ||
|
|
45bf7fa453 | ||
|
|
4195f90e0f | ||
|
|
8065092976 | ||
|
|
631c9c46c0 | ||
|
|
4560bd68a0 | ||
|
|
a7993ad1c3 | ||
|
|
a0b0c6154f | ||
|
|
a78c93a65a | ||
|
|
8459c0e644 | ||
|
|
7986e1631a | ||
|
|
d1e8dce81a | ||
|
|
94b33a11bb | ||
|
|
8c3772a9bf | ||
|
|
34ee7c1d0f | ||
|
|
870c58490b | ||
|
|
880f085b24 | ||
|
|
42bbdc2f3c | ||
|
|
bb58bdeec9 | ||
|
|
230c07cc98 | ||
|
|
b5950a2972 | ||
|
|
b09068e655 | ||
|
|
c8432f81bb | ||
|
|
2131dc7cfd | ||
|
|
52deb81710 | ||
|
|
5d1f77d324 | ||
|
|
5b117fe69a | ||
|
|
14ba7328af | ||
|
|
5a073557ad | ||
|
|
0554a17f67 | ||
|
|
6edbd62ba1 | ||
|
|
2f5536c7b4 | ||
|
|
5b8d6c114c | ||
|
|
e18fcc1e15 | ||
|
|
5aa12da666 | ||
|
|
498a1f4ac9 | ||
|
|
e5a8d1c2c9 | ||
|
|
3d5374a452 | ||
|
|
7d77d01552 | ||
|
|
2d47dcef2c | ||
|
|
4cdc7b93dd | ||
|
|
3794611567 | ||
|
|
8fa32c733c | ||
|
|
19e710f22c | ||
|
|
3ef85a5863 | ||
|
|
9a4468477d | ||
|
|
0978b30e34 | ||
|
|
c6d419594a | ||
|
|
3112adc305 | ||
|
|
b0f7475962 | ||
|
|
1ef511f476 | ||
|
|
cbd1905d69 | ||
|
|
86ac642258 | ||
|
|
2f9968742a | ||
|
|
f2a22f4017 | ||
|
|
963f53a6a4 | ||
|
|
bab2279029 | ||
|
|
ddfc6ee3cf | ||
|
|
67b7d97557 | ||
|
|
2d5682958d | ||
|
|
8ce7db0ff0 | ||
|
|
d58289ca78 | ||
|
|
6a296232bc | ||
|
|
2f11dd22ec | ||
|
|
28702daccc | ||
|
|
eb1305dbd8 | ||
|
|
f70a1d626e | ||
|
|
ee0d139844 | ||
|
|
9279cedba4 | ||
|
|
c6533d40f9 | ||
|
|
4cf64fb370 | ||
|
|
19fc0b3a36 | ||
|
|
aa327eae4b | ||
|
|
53c109cda0 | ||
|
|
7bb46ec007 | ||
|
|
dafb85eca9 | ||
|
|
d513081356 | ||
|
|
1972cd8d5f | ||
|
|
b09bc7d82f | ||
|
|
6306424102 | ||
|
|
fd4695bfbe | ||
|
|
38ab0d7325 | ||
|
|
91cc1af64c | ||
|
|
34c0b256f6 | ||
|
|
d2f80c14f9 | ||
|
|
3b74455dcb | ||
|
|
073e43a5a4 | ||
|
|
bee8f590a3 | ||
|
|
cd89009d6b | ||
|
|
44279c195f | ||
|
|
39c4cfdf81 | ||
|
|
7dfb65760d | ||
|
|
aa3e0b7416 | ||
|
|
35cd2cbd63 | ||
|
|
6331313d67 | ||
|
|
f8a0acd776 | ||
|
|
0e3e1d8af9 | ||
|
|
56c06d7c01 | ||
|
|
293805c657 | ||
|
|
19b2fb76f7 | ||
|
|
561c0d8264 | ||
|
|
6c1f867b55 | ||
|
|
99ff4934c6 | ||
|
|
abf0f9df5e | ||
|
|
4322764fe2 | ||
|
|
ef278d80a2 | ||
|
|
c613a1368d | ||
|
|
30ba1d301b | ||
|
|
26e6eef233 | ||
|
|
19b5ac81a3 | ||
|
|
5bda511154 | ||
|
|
1f330cb1a8 | ||
|
|
1e2d82ee5d | ||
|
|
e8d98a5d71 | ||
|
|
f0fd46bb60 | ||
|
|
556a814f7c | ||
|
|
98d60887b2 | ||
|
|
82c24fc4cb | ||
|
|
d1252c9a91 | ||
|
|
2b65b71538 | ||
|
|
b4ead9c0ac | ||
|
|
1b894336fc | ||
|
|
bf0a8bf50a | ||
|
|
fb70702f02 | ||
|
|
7b28ad7e28 | ||
|
|
d720e327c9 | ||
|
|
b0140727cc | ||
|
|
29aec91121 | ||
|
|
dba7d531e8 | ||
|
|
65f6fe58b7 | ||
|
|
2d9d05f00e | ||
|
|
d7c89d1d9b | ||
|
|
a22678fc46 | ||
|
|
1dda4a0468 | ||
|
|
38f4a7c144 | ||
|
|
a04843e766 | ||
|
|
09be317894 | ||
|
|
80621be0b1 | ||
|
|
432432adc1 | ||
|
|
c2d7ae230c | ||
|
|
6af532e3b3 | ||
|
|
f0275dcc92 | ||
|
|
b634582701 | ||
|
|
545f14a8b6 | ||
|
|
7dbe0f8c89 | ||
|
|
01b11823c2 | ||
|
|
15cb862bc2 | ||
|
|
e60adf229e | ||
|
|
ed3a634474 | ||
|
|
fb5efe3001 | ||
|
|
c73257d155 | ||
|
|
fd4c08fe76 | ||
|
|
6285b271b8 | ||
|
|
e840082cb1 | ||
|
|
8b92060588 | ||
|
|
cb07de4364 | ||
|
|
253997f228 | ||
|
|
2680c60215 | ||
|
|
2a465e2ee6 | ||
|
|
837c384e86 | ||
|
|
5b30cf5bc2 | ||
|
|
e87ac3da81 | ||
|
|
b20e90ea24 | ||
|
|
fa72090ea1 | ||
|
|
56670e9015 | ||
|
|
beb1dd4838 | ||
|
|
71a667effe | ||
|
|
7896fc7ea7 | ||
|
|
4c554937a0 | ||
|
|
ec977e1307 | ||
|
|
94f416ec20 | ||
|
|
f65e60703f | ||
|
|
b47b51e804 | ||
|
|
06a0f792ff | ||
|
|
9051f59c57 | ||
|
|
e3333ab578 | ||
|
|
2a3e142b7f | ||
|
|
9fd3917216 | ||
|
|
017797a668 | ||
|
|
c9e93071c2 | ||
|
|
08f1b882c8 | ||
|
|
39176afce4 | ||
|
|
e6eba27bf5 | ||
|
|
fe836000cf | ||
|
|
7615914e86 | ||
|
|
58295431a0 | ||
|
|
23f4f980ee | ||
|
|
0bcc0db03f | ||
|
|
6418df976c | ||
|
|
de3442951d | ||
|
|
c9c7c268d0 | ||
|
|
69974c6bf9 | ||
|
|
ca61f79c07 | ||
|
|
2621404695 | ||
|
|
0e99d0f280 | ||
|
|
a20e57ba59 | ||
|
|
fe39a90089 | ||
|
|
3f42c7f914 | ||
|
|
68fb5fc4bc | ||
|
|
f2dbcd9532 | ||
|
|
acbd370168 | ||
|
|
6501b40644 |
@@ -5,6 +5,7 @@ packages:
|
|||||||
- freetype-dev
|
- freetype-dev
|
||||||
- fontconfig-dev
|
- fontconfig-dev
|
||||||
- opus-dev
|
- opus-dev
|
||||||
|
- bzip2-dev
|
||||||
sources:
|
sources:
|
||||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||||
tasks:
|
tasks:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ packages:
|
|||||||
- libfreetype-dev
|
- libfreetype-dev
|
||||||
- libfontconfig-dev
|
- libfontconfig-dev
|
||||||
- libopus-dev
|
- libopus-dev
|
||||||
|
- libbz2-dev
|
||||||
sources:
|
sources:
|
||||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||||
tasks:
|
tasks:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ packages:
|
|||||||
- libfreetype-dev
|
- libfreetype-dev
|
||||||
- libfontconfig-dev
|
- libfontconfig-dev
|
||||||
- libopus-dev
|
- libopus-dev
|
||||||
|
- libbz2-dev
|
||||||
sources:
|
sources:
|
||||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||||
tasks:
|
tasks:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ packages:
|
|||||||
- print/freetype2
|
- print/freetype2
|
||||||
- x11-fonts/fontconfig
|
- x11-fonts/fontconfig
|
||||||
- audio/opus
|
- audio/opus
|
||||||
|
- archivers/bzip2
|
||||||
sources:
|
sources:
|
||||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||||
tasks:
|
tasks:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ packages:
|
|||||||
- fontconfig
|
- fontconfig
|
||||||
- libopus
|
- libopus
|
||||||
- pkgconf
|
- pkgconf
|
||||||
|
- bzip2
|
||||||
sources:
|
sources:
|
||||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||||
tasks:
|
tasks:
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ packages:
|
|||||||
- python3
|
- python3
|
||||||
- sdl2
|
- sdl2
|
||||||
- opus
|
- opus
|
||||||
|
- bzip2
|
||||||
sources:
|
sources:
|
||||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||||
tasks:
|
tasks:
|
||||||
|
|||||||
12
.cirrus.yml
12
.cirrus.yml
@@ -1,15 +1,3 @@
|
|||||||
task:
|
|
||||||
name: freebsd-13-amd64
|
|
||||||
freebsd_instance:
|
|
||||||
image_family: freebsd-13-2
|
|
||||||
setup_script:
|
|
||||||
- pkg update
|
|
||||||
- pkg install -y pkgconf git sdl2 python fontconfig opus
|
|
||||||
- git submodule update --init --recursive
|
|
||||||
test_script:
|
|
||||||
- ./scripts/cirrus/build_freebsd.sh dedicated
|
|
||||||
- ./scripts/cirrus/build_freebsd.sh full
|
|
||||||
|
|
||||||
task:
|
task:
|
||||||
name: freebsd-14-amd64
|
name: freebsd-14-amd64
|
||||||
freebsd_instance:
|
freebsd_instance:
|
||||||
|
|||||||
360
.editorconfig
360
.editorconfig
@@ -1,9 +1,365 @@
|
|||||||
# EditorConfig is awesome: https://EditorConfig.org
|
# this file is just a suggestion, you might follow it, you might not
|
||||||
root = true
|
root = true
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
charset = latin1
|
charset = utf-8
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
ij_formatter_off_tag = @formatter:off
|
||||||
|
ij_formatter_on_tag = @formatter:on
|
||||||
|
|
||||||
|
[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}]
|
||||||
|
|
||||||
|
# Visual C++ Formatting settings
|
||||||
|
cpp_indent_braces = false
|
||||||
|
cpp_indent_multi_line_relative_to = innermost_parenthesis
|
||||||
|
cpp_indent_within_parentheses = indent
|
||||||
|
cpp_indent_preserve_within_parentheses = true
|
||||||
|
cpp_indent_case_contents = true
|
||||||
|
cpp_indent_case_labels = false
|
||||||
|
cpp_indent_case_contents_when_block = false
|
||||||
|
cpp_indent_lambda_braces_when_parameter = true
|
||||||
|
cpp_indent_goto_labels = one_left
|
||||||
|
cpp_indent_preprocessor = leftmost_column
|
||||||
|
cpp_indent_access_specifiers = false
|
||||||
|
cpp_indent_namespace_contents = true
|
||||||
|
cpp_indent_preserve_comments = false
|
||||||
|
cpp_new_line_before_open_brace_namespace = new_line
|
||||||
|
cpp_new_line_before_open_brace_type = new_line
|
||||||
|
cpp_new_line_before_open_brace_function = new_line
|
||||||
|
cpp_new_line_before_open_brace_block = new_line
|
||||||
|
cpp_new_line_before_open_brace_lambda = new_line
|
||||||
|
cpp_new_line_scope_braces_on_separate_lines = true
|
||||||
|
cpp_new_line_close_brace_same_line_empty_type = false
|
||||||
|
cpp_new_line_close_brace_same_line_empty_function = false
|
||||||
|
cpp_new_line_before_catch = true
|
||||||
|
cpp_new_line_before_else = true
|
||||||
|
cpp_new_line_before_while_in_do_while = false
|
||||||
|
cpp_space_before_function_open_parenthesis = remove
|
||||||
|
cpp_space_within_parameter_list_parentheses = true
|
||||||
|
cpp_space_between_empty_parameter_list_parentheses = true
|
||||||
|
cpp_space_after_keywords_in_control_flow_statements = false
|
||||||
|
cpp_space_within_control_flow_statement_parentheses = true
|
||||||
|
cpp_space_before_lambda_open_parenthesis = false
|
||||||
|
cpp_space_within_cast_parentheses = false
|
||||||
|
cpp_space_after_cast_close_parenthesis = false
|
||||||
|
cpp_space_within_expression_parentheses = true
|
||||||
|
cpp_space_before_block_open_brace = true
|
||||||
|
cpp_space_between_empty_braces = true
|
||||||
|
cpp_space_before_initializer_list_open_brace = false
|
||||||
|
cpp_space_within_initializer_list_braces = true
|
||||||
|
cpp_space_preserve_in_initializer_list = true
|
||||||
|
cpp_space_before_open_square_bracket = false
|
||||||
|
cpp_space_within_square_brackets = false
|
||||||
|
cpp_space_before_empty_square_brackets = false
|
||||||
|
cpp_space_between_empty_square_brackets = false
|
||||||
|
cpp_space_group_square_brackets = true
|
||||||
|
cpp_space_within_lambda_brackets = false
|
||||||
|
cpp_space_between_empty_lambda_brackets = false
|
||||||
|
cpp_space_before_comma = false
|
||||||
|
cpp_space_after_comma = true
|
||||||
|
cpp_space_remove_around_member_operators = true
|
||||||
|
cpp_space_before_inheritance_colon = true
|
||||||
|
cpp_space_before_constructor_colon = true
|
||||||
|
cpp_space_remove_before_semicolon = true
|
||||||
|
cpp_space_after_semicolon = true
|
||||||
|
cpp_space_remove_around_unary_operator = true
|
||||||
|
cpp_space_around_binary_operator = insert
|
||||||
|
cpp_space_around_assignment_operator = insert
|
||||||
|
cpp_space_pointer_reference_alignment = right
|
||||||
|
cpp_space_around_ternary_operator = insert
|
||||||
|
cpp_use_unreal_engine_macro_formatting = true
|
||||||
|
cpp_wrap_preserve_blocks = one_liners
|
||||||
|
|
||||||
|
# IDEA settings
|
||||||
|
ij_c_add_brief_tag = false
|
||||||
|
ij_c_add_getter_prefix = true
|
||||||
|
ij_c_add_setter_prefix = true
|
||||||
|
ij_c_align_dictionary_pair_values = false
|
||||||
|
ij_c_align_group_field_declarations = false
|
||||||
|
ij_c_align_init_list_in_columns = true
|
||||||
|
ij_c_align_multiline_array_initializer_expression = false
|
||||||
|
ij_c_align_multiline_assignment = false
|
||||||
|
ij_c_align_multiline_binary_operation = false
|
||||||
|
ij_c_align_multiline_chained_methods = false
|
||||||
|
ij_c_align_multiline_for = true
|
||||||
|
ij_c_align_multiline_ternary_operation = false
|
||||||
|
ij_c_array_initializer_comma_on_next_line = false
|
||||||
|
ij_c_array_initializer_new_line_after_left_brace = false
|
||||||
|
ij_c_array_initializer_right_brace_on_new_line = false
|
||||||
|
ij_c_array_initializer_wrap = off
|
||||||
|
ij_c_assignment_wrap = off
|
||||||
|
ij_c_binary_operation_sign_on_next_line = false
|
||||||
|
ij_c_binary_operation_wrap = off
|
||||||
|
ij_c_blank_lines_after_class_header = 0
|
||||||
|
ij_c_blank_lines_after_imports = 1
|
||||||
|
ij_c_blank_lines_around_class = 1
|
||||||
|
ij_c_blank_lines_around_field = 0
|
||||||
|
ij_c_blank_lines_around_field_in_interface = 0
|
||||||
|
ij_c_blank_lines_around_method = 1
|
||||||
|
ij_c_blank_lines_around_method_in_interface = 1
|
||||||
|
ij_c_blank_lines_around_namespace = 0
|
||||||
|
ij_c_blank_lines_around_properties_in_declaration = 0
|
||||||
|
ij_c_blank_lines_around_properties_in_interface = 0
|
||||||
|
ij_c_blank_lines_before_imports = 1
|
||||||
|
ij_c_blank_lines_before_method_body = 0
|
||||||
|
ij_c_block_brace_placement = next_line
|
||||||
|
ij_c_block_brace_style = next_line
|
||||||
|
ij_c_block_comment_at_first_column = true
|
||||||
|
ij_c_catch_on_new_line = false
|
||||||
|
ij_c_class_brace_style = next_line
|
||||||
|
ij_c_class_constructor_init_list_align_multiline = true
|
||||||
|
ij_c_class_constructor_init_list_comma_on_next_line = false
|
||||||
|
ij_c_class_constructor_init_list_new_line_after_colon = never
|
||||||
|
ij_c_class_constructor_init_list_new_line_before_colon = if_long
|
||||||
|
ij_c_class_constructor_init_list_wrap = normal
|
||||||
|
ij_c_copy_is_deep = false
|
||||||
|
ij_c_create_interface_for_categories = true
|
||||||
|
ij_c_declare_generated_methods = true
|
||||||
|
ij_c_description_include_member_names = true
|
||||||
|
ij_c_discharged_short_ternary_operator = false
|
||||||
|
ij_c_do_not_add_breaks = false
|
||||||
|
ij_c_do_while_brace_force = never
|
||||||
|
ij_c_else_on_new_line = false
|
||||||
|
ij_c_enum_constants_comma_on_next_line = false
|
||||||
|
ij_c_enum_constants_wrap = off
|
||||||
|
ij_c_for_brace_force = never
|
||||||
|
ij_c_for_statement_new_line_after_left_paren = false
|
||||||
|
ij_c_for_statement_right_paren_on_new_line = false
|
||||||
|
ij_c_for_statement_wrap = off
|
||||||
|
ij_c_function_brace_placement = next_line
|
||||||
|
ij_c_function_call_arguments_align_multiline = true
|
||||||
|
ij_c_function_call_arguments_align_multiline_pars = false
|
||||||
|
ij_c_function_call_arguments_comma_on_next_line = false
|
||||||
|
ij_c_function_call_arguments_new_line_after_lpar = false
|
||||||
|
ij_c_function_call_arguments_new_line_before_rpar = false
|
||||||
|
ij_c_function_call_arguments_wrap = normal
|
||||||
|
ij_c_function_non_top_after_return_type_wrap = normal
|
||||||
|
ij_c_function_parameters_align_multiline = true
|
||||||
|
ij_c_function_parameters_align_multiline_pars = false
|
||||||
|
ij_c_function_parameters_comma_on_next_line = false
|
||||||
|
ij_c_function_parameters_new_line_after_lpar = false
|
||||||
|
ij_c_function_parameters_new_line_before_rpar = false
|
||||||
|
ij_c_function_parameters_wrap = normal
|
||||||
|
ij_c_function_top_after_return_type_wrap = normal
|
||||||
|
ij_c_generate_additional_eq_operators = true
|
||||||
|
ij_c_generate_additional_rel_operators = true
|
||||||
|
ij_c_generate_class_constructor = true
|
||||||
|
ij_c_generate_comparison_operators_use_std_tie = false
|
||||||
|
ij_c_generate_instance_variables_for_properties = ask
|
||||||
|
ij_c_generate_operators_as_members = true
|
||||||
|
ij_c_header_guard_style_pattern = ${PROJECT_NAME}_${FILE_NAME}_${EXT}
|
||||||
|
ij_c_if_brace_force = never
|
||||||
|
ij_c_in_line_short_ternary_operator = true
|
||||||
|
ij_c_indent_block_comment = true
|
||||||
|
ij_c_indent_c_struct_members = 4
|
||||||
|
ij_c_indent_case_from_switch = true
|
||||||
|
ij_c_indent_class_members = 4
|
||||||
|
ij_c_indent_directive_as_code = false
|
||||||
|
ij_c_indent_implementation_members = 0
|
||||||
|
ij_c_indent_inside_code_block = 4
|
||||||
|
ij_c_indent_interface_members = 0
|
||||||
|
ij_c_indent_interface_members_except_ivars_block = false
|
||||||
|
ij_c_indent_namespace_members = 4
|
||||||
|
ij_c_indent_preprocessor_directive = 0
|
||||||
|
ij_c_indent_visibility_keywords = 0
|
||||||
|
ij_c_insert_override = true
|
||||||
|
ij_c_insert_virtual_with_override = false
|
||||||
|
ij_c_introduce_auto_consts = false
|
||||||
|
ij_c_introduce_auto_vars = false
|
||||||
|
ij_c_introduce_const_params = false
|
||||||
|
ij_c_introduce_const_vars = false
|
||||||
|
ij_c_introduce_constexpr_consts = false
|
||||||
|
ij_c_introduce_generate_property = false
|
||||||
|
ij_c_introduce_generate_synthesize = true
|
||||||
|
ij_c_introduce_globals_to_header = true
|
||||||
|
ij_c_introduce_prop_to_private_category = false
|
||||||
|
ij_c_introduce_static_consts = true
|
||||||
|
ij_c_introduce_use_ns_types = false
|
||||||
|
ij_c_ivars_prefix = _
|
||||||
|
ij_c_ivars_suffix =
|
||||||
|
ij_c_keep_blank_lines_before_end = 2
|
||||||
|
ij_c_keep_blank_lines_before_right_brace = 2
|
||||||
|
ij_c_keep_blank_lines_in_code = 2
|
||||||
|
ij_c_keep_blank_lines_in_declarations = 2
|
||||||
|
ij_c_keep_case_expressions_in_one_line = false
|
||||||
|
ij_c_keep_control_statement_in_one_line = false
|
||||||
|
ij_c_keep_directive_at_first_column = true
|
||||||
|
ij_c_keep_first_column_comment = false
|
||||||
|
ij_c_keep_line_breaks = true
|
||||||
|
ij_c_keep_nested_namespaces_in_one_line = false
|
||||||
|
ij_c_keep_simple_blocks_in_one_line = false
|
||||||
|
ij_c_keep_simple_methods_in_one_line = false
|
||||||
|
ij_c_keep_structures_in_one_line = false
|
||||||
|
ij_c_lambda_capture_list_align_multiline = false
|
||||||
|
ij_c_lambda_capture_list_align_multiline_bracket = false
|
||||||
|
ij_c_lambda_capture_list_comma_on_next_line = false
|
||||||
|
ij_c_lambda_capture_list_new_line_after_lbracket = false
|
||||||
|
ij_c_lambda_capture_list_new_line_before_rbracket = false
|
||||||
|
ij_c_lambda_capture_list_wrap = off
|
||||||
|
ij_c_line_comment_add_space = false
|
||||||
|
ij_c_line_comment_at_first_column = true
|
||||||
|
ij_c_method_brace_placement = end_of_line
|
||||||
|
ij_c_method_call_arguments_align_by_colons = true
|
||||||
|
ij_c_method_call_arguments_align_multiline = false
|
||||||
|
ij_c_method_call_arguments_special_dictionary_pairs_treatment = true
|
||||||
|
ij_c_method_call_arguments_wrap = off
|
||||||
|
ij_c_method_call_chain_wrap = off
|
||||||
|
ij_c_method_parameters_align_by_colons = true
|
||||||
|
ij_c_method_parameters_align_multiline = false
|
||||||
|
ij_c_method_parameters_wrap = off
|
||||||
|
ij_c_namespace_brace_placement = next_line
|
||||||
|
ij_c_parentheses_expression_new_line_after_left_paren = false
|
||||||
|
ij_c_parentheses_expression_right_paren_on_new_line = false
|
||||||
|
ij_c_place_assignment_sign_on_next_line = false
|
||||||
|
ij_c_property_nonatomic = true
|
||||||
|
ij_c_put_ivars_to_implementation = true
|
||||||
|
ij_c_refactor_compatibility_aliases_and_classes = true
|
||||||
|
ij_c_refactor_properties_and_ivars = true
|
||||||
|
ij_c_release_style = ivar
|
||||||
|
ij_c_retain_object_parameters_in_constructor = true
|
||||||
|
ij_c_semicolon_after_method_signature = false
|
||||||
|
ij_c_shift_operation_align_multiline = true
|
||||||
|
ij_c_shift_operation_wrap = normal
|
||||||
|
ij_c_show_non_virtual_functions = false
|
||||||
|
ij_c_space_after_colon = true
|
||||||
|
ij_c_space_after_colon_in_foreach = true
|
||||||
|
ij_c_space_after_colon_in_selector = false
|
||||||
|
ij_c_space_after_comma = true
|
||||||
|
ij_c_space_after_cup_in_blocks = false
|
||||||
|
ij_c_space_after_dictionary_literal_colon = true
|
||||||
|
ij_c_space_after_for_semicolon = true
|
||||||
|
ij_c_space_after_init_list_colon = true
|
||||||
|
ij_c_space_after_method_parameter_type_parentheses = false
|
||||||
|
ij_c_space_after_method_return_type_parentheses = false
|
||||||
|
ij_c_space_after_pointer_in_declaration = false
|
||||||
|
ij_c_space_after_quest = true
|
||||||
|
ij_c_space_after_reference_in_declaration = false
|
||||||
|
ij_c_space_after_reference_in_rvalue = false
|
||||||
|
ij_c_space_after_structures_rbrace = true
|
||||||
|
ij_c_space_after_superclass_colon = true
|
||||||
|
ij_c_space_after_type_cast = false
|
||||||
|
ij_c_space_after_visibility_sign_in_method_declaration = true
|
||||||
|
ij_c_space_before_autorelease_pool_lbrace = true
|
||||||
|
ij_c_space_before_catch_keyword = true
|
||||||
|
ij_c_space_before_catch_left_brace = true
|
||||||
|
ij_c_space_before_catch_parentheses = false
|
||||||
|
ij_c_space_before_category_parentheses = true
|
||||||
|
ij_c_space_before_chained_send_message = true
|
||||||
|
ij_c_space_before_class_left_brace = true
|
||||||
|
ij_c_space_before_colon = true
|
||||||
|
ij_c_space_before_colon_in_foreach = true
|
||||||
|
ij_c_space_before_comma = false
|
||||||
|
ij_c_space_before_dictionary_literal_colon = true
|
||||||
|
ij_c_space_before_do_left_brace = true
|
||||||
|
ij_c_space_before_else_keyword = true
|
||||||
|
ij_c_space_before_else_left_brace = true
|
||||||
|
ij_c_space_before_export_lbrace = true
|
||||||
|
ij_c_space_before_for_left_brace = true
|
||||||
|
ij_c_space_before_for_parentheses = false
|
||||||
|
ij_c_space_before_for_semicolon = false
|
||||||
|
ij_c_space_before_if_left_brace = true
|
||||||
|
ij_c_space_before_if_parentheses = false
|
||||||
|
ij_c_space_before_init_list = false
|
||||||
|
ij_c_space_before_init_list_colon = true
|
||||||
|
ij_c_space_before_method_call_parentheses = false
|
||||||
|
ij_c_space_before_method_left_brace = true
|
||||||
|
ij_c_space_before_method_parentheses = false
|
||||||
|
ij_c_space_before_namespace_lbrace = true
|
||||||
|
ij_c_space_before_pointer_in_declaration = true
|
||||||
|
ij_c_space_before_property_attributes_parentheses = false
|
||||||
|
ij_c_space_before_protocols_brackets = true
|
||||||
|
ij_c_space_before_quest = true
|
||||||
|
ij_c_space_before_reference_in_declaration = true
|
||||||
|
ij_c_space_before_superclass_colon = true
|
||||||
|
ij_c_space_before_switch_left_brace = true
|
||||||
|
ij_c_space_before_switch_parentheses = false
|
||||||
|
ij_c_space_before_template_call_lt = false
|
||||||
|
ij_c_space_before_template_declaration_lt = true
|
||||||
|
ij_c_space_before_try_left_brace = true
|
||||||
|
ij_c_space_before_while_keyword = true
|
||||||
|
ij_c_space_before_while_left_brace = true
|
||||||
|
ij_c_space_before_while_parentheses = false
|
||||||
|
ij_c_space_between_adjacent_brackets = false
|
||||||
|
ij_c_space_between_operator_and_punctuator = false
|
||||||
|
ij_c_space_within_empty_array_initializer_braces = true
|
||||||
|
ij_c_spaces_around_additive_operators = true
|
||||||
|
ij_c_spaces_around_assignment_operators = true
|
||||||
|
ij_c_spaces_around_bitwise_operators = true
|
||||||
|
ij_c_spaces_around_equality_operators = true
|
||||||
|
ij_c_spaces_around_lambda_arrow = true
|
||||||
|
ij_c_spaces_around_logical_operators = true
|
||||||
|
ij_c_spaces_around_multiplicative_operators = true
|
||||||
|
ij_c_spaces_around_pm_operators = false
|
||||||
|
ij_c_spaces_around_relational_operators = true
|
||||||
|
ij_c_spaces_around_shift_operators = true
|
||||||
|
ij_c_spaces_around_unary_operator = false
|
||||||
|
ij_c_spaces_within_array_initializer_braces = true
|
||||||
|
ij_c_spaces_within_braces = false
|
||||||
|
ij_c_spaces_within_brackets = false
|
||||||
|
ij_c_spaces_within_cast_parentheses = false
|
||||||
|
ij_c_spaces_within_catch_parentheses = true
|
||||||
|
ij_c_spaces_within_category_parentheses = false
|
||||||
|
ij_c_spaces_within_empty_braces = false
|
||||||
|
ij_c_spaces_within_empty_function_call_parentheses = true
|
||||||
|
ij_c_spaces_within_empty_function_declaration_parentheses = true
|
||||||
|
ij_c_spaces_within_empty_lambda_capture_list_bracket = false
|
||||||
|
ij_c_spaces_within_empty_template_call_ltgt = false
|
||||||
|
ij_c_spaces_within_empty_template_declaration_ltgt = false
|
||||||
|
ij_c_spaces_within_for_parentheses = true
|
||||||
|
ij_c_spaces_within_function_call_parentheses = true
|
||||||
|
ij_c_spaces_within_function_declaration_parentheses = true
|
||||||
|
ij_c_spaces_within_if_parentheses = true
|
||||||
|
ij_c_spaces_within_lambda_capture_list_bracket = false
|
||||||
|
ij_c_spaces_within_method_parameter_type_parentheses = false
|
||||||
|
ij_c_spaces_within_method_return_type_parentheses = false
|
||||||
|
ij_c_spaces_within_parentheses = true
|
||||||
|
ij_c_spaces_within_property_attributes_parentheses = false
|
||||||
|
ij_c_spaces_within_protocols_brackets = false
|
||||||
|
ij_c_spaces_within_send_message_brackets = false
|
||||||
|
ij_c_spaces_within_structured_binding_list_bracket = false
|
||||||
|
ij_c_spaces_within_switch_parentheses = true
|
||||||
|
ij_c_spaces_within_template_call_ltgt = false
|
||||||
|
ij_c_spaces_within_template_declaration_ltgt = false
|
||||||
|
ij_c_spaces_within_template_double_gt = false
|
||||||
|
ij_c_spaces_within_while_parentheses = true
|
||||||
|
ij_c_special_else_if_treatment = true
|
||||||
|
ij_c_structured_binding_list_align_multiline = false
|
||||||
|
ij_c_structured_binding_list_align_multiline_bracket = false
|
||||||
|
ij_c_structured_binding_list_comma_on_next_line = false
|
||||||
|
ij_c_structured_binding_list_new_line_after_lbracket = false
|
||||||
|
ij_c_structured_binding_list_new_line_before_rbracket = false
|
||||||
|
ij_c_structured_binding_list_wrap = off
|
||||||
|
ij_c_superclass_list_after_colon = never
|
||||||
|
ij_c_superclass_list_align_multiline = true
|
||||||
|
ij_c_superclass_list_before_colon = if_long
|
||||||
|
ij_c_superclass_list_comma_on_next_line = false
|
||||||
|
ij_c_superclass_list_wrap = on_every_item
|
||||||
|
ij_c_tag_prefix_of_block_comment = at
|
||||||
|
ij_c_tag_prefix_of_line_comment = back_slash
|
||||||
|
ij_c_template_call_arguments_align_multiline = false
|
||||||
|
ij_c_template_call_arguments_align_multiline_pars = false
|
||||||
|
ij_c_template_call_arguments_comma_on_next_line = false
|
||||||
|
ij_c_template_call_arguments_new_line_after_lt = false
|
||||||
|
ij_c_template_call_arguments_new_line_before_gt = false
|
||||||
|
ij_c_template_call_arguments_wrap = off
|
||||||
|
ij_c_template_declaration_function_body_indent = false
|
||||||
|
ij_c_template_declaration_function_wrap = split_into_lines
|
||||||
|
ij_c_template_declaration_struct_body_indent = false
|
||||||
|
ij_c_template_declaration_struct_wrap = split_into_lines
|
||||||
|
ij_c_template_parameters_align_multiline = false
|
||||||
|
ij_c_template_parameters_align_multiline_pars = false
|
||||||
|
ij_c_template_parameters_comma_on_next_line = false
|
||||||
|
ij_c_template_parameters_new_line_after_lt = false
|
||||||
|
ij_c_template_parameters_new_line_before_gt = false
|
||||||
|
ij_c_template_parameters_wrap = off
|
||||||
|
ij_c_ternary_operation_signs_on_next_line = false
|
||||||
|
ij_c_ternary_operation_wrap = off
|
||||||
|
ij_c_type_qualifiers_placement = before
|
||||||
|
ij_c_use_modern_casts = true
|
||||||
|
ij_c_use_setters_in_constructor = true
|
||||||
|
ij_c_while_brace_force = never
|
||||||
|
ij_c_while_on_new_line = false
|
||||||
|
ij_c_wrap_property_declaration = off
|
||||||
|
|||||||
91
.github/workflows/c-cpp.yml
vendored
91
.github/workflows/c-cpp.yml
vendored
@@ -21,6 +21,22 @@ jobs:
|
|||||||
- os: ubuntu-20.04
|
- os: ubuntu-20.04
|
||||||
targetos: linux
|
targetos: linux
|
||||||
targetarch: i386
|
targetarch: i386
|
||||||
|
- os: ubuntu-20.04
|
||||||
|
targetos: linux
|
||||||
|
targetarch: arm64
|
||||||
|
cross: true
|
||||||
|
- os: ubuntu-20.04
|
||||||
|
targetos: linux
|
||||||
|
targetarch: armhf
|
||||||
|
cross: true
|
||||||
|
- os: ubuntu-20.04
|
||||||
|
targetos: linux
|
||||||
|
targetarch: riscv64
|
||||||
|
cross: true
|
||||||
|
- os: ubuntu-20.04
|
||||||
|
targetos: linux
|
||||||
|
targetarch: ppc64el
|
||||||
|
cross: true
|
||||||
# - os: ubuntu-aarch64-20.04
|
# - os: ubuntu-aarch64-20.04
|
||||||
# targetos: linux
|
# targetos: linux
|
||||||
# targetarch: aarch64
|
# targetarch: aarch64
|
||||||
@@ -43,80 +59,83 @@ jobs:
|
|||||||
- os: windows-2019 # always use the oldest possible for 32-bit because of older compilers, and better support of certain legacy OSes
|
- os: windows-2019 # always use the oldest possible for 32-bit because of older compilers, and better support of certain legacy OSes
|
||||||
targetos: win32
|
targetos: win32
|
||||||
targetarch: i386
|
targetarch: i386
|
||||||
|
- os: macos-14 # arm64 as per github documentation
|
||||||
|
targetos: apple
|
||||||
|
targetarch: arm64
|
||||||
|
- os: macos-13 # x86 as per github documentation (will they fix it before they deprecate this version?..)
|
||||||
|
targetos: apple
|
||||||
|
targetarch: amd64
|
||||||
env:
|
env:
|
||||||
SDL_VERSION: 2.28.5
|
SDL_VERSION: 2.30.9
|
||||||
GH_CPU_ARCH: ${{ matrix.targetarch }}
|
GH_CPU_ARCH: ${{ matrix.targetarch }}
|
||||||
|
GH_CROSSCOMPILING: ${{ matrix.cross }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: bash scripts/gha/deps_${{ matrix.targetos }}.sh
|
run: bash scripts/gha/deps_${{ matrix.targetos }}.sh
|
||||||
- name: Build engine
|
- name: Build engine
|
||||||
|
env:
|
||||||
|
FWGS_PFX_PASSWORD: ${{ secrets.FWGS_PFX_PASSWORD }}
|
||||||
run: bash scripts/gha/build_${{ matrix.targetos }}.sh
|
run: bash scripts/gha/build_${{ matrix.targetos }}.sh
|
||||||
- name: Upload engine (artifacts)
|
- name: Upload engine (artifacts)
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
|
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
|
||||||
path: artifacts/*
|
path: artifacts/*
|
||||||
flatpak:
|
flatpak:
|
||||||
name: "Flatpak"
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- app: su.xash.Engine.Compat.i386
|
- app: su.xash.Engine.Compat.i386
|
||||||
container:
|
container:
|
||||||
image: bilelmoussaoui/flatpak-github-actions:freedesktop-22.08
|
image: bilelmoussaoui/flatpak-github-actions:freedesktop-24.08
|
||||||
options: --privileged
|
options: --privileged
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Build flatpak (Compat.i386)
|
- name: Build flatpak (Compat.i386)
|
||||||
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.1
|
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.3
|
||||||
with:
|
with:
|
||||||
bundle: ${{ matrix.app }}.flatpak
|
bundle: ${{ matrix.app }}.flatpak
|
||||||
manifest-path: scripts/flatpak/${{ matrix.app }}.yml
|
manifest-path: scripts/flatpak/${{ matrix.app }}.yml
|
||||||
- name: Upload engine (artifacts)
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
|
|
||||||
path: artifacts/*
|
|
||||||
release:
|
release:
|
||||||
name: "Upload releases"
|
name: "Upload releases"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [build, flatpak]
|
needs: [build, flatpak]
|
||||||
if: ${{ github.event_name == 'push' }}
|
if: ${{ github.event_name == 'push' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Remove old release
|
- name: Remove old release, fetch artifacts, repackage binaries and upload new release
|
||||||
uses: FWGS/delete-tag-and-release@v0.2.1-dev
|
env:
|
||||||
with:
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
tag_name: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
|
RELEASE_TAG: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
|
||||||
delete_release: true
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Fetch artifacts
|
|
||||||
uses: actions/download-artifact@v3.0.1
|
|
||||||
with:
|
|
||||||
path: artifacts/
|
|
||||||
- name: Repackage binaries and allow GitHub to process removed release for few seconds
|
|
||||||
run: |
|
run: |
|
||||||
cd artifacts/
|
gh release delete "$RELEASE_TAG" \
|
||||||
for i in artifact-* su.xash.Engine.*; do
|
--yes \
|
||||||
|
--cleanup-tag \
|
||||||
|
--repo "$GITHUB_REPOSITORY" || true
|
||||||
|
sleep 20s
|
||||||
|
gh run download "$GITHUB_RUN_ID" \
|
||||||
|
--dir artifacts/ \
|
||||||
|
--repo "$GITHUB_REPOSITORY"
|
||||||
|
pushd artifacts/
|
||||||
|
echo "Found artifacts:"
|
||||||
|
ls
|
||||||
|
for i in $(find -mindepth 1 -maxdepth 1 -type d); do
|
||||||
mv "$i"/* .
|
mv "$i"/* .
|
||||||
rm -rf "$i"
|
rm -rf "$i"
|
||||||
done
|
done
|
||||||
ls -R .
|
echo "Repackaged artifacts:"
|
||||||
cd ../
|
ls -R
|
||||||
|
popd
|
||||||
sleep 20s
|
sleep 20s
|
||||||
- name: Upload new release
|
gh release create "$RELEASE_TAG" artifacts/* \
|
||||||
uses: FWGS/action-gh-release@v0.1.15
|
--title "Xash3D FWGS Continuous ${{ github.ref_name }} Build" \
|
||||||
with:
|
--target $GITHUB_SHA \
|
||||||
name: Xash3D FWGS Continuous ${{ github.ref_name }} Build
|
--repo "$GITHUB_REPOSITORY" \
|
||||||
tag_name: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
|
--prerelease
|
||||||
prerelease: true
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
files: artifacts/*
|
|
||||||
draft: false
|
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -342,3 +342,6 @@ enc_temp_folder/
|
|||||||
|
|
||||||
# KDevelop4
|
# KDevelop4
|
||||||
*.kdev4
|
*.kdev4
|
||||||
|
|
||||||
|
# ccls langauge server
|
||||||
|
.ccls-*
|
||||||
|
|||||||
15
.gitmodules
vendored
15
.gitmodules
vendored
@@ -19,3 +19,18 @@
|
|||||||
[submodule "3rdparty/xash-extras"]
|
[submodule "3rdparty/xash-extras"]
|
||||||
path = 3rdparty/extras/xash-extras
|
path = 3rdparty/extras/xash-extras
|
||||||
url = https://github.com/FWGS/xash-extras
|
url = https://github.com/FWGS/xash-extras
|
||||||
|
[submodule "3rdparty/bzip2/bzip2"]
|
||||||
|
path = 3rdparty/bzip2/bzip2
|
||||||
|
url = https://gitlab.com/bzip2/bzip2
|
||||||
|
[submodule "3rdparty/MultiEmulator"]
|
||||||
|
path = 3rdparty/MultiEmulator
|
||||||
|
url = https://github.com/FWGS/MultiEmulator
|
||||||
|
[submodule "3rdparty/libogg/libogg"]
|
||||||
|
path = 3rdparty/libogg/libogg
|
||||||
|
url = https://gitlab.xiph.org/xiph/ogg.git
|
||||||
|
[submodule "3rdparty/vorbis/vorbis-src"]
|
||||||
|
path = 3rdparty/vorbis/vorbis-src
|
||||||
|
url = https://gitlab.xiph.org/xiph/vorbis.git
|
||||||
|
[submodule "3rdparty/opusfile/opusfile"]
|
||||||
|
path = 3rdparty/opusfile/opusfile
|
||||||
|
url = https://gitlab.xiph.org/xiph/opusfile.git
|
||||||
|
|||||||
1
3rdparty/MultiEmulator
vendored
Submodule
1
3rdparty/MultiEmulator
vendored
Submodule
Submodule 3rdparty/MultiEmulator added at 7e989e670e
1
3rdparty/bzip2/bzip2
vendored
Submodule
1
3rdparty/bzip2/bzip2
vendored
Submodule
Submodule 3rdparty/bzip2/bzip2 added at 66c46b8c94
27
3rdparty/bzip2/wscript
vendored
Normal file
27
3rdparty/bzip2/wscript
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#! /usr/bin/env python
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
def options(opt):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def configure(conf):
|
||||||
|
conf.define('_GNU_SOURCE', 1)
|
||||||
|
conf.define('BZ_NO_STDIO', 1)
|
||||||
|
|
||||||
|
if conf.env.DEST_OS == 'win32':
|
||||||
|
conf.define('BZ_LCCWIN32', 1)
|
||||||
|
else:
|
||||||
|
conf.define('BZ_UNIX', 1)
|
||||||
|
|
||||||
|
def build(bld):
|
||||||
|
bld(features = 'subst', source = 'bzip2/bz_version.h.in', target = 'bzip2/bz_version.h', BZ_VERSION='1.1.0-fwgs', name = 'bz_version')
|
||||||
|
|
||||||
|
bz_sources = ['bzip2/blocksort.c', 'bzip2/huffman.c', 'bzip2/crctable.c', 'bzip2/randtable.c', 'bzip2/compress.c', 'bzip2/decompress.c', 'bzip2/bzlib.c']
|
||||||
|
|
||||||
|
bld.stlib(
|
||||||
|
source = bz_sources,
|
||||||
|
target = 'bzip2',
|
||||||
|
use = 'bz_version',
|
||||||
|
includes = 'bzip2/',
|
||||||
|
export_includes = 'bzip2/'
|
||||||
|
)
|
||||||
2
3rdparty/extras/xash-extras
vendored
2
3rdparty/extras/xash-extras
vendored
Submodule 3rdparty/extras/xash-extras updated: 853f633be1...1bdeab2d8f
2
3rdparty/gl-wes-v2
vendored
2
3rdparty/gl-wes-v2
vendored
Submodule 3rdparty/gl-wes-v2 updated: 2d9b5afe10...6b392aecbb
2
3rdparty/gl4es/wscript
vendored
2
3rdparty/gl4es/wscript
vendored
@@ -16,9 +16,7 @@ def build(bld):
|
|||||||
|
|
||||||
bld.stlib(source = gl4es_srcdir.ant_glob(['gl/*.c', 'gl/*/*.c', 'glx/hardext.c']),
|
bld.stlib(source = gl4es_srcdir.ant_glob(['gl/*.c', 'gl/*/*.c', 'glx/hardext.c']),
|
||||||
target = 'gl4es',
|
target = 'gl4es',
|
||||||
features = 'c',
|
|
||||||
includes = ['gl4es/src', 'gl4es/src/gl', 'gl4es/src/glx', 'gl4es/include'],
|
includes = ['gl4es/src', 'gl4es/src/gl', 'gl4es/src/glx', 'gl4es/include'],
|
||||||
defines = ['NOX11', 'NO_GBM', 'NO_INIT_CONSTRUCTOR', 'DEFAULT_ES=2', 'NOEGL', 'NO_LOADER', 'STATICLIB'],
|
defines = ['NOX11', 'NO_GBM', 'NO_INIT_CONSTRUCTOR', 'DEFAULT_ES=2', 'NOEGL', 'NO_LOADER', 'STATICLIB'],
|
||||||
cflags = ['-w', '-fvisibility=hidden', '-std=gnu99'],
|
cflags = ['-w', '-fvisibility=hidden', '-std=gnu99'],
|
||||||
subsystem = bld.env.MSVC_SUBSYSTEM,
|
|
||||||
export_includes = '.')
|
export_includes = '.')
|
||||||
|
|||||||
1
3rdparty/libogg/libogg
vendored
Submodule
1
3rdparty/libogg/libogg
vendored
Submodule
Submodule 3rdparty/libogg/libogg added at 7cf42ea17a
50
3rdparty/libogg/wscript
vendored
Normal file
50
3rdparty/libogg/wscript
vendored
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#! /usr/bin/env python
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
def options(opt):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def configure(conf):
|
||||||
|
if not conf.path.find_dir('libogg') or not conf.path.find_dir('libogg/src'):
|
||||||
|
conf.fatal('Can\'t find libogg submodule. Run `git submodule update --init --recursive`.')
|
||||||
|
return
|
||||||
|
|
||||||
|
conf.env.INCLUDE_INTTYPES_H = 0
|
||||||
|
conf.env.INCLUDE_SYS_TYPES_H = 0
|
||||||
|
conf.env.INCLUDE_STDINT_H = 0
|
||||||
|
|
||||||
|
if conf.check_cc(header_name='inttypes.h', mandatory = False):
|
||||||
|
conf.env.INCLUDE_INTTYPES_H = 1
|
||||||
|
elif conf.check_cc(header_name='sys/types.h', mandatory = False):
|
||||||
|
conf.env.INCLUDE_SYS_TYPES_H = 1
|
||||||
|
elif conf.check_cc(header_name='stdint.h', mandatory = False):
|
||||||
|
conf.env.INCLUDE_STDINT_H = 1
|
||||||
|
|
||||||
|
def build(bld):
|
||||||
|
sources = bld.path.ant_glob([
|
||||||
|
'libogg/src/*.c'
|
||||||
|
])
|
||||||
|
|
||||||
|
bld(
|
||||||
|
features = 'subst',
|
||||||
|
name = 'libogg_config_types',
|
||||||
|
source = 'libogg/include/ogg/config_types.h.in',
|
||||||
|
target = 'libogg/include/ogg/config_types.h',
|
||||||
|
INCLUDE_INTTYPES_H = bld.env.INCLUDE_INTTYPES_H,
|
||||||
|
INCLUDE_SYS_TYPES_H = bld.env.INCLUDE_SYS_TYPES_H,
|
||||||
|
INCLUDE_STDINT_H = bld.env.INCLUDE_STDINT_H,
|
||||||
|
SIZE16 = 'int16_t',
|
||||||
|
USIZE16 = 'uint16_t',
|
||||||
|
SIZE32 = 'int32_t',
|
||||||
|
USIZE32 = 'uint32_t',
|
||||||
|
SIZE64 = 'int64_t',
|
||||||
|
USIZE64 = 'uint64_t'
|
||||||
|
)
|
||||||
|
|
||||||
|
bld.stlib(
|
||||||
|
source = sources,
|
||||||
|
target = 'ogg',
|
||||||
|
use = 'libogg_config_types',
|
||||||
|
includes = 'libogg/include/',
|
||||||
|
export_includes = 'libogg/include/'
|
||||||
|
)
|
||||||
2
3rdparty/mainui
vendored
2
3rdparty/mainui
vendored
Submodule 3rdparty/mainui updated: f5497ceb04...c92a06e979
2
3rdparty/nanogl
vendored
2
3rdparty/nanogl
vendored
Submodule 3rdparty/nanogl updated: e75792de03...dbfe2e75b3
2
3rdparty/opus/opus
vendored
2
3rdparty/opus/opus
vendored
Submodule 3rdparty/opus/opus updated: 8cf872a186...82ac57d9f1
32
3rdparty/opus/wscript
vendored
32
3rdparty/opus/wscript
vendored
@@ -3,6 +3,26 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
FRAGMENT_VLA='''int main (int argc, char **argv) {
|
||||||
|
char a[argc];
|
||||||
|
a[sizeof( a ) - 1] = 0;
|
||||||
|
int N;
|
||||||
|
return a[0];
|
||||||
|
}'''
|
||||||
|
|
||||||
|
FRAGMENT_ALLOCA_H='''#include <alloca.h>
|
||||||
|
int main (void) {
|
||||||
|
int foo=10;
|
||||||
|
int * array = alloca(foo);
|
||||||
|
}'''
|
||||||
|
|
||||||
|
FRAGMENT_STDLIB_H='''#include <malloc.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
int main (void) {
|
||||||
|
int foo=10;
|
||||||
|
int * array = alloca(foo);
|
||||||
|
}'''
|
||||||
|
|
||||||
def options(opt):
|
def options(opt):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -11,6 +31,15 @@ def configure(conf):
|
|||||||
conf.fatal('Can\'t find opus submodule. Run `git submodule update --init --recursive`.')
|
conf.fatal('Can\'t find opus submodule. Run `git submodule update --init --recursive`.')
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Check for C99 variable-size arrays, or alloca() as fallback
|
||||||
|
if conf.check_cc(fragment=FRAGMENT_VLA, msg = 'Checking for C99 VLA support', mandatory = False):
|
||||||
|
conf.define('VAR_ARRAYS', 1)
|
||||||
|
elif conf.check_cc(fragment=FRAGMENT_ALLOCA_H, msg = 'Checking for alloca in alloca.h header', mandatory = False):
|
||||||
|
conf.define('USE_ALLOCA', 1)
|
||||||
|
conf.define('HAVE_ALLOCA_H', 1)
|
||||||
|
elif conf.check_cc(fragmenmt=FRAGMENT_STDLIB_H, msg = 'Checking for alloca.h in stdlib.h', mandatory = False):
|
||||||
|
conf.define('USE_ALLOCA', 1)
|
||||||
|
|
||||||
# TODO: ARM/x86 intrinsics detection
|
# TODO: ARM/x86 intrinsics detection
|
||||||
# TODO: maybe call autotools/cmake/meson instead?
|
# TODO: maybe call autotools/cmake/meson instead?
|
||||||
|
|
||||||
@@ -27,7 +56,7 @@ def build(bld):
|
|||||||
'opus/celt/opus_custom_demo.c'
|
'opus/celt/opus_custom_demo.c'
|
||||||
])
|
])
|
||||||
includes = ['opus/include/', 'opus/celt/', 'opus/silk/', 'opus/silk/float/']
|
includes = ['opus/include/', 'opus/celt/', 'opus/silk/', 'opus/silk/float/']
|
||||||
defines = ['USE_ALLOCA', 'OPUS_BUILD', 'FLOAT_APPROX', 'PACKAGE_VERSION="1.3.1"', 'CUSTOM_MODES']
|
defines = ['OPUS_BUILD', 'FLOAT_APPROX', 'PACKAGE_VERSION="1.4.0"', 'CUSTOM_MODES']
|
||||||
|
|
||||||
bld.stlib(
|
bld.stlib(
|
||||||
source = sources,
|
source = sources,
|
||||||
@@ -35,6 +64,5 @@ def build(bld):
|
|||||||
features = 'c',
|
features = 'c',
|
||||||
includes = includes,
|
includes = includes,
|
||||||
defines = defines,
|
defines = defines,
|
||||||
subsystem = bld.env.MSVC_SUBSYSTEM,
|
|
||||||
export_includes = ['opus/include/']
|
export_includes = ['opus/include/']
|
||||||
)
|
)
|
||||||
|
|||||||
1
3rdparty/opusfile/opusfile
vendored
Submodule
1
3rdparty/opusfile/opusfile
vendored
Submodule
Submodule 3rdparty/opusfile/opusfile added at 3ecc22aa0a
37
3rdparty/opusfile/wscript
vendored
Normal file
37
3rdparty/opusfile/wscript
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#! /usr/bin/env python
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
def options(opt):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def configure(conf):
|
||||||
|
if not conf.path.find_dir('opusfile') or not conf.path.find_dir('opusfile/src'):
|
||||||
|
conf.fatal('Can\'t find opusfile submodule. Run `git submodule update --init --recursive`.')
|
||||||
|
return
|
||||||
|
|
||||||
|
if conf.env.COMPILER_CC == 'msvc':
|
||||||
|
conf.define('_CRT_SECURE_NO_WARNINGS', 1)
|
||||||
|
conf.define('_CRT_SECURE_NO_DEPRECATE', 1)
|
||||||
|
conf.define('_CRT_NONSTDC_NO_DEPRECATE', 1)
|
||||||
|
|
||||||
|
if conf.env.DEST_OS == 'android':
|
||||||
|
# HACKHACK: set it to 32 here because opusfile can't be built on Android SDK < 24
|
||||||
|
# with _FILE_OFFSET_BITS 64 (which it sets automatically in src/internal.h)
|
||||||
|
# we are not (????) relying on this part of the API, so it should be harmless
|
||||||
|
conf.define('_FILE_OFFSET_BITS', 32)
|
||||||
|
|
||||||
|
def build(bld):
|
||||||
|
sources = [
|
||||||
|
'opusfile/src/info.c',
|
||||||
|
'opusfile/src/internal.c',
|
||||||
|
'opusfile/src/opusfile.c',
|
||||||
|
'opusfile/src/stream.c'
|
||||||
|
]
|
||||||
|
|
||||||
|
bld.stlib(
|
||||||
|
source = sources,
|
||||||
|
target = 'opusfile',
|
||||||
|
includes = 'opusfile/include/',
|
||||||
|
use = 'ogg opus',
|
||||||
|
export_includes = 'opusfile/include/'
|
||||||
|
)
|
||||||
2
3rdparty/vgui_support
vendored
2
3rdparty/vgui_support
vendored
Submodule 3rdparty/vgui_support updated: a2a7b9073f...d585ab86da
1
3rdparty/vorbis/vorbis-src
vendored
Submodule
1
3rdparty/vorbis/vorbis-src
vendored
Submodule
Submodule 3rdparty/vorbis/vorbis-src added at bb4047de4c
71
3rdparty/vorbis/wscript
vendored
Normal file
71
3rdparty/vorbis/wscript
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#! /usr/bin/env python
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
FRAGMENT_MEMORY_H='''#include <memory.h>
|
||||||
|
int main (void) {
|
||||||
|
return 0;
|
||||||
|
}'''
|
||||||
|
|
||||||
|
FRAGMENT_ALLOCA_H='''#include <alloca.h>
|
||||||
|
int main (void) {
|
||||||
|
int foo=10;
|
||||||
|
int * array = alloca(foo);
|
||||||
|
}'''
|
||||||
|
|
||||||
|
def options(opt):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def configure(conf):
|
||||||
|
if not conf.path.find_dir('vorbis-src') or not conf.path.find_dir('vorbis-src/lib'):
|
||||||
|
conf.fatal('Can\'t find Vorbis submodule. Run `git submodule update --init --recursive`.')
|
||||||
|
return
|
||||||
|
|
||||||
|
if conf.check_cc(fragment=FRAGMENT_MEMORY_H, msg = 'Checking for memory.h header', mandatory = False):
|
||||||
|
conf.define('USE_MEMORY_H', 1)
|
||||||
|
|
||||||
|
conf.check_cc(fragment=FRAGMENT_ALLOCA_H, msg = 'Checking for alloca in alloca.h header', mandatory = False)
|
||||||
|
|
||||||
|
if conf.env.COMPILER_CC == 'msvc':
|
||||||
|
conf.define('_CRT_SECURE_NO_WARNINGS', 1)
|
||||||
|
conf.define('_CRT_SECURE_NO_DEPRECATE', 1)
|
||||||
|
conf.define('_CRT_NONSTDC_NO_DEPRECATE', 1)
|
||||||
|
|
||||||
|
def build(bld):
|
||||||
|
libvorbis_sources = [
|
||||||
|
'vorbis-src/lib/mdct.c',
|
||||||
|
'vorbis-src/lib/smallft.c',
|
||||||
|
'vorbis-src/lib/block.c',
|
||||||
|
'vorbis-src/lib/envelope.c',
|
||||||
|
'vorbis-src/lib/window.c',
|
||||||
|
'vorbis-src/lib/lsp.c',
|
||||||
|
'vorbis-src/lib/lpc.c',
|
||||||
|
'vorbis-src/lib/analysis.c',
|
||||||
|
'vorbis-src/lib/synthesis.c',
|
||||||
|
'vorbis-src/lib/psy.c',
|
||||||
|
'vorbis-src/lib/info.c',
|
||||||
|
'vorbis-src/lib/floor1.c',
|
||||||
|
'vorbis-src/lib/floor0.c',
|
||||||
|
'vorbis-src/lib/res0.c',
|
||||||
|
'vorbis-src/lib/mapping0.c',
|
||||||
|
'vorbis-src/lib/registry.c',
|
||||||
|
'vorbis-src/lib/codebook.c',
|
||||||
|
'vorbis-src/lib/sharedbook.c',
|
||||||
|
'vorbis-src/lib/lookup.c',
|
||||||
|
'vorbis-src/lib/bitrate.c'
|
||||||
|
]
|
||||||
|
|
||||||
|
bld.stlib(
|
||||||
|
source = libvorbis_sources,
|
||||||
|
target = 'vorbis',
|
||||||
|
includes = 'vorbis-src/include/',
|
||||||
|
use = 'ogg',
|
||||||
|
export_includes = 'vorbis-src/include/'
|
||||||
|
)
|
||||||
|
|
||||||
|
bld.stlib(
|
||||||
|
source = 'vorbis-src/lib/vorbisfile.c',
|
||||||
|
target = 'vorbisfile',
|
||||||
|
includes = 'vorbis-src/include/',
|
||||||
|
use = 'vorbis',
|
||||||
|
export_includes = 'vorbis-src/include/'
|
||||||
|
)
|
||||||
@@ -13,3 +13,6 @@ When `-bugcomp` is specified with argument, it interpreted as flags separated wi
|
|||||||
| Flag | Description | Games that require this flag |
|
| Flag | Description | Games that require this flag |
|
||||||
| ------- | ----------- | ---------------------------- |
|
| ------- | ----------- | ---------------------------- |
|
||||||
| `peoei` | Reverts `pfnPEntityOfEntIndex` behavior to GoldSrc, where it returns NULL for last player due to incorrect player index comparison | * Counter-Strike: Condition Zero - Deleted Scenes |
|
| `peoei` | Reverts `pfnPEntityOfEntIndex` behavior to GoldSrc, where it returns NULL for last player due to incorrect player index comparison | * Counter-Strike: Condition Zero - Deleted Scenes |
|
||||||
|
| `gsmrf` | Rewrites message at the moment when Game DLL attempts to write an internal engine message, usually specific to GoldSrc protocol.<br>Right now only supports `svc_spawnstaticsound`, more messages added by request. | * MetaMod/AMXModX based mods |
|
||||||
|
| `sp_attn_none` | Makes sounds with attenuation zero spatialized, i.e. have a stereo effect. | Possibly, every game that was made for GoldSrc. |
|
||||||
|
| `get_game_dir_full` | Makes server return full path in server's `pfnGetGameDir` API function | Mods targetting engine before HL 1.1.1.1, according to MetaMod [documentation](http://metamod.org/engine_notes.html#GetGameDir) |
|
||||||
|
|||||||
@@ -5,5 +5,10 @@ This can be useful to test engine in Wine without using virtual machines or dual
|
|||||||
0. Clone and install https://github.com/mstorsjo/msvc-wine (you can skip CMake part)
|
0. Clone and install https://github.com/mstorsjo/msvc-wine (you can skip CMake part)
|
||||||
1. Set environment variable MSVC_WINE_PATH to the path to installed MSVC toolchain
|
1. Set environment variable MSVC_WINE_PATH to the path to installed MSVC toolchain
|
||||||
2. Pre-load wine: `wineserver -k; wineserver -p; wine64 wineboot`
|
2. Pre-load wine: `wineserver -k; wineserver -p; wine64 wineboot`
|
||||||
3. Run `./waf configure -T <build-type> --enable-wine-msvc --sdl2=../SDL2_VC`. Configuration step will take more time than usual.
|
3. Run `PKGCONFIG=/bin/false ./waf configure -T <build-type> --enable-wine-msvc --sdl2=../SDL2_VC`. Configuration step will take more time than usual.
|
||||||
4. .. other typical steps to build from console ...
|
4. .. other typical steps to build from console ...
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Notice the usage of PKGCONFIG=/bin/false here. We're disabling pkg-config so we don't accidentally pull
|
||||||
|
> system-wide dependencies and force building them from source. In future builds we might set custom
|
||||||
|
> directory to pull dependencies from, like ffmpeg...
|
||||||
|
|||||||
@@ -1,150 +0,0 @@
|
|||||||
# There are few new commands availiable in xash3d fork:
|
|
||||||
|
|
||||||
## Commands:
|
|
||||||
### ent_create
|
|
||||||
Create entity with specified classname and key/values
|
|
||||||
|
|
||||||
`ent_create <classname> <key> <value> <key> <value> ...`
|
|
||||||
|
|
||||||
for example:
|
|
||||||
|
|
||||||
`ent_create monster_zombie targetname zomb1`
|
|
||||||
|
|
||||||
after creating entity, ent_last_xxx cvars are set to new entity and ent_last_cb called, look at ent_getvars description
|
|
||||||
|
|
||||||
### ent_fire
|
|
||||||
|
|
||||||
Make some actions on entity
|
|
||||||
|
|
||||||
`ent_fire <pattern> <command> <args>`
|
|
||||||
Availiavle commands:
|
|
||||||
* Set fields (Only set entity field, does not call any functions):
|
|
||||||
* health
|
|
||||||
* gravity
|
|
||||||
* movetype
|
|
||||||
* solid
|
|
||||||
* rendermode
|
|
||||||
* rendercolor (vector)
|
|
||||||
* renderfx
|
|
||||||
* renderamt
|
|
||||||
* hullmin (vector)
|
|
||||||
* hullmax (vector)
|
|
||||||
* Actions
|
|
||||||
* rename: set entity targetname
|
|
||||||
* settarget: set entity target (only targetnames)
|
|
||||||
* setmodel: set entity model (does not update)
|
|
||||||
* set: set key/value by server library
|
|
||||||
* See game FGD to get list.
|
|
||||||
* command takes two arguments
|
|
||||||
* touch: touch entity by current player.
|
|
||||||
* use: use entity by current player.
|
|
||||||
* movehere: place entity in player fov.
|
|
||||||
* drop2floor: place entity to nearest floor surface
|
|
||||||
* moveup: move entity to 25 units up
|
|
||||||
* moveup (value): move by y axis relatively to specified value
|
|
||||||
* Flags (Set/clear specified flag bit, arg is bit number):
|
|
||||||
* setflag
|
|
||||||
* clearflag
|
|
||||||
* setspawnflag
|
|
||||||
* clearspawnflag
|
|
||||||
|
|
||||||
### ent_info
|
|
||||||
Print information about entity by identificator
|
|
||||||
|
|
||||||
`ent_info <identificator>`
|
|
||||||
|
|
||||||
### ent_getvars
|
|
||||||
Set client cvars containing entity information (useful for [[Scripting]]) and call ent_last_cb
|
|
||||||
|
|
||||||
`ent_getvars <identificator>`
|
|
||||||
|
|
||||||
These cvars are set:
|
|
||||||
```
|
|
||||||
ent_last_name
|
|
||||||
ent_last_num
|
|
||||||
ent_last_inst
|
|
||||||
ent_last_origin
|
|
||||||
ent_last_class
|
|
||||||
```
|
|
||||||
|
|
||||||
### ent_list
|
|
||||||
Print short information about antities, filtered by pattern
|
|
||||||
|
|
||||||
`ent_list <pattern>`
|
|
||||||
|
|
||||||
## Syntax description
|
|
||||||
|
|
||||||
### \<identificator\>
|
|
||||||
|
|
||||||
* !cross: entity under aim
|
|
||||||
* Instance code: !\<number\>_\<seria\l>
|
|
||||||
* set by ent_getvars command
|
|
||||||
* Entity index
|
|
||||||
* targetname pattern
|
|
||||||
|
|
||||||
### \<pattern\>
|
|
||||||
|
|
||||||
Pattern is like identificator, but may filter many entities by classname
|
|
||||||
|
|
||||||
### (vector)
|
|
||||||
|
|
||||||
used by ent_fire command. vector means three float values, entered without quotes
|
|
||||||
|
|
||||||
### key/value
|
|
||||||
|
|
||||||
All entities parameters may be set by specifiing key and value strings.
|
|
||||||
|
|
||||||
Originally, this mechanizm is used in map/bsp format, but it can be used in enttools too.
|
|
||||||
|
|
||||||
Keys and values are passed to server library and processed by entity keyvalue function, setting edict and entity owns parameters.
|
|
||||||
|
|
||||||
If value contains spaces, it must be put in quotes:
|
|
||||||
|
|
||||||
`ent_fire !cross set origin "0 0 0"`
|
|
||||||
|
|
||||||
## Using with scripting
|
|
||||||
|
|
||||||
ent_create and ent_getvars commands are setting cvars on client
|
|
||||||
|
|
||||||
It can be used with ent_last_cb alias that is executed after setting cvars.
|
|
||||||
|
|
||||||
Simple example:
|
|
||||||
|
|
||||||
```
|
|
||||||
ent_create weapon_c4
|
|
||||||
alias ent_last_cb "ent_fire \$ent_last_inst use"
|
|
||||||
```
|
|
||||||
|
|
||||||
Use weapon_c4 after creating it.
|
|
||||||
|
|
||||||
Note that you cannot use many dfferent callbacks at the same time.
|
|
||||||
|
|
||||||
You can set entity name by by pattern and create special script, contatning all callbacks.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
example.cfg
|
|
||||||
```
|
|
||||||
alias ent_last_cb exec entity_cb.cfg
|
|
||||||
ent create \<class\> targetname my_ent1_$name
|
|
||||||
ent_create \<class\> targetname my_ent2_$name
|
|
||||||
```
|
|
||||||
entity_cb.cfg
|
|
||||||
```
|
|
||||||
if $ent_last_name == my_ent1_$name
|
|
||||||
:(ent1 actions)
|
|
||||||
if $ent_last_name == my_ent2_$name
|
|
||||||
:(ent2 actions)
|
|
||||||
```
|
|
||||||
Note that scripting cannot be blocking. You cannot wait for server answer and continue. But you can use small scripts, connected with ent_last_cb command. The best usage is user interaction. You can add touch buttons to screen or call user command menu actions by callbacks.
|
|
||||||
## Server side
|
|
||||||
|
|
||||||
To enable entity tools on server, set sv_enttools_enable to 1
|
|
||||||
|
|
||||||
To change maximum number of entities, touched by ent_fire, change sv_enttools_maxfire to required number.
|
|
||||||
|
|
||||||
To enable actions on players, set sv_enttools_players to 1.
|
|
||||||
|
|
||||||
To enable entity tools for player by nickname, set sv_enttools_godplayer to nickname. Useful to temporary enable from rcon.
|
|
||||||
|
|
||||||
To prevent crash on some actions, set host_mapdesign_fatal to 0
|
|
||||||
152
Documentation/extensions/entity-tools.md
Normal file
152
Documentation/extensions/entity-tools.md
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
# Entity tools
|
||||||
|
|
||||||
|
For some features described below, you need to enable [console scripting](https://github.com/FWGS/xash3d-fwgs/blob/master/Documentation/extensions/console-scripting.md) with command `cmd_scripting 1` in console.
|
||||||
|
To get more information about it, check another according page related to console scripting.
|
||||||
|
|
||||||
|
## Commands description
|
||||||
|
|
||||||
|
### ent_create
|
||||||
|
Create entity with specified classname and key/values.
|
||||||
|
|
||||||
|
`ent_create <classname> <key> <value> <key> <value> ...`
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
`ent_create monster_zombie targetname zomb1`
|
||||||
|
|
||||||
|
After creating entity, ent_last_xxx cvars are set to new entity and ent_last_cb called, look at ent_getvars description.
|
||||||
|
|
||||||
|
### ent_fire
|
||||||
|
|
||||||
|
Makes some actions on entity.
|
||||||
|
|
||||||
|
`ent_fire <pattern> <command> <args>`
|
||||||
|
|
||||||
|
#### Available commands:
|
||||||
|
|
||||||
|
Set fields (only set entity field, does not call any functions)
|
||||||
|
* health
|
||||||
|
* gravity
|
||||||
|
* movetype
|
||||||
|
* solid
|
||||||
|
* rendermode
|
||||||
|
* rendercolor (vector)
|
||||||
|
* renderfx
|
||||||
|
* renderamt
|
||||||
|
* hullmin (vector)
|
||||||
|
* hullmax (vector)
|
||||||
|
|
||||||
|
Actions
|
||||||
|
* rename: set entity targetname
|
||||||
|
* settarget: set entity target (only targetnames)
|
||||||
|
* setmodel: set entity model (does not update)
|
||||||
|
* set: set key/value by server library
|
||||||
|
* See game FGD to get list.
|
||||||
|
* command takes two arguments
|
||||||
|
* touch: touch entity by current player.
|
||||||
|
* use: use entity by current player.
|
||||||
|
* movehere: place entity in player fov.
|
||||||
|
* drop2floor: place entity to nearest floor surface
|
||||||
|
* moveup: move entity to 25 units up
|
||||||
|
* moveup (value): move by y axis relatively to specified value
|
||||||
|
|
||||||
|
Flags (set/clear specified flag bit, arg is bit number):
|
||||||
|
* setflag
|
||||||
|
* clearflag
|
||||||
|
* setspawnflag
|
||||||
|
* clearspawnflag
|
||||||
|
|
||||||
|
### ent_info
|
||||||
|
Print information about entity by identificator.
|
||||||
|
|
||||||
|
`ent_info <identificator>`
|
||||||
|
|
||||||
|
### ent_getvars
|
||||||
|
Set client cvars containing entity information (useful for [scripting](extensions/console-scripting.md)) and then calls ent_last_cb.
|
||||||
|
|
||||||
|
`ent_getvars <identificator>`
|
||||||
|
|
||||||
|
These cvars are set:
|
||||||
|
```
|
||||||
|
ent_last_name
|
||||||
|
ent_last_num
|
||||||
|
ent_last_inst
|
||||||
|
ent_last_origin
|
||||||
|
ent_last_class
|
||||||
|
```
|
||||||
|
|
||||||
|
### ent_list
|
||||||
|
Print short information about antities, filtered by pattern.
|
||||||
|
|
||||||
|
`ent_list <pattern>`
|
||||||
|
|
||||||
|
## Syntax description
|
||||||
|
|
||||||
|
#### \<identificator\>
|
||||||
|
* !cross: entity under aim
|
||||||
|
* !\<number\>_\<serial\>: instance code
|
||||||
|
* Set by ent_getvars command
|
||||||
|
* Entity index
|
||||||
|
* Targetname pattern
|
||||||
|
|
||||||
|
#### \<pattern\>
|
||||||
|
|
||||||
|
Pattern is like identificator, but may filter many entities by classname.
|
||||||
|
|
||||||
|
#### (vector)
|
||||||
|
|
||||||
|
Used by ent_fire command. vector means three float values, entered without quotes.
|
||||||
|
|
||||||
|
#### key/value
|
||||||
|
|
||||||
|
All entities parameters may be set by specifiing key and value strings.
|
||||||
|
|
||||||
|
Originally, this mechanizm is used in map/bsp format, but it can be used in enttools too.
|
||||||
|
|
||||||
|
Keys and values are passed to server library and processed by entity keyvalue function, setting edict and entity owns parameters.
|
||||||
|
|
||||||
|
If value contains spaces, it must be put in quotes:
|
||||||
|
|
||||||
|
`ent_fire !cross set origin "0 0 0"`
|
||||||
|
|
||||||
|
## Using with scripting
|
||||||
|
|
||||||
|
ent_create and ent_getvars commands are setting cvars on client
|
||||||
|
|
||||||
|
It can be used with ent_last_cb alias that is executed after setting cvars.
|
||||||
|
|
||||||
|
Simple example:
|
||||||
|
|
||||||
|
```
|
||||||
|
ent_create weapon_c4
|
||||||
|
alias ent_last_cb "ent_fire \$ent_last_inst use"
|
||||||
|
```
|
||||||
|
|
||||||
|
Use weapon_c4 after creating it.
|
||||||
|
|
||||||
|
Note that you cannot use many different callbacks at the same time.
|
||||||
|
|
||||||
|
You can set entity name by by pattern and create special script, contatning all callbacks.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
> example.cfg
|
||||||
|
```
|
||||||
|
alias ent_last_cb exec entity_cb.cfg
|
||||||
|
ent create \<class\> targetname my_ent1_$name
|
||||||
|
ent_create \<class\> targetname my_ent2_$name
|
||||||
|
```
|
||||||
|
> entity_cb.cfg
|
||||||
|
```
|
||||||
|
if $ent_last_name == my_ent1_$name
|
||||||
|
:(ent1 actions)
|
||||||
|
if $ent_last_name == my_ent2_$name
|
||||||
|
:(ent2 actions)
|
||||||
|
```
|
||||||
|
Note that scripting cannot be blocking. You cannot wait for server answer and continue. But you can use small scripts, connected with ent_last_cb command. The best usage is user interaction. You can add touch buttons to screen or call user command menu actions by callbacks.
|
||||||
|
|
||||||
|
## Server side configuration
|
||||||
|
|
||||||
|
To enable entity tools on server, set sv_enttools_enable to 1
|
||||||
|
|
||||||
|
To change maximum number of entities, touched by ent_fire, change sv_enttools_maxfire to required number.
|
||||||
@@ -78,6 +78,7 @@ These strings are specific to Xash3D FWGS.
|
|||||||
| `internal_vgui_support` | boolean | 0 | Only for programmers! Required to be set as 1 for PrimeXT!<br>When set to 1, the engine will not load vgui_support DLL, as VGUI support is done (or intentionally ignored) on the game side. |
|
| `internal_vgui_support` | boolean | 0 | Only for programmers! Required to be set as 1 for PrimeXT!<br>When set to 1, the engine will not load vgui_support DLL, as VGUI support is done (or intentionally ignored) on the game side. |
|
||||||
| `render_picbutton_text` | boolean | 0 | When set to 1, the UI will not use prerendered `btns_main.bmp` and dynamically render them instead |
|
| `render_picbutton_text` | boolean | 0 | When set to 1, the UI will not use prerendered `btns_main.bmp` and dynamically render them instead |
|
||||||
| `quicksave_aged_count` | integer | 2 | Quick saves limit used in saves rotation |
|
| `quicksave_aged_count` | integer | 2 | Quick saves limit used in saves rotation |
|
||||||
|
| `demomap` | string | Empty string | The name of the demo chapter map (Half-Life Uplink) |
|
||||||
|
|
||||||
## Note on GoldSrc liblist.gam support
|
## Note on GoldSrc liblist.gam support
|
||||||
|
|
||||||
|
|||||||
15
Documentation/goldsrc-protocol-support.md
Normal file
15
Documentation/goldsrc-protocol-support.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Support for GoldSrc network protocol
|
||||||
|
This feature is still work-in-progress, but for now it's available for all users, and we appreciate any bug-reports and contributions around it.
|
||||||
|
|
||||||
|
For connecting to GoldSrc-based servers, use this command:
|
||||||
|
```
|
||||||
|
connect ip:port gs
|
||||||
|
```
|
||||||
|
|
||||||
|
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should use Reunion or Dproto.
|
||||||
|
Without this requirement, you will just get "Steam validation rejected" error on connecting.
|
||||||
|
|
||||||
|
That is because proper authorization with Steam API is not implemented in engine yet (but we have plans on it).
|
||||||
|
|
||||||
|
Also, we encountered that some GoldSrc-based servers are recognizing Xash3D clients as "fake clients" and banning/kicking them. Maybe this problem will be
|
||||||
|
solved along with better compatibility with GoldSrc behavior, but may be not - we don't know logic behind this fake client checks.
|
||||||
40
Documentation/hd-textures.md
Normal file
40
Documentation/hd-textures.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
### HD (external) textures support
|
||||||
|
|
||||||
|
Xash3D supports loading texture replacements in TGA format for almost all types of models in the game, except alias models at this time.
|
||||||
|
|
||||||
|
Textures are expected to be located at:
|
||||||
|
* `modfolder/materials/<mapname>` - for a specific map
|
||||||
|
* `modfolder/materials/common` - common for all maps
|
||||||
|
* `modfolder/materials/decals` - for decals
|
||||||
|
* `modfolder/materials/models/<model>` - for models (texture name must match the internal texture name in the model)
|
||||||
|
|
||||||
|
Support for high-resolution textures is enabled setting `host_allow_materials` cvar to `1` or in the menu, in "Video options" section.
|
||||||
|
|
||||||
|
#### Xash3D FWGS additions
|
||||||
|
|
||||||
|
In addition to paths above, Xash3D FWGS checks following paths:
|
||||||
|
|
||||||
|
* `modfolder/materials/sprites/<sprite>` - for sprites, except HUD sprites
|
||||||
|
|
||||||
|
Also, to check which texture replacements are loaded successfully, failed or weren't found, a mod developer can set `host_allow_materials` cvar value to `2`. The engine will spew log at any developer level in the following format:
|
||||||
|
|
||||||
|
```
|
||||||
|
Looking for <replacement> replacement... <status code> (<path relative to mod directory>)
|
||||||
|
```
|
||||||
|
|
||||||
|
Status codes:
|
||||||
|
* `OK` - texture replacement file was found and loaded into GPU memory successfully
|
||||||
|
* `FAIL` - texture file was found but hasn't been parsed or loaded successfully. Refer to engine log for more details.
|
||||||
|
* `MISS` - texture file wasn't found
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
Looking for maps/bounce.bsp:!waterblue tex replacement...OK (materials/common/!waterblue.tga)
|
||||||
|
Looking for maps/bounce.bsp:!waterblue_luma tex replacement...MISS (not found)
|
||||||
|
Looking for {shot2 decal replacement...MISS (materials/decals/{shot2.tga)
|
||||||
|
Looking for {shot4 decal replacement...MISS (materials/decals/{shot4.tga)
|
||||||
|
Looking for {shot3 decal replacement...MISS (materials/decals/{shot3.tga)
|
||||||
|
Looking for models/gman tex replacement...FAIL (materials/models/gman/GMan_Case1.tga)
|
||||||
|
Looking for models/gman tex replacement...FAIL (materials/models/gman/inside_1.tga)
|
||||||
|
```
|
||||||
|
|
||||||
32
Documentation/nat-bypass-usage.md
Normal file
32
Documentation/nat-bypass-usage.md
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# NAT bypass feature in Xash3D FWGS
|
||||||
|
Since IPv6 not as widespread as we would like, NAT (Network Address Translation) still being actively used by many internet service providers in an attempts to
|
||||||
|
mitigate IPv4 addresses exhaustion. In short, they uses one IPv4 address and doing some tricks with ports to represent many other users behind this address.
|
||||||
|
|
||||||
|
But this leads to a problem for users: they cannot accept direct
|
||||||
|
incoming connections anymore. This means that if you are behind provider's NAT and will try to setup Xash3D FWGS server - nobody will be able to connect to it,
|
||||||
|
and the server will not show up in servers public list.
|
||||||
|
|
||||||
|
## Is it possible to avoid this problem?
|
||||||
|
In most cases, it is possible to bypass NAT with UDP hole punching, and Xash3D FWGS uses this method too. But this method is not 100% guaranteed to work - it depends
|
||||||
|
on NAT configurations on both server and client side, and there is no way to control it.
|
||||||
|
|
||||||
|
First of all, server should not be behind symmetric NAT. You can check your NAT type on [this page](https://www.checkmynat.com/).
|
||||||
|
If you get "Symmetric NAT" result in this test, that means you cannot setup publicly available server with internet connection that you are using.
|
||||||
|
|
||||||
|
Here is more detailed scheme of different NAT types compatibility, it explains are users with different NAT types can connect to each other or not.
|
||||||
|
Client NAT type on rows, server NAT type on columns:
|
||||||
|
|
||||||
|
| *NAT Type* | Full Cone | Restricted Cone | Port Restricted Cone | Symmetric |
|
||||||
|
| -------------------- | --------- | --------------- | -------------------- | --------- |
|
||||||
|
| Full Cone | ✔️ | ✔️ | ✔️ | ✔️ |
|
||||||
|
| Restricted Cone | ✔️ | ✔️ | ✔️ | ✔️ |
|
||||||
|
| Port Restricted Cone | ✔️ | ✔️ | ✔️ | ❌ |
|
||||||
|
| Symmetric | ✔️ | ✔️ | ❌ | ❌ |
|
||||||
|
|
||||||
|
## How to use NAT bypass feature?
|
||||||
|
If you are starting server within the game, you need to enable option "*Use NAT Bypass instead of direct mode*" in bottom left corner of screen.
|
||||||
|
|
||||||
|
If you are starting dedicated server, you should add console variable `sv_nat 1` to server.cfg file, or add `+sv_nat 1` to server startup parameters.
|
||||||
|
|
||||||
|
If you need to connect to server behind NAT, there is separate tab named *NAT* for such servers in server browser. Note that it is useless to add NAT server to favorites,
|
||||||
|
or somehow trying manually to store it, because it has changing address and port.
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
Xash3D FWGS is intended to be easily ported to specific platform, however main issue is maintaining such ports.
|
Xash3D FWGS is intended to be easily portable for various platforms, however main issue is maintaining such ports.
|
||||||
|
|
||||||
This page is about merged ports to main source tree and responsible for it developers.
|
This page is about merged ports to main source tree and responsible for it developers.
|
||||||
|
|
||||||
For porting guidelines, look engine-porting-guide.md.
|
For porting guidelines, read engine-porting-guide.md.
|
||||||
|
|
||||||
Status:
|
Status:
|
||||||
* **Supported**: active, was confirmed to be fully functional.
|
* **Supported**: active, confirmed to be fully functional, gets built on CI.
|
||||||
|
* **Orphaned**: some work was done but not finished or actively tested due to lack of human resources.
|
||||||
* **In progress**: active, under development.
|
* **In progress**: active, under development.
|
||||||
* **Old Engine**: port was for old engine fork
|
* **Old Engine**: port was for old engine fork.
|
||||||
* **Not maintained**: lack of human resources
|
* **Deprecated**: not supported anymore.
|
||||||
* **Deprecated**: not supported anymore
|
|
||||||
|
|
||||||
Table is sorted by status and platform.
|
Table is sorted by status and platform.
|
||||||
|
|
||||||
@@ -17,17 +17,22 @@ Table is sorted by status and platform.
|
|||||||
| -------- | ------ | ---------- | ----
|
| -------- | ------ | ---------- | ----
|
||||||
| Android | Supported | @Velaron |
|
| Android | Supported | @Velaron |
|
||||||
| *BSD | Supported | @nekonomicon |
|
| *BSD | Supported | @nekonomicon |
|
||||||
| DOS4GW | Supported | @mittorn |
|
|
||||||
| GNU/Linux | Supported | @a1batross, @mittorn |
|
| GNU/Linux | Supported | @a1batross, @mittorn |
|
||||||
| Haiku | Supported | not maintained | Was added by #478 and #483
|
|
||||||
| macOS | Supported | @sofakng |
|
| macOS | Supported | @sofakng |
|
||||||
| MotoMAGX | Supported | @a1batross |
|
|
||||||
| PSVita | Supported | @fgsfdsfgs |
|
| PSVita | Supported | @fgsfdsfgs |
|
||||||
| Switch | Supported | @fgsfdsfgs |
|
| Switch | Supported | @fgsfdsfgs |
|
||||||
| Windows | Supported | @a1batross, @SNMetamorph |
|
| Windows | Supported | @a1batross, @SNMetamorph |
|
||||||
|
| DOS4GW | Orphaned | N/A | Haven't been confirmed to work for a very long time
|
||||||
|
| Haiku | Orphaned | N/A | Was added by #478 and #483
|
||||||
|
| IRIX | Orphaned | N/A | Undone, compiles but requires big endian port
|
||||||
|
| MotoMAGX | Orphaned | N/A | Should work but the compiler used for this platform is very unstable and easy to crash (it's GCC 3.4)
|
||||||
|
| SerenityOS | Orphaned | N/A | Works but not throughly tested
|
||||||
|
| Solaris | Orphaned | N/A | Works but not throughly tested
|
||||||
|
| WebAssembly System Interface | Orphaned | N/A | Undone, WASI is missing a lot of APIs we want to use
|
||||||
|
| Dreamcast | In progress | @maximqaxd | [GitHub Repository](https://github.com/maximqaxd/xash3d-fwgs_dc/)
|
||||||
| PSP | In progress | @Crow_bar, @Velaron | [GitHub Repository](https://github.com/Crow-bar/xash3d-fwgs)
|
| PSP | In progress | @Crow_bar, @Velaron | [GitHub Repository](https://github.com/Crow-bar/xash3d-fwgs)
|
||||||
| Wii | In progress | Collaborative effort | [GitHub Repository](https://github.com/saucesaft/xash3d-wii)
|
| Wii | In progress | Collaborative effort | [GitHub Repository](https://github.com/saucesaft/xash3d-wii)
|
||||||
| Emscripten | Old Engine | not maintained |
|
| Emscripten | Old Engine | N/A |
|
||||||
| 3DS | Old Engine fork | not maintained | [GitHub Repository](https://github.com/masterfeizz/Xash3DS)
|
| 3DS | Old Engine fork | N/A | [GitHub Repository](https://github.com/masterfeizz/Xash3DS)
|
||||||
| Oculus Quest | Old Engine fork | @DrBeef | [GitHub Repository](https://github.com/DrBeef/Lambda1VR)
|
| Oculus Quest | Old Engine fork | N/A | [GitHub Repository](https://github.com/DrBeef/Lambda1VR)
|
||||||
| iOS | Deprecated | not maintained | See GitHub issue #61
|
| iOS | Deprecated | N/A | See GitHub issue #61
|
||||||
|
|||||||
@@ -19,7 +19,22 @@
|
|||||||
- [List of XashXT-based mods](#list-of-xashxt-based-mods)
|
- [List of XashXT-based mods](#list-of-xashxt-based-mods)
|
||||||
- [List of maps for They Hunger](#list-of-maps-for-they-hunger)
|
- [List of maps for They Hunger](#list-of-maps-for-they-hunger)
|
||||||
- [List of games and mods with custom gamedll](#list-of-games-and-mods-with-custom-gamedll)
|
- [List of games and mods with custom gamedll](#list-of-games-and-mods-with-custom-gamedll)
|
||||||
- [List of mods for Counter Strike(Android only)](#list-of-mods-for-counter-strike)
|
- [List of mods for Counter Strike](#list-of-mods-for-counter-strike)
|
||||||
|
- [List of supported mods from mobile_hacks branch of HLSDK Portable by FWGS](#list-of-supported-mods-from-mobile_hacks-branch-of-hlsdk-portable-by-fwgs)
|
||||||
|
|
||||||
|
# List of supported mods from mobile_hacks branch of HLSDK Portable by FWGS
|
||||||
|
1. [Afraid of Monsters](https://www.moddb.com/mods/afraid-of-monsters/downloads/afraid-of-monsters-v1)
|
||||||
|
2. [Big Lolly](https://www.moddb.com/mods/big-lolly)
|
||||||
|
3. [Half-Life: Blue Shift](https://store.steampowered.com/app/130/HalfLife_Blue_Shift/)
|
||||||
|
4. [Half-Secret](https://www.moddb.com/mods/half-secret)
|
||||||
|
5. [Case Closed](https://www.moddb.com/mods/caseclosed)
|
||||||
|
6. [Bloody Pizza - Vendetta](https://www.moddb.com/games/half-life/addons/bloody-pizza-vendetta)
|
||||||
|
7. [Borderlands](https://www.moddb.com/games/half-life/addons/borderlands-v04)
|
||||||
|
8. [Half-Life: Induction](https://www.moddb.com/mods/half-life-induction/downloads/half-life-induction-12)
|
||||||
|
9. [Redemption/Absolute Redemption](https://www.moddb.com/mods/absolute-redemption)
|
||||||
|
10. [Sewer beta](https://www.moddb.com/games/half-life/addons/sewer-beta)
|
||||||
|
11. [Times of Troubles](https://www.moddb.com/mods/times-of-troubles)
|
||||||
|
12. [Half-Life: Urbicide](https://www.moddb.com/mods/half-life-urbicide)
|
||||||
|
|
||||||
# List of Half-Life-based mods
|
# List of Half-Life-based mods
|
||||||
Originally this list was written by *Qwertyus*(*Qortez*)
|
Originally this list was written by *Qwertyus*(*Qortez*)
|
||||||
@@ -176,7 +191,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
|
|||||||
143. [Operation: Nova](http://www.moddb.com/mods/half-life-operation-nova) (there is an inner bug with an M60 machinegun on a map with Osprey: it can be activated and used if you are staying in front of it, not behind it)
|
143. [Operation: Nova](http://www.moddb.com/mods/half-life-operation-nova) (there is an inner bug with an M60 machinegun on a map with Osprey: it can be activated and used if you are staying in front of it, not behind it)
|
||||||
144. [Optimum Fear](https://www.fileplanet.com/7472/0/fileinfo/Optimum-Fear)
|
144. [Optimum Fear](https://www.fileplanet.com/7472/0/fileinfo/Optimum-Fear)
|
||||||
145. [Outrun](http://www.moddb.com/mods/outrun)
|
145. [Outrun](http://www.moddb.com/mods/outrun)
|
||||||
146. [Outwards (Day One)](https://drive.google.com/file/d/1mjQ8wUazYbwTq9Ocg0Vs0raq4avbTRne/view?usp=sharing)
|
146. [Outwards (Day One)](https://web.archive.org/web/20161026104825/http://visgi.info/maps/)
|
||||||
147. [Overhaul Pack](http://www.moddb.com/mods/half-life-overhaul-pack) (Just HD pack for Half-Life)
|
147. [Overhaul Pack](http://www.moddb.com/mods/half-life-overhaul-pack) (Just HD pack for Half-Life)
|
||||||
148. [P.I.Z.D.E.C.](https://www.runthinkshootlive.com/posts/pizdec/)
|
148. [P.I.Z.D.E.C.](https://www.runthinkshootlive.com/posts/pizdec/)
|
||||||
149. [pagoda](http://www.moddb.com/mods/pagoda1)
|
149. [pagoda](http://www.moddb.com/mods/pagoda1)
|
||||||
@@ -282,7 +297,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
|
|||||||
6. [Catacombs: Part 1](https://www.runthinkshootlive.com/posts/catacombs/)
|
6. [Catacombs: Part 1](https://www.runthinkshootlive.com/posts/catacombs/)
|
||||||
7. [Cro-man's Office Mappack](http://twhl.info/vault.php?map=5547)
|
7. [Cro-man's Office Mappack](http://twhl.info/vault.php?map=5547)
|
||||||
8. [Half-Life Episode Two Demo Alpha v1.0](http://hl.loess.ru/?mod=451)
|
8. [Half-Life Episode Two Demo Alpha v1.0](http://hl.loess.ru/?mod=451)
|
||||||
9. [Hazardous-Course (first version of Hazardous-Course 2)](https://drive.google.com/file/d/16djJZSpNWKyScSxSyMqX-u_S-2i400rl/view?usp=sharing)
|
9. [Hazardous-Course (first version of Hazardous-Course 2)](https://web.archive.org/web/20110512012317/http://www.richmans-maps.ch.vu/)
|
||||||
10. [High Tech v0.2](http://hl.loess.ru/?mod=499)
|
10. [High Tech v0.2](http://hl.loess.ru/?mod=499)
|
||||||
11. [HL Shadows, Part 1](https://www.fileplanet.com/7466/0/fileinfo/'HL-Shadows',-Part-1)
|
11. [HL Shadows, Part 1](https://www.fileplanet.com/7466/0/fileinfo/'HL-Shadows',-Part-1)
|
||||||
12. [HLNewEnd](http://twhl.info/vault.php?map=2275)
|
12. [HLNewEnd](http://twhl.info/vault.php?map=2275)
|
||||||
@@ -305,11 +320,11 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
|
|||||||
29. [Shortcut v1.0 Beta](https://www.runthinkshootlive.com/posts/shortcut/)
|
29. [Shortcut v1.0 Beta](https://www.runthinkshootlive.com/posts/shortcut/)
|
||||||
30. [Stoka](https://www.ceskemody.cz/mapy.php?lng=1&clanek=222&razeni_hra=1&pn=stoka)
|
30. [Stoka](https://www.ceskemody.cz/mapy.php?lng=1&clanek=222&razeni_hra=1&pn=stoka)
|
||||||
31. [Striker's Compo 26](http://twhl.info/vault.php?map=5190) (buggy)
|
31. [Striker's Compo 26](http://twhl.info/vault.php?map=5190) (buggy)
|
||||||
32. [Technology Test 2](https://drive.google.com/file/d/1LfldzsMIN5j07bgtNkfY5v0Xl0S9de_G/view?usp=sharing)
|
32. [Technology Test 2](https://web.archive.org/web/20110512012317/http://www.richmans-maps.ch.vu/)
|
||||||
33. [The Gate Playable Demo](https://www.fileplanet.com/116347/110000/fileinfo/The-Gate-Playable-Demo)
|
33. [The Gate Playable Demo](https://www.fileplanet.com/116347/110000/fileinfo/The-Gate-Playable-Demo)
|
||||||
34. [They are Back](https://www.runthinkshootlive.com/posts/they-are-back/)
|
34. [They are Back](https://www.runthinkshootlive.com/posts/they-are-back/)
|
||||||
35. [Tiefseelabor( Deep Sea Laboratory )](https://www.runthinkshootlive.com/posts/deep-sea-laboratory/)
|
35. [Tiefseelabor( Deep Sea Laboratory )](https://www.runthinkshootlive.com/posts/deep-sea-laboratory/)
|
||||||
36. [Time-Shift](https://drive.google.com/file/d/1pK1s-2SIlSMQHVRPMLdC_94wTa__8_DX/view?usp=sharing)
|
36. [Time-Shift](https://web.archive.org/web/20110512012317/http://www.richmans-maps.ch.vu/)
|
||||||
37. [Train Single Beta](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (Remove **gfx.wad** from **TrainSingle** folder)
|
37. [Train Single Beta](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (Remove **gfx.wad** from **TrainSingle** folder)
|
||||||
38. [WAR: The Killer Beta 0.1](http://www.moddb.com/mods/war)
|
38. [WAR: The Killer Beta 0.1](http://www.moddb.com/mods/war)
|
||||||
39. [White Force Beta( Residual Point prototype )](http://www.moddb.com/mods/hl-residual-point/downloads/white-force-beta-2002)
|
39. [White Force Beta( Residual Point prototype )](http://www.moddb.com/mods/hl-residual-point/downloads/white-force-beta-2002)
|
||||||
@@ -379,7 +394,7 @@ Mods:
|
|||||||
5. [Half-Life Baby v1.4](http://www.moddb.com/games/half-life/addons/half-life-baby) (it's an unfinished but playable mod; after installing of the mod open **liblist.gam** or **gameinfo.txt** file in the mod's folder and correct the line **gamedll "..\hlbaby\dlls\hl.dll"** for **gamedll "dlls\hl.dll"**, otherwise you'll not be able to start a game)
|
5. [Half-Life Baby v1.4](http://www.moddb.com/games/half-life/addons/half-life-baby) (it's an unfinished but playable mod; after installing of the mod open **liblist.gam** or **gameinfo.txt** file in the mod's folder and correct the line **gamedll "..\hlbaby\dlls\hl.dll"** for **gamedll "dlls\hl.dll"**, otherwise you'll not be able to start a game)
|
||||||
6. [Half-Secret](http://www.moddb.com/mods/half-secret) (this mod has custom **weapon_snark** code)
|
6. [Half-Secret](http://www.moddb.com/mods/half-secret) (this mod has custom **weapon_snark** code)
|
||||||
7. [Induction](http://www.moddb.com/mods/half-life-induction) (this mod has new item - **item_flashlight**)
|
7. [Induction](http://www.moddb.com/mods/half-life-induction) (this mod has new item - **item_flashlight**)
|
||||||
8. [Lost in Black Mesa(first version without HLFX)](https://drive.google.com/file/d/1bEnm_AxJs-ly8hTEZIQBw_v2BsXdSiGa/view?usp=sharing)
|
8. [Lost in Black Mesa(first version without HLFX)](https://web.archive.org/web/20160407041812/http://half-life.ru/forum/showthread.php?threadid=13959) (download links dead!)
|
||||||
9. [Soldier](http://www.moddb.com/mods/half-life-soldier)
|
9. [Soldier](http://www.moddb.com/mods/half-life-soldier)
|
||||||
10. [Solo Operations](http://www.moddb.com/mods/solo-operations)
|
10. [Solo Operations](http://www.moddb.com/mods/solo-operations)
|
||||||
11. [The Blood v1.1](http://hl.loess.ru/?mods=&search=The+Blood) (there are some inner bugs in the mod, but they don't interfere with a game progress)
|
11. [The Blood v1.1](http://hl.loess.ru/?mods=&search=The+Blood) (there are some inner bugs in the mod, but they don't interfere with a game progress)
|
||||||
@@ -440,7 +455,7 @@ Mods:
|
|||||||
51. [Data-base](https://www.runthinkshootlive.com/posts/database/)
|
51. [Data-base](https://www.runthinkshootlive.com/posts/database/)
|
||||||
52. [de_dust2_azabetfeN](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (remove **cl_dlls** & **dlls** folders from inside of mod's directory before you start the game)
|
52. [de_dust2_azabetfeN](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (remove **cl_dlls** & **dlls** folders from inside of mod's directory before you start the game)
|
||||||
53. [De-railed](http://twhl.info/competitions.php?results=7)
|
53. [De-railed](http://twhl.info/competitions.php?results=7)
|
||||||
54. [Dead Shift Beta](http://www.moddb.com/mods/dead-shift) - [Demo 1](https://www.gamewatcher.com/mods/half-life-mod/dead-shift-1-0-beta) & [Demo 2](https://drive.google.com/file/d/1uHvr8xONogTTNOy-8X6G4ehFV6Eawvbq/view?usp=sharing)
|
54. [Dead Shift Beta](http://www.moddb.com/mods/dead-shift) - [Demo 1](https://www.gamewatcher.com/mods/half-life-mod/dead-shift-1-0-beta) & [Demo 2](https://web.archive.org/web/20151030005310/http://www.gamefront.com/files/13532512)
|
||||||
55. [Deep](http://twhl.info/vault.php?map=1669)
|
55. [Deep](http://twhl.info/vault.php?map=1669)
|
||||||
56. [Desert Attack](http://fyzzer.narod.ru/index.html)
|
56. [Desert Attack](http://fyzzer.narod.ru/index.html)
|
||||||
57. [Desert Combat Demo](https://www.fileplanet.com/190487/190000/fileinfo/Half-Life---Desert-Combat-Mod) (despite a big file size there's only one small unfinished map)
|
57. [Desert Combat Demo](https://www.fileplanet.com/190487/190000/fileinfo/Half-Life---Desert-Combat-Mod) (despite a big file size there's only one small unfinished map)
|
||||||
@@ -498,8 +513,8 @@ Mods:
|
|||||||
109. [Hospital](https://gamebanana.com/maps/167446) (you need to edit **liblist.gam** file in the mod's folder - delete *gamedll & type* strings from it before you start to play)
|
109. [Hospital](https://gamebanana.com/maps/167446) (you need to edit **liblist.gam** file in the mod's folder - delete *gamedll & type* strings from it before you start to play)
|
||||||
110. [Hostage](https://www.runthinkshootlive.com/posts/hostage-2/)
|
110. [Hostage](https://www.runthinkshootlive.com/posts/hostage-2/)
|
||||||
111. [House](http://www.artpeter.net/Data/HalfLife/Hl.php)
|
111. [House](http://www.artpeter.net/Data/HalfLife/Hl.php)
|
||||||
112. [Impulse 101 Fun - The Train](https://drive.google.com/file/d/1jAuMCCmREH0mfAEAscqaG8FQGa2uNknb/view?usp=sharing) (map from *TWHL* by *Archie* aka *The Hunter*)
|
112. [Impulse 101 Fun - The Train](http://web.archive.org/web/20070305075816/http://www.twhl.co.za/mapvault/2817.zip) (map from *TWHL* by *Archie* aka *The Hunter*)
|
||||||
113. [In America](https://drive.google.com/file/d/1gOC8zfnUvBxRy8Rr8juNiUNbLYjoZpnn/view?usp=sharing)
|
113. [In America](https://web.archive.org/web/20170221213409/http://www.lambda-force.org/load/half_life/karty/half_life_in_america/18-1-0-476)
|
||||||
114. [In the Kitchen](http://twhl.info/vault.php?map=4314)
|
114. [In the Kitchen](http://twhl.info/vault.php?map=4314)
|
||||||
115. [Infiltration](https://www.fileplanet.com/7467/0/fileinfo/Infiltration)
|
115. [Infiltration](https://www.fileplanet.com/7467/0/fileinfo/Infiltration)
|
||||||
116. [Interactivity & Lots of Entities](http://twhl.info/vault.php?map=5744) (link dead!)
|
116. [Interactivity & Lots of Entities](http://twhl.info/vault.php?map=5744) (link dead!)
|
||||||
|
|||||||
71
README.md
71
README.md
@@ -2,7 +2,7 @@
|
|||||||
[](https://builds.sr.ht/~a1batross/xash3d-fwgs?) [](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [](http://fwgsdiscord.mentality.rip/) \
|
[](https://builds.sr.ht/~a1batross/xash3d-fwgs?) [](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [](http://fwgsdiscord.mentality.rip/) \
|
||||||
[](https://github.com/FWGS/xash3d-fwgs/releases/latest) [](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
|
[](https://github.com/FWGS/xash3d-fwgs/releases/latest) [](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
|
||||||
|
|
||||||
Xash3D FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
|
Xash3D (pronounced `[ksɑʂ]`) FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
|
||||||
|
|
||||||
Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://www.moddb.com/engines/xash3d-engine) by Unkle Mike.
|
Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://www.moddb.com/engines/xash3d-engine) by Unkle Mike.
|
||||||
|
|
||||||
@@ -11,16 +11,17 @@ Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://ww
|
|||||||
If you like Xash3D FWGS, consider supporting individual engine maintainers. By supporting us, you help to continue developing this game engine further. The sponsorship links are available in [documentation](Documentation/donate.md).
|
If you like Xash3D FWGS, consider supporting individual engine maintainers. By supporting us, you help to continue developing this game engine further. The sponsorship links are available in [documentation](Documentation/donate.md).
|
||||||
|
|
||||||
## Fork features
|
## Fork features
|
||||||
* Steam Half-Life (HLSDK 2.4) support.
|
* Steam Half-Life (HLSDK 2.5) support.
|
||||||
* Crossplatform and modern compilers support: supports Windows, Linux, BSD & Android on x86 & ARM and [many more](Documentation/ports.md).
|
* Crossplatform and modern compilers support: supports Windows, Linux, BSD & Android on x86 & ARM and [many more](Documentation/ports.md).
|
||||||
* Better multiplayer support: multiple master servers, headless dedicated server, voice chat and IPv6 support.
|
* Better multiplayer: multiple master servers, headless dedicated server, voice chat, [GoldSrc protocol support](Documentation/goldsrc-protocol-support.md) and IPv6 support.
|
||||||
* Multiple renderers support: OpenGL, GLESv1, GLESv2 and Software.
|
* Multiple renderers support: OpenGL, GLESv1, GLESv2 and Software.
|
||||||
* Advanced virtual filesystem: `.pk3` and `.pk3dir` support, compatibility with GoldSrc FS module, fast case-insensitivity emulation for crossplatform.
|
* Advanced virtual filesystem: `.pk3` and `.pk3dir` support, compatibility with GoldSrc FS module, fast case-insensitivity emulation for crossplatform.
|
||||||
* Mobility API: better game integration on mobile devices (vibration, touch controls)
|
* Mobility API: better game integration on mobile devices (vibration, touch controls).
|
||||||
* Different input methods: touch and gamepad in addition to mouse & keyboard.
|
* Different input methods: touch and gamepad in addition to mouse & keyboard.
|
||||||
* TrueType font rendering, as a part of mainui_cpp.
|
* TrueType font rendering, as a part of mainui_cpp.
|
||||||
* External VGUI support module.
|
* External VGUI support module.
|
||||||
* PNG & KTX2 image format support.
|
* PNG & KTX2 image format support.
|
||||||
|
* Ogg Vorbis (`.ogg`) & Ogg Opus (`.opus`) audio formats support.
|
||||||
* [A set of small improvements](Documentation/), without broken compatibility.
|
* [A set of small improvements](Documentation/), without broken compatibility.
|
||||||
|
|
||||||
## Installation & Running
|
## Installation & Running
|
||||||
@@ -28,29 +29,28 @@ If you like Xash3D FWGS, consider supporting individual engine maintainers. By s
|
|||||||
1) Copy engine binaries to some directory.
|
1) Copy engine binaries to some directory.
|
||||||
2) Copy `valve` directory from [Half-Life](https://store.steampowered.com/app/70/HalfLife/) to directory with engine binaries.
|
2) Copy `valve` directory from [Half-Life](https://store.steampowered.com/app/70/HalfLife/) to directory with engine binaries.
|
||||||
If your CPU is NOT x86 compatible or you're running 64-bit version of the engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
|
If your CPU is NOT x86 compatible or you're running 64-bit version of the engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
|
||||||
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
|
This repository contains our fork of HLSDK and restored source code for Half-Life expansions and some mods.
|
||||||
You still needed to copy `valve` directory as all game resources located there.
|
You still needed to copy `valve` directory as all game resources located there.
|
||||||
3) Run the main executable (`xash3d.exe` or AppImage).
|
3) Run the main executable (`xash3d.exe` or AppImage).
|
||||||
|
|
||||||
For additional info, run Xash3D with `-help` command line key.
|
For additional info, run Xash3D with `-help` command line key.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
* Before sending an issue, check if someone already reported your issue. Make sure you're following "How To Ask Questions The Smart Way" guide by Eric Steven Raymond. Read more: http://www.catb.org/~esr/faqs/smart-questions.html
|
* Before sending an issue, check if someone already reported your issue. Make sure you're following "How To Ask Questions The Smart Way" guide by Eric Steven Raymond. Read more: http://www.catb.org/~esr/faqs/smart-questions.html.
|
||||||
* Issues are accepted in both English and Russian
|
* Issues are accepted in both English and Russian.
|
||||||
* Before sending a PR, check if you followed our contribution guide in CONTRIBUTING.md file.
|
* Before sending a PR, check if you followed our contribution guide in CONTRIBUTING.md file.
|
||||||
|
|
||||||
## Build instructions
|
## Build instructions
|
||||||
We are using Waf build system. If you have some Waf-related questions, I recommend you to read https://waf.io/book/
|
We are using Waf build system. If you have some Waf-related questions, I recommend you to read [Waf Book](https://waf.io/book/).
|
||||||
|
|
||||||
NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependencies we're using!
|
NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependencies we're using!
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
If your CPU is x86 compatible and you're on Windows or Linux, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games.
|
||||||
If your CPU is x86 compatible, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games.
|
|
||||||
Even if Xash3D FWGS does support targetting 64-bit, you can't load games without recompiling them from source code!
|
Even if Xash3D FWGS does support targetting 64-bit, you can't load games without recompiling them from source code!
|
||||||
|
|
||||||
If your CPU is NOT x86 compatible or you decided build 64-bit version of engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
|
If your CPU is NOT x86 compatible or you decided build 64-bit version of engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
|
||||||
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
|
This repository contains our fork of HLSDK and restored source code for Half-Life expansions and some mods.
|
||||||
|
|
||||||
#### Windows (Visual Studio)
|
#### Windows (Visual Studio)
|
||||||
* Install Visual Studio.
|
* Install Visual Studio.
|
||||||
@@ -62,31 +62,40 @@ This repository contains our fork of HLSDK and restored source code for some of
|
|||||||
|
|
||||||
#### GNU/Linux
|
#### GNU/Linux
|
||||||
##### Debian/Ubuntu
|
##### Debian/Ubuntu
|
||||||
* Enable i386 on your system, if you're compiling 32-bit engine on amd64. If not, skip this
|
* Only for 32-bit engine on 64-bit x86 operating system:
|
||||||
|
* Enable i386 on your system: `$ sudo dpkg --add-architecture i386`.
|
||||||
|
* Install `aptitude` ([why?](https://github.com/FWGS/xash3d-fwgs/issues/1828#issuecomment-2415131759)): `$ sudo apt update && sudo apt upgrade && sudo apt install aptitude`
|
||||||
|
* Install development tools: `$ sudo aptitude --without-recommends install git build-essential gcc-multilib g++-multilib libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype-dev:i386 libopus-dev:i386 libbz2-dev:i386`.
|
||||||
|
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig`.
|
||||||
|
|
||||||
`$ sudo dpkg --add-architecture i386`
|
* For 64-bit engine on 64-bit x86 and other non-x86 systems:
|
||||||
* Install development tools
|
* Install development tools: `$ sudo apt install git build-essential python libsdl2-dev libfontconfig-dev libfreetype6-dev libopus-dev libbz2-dev`.
|
||||||
* For 32-bit engine on amd64: \
|
|
||||||
`$ sudo apt install build-essential gcc-multilib g++-multilib python libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype6-dev:i386`
|
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
|
||||||
* For everything else: \
|
|
||||||
`$ sudo apt install build-essential python libsdl2-dev libfontconfig-dev libfreetype6-dev`
|
##### RedHat/Fedora
|
||||||
* Clone this repostory:
|
* Only for 32-bit engine on 64-bit x86 operating system:
|
||||||
`$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`
|
* Install development tools: `$ sudo dnf install git gcc gcc-c++ glibc-devel.i686 SDL2-devel.i686 opus-devel.i686 fontconfig-devel.i686 freetype-devel.i686 bzip2-devel.i686`.
|
||||||
|
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/pkgconfig`.
|
||||||
|
|
||||||
|
* For 64-bit engine on 64-bit x86 and other non-x86 systems:
|
||||||
|
* Install development tools: `$ sudo dnf install git gcc gcc-c++ SDL2-devel opus-devel fontconfig-devel freetype-devel bzip2-devel`.
|
||||||
|
|
||||||
|
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
|
||||||
|
|
||||||
### Building
|
### Building
|
||||||
#### Windows (Visual Studio)
|
#### Windows (Visual Studio)
|
||||||
0) Open command line
|
0) Open command line.
|
||||||
1) Navigate to `xash3d-fwgs` directory.
|
1) Navigate to `xash3d-fwgs` directory.
|
||||||
2) Carefully examine which build options are available: `waf --help`
|
2) (optional) Examine which build options are available: `waf --help`.
|
||||||
3) Configure build: `waf configure -T release --sdl2=c:/path/to/SDL2`
|
3) Configure build: `waf configure --sdl2=c:/path/to/SDL2`.
|
||||||
4) Compile: `waf build`
|
4) Compile: `waf build`.
|
||||||
5) Install: `waf install --destdir=c:/path/to/any/output/directory`
|
5) Install: `waf install --destdir=c:/path/to/any/output/directory`.
|
||||||
|
|
||||||
#### Linux
|
#### Linux
|
||||||
If compiling 32-bit on amd64, you may need to supply `export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig` prior to running configure.
|
If compiling 32-bit on amd64, make sure `PKG_CONFIG_PATH` from the previous step is set correctly, prior to running configure.
|
||||||
|
|
||||||
0) Examine which build options are available: `./waf --help`
|
0) (optional) Examine which build options are available: `./waf --help`.
|
||||||
1) Configure build: `./waf configure -T release`
|
1) Configure build: `./waf configure` (you need to pass `-8` to compile 64-bit engine on 64-bit x86 processor).
|
||||||
(You need to pass `-8` to compile 64-bit engine on 64-bit x86 processor)
|
2) Compile: `./waf build`.
|
||||||
2) Compile: `./waf build`
|
3) Install: `./waf install --destdir=/path/to/any/output/directory`.
|
||||||
3) Install(optional): `./waf install --destdir=/path/to/any/output/directory`
|
|
||||||
|
|||||||
14
android/.gitignore
vendored
Normal file
14
android/.gitignore
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
.externalNativeBuild
|
||||||
|
.cxx/
|
||||||
|
.idea/
|
||||||
|
local.properties
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.gradle
|
||||||
|
.settings
|
||||||
|
release/
|
||||||
|
*.hprof
|
||||||
|
.vscode/
|
||||||
|
*.bak
|
||||||
60
android/app/CMakeLists.txt
Normal file
60
android/app/CMakeLists.txt
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.6)
|
||||||
|
|
||||||
|
# Only used to build Android project
|
||||||
|
|
||||||
|
project(XASH_ANDROID)
|
||||||
|
|
||||||
|
# armeabi-v7a requires cpufeatures library
|
||||||
|
include(AndroidNdkModules)
|
||||||
|
android_ndk_import_module_cpufeatures()
|
||||||
|
|
||||||
|
find_package(PythonInterp 2.7 REQUIRED)
|
||||||
|
|
||||||
|
get_filename_component(C_COMPILER_ID ${CMAKE_C_COMPILER} NAME_WE)
|
||||||
|
get_filename_component(CXX_COMPILER_ID ${CMAKE_CXX_COMPILER} NAME_WE)
|
||||||
|
|
||||||
|
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||||
|
set(BUILD_TYPE "debug")
|
||||||
|
else()
|
||||||
|
set(BUILD_TYPE "release")
|
||||||
|
list(APPEND WAF_EXTRA_ARGS --enable-poly-opt --enable-lto)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||||
|
set(64BIT ON CACHE BOOL "" FORCE)
|
||||||
|
list(APPEND WAF_EXTRA_ARGS -8) # only required for x86 when testing this cmakelist under linux
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||||
|
|
||||||
|
set(WAF_CC "${CMAKE_C_COMPILER} --target=${CMAKE_C_COMPILER_TARGET}")
|
||||||
|
set(WAF_CXX "${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET}")
|
||||||
|
|
||||||
|
# not cleanest way to get upper directory
|
||||||
|
set(ENGINE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../")
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E env
|
||||||
|
CC=${WAF_CC} CXX=${WAF_CXX}
|
||||||
|
AR=${CMAKE_AR} STRIP=${CMAKE_STRIP}
|
||||||
|
${PYTHON_EXECUTABLE} waf configure -T ${BUILD_TYPE} ${WAF_EXTRA_ARGS} cmake
|
||||||
|
--check-c-compiler=${C_COMPILER_ID} --check-cxx-compiler=${CXX_COMPILER_ID}
|
||||||
|
-s "${ENGINE_SOURCE_DIR}/SDL" --skip-sdl2-sanity-check --enable-bundled-deps
|
||||||
|
WORKING_DIRECTORY "${ENGINE_SOURCE_DIR}"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/hlsdk-portable" hlsdk-portable)
|
||||||
|
|
||||||
|
# try to build minimal SDL. Enable features as we're gonna use them
|
||||||
|
set(SDL_RENDER OFF)
|
||||||
|
set(SDL_POWER OFF)
|
||||||
|
set(SDL_VULKAN OFF)
|
||||||
|
set(SDL_DISKAUDIO OFF)
|
||||||
|
set(SDL_DUMMYAUDIO OFF)
|
||||||
|
set(SDL_DUMMYVIDEO OFF)
|
||||||
|
set(SDL_VULKAN OFF)
|
||||||
|
set(SDL_OFFSCREEN OFF)
|
||||||
|
set(SDL_STATIC OFF)
|
||||||
|
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/SDL" SDL)
|
||||||
|
add_subdirectory("${ENGINE_SOURCE_DIR}/" xash3d-fwgs)
|
||||||
|
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/mainui" mainui)
|
||||||
129
android/app/build.gradle.kts
Normal file
129
android/app/build.gradle.kts
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.Month
|
||||||
|
import java.time.temporal.ChronoUnit
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("com.android.application")
|
||||||
|
id("org.jetbrains.kotlin.android")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "su.xash.engine"
|
||||||
|
ndkVersion = "27.2.12479018"
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId = "su.xash"
|
||||||
|
applicationIdSuffix = "engine"
|
||||||
|
versionName = "0.21"
|
||||||
|
versionCode = getBuildNum()
|
||||||
|
minSdk = 21
|
||||||
|
targetSdk = 34
|
||||||
|
compileSdk = 34
|
||||||
|
|
||||||
|
externalNativeBuild {
|
||||||
|
cmake {
|
||||||
|
abiFilters("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
|
||||||
|
arguments("-DANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
externalNativeBuild {
|
||||||
|
cmake {
|
||||||
|
version = "3.22.1"
|
||||||
|
path = file("CMakeLists.txt")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
debug {
|
||||||
|
isMinifyEnabled = false
|
||||||
|
isShrinkResources = false
|
||||||
|
isDebuggable = true
|
||||||
|
applicationIdSuffix = ".test"
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
release {
|
||||||
|
isMinifyEnabled = true
|
||||||
|
isShrinkResources = true
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
register("asan") {
|
||||||
|
initWith(getByName("debug"))
|
||||||
|
}
|
||||||
|
|
||||||
|
register("continuous") {
|
||||||
|
initWith(getByName("release"))
|
||||||
|
applicationIdSuffix = ".test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
getByName("main") {
|
||||||
|
assets.srcDirs("../../3rdparty/extras/xash-extras", "../moddb")
|
||||||
|
java.srcDir("../../3rdparty/SDL/android-project/app/src/main/java")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lint {
|
||||||
|
abortOnError = false
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
viewBinding = true
|
||||||
|
buildConfig = true
|
||||||
|
}
|
||||||
|
|
||||||
|
androidResources {
|
||||||
|
noCompress += ""
|
||||||
|
}
|
||||||
|
|
||||||
|
packaging {
|
||||||
|
jniLibs {
|
||||||
|
useLegacyPackaging = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("com.google.android.material:material:1.11.0")
|
||||||
|
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||||
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||||
|
implementation("androidx.navigation:navigation-fragment-ktx:2.7.7")
|
||||||
|
implementation("androidx.navigation:navigation-ui-ktx:2.7.7")
|
||||||
|
implementation("androidx.cardview:cardview:1.0.0")
|
||||||
|
implementation("androidx.annotation:annotation:1.7.1")
|
||||||
|
implementation("androidx.fragment:fragment-ktx:1.6.2")
|
||||||
|
implementation("androidx.preference:preference-ktx:1.2.1")
|
||||||
|
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||||
|
implementation("androidx.work:work-runtime-ktx:2.9.0")
|
||||||
|
// implementation "androidx.legacy:legacy-support-v4:1.0.0"
|
||||||
|
|
||||||
|
implementation("com.madgag.spongycastle:prov:1.58.0.0")
|
||||||
|
implementation("in.dragonbra:javasteam:1.2.0")
|
||||||
|
|
||||||
|
implementation("ch.acra:acra-http:5.11.2")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBuildNum(): Int {
|
||||||
|
val now = LocalDateTime.now()
|
||||||
|
val releaseDate = LocalDateTime.of(2015, Month.APRIL, 1, 0, 0, 0)
|
||||||
|
val qBuildNum = releaseDate.until(now, ChronoUnit.DAYS)
|
||||||
|
val minuteOfDay = now.hour * 60 + now.minute
|
||||||
|
return (qBuildNum * 10000 + minuteOfDay).toInt()
|
||||||
|
}
|
||||||
89
android/app/proguard-rules.pro
vendored
Normal file
89
android/app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
-keep class su.xash.engine.XashActivity {
|
||||||
|
java.lang.String loadAndroidID();
|
||||||
|
java.lang.String getAndroidID();
|
||||||
|
void saveAndroidID(java.lang.String);
|
||||||
|
java.lang.String getCallingPackage();
|
||||||
|
java.lang.String[] getAssetsList(boolean, java.lang.String);
|
||||||
|
android.content.res.AssetManager getAssets(boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLInputConnection {
|
||||||
|
void nativeCommitText(java.lang.String, int);
|
||||||
|
void nativeGenerateScancodeForUnichar(char);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep,includedescriptorclasses class org.libsdl.app.SDLActivity {
|
||||||
|
# for some reason these aren't compatible with allowoptimization modifier
|
||||||
|
boolean supportsRelativeMouse();
|
||||||
|
void setWindowStyle(boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLActivity {
|
||||||
|
java.lang.String nativeGetHint(java.lang.String); # Java-side doesn't use this, so it gets minified, but C-side still tries to register it
|
||||||
|
boolean onNativeSoftReturnKey();
|
||||||
|
void onNativeKeyboardFocusLost();
|
||||||
|
boolean isScreenKeyboardShown();
|
||||||
|
android.util.DisplayMetrics getDisplayDPI();
|
||||||
|
java.lang.String clipboardGetText();
|
||||||
|
boolean clipboardHasText();
|
||||||
|
void clipboardSetText(java.lang.String);
|
||||||
|
int createCustomCursor(int[], int, int, int, int);
|
||||||
|
void destroyCustomCursor(int);
|
||||||
|
android.content.Context getContext();
|
||||||
|
boolean getManifestEnvironmentVariables();
|
||||||
|
android.view.Surface getNativeSurface();
|
||||||
|
void initTouch();
|
||||||
|
boolean isAndroidTV();
|
||||||
|
boolean isChromebook();
|
||||||
|
boolean isDeXMode();
|
||||||
|
boolean isTablet();
|
||||||
|
void manualBackButton();
|
||||||
|
int messageboxShowMessageBox(int, java.lang.String, java.lang.String, int[], int[], java.lang.String[], int[]);
|
||||||
|
void minimizeWindow();
|
||||||
|
int openURL(java.lang.String);
|
||||||
|
void requestPermission(java.lang.String, int);
|
||||||
|
int showToast(java.lang.String, int, int, int, int);
|
||||||
|
boolean sendMessage(int, int);
|
||||||
|
boolean setActivityTitle(java.lang.String);
|
||||||
|
boolean setCustomCursor(int);
|
||||||
|
void setOrientation(int, int, boolean, java.lang.String);
|
||||||
|
boolean setRelativeMouseEnabled(boolean);
|
||||||
|
boolean setSystemCursor(int);
|
||||||
|
boolean shouldMinimizeOnFocusLoss();
|
||||||
|
boolean showTextInput(int, int, int, int);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.HIDDeviceManager {
|
||||||
|
boolean initialize(boolean, boolean);
|
||||||
|
boolean openDevice(int);
|
||||||
|
int sendOutputReport(int, byte[]);
|
||||||
|
int sendFeatureReport(int, byte[]);
|
||||||
|
boolean getFeatureReport(int, byte[]);
|
||||||
|
void closeDevice(int);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLAudioManager {
|
||||||
|
int[] getAudioOutputDevices();
|
||||||
|
int[] getAudioInputDevices();
|
||||||
|
int[] audioOpen(int, int, int, int, int);
|
||||||
|
void audioWriteFloatBuffer(float[]);
|
||||||
|
void audioWriteShortBuffer(short[]);
|
||||||
|
void audioWriteByteBuffer(byte[]);
|
||||||
|
void audioClose();
|
||||||
|
int[] captureOpen(int, int, int, int, int);
|
||||||
|
int captureReadFloatBuffer(float[], boolean);
|
||||||
|
int captureReadShortBuffer(short[], boolean);
|
||||||
|
int captureReadByteBuffer(byte[], boolean);
|
||||||
|
void captureClose();
|
||||||
|
void audioSetThreadPriority(boolean, int);
|
||||||
|
native int nativeSetupJNI();
|
||||||
|
native void removeAudioDevice(boolean, int);
|
||||||
|
native void addAudioDevice(boolean, int);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLControllerManager {
|
||||||
|
void pollInputDevices();
|
||||||
|
void pollHapticDevices();
|
||||||
|
void hapticRun(int, float, int);
|
||||||
|
void hapticStop(int);
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
5
android/app/src/asan/res/values/strings.xml
Normal file
5
android/app/src/asan/res/values/strings.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name" translatable="false">Xash3D FWGS (Test)</string>
|
||||||
|
<string name="authority" translatable="false">su.xash.engine.test.documents</string>
|
||||||
|
</resources>
|
||||||
26
android/app/src/asan/resources/lib/arm64-v8a/wrap.sh
Normal file
26
android/app/src/asan/resources/lib/arm64-v8a/wrap.sh
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
#!/system/bin/sh
|
||||||
|
HERE=$(cd "$(dirname "$0")" && pwd)
|
||||||
|
cmd=$1
|
||||||
|
shift
|
||||||
|
# This must be called *before* `LD_PRELOAD` is set. Otherwise, if this is a 32-
|
||||||
|
# bit app running on a 64-bit device, the 64-bit getprop will fail to load
|
||||||
|
# because it will preload a 32-bit ASan runtime.
|
||||||
|
# https://github.com/android/ndk/issues/1744
|
||||||
|
os_version=$(getprop ro.build.version.sdk)
|
||||||
|
if [ "$os_version" -eq "27" ]; then
|
||||||
|
cmd="$cmd -Xrunjdwp:transport=dt_android_adb,suspend=n,server=y -Xcompiler-option --debuggable $@"
|
||||||
|
elif [ "$os_version" -eq "28" ]; then
|
||||||
|
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y -Xcompiler-option --debuggable $@"
|
||||||
|
else
|
||||||
|
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y $@"
|
||||||
|
fi
|
||||||
|
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
|
||||||
|
ASAN_LIB=$(ls "$HERE"/libclang_rt.asan-*-android.so)
|
||||||
|
if [ -f "$HERE/libc++_shared.so" ]; then
|
||||||
|
# Workaround for https://github.com/android-ndk/ndk/issues/988.
|
||||||
|
export LD_PRELOAD="$ASAN_LIB $HERE/libc++_shared.so"
|
||||||
|
else
|
||||||
|
export LD_PRELOAD="$ASAN_LIB"
|
||||||
|
fi
|
||||||
|
exec $cmd
|
||||||
26
android/app/src/asan/resources/lib/armeabi-v7a/wrap.sh
Normal file
26
android/app/src/asan/resources/lib/armeabi-v7a/wrap.sh
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
#!/system/bin/sh
|
||||||
|
HERE=$(cd "$(dirname "$0")" && pwd)
|
||||||
|
cmd=$1
|
||||||
|
shift
|
||||||
|
# This must be called *before* `LD_PRELOAD` is set. Otherwise, if this is a 32-
|
||||||
|
# bit app running on a 64-bit device, the 64-bit getprop will fail to load
|
||||||
|
# because it will preload a 32-bit ASan runtime.
|
||||||
|
# https://github.com/android/ndk/issues/1744
|
||||||
|
os_version=$(getprop ro.build.version.sdk)
|
||||||
|
if [ "$os_version" -eq "27" ]; then
|
||||||
|
cmd="$cmd -Xrunjdwp:transport=dt_android_adb,suspend=n,server=y -Xcompiler-option --debuggable $@"
|
||||||
|
elif [ "$os_version" -eq "28" ]; then
|
||||||
|
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y -Xcompiler-option --debuggable $@"
|
||||||
|
else
|
||||||
|
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y $@"
|
||||||
|
fi
|
||||||
|
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
|
||||||
|
ASAN_LIB=$(ls "$HERE"/libclang_rt.asan-*-android.so)
|
||||||
|
if [ -f "$HERE/libc++_shared.so" ]; then
|
||||||
|
# Workaround for https://github.com/android-ndk/ndk/issues/988.
|
||||||
|
export LD_PRELOAD="$ASAN_LIB $HERE/libc++_shared.so"
|
||||||
|
else
|
||||||
|
export LD_PRELOAD="$ASAN_LIB"
|
||||||
|
fi
|
||||||
|
exec $cmd
|
||||||
26
android/app/src/asan/resources/lib/x86/wrap.sh
Normal file
26
android/app/src/asan/resources/lib/x86/wrap.sh
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
#!/system/bin/sh
|
||||||
|
HERE=$(cd "$(dirname "$0")" && pwd)
|
||||||
|
cmd=$1
|
||||||
|
shift
|
||||||
|
# This must be called *before* `LD_PRELOAD` is set. Otherwise, if this is a 32-
|
||||||
|
# bit app running on a 64-bit device, the 64-bit getprop will fail to load
|
||||||
|
# because it will preload a 32-bit ASan runtime.
|
||||||
|
# https://github.com/android/ndk/issues/1744
|
||||||
|
os_version=$(getprop ro.build.version.sdk)
|
||||||
|
if [ "$os_version" -eq "27" ]; then
|
||||||
|
cmd="$cmd -Xrunjdwp:transport=dt_android_adb,suspend=n,server=y -Xcompiler-option --debuggable $@"
|
||||||
|
elif [ "$os_version" -eq "28" ]; then
|
||||||
|
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y -Xcompiler-option --debuggable $@"
|
||||||
|
else
|
||||||
|
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y $@"
|
||||||
|
fi
|
||||||
|
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
|
||||||
|
ASAN_LIB=$(ls "$HERE"/libclang_rt.asan-*-android.so)
|
||||||
|
if [ -f "$HERE/libc++_shared.so" ]; then
|
||||||
|
# Workaround for https://github.com/android-ndk/ndk/issues/988.
|
||||||
|
export LD_PRELOAD="$ASAN_LIB $HERE/libc++_shared.so"
|
||||||
|
else
|
||||||
|
export LD_PRELOAD="$ASAN_LIB"
|
||||||
|
fi
|
||||||
|
exec $cmd
|
||||||
26
android/app/src/asan/resources/lib/x86_64/wrap.sh
Normal file
26
android/app/src/asan/resources/lib/x86_64/wrap.sh
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
#!/system/bin/sh
|
||||||
|
HERE=$(cd "$(dirname "$0")" && pwd)
|
||||||
|
cmd=$1
|
||||||
|
shift
|
||||||
|
# This must be called *before* `LD_PRELOAD` is set. Otherwise, if this is a 32-
|
||||||
|
# bit app running on a 64-bit device, the 64-bit getprop will fail to load
|
||||||
|
# because it will preload a 32-bit ASan runtime.
|
||||||
|
# https://github.com/android/ndk/issues/1744
|
||||||
|
os_version=$(getprop ro.build.version.sdk)
|
||||||
|
if [ "$os_version" -eq "27" ]; then
|
||||||
|
cmd="$cmd -Xrunjdwp:transport=dt_android_adb,suspend=n,server=y -Xcompiler-option --debuggable $@"
|
||||||
|
elif [ "$os_version" -eq "28" ]; then
|
||||||
|
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y -Xcompiler-option --debuggable $@"
|
||||||
|
else
|
||||||
|
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y $@"
|
||||||
|
fi
|
||||||
|
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
|
||||||
|
ASAN_LIB=$(ls "$HERE"/libclang_rt.asan-*-android.so)
|
||||||
|
if [ -f "$HERE/libc++_shared.so" ]; then
|
||||||
|
# Workaround for https://github.com/android-ndk/ndk/issues/988.
|
||||||
|
export LD_PRELOAD="$ASAN_LIB $HERE/libc++_shared.so"
|
||||||
|
else
|
||||||
|
export LD_PRELOAD="$ASAN_LIB"
|
||||||
|
fi
|
||||||
|
exec $cmd
|
||||||
5
android/app/src/continuous/res/values/strings.xml
Normal file
5
android/app/src/continuous/res/values/strings.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name" translatable="false">Xash3D FWGS (Test)</string>
|
||||||
|
<string name="authority" translatable="false">su.xash.engine.test.documents</string>
|
||||||
|
</resources>
|
||||||
5
android/app/src/debug/res/values/strings.xml
Normal file
5
android/app/src/debug/res/values/strings.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name" translatable="false">Xash3D FWGS (Test)</string>
|
||||||
|
<string name="authority" translatable="false">su.xash.engine.test.documents</string>
|
||||||
|
</resources>
|
||||||
101
android/app/src/main/AndroidManifest.xml
Normal file
101
android/app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:allowAudioPlaybackCapture="true"
|
||||||
|
android:installLocation="preferExternal"
|
||||||
|
tools:targetApi="q">
|
||||||
|
<!-- OpenGL ES 1.1 -->
|
||||||
|
<uses-feature android:glEsVersion="0x00010000" />
|
||||||
|
<!-- Touchscreen support -->
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.touchscreen"
|
||||||
|
android:required="false" />
|
||||||
|
<!-- Game controller support -->
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.bluetooth"
|
||||||
|
android:required="false" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.gamepad"
|
||||||
|
android:required="false" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.usb.host"
|
||||||
|
android:required="false" />
|
||||||
|
<!-- External mouse input events -->
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.type.pc"
|
||||||
|
android:required="false" />
|
||||||
|
<!-- Audio recording support -->
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.microphone"
|
||||||
|
android:required="false" />
|
||||||
|
<!-- Allow downloading to the external storage on Android 5.1 and older -->
|
||||||
|
<uses-permission
|
||||||
|
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
|
android:maxSdkVersion="22" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||||
|
android:maxSdkVersion="32" />
|
||||||
|
<!-- Allow access to Bluetooth devices -->
|
||||||
|
<!-- Currently this is just for Steam Controller support and requires setting SDL_HINT_JOYSTICK_HIDAPI_STEAM -->
|
||||||
|
<uses-permission
|
||||||
|
android:name="android.permission.BLUETOOTH"
|
||||||
|
android:maxSdkVersion="30" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||||
|
<!-- Allow access to the vibrator -->
|
||||||
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
<!-- Allow recording audio -->
|
||||||
|
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||||
|
<!-- Allow internet access -->
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<!-- Dedicated server -->
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:name=".MainApplication"
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher"
|
||||||
|
android:theme="@style/Theme.App"
|
||||||
|
android:usesCleartextTraffic="true">
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".XashActivity"
|
||||||
|
android:alwaysRetainTaskState="true"
|
||||||
|
android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation|touchscreen"
|
||||||
|
android:exported="true"
|
||||||
|
android:launchMode="singleTask"
|
||||||
|
android:preferMinimalPostProcessing="true"
|
||||||
|
android:windowSoftInputMode="adjustResize"
|
||||||
|
tools:targetApi="r">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name=".XashDocumentsProvider"
|
||||||
|
android:authorities="@string/authority"
|
||||||
|
android:exported="true"
|
||||||
|
android:grantUriPermissions="true"
|
||||||
|
android:permission="android.permission.MANAGE_DOCUMENTS">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
|
||||||
|
</intent-filter>
|
||||||
|
</provider>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
<queries>
|
||||||
|
<intent>
|
||||||
|
<action android:name="su.xash.engine.MOD" />
|
||||||
|
</intent>
|
||||||
|
</queries>
|
||||||
|
</manifest>
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package su.xash.engine;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
|
public class AndroidBug5497Workaround {
|
||||||
|
// For more information, see https://code.google.com/p/android/issues/detail?id=5497
|
||||||
|
// To use this class, simply invoke assistActivity() on an Activity that already has its content view set.
|
||||||
|
|
||||||
|
public static void assistActivity(Activity activity) {
|
||||||
|
new AndroidBug5497Workaround(activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private View mChildOfContent;
|
||||||
|
private int usableHeightPrevious;
|
||||||
|
private FrameLayout.LayoutParams frameLayoutParams;
|
||||||
|
|
||||||
|
private AndroidBug5497Workaround(Activity activity) {
|
||||||
|
FrameLayout content = activity.findViewById(android.R.id.content);
|
||||||
|
mChildOfContent = content.getChildAt(0);
|
||||||
|
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(this::possiblyResizeChildOfContent);
|
||||||
|
frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void possiblyResizeChildOfContent() {
|
||||||
|
int usableHeightNow = computeUsableHeight();
|
||||||
|
if (usableHeightNow != usableHeightPrevious) {
|
||||||
|
int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
|
||||||
|
int heightDifference = usableHeightSansKeyboard - usableHeightNow;
|
||||||
|
if (heightDifference > (usableHeightSansKeyboard / 4)) {
|
||||||
|
// keyboard probably just became visible
|
||||||
|
frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
|
||||||
|
} else {
|
||||||
|
// keyboard probably just became hidden
|
||||||
|
frameLayoutParams.height = usableHeightSansKeyboard;
|
||||||
|
}
|
||||||
|
mChildOfContent.requestLayout();
|
||||||
|
usableHeightPrevious = usableHeightNow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int computeUsableHeight() {
|
||||||
|
Rect r = new Rect();
|
||||||
|
mChildOfContent.getWindowVisibleDisplayFrame(r);
|
||||||
|
return (r.bottom - r.top);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package su.xash.engine
|
||||||
|
|
||||||
|
class DedicatedActivity {
|
||||||
|
}
|
||||||
11
android/app/src/main/java/su/xash/engine/DedicatedService.kt
Normal file
11
android/app/src/main/java/su/xash/engine/DedicatedService.kt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package su.xash.engine
|
||||||
|
|
||||||
|
import android.app.Service
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.IBinder
|
||||||
|
|
||||||
|
class DedicatedService: Service() {
|
||||||
|
override fun onBind(intent: Intent?): IBinder? {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
35
android/app/src/main/java/su/xash/engine/MainActivity.kt
Normal file
35
android/app/src/main/java/su/xash/engine/MainActivity.kt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package su.xash.engine
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
|
import androidx.navigation.ui.AppBarConfiguration
|
||||||
|
import androidx.navigation.ui.navigateUp
|
||||||
|
import androidx.navigation.ui.setupActionBarWithNavController
|
||||||
|
import su.xash.engine.databinding.ActivityMainBinding
|
||||||
|
|
||||||
|
class MainActivity : AppCompatActivity() {
|
||||||
|
private lateinit var binding: ActivityMainBinding
|
||||||
|
private lateinit var appBarConfiguration: AppBarConfiguration
|
||||||
|
private lateinit var navController: NavController
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
setSupportActionBar(binding.toolbar)
|
||||||
|
|
||||||
|
val navHostFragment =
|
||||||
|
supportFragmentManager.findFragmentById(R.id.fragmentContainerView) as NavHostFragment
|
||||||
|
navController = navHostFragment.navController
|
||||||
|
appBarConfiguration = AppBarConfiguration(navController.graph)
|
||||||
|
setupActionBarWithNavController(navController, appBarConfiguration)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSupportNavigateUp(): Boolean {
|
||||||
|
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
|
||||||
|
}
|
||||||
|
}
|
||||||
28
android/app/src/main/java/su/xash/engine/MainApplication.kt
Normal file
28
android/app/src/main/java/su/xash/engine/MainApplication.kt
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package su.xash.engine
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.StrictMode
|
||||||
|
import org.acra.config.httpSender
|
||||||
|
import org.acra.data.StringFormat
|
||||||
|
import org.acra.ktx.initAcra
|
||||||
|
|
||||||
|
class MainApplication : Application() {
|
||||||
|
override fun attachBaseContext(base: Context?) {
|
||||||
|
super.attachBaseContext(base)
|
||||||
|
|
||||||
|
if (!BuildConfig.DEBUG) {
|
||||||
|
initAcra {
|
||||||
|
buildConfigClass = BuildConfig::class.java
|
||||||
|
reportFormat = StringFormat.JSON
|
||||||
|
|
||||||
|
httpSender {
|
||||||
|
uri = "http://bodis.pp.ua:5000/report"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// enable strict mode to detect memory leaks etc.
|
||||||
|
StrictMode.enableDefaults();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
136
android/app/src/main/java/su/xash/engine/XashActivity.java
Normal file
136
android/app/src/main/java/su/xash/engine/XashActivity.java
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
package su.xash.engine;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.res.AssetManager;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.provider.Settings.Secure;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import org.libsdl.app.SDLActivity;
|
||||||
|
|
||||||
|
public class XashActivity extends SDLActivity {
|
||||||
|
private boolean mUseVolumeKeys;
|
||||||
|
private String mPackageName;
|
||||||
|
private static final String TAG = "XashActivity";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
|
//getWindow().addFlags(WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES);
|
||||||
|
getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidBug5497Workaround.assistActivity(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getLibraries() {
|
||||||
|
return new String[]{"SDL2", "xash"};
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("HardwareIds")
|
||||||
|
private String getAndroidID() {
|
||||||
|
return Secure.getString(getContentResolver(), Secure.ANDROID_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ApplySharedPref")
|
||||||
|
private void saveAndroidID(String id) {
|
||||||
|
getSharedPreferences("xash_preferences", MODE_PRIVATE).edit().putString("xash_id", id).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String loadAndroidID() {
|
||||||
|
return getSharedPreferences("xash_preferences", MODE_PRIVATE).getString("xash_id", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCallingPackage() {
|
||||||
|
if (mPackageName != null) {
|
||||||
|
return mPackageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.getCallingPackage();
|
||||||
|
}
|
||||||
|
|
||||||
|
private AssetManager getAssets(boolean isEngine) {
|
||||||
|
AssetManager am = null;
|
||||||
|
|
||||||
|
if (isEngine) {
|
||||||
|
am = getAssets();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
am = getPackageManager().getResourcesForApplication(getCallingPackage()).getAssets();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Unable to load mod assets!");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return am;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] getAssetsList(boolean isEngine, String path) {
|
||||||
|
AssetManager am = getAssets(isEngine);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return am.list(path);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new String[]{};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||||
|
if (SDLActivity.mBrokenLibraries) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int keyCode = event.getKeyCode();
|
||||||
|
if (!mUseVolumeKeys) {
|
||||||
|
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
|
||||||
|
keyCode == KeyEvent.KEYCODE_VOLUME_UP ||
|
||||||
|
keyCode == KeyEvent.KEYCODE_CAMERA ||
|
||||||
|
keyCode == KeyEvent.KEYCODE_ZOOM_IN ||
|
||||||
|
keyCode == KeyEvent.KEYCODE_ZOOM_OUT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getWindow().superDispatchKeyEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: REMOVE LATER, temporary launchers support?
|
||||||
|
@Override
|
||||||
|
protected String[] getArguments() {
|
||||||
|
String gamedir = getIntent().getStringExtra("gamedir");
|
||||||
|
if (gamedir == null) gamedir = "valve";
|
||||||
|
nativeSetenv("XASH3D_GAME", gamedir);
|
||||||
|
|
||||||
|
String gamelibdir = getIntent().getStringExtra("gamelibdir");
|
||||||
|
if (gamelibdir != null) nativeSetenv("XASH3D_GAMELIBDIR", gamelibdir);
|
||||||
|
|
||||||
|
String pakfile = getIntent().getStringExtra("pakfile");
|
||||||
|
if (pakfile != null) nativeSetenv("XASH3D_EXTRAS_PAK2", pakfile);
|
||||||
|
|
||||||
|
mUseVolumeKeys = getIntent().getBooleanExtra("usevolume", false);
|
||||||
|
mPackageName = getIntent().getStringExtra("package");
|
||||||
|
|
||||||
|
String[] env = getIntent().getStringArrayExtra("env");
|
||||||
|
if (env != null) {
|
||||||
|
for (int i = 0; i < env.length; i += 2)
|
||||||
|
nativeSetenv(env[i], env[i + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
String argv = getIntent().getStringExtra("argv");
|
||||||
|
if (argv == null) argv = "-console -log";
|
||||||
|
return argv.split(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,253 @@
|
|||||||
|
package su.xash.engine;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.content.res.AssetFileDescriptor;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.MatrixCursor;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.CancellationSignal;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.provider.DocumentsContract.Document;
|
||||||
|
import android.provider.DocumentsContract.Root;
|
||||||
|
import android.provider.DocumentsProvider;
|
||||||
|
import android.webkit.MimeTypeMap;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||||
|
public class XashDocumentsProvider extends DocumentsProvider {
|
||||||
|
private static final String ALL_MIME_TYPES = "*/*";
|
||||||
|
private File mRootDir;
|
||||||
|
|
||||||
|
private static final String TAG = "XashDocumentsProvider";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreate() {
|
||||||
|
mRootDir = getContext().getExternalFilesDir(null);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String[] DEFAULT_ROOT_PROJECTION = new String[]{Root.COLUMN_ROOT_ID,
|
||||||
|
Root.COLUMN_MIME_TYPES,
|
||||||
|
Root.COLUMN_FLAGS,
|
||||||
|
Root.COLUMN_ICON,
|
||||||
|
Root.COLUMN_TITLE,
|
||||||
|
Root.COLUMN_SUMMARY,
|
||||||
|
Root.COLUMN_DOCUMENT_ID,
|
||||||
|
Root.COLUMN_AVAILABLE_BYTES};
|
||||||
|
|
||||||
|
private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[]{Document.COLUMN_DOCUMENT_ID,
|
||||||
|
Document.COLUMN_MIME_TYPE,
|
||||||
|
Document.COLUMN_DISPLAY_NAME,
|
||||||
|
Document.COLUMN_LAST_MODIFIED,
|
||||||
|
Document.COLUMN_FLAGS,
|
||||||
|
Document.COLUMN_SIZE};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cursor queryRoots(String[] projection) {
|
||||||
|
final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_ROOT_PROJECTION);
|
||||||
|
|
||||||
|
final String appName = getContext().getString(R.string.app_name);
|
||||||
|
final String docId = getDocIdForFile(mRootDir);
|
||||||
|
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_SEARCH;
|
||||||
|
} else {
|
||||||
|
flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD;
|
||||||
|
}
|
||||||
|
|
||||||
|
final MatrixCursor.RowBuilder row = result.newRow();
|
||||||
|
row.add(Root.COLUMN_ROOT_ID, docId);
|
||||||
|
row.add(Root.COLUMN_DOCUMENT_ID, docId);
|
||||||
|
row.add(Root.COLUMN_SUMMARY, null);
|
||||||
|
row.add(Root.COLUMN_FLAGS, flags);
|
||||||
|
row.add(Root.COLUMN_TITLE, appName);
|
||||||
|
row.add(Root.COLUMN_MIME_TYPES, ALL_MIME_TYPES);
|
||||||
|
row.add(Root.COLUMN_AVAILABLE_BYTES, mRootDir.getFreeSpace());
|
||||||
|
row.add(Root.COLUMN_ICON, R.mipmap.ic_launcher);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cursor queryDocument(String documentId, String[] projection) throws FileNotFoundException {
|
||||||
|
final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);
|
||||||
|
|
||||||
|
includeFile(result, documentId, null);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cursor queryChildDocuments(String parentDocumentId, String[] projection, String sortOrder) throws FileNotFoundException {
|
||||||
|
final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);
|
||||||
|
|
||||||
|
final File parent = getFileForDocId(parentDocumentId);
|
||||||
|
final File[] filesList = parent.listFiles();
|
||||||
|
|
||||||
|
if (filesList != null) {
|
||||||
|
for (File file : filesList) {
|
||||||
|
includeFile(result, null, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParcelFileDescriptor openDocument(final String documentId, String mode, CancellationSignal signal) throws FileNotFoundException {
|
||||||
|
final File file = getFileForDocId(documentId);
|
||||||
|
|
||||||
|
final int accessMode = ParcelFileDescriptor.parseMode(mode);
|
||||||
|
|
||||||
|
return ParcelFileDescriptor.open(file, accessMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AssetFileDescriptor openDocumentThumbnail(String documentId, Point sizeHint, CancellationSignal signal) throws FileNotFoundException {
|
||||||
|
final File file = getFileForDocId(documentId);
|
||||||
|
|
||||||
|
final ParcelFileDescriptor pfd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||||
|
|
||||||
|
return new AssetFileDescriptor(pfd, 0, file.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String createDocument(String parentDocumentId, String mimeType, String displayName) throws FileNotFoundException {
|
||||||
|
File newFile = new File(parentDocumentId, displayName);
|
||||||
|
|
||||||
|
int noConflictId = 1;
|
||||||
|
|
||||||
|
while (newFile.exists()) {
|
||||||
|
newFile = new File(parentDocumentId, displayName + " (" + noConflictId++ + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
boolean succeeded;
|
||||||
|
|
||||||
|
if (Document.MIME_TYPE_DIR.equals(mimeType)) {
|
||||||
|
succeeded = newFile.mkdir();
|
||||||
|
} else {
|
||||||
|
succeeded = newFile.createNewFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!succeeded) {
|
||||||
|
throw new FileNotFoundException("Failed to create document with id " + newFile.getPath());
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new FileNotFoundException("Failed to create document with id " + newFile.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
return newFile.getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteDocument(String documentId) throws FileNotFoundException {
|
||||||
|
File file = getFileForDocId(documentId);
|
||||||
|
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
if (!deleteDirectory(file)) {
|
||||||
|
throw new FileNotFoundException("Failed to delete document with id " + documentId);
|
||||||
|
}
|
||||||
|
} else if (!file.delete()) {
|
||||||
|
throw new FileNotFoundException("Failed to delete document with id " + documentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDocumentType(String documentId) throws FileNotFoundException {
|
||||||
|
File file = getFileForDocId(documentId);
|
||||||
|
|
||||||
|
return getMimeType(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChildDocument(String parentDocumentId, String documentId) {
|
||||||
|
return documentId.startsWith(parentDocumentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static File getFileForDocId(String docId) throws FileNotFoundException {
|
||||||
|
final File f = new File(docId);
|
||||||
|
|
||||||
|
if (!f.exists()) throw new FileNotFoundException(f.getAbsolutePath() + " not found");
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getDocIdForFile(File file) {
|
||||||
|
return file.getAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getMimeType(File file) {
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
return Document.MIME_TYPE_DIR;
|
||||||
|
} else {
|
||||||
|
final String name = file.getName();
|
||||||
|
final int lastDot = name.lastIndexOf('.');
|
||||||
|
|
||||||
|
if (lastDot >= 0) {
|
||||||
|
final String extension = name.substring(lastDot + 1).toLowerCase();
|
||||||
|
final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
|
||||||
|
|
||||||
|
if (mime != null) return mime;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "application/octet-stream";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean deleteDirectory(File dir) {
|
||||||
|
final File[] allContents = dir.listFiles();
|
||||||
|
|
||||||
|
if (allContents != null) {
|
||||||
|
for (File file : allContents) {
|
||||||
|
deleteDirectory(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dir.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void includeFile(MatrixCursor result, String docId, File file) throws FileNotFoundException {
|
||||||
|
if (docId == null) {
|
||||||
|
docId = getDocIdForFile(file);
|
||||||
|
} else {
|
||||||
|
file = getFileForDocId(docId);
|
||||||
|
}
|
||||||
|
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
if (file.canWrite()) {
|
||||||
|
flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
|
||||||
|
}
|
||||||
|
} else if (file.canWrite()) {
|
||||||
|
flags |= Document.FLAG_SUPPORTS_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
File parentFile = file.getParentFile();
|
||||||
|
if (parentFile != null && parentFile.canWrite()) {
|
||||||
|
flags |= Document.FLAG_SUPPORTS_DELETE;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String displayName = file.getName();
|
||||||
|
final String mimeType = getMimeType(file);
|
||||||
|
|
||||||
|
if (mimeType.startsWith("image/")) {
|
||||||
|
flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
final MatrixCursor.RowBuilder row = result.newRow();
|
||||||
|
row.add(Document.COLUMN_DOCUMENT_ID, docId);
|
||||||
|
row.add(Document.COLUMN_DISPLAY_NAME, displayName);
|
||||||
|
row.add(Document.COLUMN_SIZE, file.length());
|
||||||
|
row.add(Document.COLUMN_MIME_TYPE, mimeType);
|
||||||
|
row.add(Document.COLUMN_LAST_MODIFIED, file.lastModified());
|
||||||
|
row.add(Document.COLUMN_FLAGS, flags);
|
||||||
|
row.add(Document.COLUMN_ICON, R.mipmap.ic_launcher);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package su.xash.engine.adapters
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.navigation.findNavController
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import su.xash.engine.R
|
||||||
|
import su.xash.engine.databinding.CardGameBinding
|
||||||
|
import su.xash.engine.model.Game
|
||||||
|
import su.xash.engine.ui.library.LibraryViewModel
|
||||||
|
|
||||||
|
|
||||||
|
class GameAdapter(private val libraryViewModel: LibraryViewModel) :
|
||||||
|
ListAdapter<Game, GameAdapter.GameViewHolder>(DiffCallback()) {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GameAdapter.GameViewHolder {
|
||||||
|
val binding = CardGameBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
|
return GameViewHolder(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: GameAdapter.GameViewHolder, position: Int) {
|
||||||
|
return holder.bind(getItem(position))
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DiffCallback : DiffUtil.ItemCallback<Game>() {
|
||||||
|
override fun areItemsTheSame(oldItem: Game, newItem: Game): Boolean {
|
||||||
|
return oldItem.basedir.name == newItem.basedir.name
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: Game, newItem: Game): Boolean {
|
||||||
|
return oldItem.basedir.name == newItem.basedir.name && oldItem.installed == newItem.installed
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class GameViewHolder(val binding: CardGameBinding) :
|
||||||
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
|
fun bind(game: Game) {
|
||||||
|
binding.apply {
|
||||||
|
gameTitle.text = game.title
|
||||||
|
|
||||||
|
if (game.icon != null) {
|
||||||
|
gameIcon.setImageBitmap(game.icon)
|
||||||
|
} else {
|
||||||
|
gameIcon.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
if (game.cover != null) {
|
||||||
|
gameCover.setImageBitmap(game.cover)
|
||||||
|
} else {
|
||||||
|
gameCover.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!game.installed) {
|
||||||
|
launchButton.visibility = View.GONE
|
||||||
|
settingsButton.visibility = View.GONE
|
||||||
|
progressIndicator.visibility = View.VISIBLE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
settingsButton.setOnClickListener {
|
||||||
|
libraryViewModel.setSelectedGame(game)
|
||||||
|
it.findNavController()
|
||||||
|
.navigate(R.id.action_libraryFragment_to_gameSettingsFragment)
|
||||||
|
}
|
||||||
|
|
||||||
|
root.setOnClickListener { libraryViewModel.startEngine(it.context, game) }
|
||||||
|
launchButton.setOnClickListener {
|
||||||
|
libraryViewModel.startEngine(it.context, game)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package su.xash.engine.model
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import androidx.documentfile.provider.DocumentFile
|
||||||
|
import su.xash.engine.util.TGAReader
|
||||||
|
import java.util.Scanner
|
||||||
|
|
||||||
|
|
||||||
|
object BackgroundBitmap {
|
||||||
|
private const val BACKGROUND_ROWS = 3
|
||||||
|
private const val BACKGROUND_COLUMNS = 4
|
||||||
|
private const val BACKGROUND_WIDTH = 800
|
||||||
|
private const val BACKGROUND_HEIGHT = 600
|
||||||
|
|
||||||
|
fun createBackground(ctx: Context, file: DocumentFile): Bitmap {
|
||||||
|
var bitmap =
|
||||||
|
Bitmap.createBitmap(BACKGROUND_WIDTH, BACKGROUND_HEIGHT, Bitmap.Config.ARGB_8888)
|
||||||
|
var canvas = Canvas(bitmap)
|
||||||
|
var x: Int
|
||||||
|
var y = 0
|
||||||
|
var width: Int
|
||||||
|
var height = 0
|
||||||
|
|
||||||
|
var bgLayout = file.findFile("resource")?.findFile("HD_BackgroundLayout.txt")
|
||||||
|
if (bgLayout == null) {
|
||||||
|
bgLayout = file.findFile("resource")?.findFile("BackgroundLayout.txt")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bgLayout == null) {
|
||||||
|
val dir = file.findFile("resource")?.findFile("background")
|
||||||
|
for (i in 0 until BACKGROUND_ROWS) {
|
||||||
|
x = 0
|
||||||
|
for (j in 0 until BACKGROUND_COLUMNS) {
|
||||||
|
val filename = "${BACKGROUND_WIDTH}_${i + 1}_${'a' + j}_loading.tga"
|
||||||
|
val bmpFile = dir?.findFile(filename)
|
||||||
|
val bmpImage = loadTga(ctx, bmpFile!!)
|
||||||
|
|
||||||
|
canvas.drawBitmap(bmpImage, x.toFloat(), y.toFloat(), null)
|
||||||
|
x += bmpImage.width
|
||||||
|
height = bmpImage.height
|
||||||
|
|
||||||
|
}
|
||||||
|
y += height
|
||||||
|
}
|
||||||
|
return bitmap
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.contentResolver.openInputStream(bgLayout.uri).use { inputStream ->
|
||||||
|
Scanner(inputStream).use { scanner ->
|
||||||
|
while (scanner.hasNext()) {
|
||||||
|
when (val str = scanner.next()) {
|
||||||
|
"resolution" -> {
|
||||||
|
width = scanner.nextInt()
|
||||||
|
height = scanner.nextInt()
|
||||||
|
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||||||
|
canvas = Canvas(bitmap)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
var bmpFile = file
|
||||||
|
str.split("/").forEach { bmpFile = bmpFile.findFile(it)!! }
|
||||||
|
//skip
|
||||||
|
scanner.next()
|
||||||
|
x = scanner.nextInt()
|
||||||
|
y = scanner.nextInt()
|
||||||
|
val bmp = loadTga(ctx, bmpFile)
|
||||||
|
canvas.drawBitmap(bmp, x.toFloat(), y.toFloat(), null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bitmap
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadTga(ctx: Context, file: DocumentFile): Bitmap {
|
||||||
|
ctx.contentResolver.openInputStream(file.uri).use {
|
||||||
|
val buffer = it?.readBytes()
|
||||||
|
val pixels = TGAReader.read(buffer, TGAReader.ARGB)
|
||||||
|
|
||||||
|
val width = TGAReader.getWidth(buffer)
|
||||||
|
val height = TGAReader.getHeight(buffer)
|
||||||
|
|
||||||
|
return Bitmap.createBitmap(pixels, 0, width, width, height, Bitmap.Config.ARGB_8888)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
133
android/app/src/main/java/su/xash/engine/model/Game.kt
Normal file
133
android/app/src/main/java/su/xash/engine/model/Game.kt
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
package su.xash.engine.model
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageInfo
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.net.Uri
|
||||||
|
import android.provider.MediaStore
|
||||||
|
import androidx.documentfile.provider.DocumentFile
|
||||||
|
import su.xash.engine.XashActivity
|
||||||
|
|
||||||
|
|
||||||
|
class Game(val ctx: Context, val basedir: DocumentFile, var installed: Boolean = true) {
|
||||||
|
private var iconName = "game.ico"
|
||||||
|
var title = "Unknown Game"
|
||||||
|
var icon: Bitmap? = null
|
||||||
|
var cover: Bitmap? = null
|
||||||
|
|
||||||
|
private val pref = ctx.getSharedPreferences(basedir.name, Context.MODE_PRIVATE)
|
||||||
|
|
||||||
|
init {
|
||||||
|
basedir.findFile("gameinfo.txt")?.let {
|
||||||
|
parseGameInfo(it)
|
||||||
|
} ?: basedir.findFile("liblist.gam")?.let { parseGameInfo(it) }
|
||||||
|
|
||||||
|
basedir.findFile(iconName)
|
||||||
|
?.let { icon = MediaStore.Images.Media.getBitmap(ctx.contentResolver, it.uri) }
|
||||||
|
|
||||||
|
try {
|
||||||
|
cover = BackgroundBitmap.createBackground(ctx, basedir)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startEngine(ctx: Context) {
|
||||||
|
ctx.startActivity(Intent(ctx, XashActivity::class.java).apply {
|
||||||
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||||
|
putExtra("gamedir", basedir.name)
|
||||||
|
putExtra("argv", pref.getString("arguments", "-console -log"))
|
||||||
|
putExtra("usevolume", pref.getBoolean("use_volume_buttons", false))
|
||||||
|
//.putExtra("gamelibdir", getGameLibDir(context))
|
||||||
|
//.putExtra("package", getPackageName()) }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseGameInfo(file: DocumentFile) {
|
||||||
|
ctx.contentResolver.openInputStream(file.uri).use { inputStream ->
|
||||||
|
inputStream?.bufferedReader().use { reader ->
|
||||||
|
reader?.forEachLine {
|
||||||
|
val tokens = it.split("\\s+".toRegex(), limit = 2)
|
||||||
|
if (tokens.size >= 2) {
|
||||||
|
val k = tokens[0]
|
||||||
|
val v = tokens[1].trim('"')
|
||||||
|
|
||||||
|
if (k == "title" || k == "game") title = v
|
||||||
|
if (k == "icon") iconName = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getPackageName(): String? {
|
||||||
|
// return if (mDbEntry != null) {
|
||||||
|
// mDbEntry.getPackageName()
|
||||||
|
// } else null
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getGameLibDir(ctx: Context): String? {
|
||||||
|
val pkgName = getPackageName()
|
||||||
|
if (pkgName != null) {
|
||||||
|
val pkgInfo: PackageInfo = try {
|
||||||
|
ctx.packageManager.getPackageInfo(pkgName, 0)
|
||||||
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
ctx.startActivity(
|
||||||
|
Intent(
|
||||||
|
Intent.ACTION_VIEW, Uri.parse("market://details?id=$pkgName")
|
||||||
|
).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||||
|
)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return pkgInfo.applicationInfo.nativeLibraryDir
|
||||||
|
}
|
||||||
|
return ctx.applicationInfo.nativeLibraryDir
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun getGames(ctx: Context, file: DocumentFile): List<Game> {
|
||||||
|
val games = mutableListOf<Game>()
|
||||||
|
|
||||||
|
if (checkIfGamedir(file)) {
|
||||||
|
games.add(Game(ctx, file))
|
||||||
|
} else {
|
||||||
|
file.listFiles().forEach {
|
||||||
|
if (it.isDirectory) {
|
||||||
|
if (checkIfGamedir(it)) {
|
||||||
|
games.add(Game(ctx, it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return games
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkIfGamedir(file: DocumentFile): Boolean {
|
||||||
|
// exclude unfinished downloads
|
||||||
|
if (file.name?.startsWith('.') == true)
|
||||||
|
return false
|
||||||
|
|
||||||
|
file.findFile("liblist.gam")?.let { return true }
|
||||||
|
file.findFile("gameinfo.txt")?.let { return true }
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intent intent = new Intent("su.xash.engine.MOD");
|
||||||
|
// for (ResolveInfo info : context.getPackageManager()
|
||||||
|
// .queryIntentActivities(intent, PackageManager.GET_META_DATA)) {
|
||||||
|
// String packageName = info.activityInfo.applicationInfo.packageName;
|
||||||
|
// String gameDir = info.activityInfo.applicationInfo.metaData.getString(
|
||||||
|
// "su.xash.engine.gamedir");
|
||||||
|
// Log.d(TAG, "package = " + packageName + " gamedir = " + gameDir);
|
||||||
|
// }
|
||||||
|
|
||||||
|
//public void startEngine(Context context) {
|
||||||
|
// context.startActivity(new Intent(context, XashActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP).putExtra("gamedir", getGameDir()).putExtra("argv", getArguments()).putExtra("usevolume", getVolumeState()).putExtra("gamelibdir", getGameLibDir(context)).putExtra("package", getPackageName()));
|
||||||
|
//}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package su.xash.engine.model
|
||||||
|
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
class ModDatabase(inputStream: InputStream) {
|
||||||
|
val entries = mutableListOf<Entry>()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val VERSION = 1
|
||||||
|
|
||||||
|
fun getFilename(): String {
|
||||||
|
return "v${VERSION}.json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
inputStream.bufferedReader().use {
|
||||||
|
val jsonArray = JSONArray(it.readText())
|
||||||
|
|
||||||
|
for (i in 0..<jsonArray.length()) {
|
||||||
|
entries.add(Entry(jsonArray.getJSONObject(i)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getByGameDir(gamedir: String): Entry? {
|
||||||
|
return entries.filter { it.gamedir.equals(gamedir) }.firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inner class Entry(jsonObject: JSONObject) {
|
||||||
|
var name: String? = null
|
||||||
|
var appid: Int? = null
|
||||||
|
var gamedir: String? = null
|
||||||
|
|
||||||
|
// TODO Depots
|
||||||
|
var pkgname: String? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (jsonObject.has("name")) {
|
||||||
|
name = jsonObject.getString("name");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonObject.has("app_id")) {
|
||||||
|
appid = jsonObject.getInt("app_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonObject.has("gamedir")) {
|
||||||
|
gamedir = jsonObject.getString("gamedir");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonObject.has("package_name")) {
|
||||||
|
pkgname = jsonObject.getString("package_name");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package su.xash.engine.ui.library
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.MenuProvider
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import su.xash.engine.R
|
||||||
|
import su.xash.engine.adapters.GameAdapter
|
||||||
|
import su.xash.engine.databinding.FragmentLibraryBinding
|
||||||
|
|
||||||
|
class LibraryFragment : Fragment(), MenuProvider {
|
||||||
|
private var _binding: FragmentLibraryBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
private val libraryViewModel: LibraryViewModel by activityViewModels()
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
_binding = FragmentLibraryBinding.inflate(inflater, container, false)
|
||||||
|
|
||||||
|
val adapter = GameAdapter(libraryViewModel)
|
||||||
|
binding.gamesList.adapter = adapter
|
||||||
|
|
||||||
|
requireActivity().addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED)
|
||||||
|
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
binding.swipeRefresh.setOnRefreshListener { libraryViewModel.reloadGames(requireContext()) }
|
||||||
|
|
||||||
|
libraryViewModel.isReloading.observe(viewLifecycleOwner) {
|
||||||
|
binding.swipeRefresh.isRefreshing = it
|
||||||
|
}
|
||||||
|
|
||||||
|
libraryViewModel.installedGames.observe(viewLifecycleOwner) {
|
||||||
|
(binding.gamesList.adapter as GameAdapter).submitList(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
libraryViewModel.workInfos.observe(viewLifecycleOwner) {
|
||||||
|
libraryViewModel.refreshDownloads(requireContext())
|
||||||
|
}
|
||||||
|
|
||||||
|
libraryViewModel.downloads.observe(viewLifecycleOwner) {
|
||||||
|
libraryViewModel.reloadGames(requireContext())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
||||||
|
menuInflater.inflate(R.menu.menu_library, menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
|
||||||
|
when (menuItem.itemId) {
|
||||||
|
R.id.action_browse -> {
|
||||||
|
startActivity(
|
||||||
|
Intent(Intent.ACTION_VIEW).setDataAndType(
|
||||||
|
null, "vnd.android.document/directory"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.action_install -> {
|
||||||
|
findNavController().navigate(R.id.action_libraryFragment_to_setupFragment)
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.action_settings -> {
|
||||||
|
findNavController().navigate(R.id.action_libraryFragment_to_appSettingsFragment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
package su.xash.engine.ui.library
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.net.Uri
|
||||||
|
import androidx.documentfile.provider.DocumentFile
|
||||||
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import androidx.work.Data
|
||||||
|
import androidx.work.OneTimeWorkRequestBuilder
|
||||||
|
import androidx.work.OutOfQuotaPolicy
|
||||||
|
import androidx.work.WorkInfo
|
||||||
|
import androidx.work.WorkManager
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import su.xash.engine.model.Game
|
||||||
|
import su.xash.engine.model.ModDatabase
|
||||||
|
import su.xash.engine.workers.FileCopyWorker
|
||||||
|
import su.xash.engine.workers.KEY_FILE_URI
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
const val TAG_INSTALL = "TAG_INSTALL"
|
||||||
|
|
||||||
|
class LibraryViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
|
val installedGames: LiveData<List<Game>> get() = _installedGames
|
||||||
|
private val _installedGames = MutableLiveData(emptyList<Game>())
|
||||||
|
|
||||||
|
val downloads: LiveData<List<Game>> get() = _downloads
|
||||||
|
private val _downloads = MutableLiveData(emptyList<Game>())
|
||||||
|
|
||||||
|
val isReloading: LiveData<Boolean> get() = _isReloading
|
||||||
|
private val _isReloading = MutableLiveData(false)
|
||||||
|
|
||||||
|
private val workManager = WorkManager.getInstance(application.applicationContext)
|
||||||
|
val workInfos: LiveData<List<WorkInfo>> = workManager.getWorkInfosByTagLiveData(TAG_INSTALL)
|
||||||
|
|
||||||
|
val selectedItem: LiveData<Game> get() = _selectedItem
|
||||||
|
private val _selectedItem = MutableLiveData<Game>()
|
||||||
|
|
||||||
|
val appPreferences = application.getSharedPreferences("app_preferences", Context.MODE_PRIVATE)
|
||||||
|
val modDb: ModDatabase
|
||||||
|
|
||||||
|
init {
|
||||||
|
modDb = application.assets.open(ModDatabase.getFilename()).use { ModDatabase(it) }
|
||||||
|
reloadGames(application.applicationContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reloadGames(ctx: Context) {
|
||||||
|
if (isReloading.value == true) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_isReloading.value = true
|
||||||
|
|
||||||
|
viewModelScope.launch {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
val games = mutableListOf<Game>()
|
||||||
|
val root = DocumentFile.fromFile(ctx.getExternalFilesDir(null)!!)
|
||||||
|
|
||||||
|
val installedGames = Game.getGames(ctx, root)
|
||||||
|
.filter { p -> _downloads.value?.any { p.basedir.name == it.basedir.name } == false }
|
||||||
|
|
||||||
|
games.addAll(installedGames)
|
||||||
|
downloads.value?.let { games.addAll(it) }
|
||||||
|
|
||||||
|
_installedGames.postValue(games)
|
||||||
|
_isReloading.postValue(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun refreshDownloads(ctx: Context) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
val games = mutableListOf<Game>()
|
||||||
|
|
||||||
|
workInfos.value?.filter {
|
||||||
|
it.state == WorkInfo.State.RUNNING && !it.progress.getString(FileCopyWorker.Input)
|
||||||
|
.isNullOrEmpty()
|
||||||
|
}?.forEach {
|
||||||
|
val uri = Uri.parse(it.progress.getString(FileCopyWorker.Input))
|
||||||
|
val file = DocumentFile.fromTreeUri(ctx, uri)
|
||||||
|
games.addAll(Game.getGames(ctx, file!!))
|
||||||
|
games.forEach { g -> g.installed = false }
|
||||||
|
}
|
||||||
|
|
||||||
|
_downloads.postValue(games)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun installGame(uri: Uri) {
|
||||||
|
val data = Data.Builder().putString(KEY_FILE_URI, uri.toString()).build()
|
||||||
|
val request = OneTimeWorkRequestBuilder<FileCopyWorker>().run {
|
||||||
|
setInputData(data)
|
||||||
|
addTag(TAG_INSTALL)
|
||||||
|
build()
|
||||||
|
}
|
||||||
|
workManager.enqueue(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setSelectedGame(game: Game) {
|
||||||
|
_selectedItem.value = game
|
||||||
|
}
|
||||||
|
|
||||||
|
fun uninstallGame(game: Game) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
game.installed = false
|
||||||
|
game.basedir.delete()
|
||||||
|
_installedGames.postValue(_installedGames.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startEngine(ctx: Context, game: Game) {
|
||||||
|
game.startEngine(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package su.xash.engine.ui.settings
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import su.xash.engine.databinding.FragmentAppSettingsBinding
|
||||||
|
|
||||||
|
class AppSettingsFragment : Fragment() {
|
||||||
|
private var _binding: FragmentAppSettingsBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
_binding = FragmentAppSettingsBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
childFragmentManager.beginTransaction()
|
||||||
|
.add(binding.settingsFragment.id, AppSettingsPreferenceFragment()).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package su.xash.engine.ui.settings
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
|
import su.xash.engine.R
|
||||||
|
|
||||||
|
class AppSettingsPreferenceFragment() : PreferenceFragmentCompat() {
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
preferenceManager.sharedPreferencesName = "app_preferences";
|
||||||
|
setPreferencesFromResource(R.xml.app_preferences, rootKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package su.xash.engine.ui.settings
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import su.xash.engine.R
|
||||||
|
import su.xash.engine.databinding.FragmentGameSettingsBinding
|
||||||
|
import su.xash.engine.ui.library.LibraryViewModel
|
||||||
|
|
||||||
|
class GameSettingsFragment : Fragment() {
|
||||||
|
private var _binding: FragmentGameSettingsBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
private val libraryViewModel: LibraryViewModel by activityViewModels()
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
_binding = FragmentGameSettingsBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
val game = libraryViewModel.selectedItem.value!!
|
||||||
|
|
||||||
|
binding.gameCard.apply {
|
||||||
|
gameTitle.text = game.title
|
||||||
|
|
||||||
|
if (game.icon != null) {
|
||||||
|
gameIcon.setImageBitmap(game.icon)
|
||||||
|
} else {
|
||||||
|
gameIcon.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
if (game.cover != null) {
|
||||||
|
gameCover.setImageBitmap(game.cover)
|
||||||
|
} else {
|
||||||
|
gameCover.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonsContainer.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
childFragmentManager.beginTransaction()
|
||||||
|
.add(binding.settingsFragment.id, GameSettingsPreferenceFragment(game))
|
||||||
|
.commit();
|
||||||
|
|
||||||
|
binding.bottomNavigation.menu.findItem(R.id.action_uninstall).setOnMenuItemClickListener {
|
||||||
|
libraryViewModel.uninstallGame(game)
|
||||||
|
findNavController().popBackStack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package su.xash.engine.ui.settings
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.preference.ListPreference
|
||||||
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
|
import androidx.preference.SwitchPreferenceCompat
|
||||||
|
import su.xash.engine.R
|
||||||
|
import su.xash.engine.model.Game
|
||||||
|
|
||||||
|
class GameSettingsPreferenceFragment(val game: Game) : PreferenceFragmentCompat() {
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
preferenceManager.sharedPreferencesName = game.basedir.name;
|
||||||
|
setPreferencesFromResource(R.xml.game_preferences, rootKey);
|
||||||
|
|
||||||
|
val packageList = findPreference<ListPreference>("package_name")!!
|
||||||
|
packageList.entries = arrayOf(getString(R.string.app_name))
|
||||||
|
packageList.entryValues = arrayOf(requireContext().packageName)
|
||||||
|
|
||||||
|
if (packageList.value == null) {
|
||||||
|
packageList.setValueIndex(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
val separatePackages = findPreference<SwitchPreferenceCompat>("separate_libraries")!!
|
||||||
|
val clientPackage = findPreference<ListPreference>("client_package")!!
|
||||||
|
val serverPackage = findPreference<ListPreference>("server_package")!!
|
||||||
|
separatePackages.setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
if (newValue == true) {
|
||||||
|
packageList.isVisible = false
|
||||||
|
clientPackage.isVisible = true
|
||||||
|
serverPackage.isVisible = true
|
||||||
|
} else {
|
||||||
|
packageList.isVisible = true
|
||||||
|
clientPackage.isVisible = false
|
||||||
|
serverPackage.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package su.xash.engine.ui.setup
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
|
import su.xash.engine.databinding.FragmentSetupBinding
|
||||||
|
import su.xash.engine.ui.setup.pages.LocationPageFragment
|
||||||
|
import su.xash.engine.ui.setup.pages.WelcomePageFragment
|
||||||
|
|
||||||
|
class SetupFragment : Fragment() {
|
||||||
|
private var _binding: FragmentSetupBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
private val setupViewModel: SetupViewModel by activityViewModels()
|
||||||
|
|
||||||
|
private lateinit var setupPageAdapter: SetupPageAdapter
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
_binding = FragmentSetupBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
setupPageAdapter = SetupPageAdapter(this)
|
||||||
|
binding.viewPager.isUserInputEnabled = false
|
||||||
|
binding.viewPager.adapter = setupPageAdapter
|
||||||
|
|
||||||
|
setupViewModel.pageNumber.observe(viewLifecycleOwner) {
|
||||||
|
binding.viewPager.setCurrentItem(it, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SetupPageAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
|
||||||
|
val pages = listOf(WelcomePageFragment(), LocationPageFragment())
|
||||||
|
override fun getItemCount(): Int = 2
|
||||||
|
override fun createFragment(position: Int): Fragment = pages[position]
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package su.xash.engine.ui.setup
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import android.net.Uri
|
||||||
|
import androidx.documentfile.provider.DocumentFile
|
||||||
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import su.xash.engine.MainApplication
|
||||||
|
import su.xash.engine.model.Game
|
||||||
|
|
||||||
|
class SetupViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
|
val pageNumber: LiveData<Int> get() = _pageNumber
|
||||||
|
private val _pageNumber = MutableLiveData(0)
|
||||||
|
|
||||||
|
fun checkIfGameDir(uri: Uri): Boolean {
|
||||||
|
val ctx = getApplication<MainApplication>().applicationContext
|
||||||
|
val file = DocumentFile.fromTreeUri(ctx, uri)!!
|
||||||
|
return Game.checkIfGamedir(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setPageNumber(pos: Int) {
|
||||||
|
_pageNumber.value = pos
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package su.xash.engine.ui.setup.pages
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import su.xash.engine.R
|
||||||
|
import su.xash.engine.databinding.PageLocationBinding
|
||||||
|
import su.xash.engine.ui.library.LibraryViewModel
|
||||||
|
import su.xash.engine.ui.setup.SetupViewModel
|
||||||
|
|
||||||
|
class LocationPageFragment : Fragment() {
|
||||||
|
private var _binding: PageLocationBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
private val setupViewModel: SetupViewModel by activityViewModels()
|
||||||
|
private val libraryViewModel: LibraryViewModel by activityViewModels()
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
_binding = PageLocationBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
binding.pageButton.setOnClickListener {
|
||||||
|
getGamesDirectory.launch(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
|
}
|
||||||
|
|
||||||
|
private val getGamesDirectory =
|
||||||
|
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) {
|
||||||
|
it?.let {
|
||||||
|
if (!setupViewModel.checkIfGameDir(it)) {
|
||||||
|
MaterialAlertDialogBuilder(requireContext()).apply {
|
||||||
|
setTitle(R.string.error)
|
||||||
|
setMessage(R.string.setup_location_empty)
|
||||||
|
setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() }
|
||||||
|
show()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
requireContext().contentResolver.takePersistableUriPermission(it, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
|
libraryViewModel.installGame(it)
|
||||||
|
findNavController().navigate(R.id.action_setupFragment_to_libraryFragment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package su.xash.engine.ui.setup.pages
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import su.xash.engine.databinding.PageWelcomeBinding
|
||||||
|
import su.xash.engine.ui.setup.SetupViewModel
|
||||||
|
|
||||||
|
class WelcomePageFragment : Fragment() {
|
||||||
|
private var _binding: PageWelcomeBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
private val setupViewModel: SetupViewModel by activityViewModels()
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
_binding = PageWelcomeBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
binding.pageButton.setOnClickListener {
|
||||||
|
setupViewModel.setPageNumber(1)
|
||||||
|
}
|
||||||
|
setupViewModel.setPageNumber(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
|
}
|
||||||
|
}
|
||||||
589
android/app/src/main/java/su/xash/engine/util/TGAReader.java
Normal file
589
android/app/src/main/java/su/xash/engine/util/TGAReader.java
Normal file
@@ -0,0 +1,589 @@
|
|||||||
|
/**
|
||||||
|
* TGAReader.java
|
||||||
|
* <p>
|
||||||
|
* Copyright (c) 2014 Kenji Sasaki
|
||||||
|
* Released under the MIT license.
|
||||||
|
* https://github.com/npedotnet/TGAReader/blob/master/LICENSE
|
||||||
|
* <p>
|
||||||
|
* English document
|
||||||
|
* https://github.com/npedotnet/TGAReader/blob/master/README.md
|
||||||
|
* <p>
|
||||||
|
* Japanese document
|
||||||
|
* http://3dtech.jp/wiki/index.php?TGAReader
|
||||||
|
*/
|
||||||
|
|
||||||
|
package su.xash.engine.util;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public final class TGAReader {
|
||||||
|
|
||||||
|
public static final Order ARGB = new Order(16, 8, 0, 24);
|
||||||
|
public static final Order ABGR = new Order(0, 8, 16, 24);
|
||||||
|
|
||||||
|
public static int getWidth(byte[] buffer) {
|
||||||
|
return (buffer[12] & 0xFF) | (buffer[13] & 0xFF) << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getHeight(byte[] buffer) {
|
||||||
|
return (buffer[14] & 0xFF) | (buffer[15] & 0xFF) << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] read(byte[] buffer, Order order) throws IOException {
|
||||||
|
|
||||||
|
// header
|
||||||
|
// int idFieldLength = buffer[0] & 0xFF;
|
||||||
|
// int colormapType = buffer[1] & 0xFF;
|
||||||
|
int type = buffer[2] & 0xFF;
|
||||||
|
int colormapOrigin = (buffer[3] & 0xFF) | (buffer[4] & 0xFF) << 8;
|
||||||
|
int colormapLength = (buffer[5] & 0xFF) | (buffer[6] & 0xFF) << 8;
|
||||||
|
int colormapDepth = buffer[7] & 0xFF;
|
||||||
|
// int originX = (buffer[8] & 0xFF) | (buffer[9] & 0xFF) << 8; // unsupported
|
||||||
|
// int originY = (buffer[10] & 0xFF) | (buffer[11] & 0xFF) << 8; // unsupported
|
||||||
|
int width = getWidth(buffer);
|
||||||
|
int height = getHeight(buffer);
|
||||||
|
int depth = buffer[16] & 0xFF;
|
||||||
|
int descriptor = buffer[17] & 0xFF;
|
||||||
|
|
||||||
|
int[] pixels;
|
||||||
|
|
||||||
|
// data
|
||||||
|
switch (type) {
|
||||||
|
case COLORMAP: {
|
||||||
|
int imageDataOffset = 18 + (colormapDepth / 8) * colormapLength;
|
||||||
|
pixels = createPixelsFromColormap(width, height, colormapDepth, buffer, imageDataOffset, buffer, colormapOrigin, descriptor, order);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RGB:
|
||||||
|
pixels = createPixelsFromRGB(width, height, depth, buffer, 18, descriptor, order);
|
||||||
|
break;
|
||||||
|
case GRAYSCALE:
|
||||||
|
pixels = createPixelsFromGrayscale(width, height, depth, buffer, 18, descriptor, order);
|
||||||
|
break;
|
||||||
|
case COLORMAP_RLE: {
|
||||||
|
int imageDataOffset = 18 + (colormapDepth / 8) * colormapLength;
|
||||||
|
byte[] decodeBuffer = decodeRLE(width, height, depth, buffer, imageDataOffset);
|
||||||
|
pixels = createPixelsFromColormap(width, height, colormapDepth, decodeBuffer, 0, buffer, colormapOrigin, descriptor, order);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RGB_RLE: {
|
||||||
|
byte[] decodeBuffer = decodeRLE(width, height, depth, buffer, 18);
|
||||||
|
pixels = createPixelsFromRGB(width, height, depth, decodeBuffer, 0, descriptor, order);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GRAYSCALE_RLE: {
|
||||||
|
byte[] decodeBuffer = decodeRLE(width, height, depth, buffer, 18);
|
||||||
|
pixels = createPixelsFromGrayscale(width, height, depth, decodeBuffer, 0, descriptor, order);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IOException("Unsupported image type: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pixels;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int COLORMAP = 1;
|
||||||
|
private static final int RGB = 2;
|
||||||
|
private static final int GRAYSCALE = 3;
|
||||||
|
private static final int COLORMAP_RLE = 9;
|
||||||
|
private static final int RGB_RLE = 10;
|
||||||
|
private static final int GRAYSCALE_RLE = 11;
|
||||||
|
|
||||||
|
private static final int RIGHT_ORIGIN = 0x10;
|
||||||
|
private static final int UPPER_ORIGIN = 0x20;
|
||||||
|
|
||||||
|
private static byte[] decodeRLE(int width, int height, int depth, byte[] buffer, int offset) {
|
||||||
|
int elementCount = depth / 8;
|
||||||
|
byte[] elements = new byte[elementCount];
|
||||||
|
int decodeBufferLength = elementCount * width * height;
|
||||||
|
byte[] decodeBuffer = new byte[decodeBufferLength];
|
||||||
|
int decoded = 0;
|
||||||
|
while (decoded < decodeBufferLength) {
|
||||||
|
int packet = buffer[offset++] & 0xFF;
|
||||||
|
if ((packet & 0x80) != 0) { // RLE
|
||||||
|
for (int i = 0; i < elementCount; i++) {
|
||||||
|
elements[i] = buffer[offset++];
|
||||||
|
}
|
||||||
|
int count = (packet & 0x7F) + 1;
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
for (int j = 0; j < elementCount; j++) {
|
||||||
|
decodeBuffer[decoded++] = elements[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // RAW
|
||||||
|
int count = (packet + 1) * elementCount;
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
decodeBuffer[decoded++] = buffer[offset++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return decodeBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int[] createPixelsFromColormap(int width, int height, int depth, byte[] bytes, int offset, byte[] palette, int colormapOrigin, int descriptor, Order order) throws IOException {
|
||||||
|
int[] pixels;
|
||||||
|
int rs = order.redShift;
|
||||||
|
int gs = order.greenShift;
|
||||||
|
int bs = order.blueShift;
|
||||||
|
int as = order.alphaShift;
|
||||||
|
switch (depth) {
|
||||||
|
case 24:
|
||||||
|
pixels = new int[width * height];
|
||||||
|
if ((descriptor & RIGHT_ORIGIN) != 0) {
|
||||||
|
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||||
|
// UpperRight
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int colormapIndex = bytes[offset + width * i + j] &
|
||||||
|
0xFF - colormapOrigin;
|
||||||
|
int color = 0xFFFFFFFF;
|
||||||
|
if (colormapIndex >= 0) {
|
||||||
|
int index = 3 * colormapIndex + 18;
|
||||||
|
int b = palette[index] & 0xFF;
|
||||||
|
int g = palette[index + 1] & 0xFF;
|
||||||
|
int r = palette[index + 2] & 0xFF;
|
||||||
|
int a = 0xFF;
|
||||||
|
color = (r << rs) | (g << gs) | (b << bs) | (a << as);
|
||||||
|
}
|
||||||
|
pixels[width * i + (width - j - 1)] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// LowerRight
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int colormapIndex = bytes[offset + width * i + j] &
|
||||||
|
0xFF - colormapOrigin;
|
||||||
|
int color = 0xFFFFFFFF;
|
||||||
|
if (colormapIndex >= 0) {
|
||||||
|
int index = 3 * colormapIndex + 18;
|
||||||
|
int b = palette[index] & 0xFF;
|
||||||
|
int g = palette[index + 1] & 0xFF;
|
||||||
|
int r = palette[index + 2] & 0xFF;
|
||||||
|
int a = 0xFF;
|
||||||
|
color = (r << rs) | (g << gs) | (b << bs) | (a << as);
|
||||||
|
}
|
||||||
|
pixels[width * (height - i - 1) + (width - j - 1)] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||||
|
// UpperLeft
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int colormapIndex = bytes[offset + width * i + j] &
|
||||||
|
0xFF - colormapOrigin;
|
||||||
|
int color = 0xFFFFFFFF;
|
||||||
|
if (colormapIndex >= 0) {
|
||||||
|
int index = 3 * colormapIndex + 18;
|
||||||
|
int b = palette[index] & 0xFF;
|
||||||
|
int g = palette[index + 1] & 0xFF;
|
||||||
|
int r = palette[index + 2] & 0xFF;
|
||||||
|
int a = 0xFF;
|
||||||
|
color = (r << rs) | (g << gs) | (b << bs) | (a << as);
|
||||||
|
}
|
||||||
|
pixels[width * i + j] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// LowerLeft
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int colormapIndex = bytes[offset + width * i + j] &
|
||||||
|
0xFF - colormapOrigin;
|
||||||
|
int color = 0xFFFFFFFF;
|
||||||
|
if (colormapIndex >= 0) {
|
||||||
|
int index = 3 * colormapIndex + 18;
|
||||||
|
int b = palette[index] & 0xFF;
|
||||||
|
int g = palette[index + 1] & 0xFF;
|
||||||
|
int r = palette[index + 2] & 0xFF;
|
||||||
|
int a = 0xFF;
|
||||||
|
color = (r << rs) | (g << gs) | (b << bs) | (a << as);
|
||||||
|
}
|
||||||
|
pixels[width * (height - i - 1) + j] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
pixels = new int[width * height];
|
||||||
|
if ((descriptor & RIGHT_ORIGIN) != 0) {
|
||||||
|
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||||
|
// UpperRight
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int colormapIndex = bytes[offset + width * i + j] &
|
||||||
|
0xFF - colormapOrigin;
|
||||||
|
int color = 0xFFFFFFFF;
|
||||||
|
if (colormapIndex >= 0) {
|
||||||
|
int index = 4 * colormapIndex + 18;
|
||||||
|
int b = palette[index] & 0xFF;
|
||||||
|
int g = palette[index + 1] & 0xFF;
|
||||||
|
int r = palette[index + 2] & 0xFF;
|
||||||
|
int a = palette[index + 3] & 0xFF;
|
||||||
|
color = (r << rs) | (g << gs) | (b << bs) | (a << as);
|
||||||
|
}
|
||||||
|
pixels[width * i + (width - j - 1)] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// LowerRight
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int colormapIndex = bytes[offset + width * i + j] &
|
||||||
|
0xFF - colormapOrigin;
|
||||||
|
int color = 0xFFFFFFFF;
|
||||||
|
if (colormapIndex >= 0) {
|
||||||
|
int index = 4 * colormapIndex + 18;
|
||||||
|
int b = palette[index] & 0xFF;
|
||||||
|
int g = palette[index + 1] & 0xFF;
|
||||||
|
int r = palette[index + 2] & 0xFF;
|
||||||
|
int a = palette[index + 3] & 0xFF;
|
||||||
|
color = (r << rs) | (g << gs) | (b << bs) | (a << as);
|
||||||
|
}
|
||||||
|
pixels[width * (height - i - 1) + (width - j - 1)] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||||
|
// UpperLeft
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int colormapIndex = bytes[offset + width * i + j] &
|
||||||
|
0xFF - colormapOrigin;
|
||||||
|
int color = 0xFFFFFFFF;
|
||||||
|
if (colormapIndex >= 0) {
|
||||||
|
int index = 4 * colormapIndex + 18;
|
||||||
|
int b = palette[index] & 0xFF;
|
||||||
|
int g = palette[index + 1] & 0xFF;
|
||||||
|
int r = palette[index + 2] & 0xFF;
|
||||||
|
int a = palette[index + 3] & 0xFF;
|
||||||
|
color = (r << rs) | (g << gs) | (b << bs) | (a << as);
|
||||||
|
}
|
||||||
|
pixels[width * i + j] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// LowerLeft
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int colormapIndex = bytes[offset + width * i + j] &
|
||||||
|
0xFF - colormapOrigin;
|
||||||
|
int color = 0xFFFFFFFF;
|
||||||
|
if (colormapIndex >= 0) {
|
||||||
|
int index = 4 * colormapIndex + 18;
|
||||||
|
int b = palette[index] & 0xFF;
|
||||||
|
int g = palette[index + 1] & 0xFF;
|
||||||
|
int r = palette[index + 2] & 0xFF;
|
||||||
|
int a = palette[index + 3] & 0xFF;
|
||||||
|
color = (r << rs) | (g << gs) | (b << bs) | (a << as);
|
||||||
|
}
|
||||||
|
pixels[width * (height - i - 1) + j] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IOException("Unsupported depth:" + depth);
|
||||||
|
}
|
||||||
|
return pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int[] createPixelsFromRGB(int width, int height, int depth, byte[] bytes, int offset, int descriptor, Order order) throws IOException {
|
||||||
|
int[] pixels;
|
||||||
|
int rs = order.redShift;
|
||||||
|
int gs = order.greenShift;
|
||||||
|
int bs = order.blueShift;
|
||||||
|
int as = order.alphaShift;
|
||||||
|
switch (depth) {
|
||||||
|
case 24:
|
||||||
|
pixels = new int[width * height];
|
||||||
|
if ((descriptor & RIGHT_ORIGIN) != 0) {
|
||||||
|
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||||
|
// UpperRight
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int index = offset + 3 * width * i + 3 * j;
|
||||||
|
int b = bytes[index] & 0xFF;
|
||||||
|
int g = bytes[index + 1] & 0xFF;
|
||||||
|
int r = bytes[index + 2] & 0xFF;
|
||||||
|
int a = 0xFF;
|
||||||
|
pixels[width * i + (width - j - 1)] = (r << rs) |
|
||||||
|
(g << gs) |
|
||||||
|
(b << bs) |
|
||||||
|
(a << as);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// LowerRight
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int index = offset + 3 * width * i + 3 * j;
|
||||||
|
int b = bytes[index] & 0xFF;
|
||||||
|
int g = bytes[index + 1] & 0xFF;
|
||||||
|
int r = bytes[index + 2] & 0xFF;
|
||||||
|
int a = 0xFF;
|
||||||
|
pixels[width * (height - i - 1) + (width - j - 1)] = (r << rs) |
|
||||||
|
(g << gs) |
|
||||||
|
(b << bs) |
|
||||||
|
(a << as);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||||
|
// UpperLeft
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int index = offset + 3 * width * i + 3 * j;
|
||||||
|
int b = bytes[index] & 0xFF;
|
||||||
|
int g = bytes[index + 1] & 0xFF;
|
||||||
|
int r = bytes[index + 2] & 0xFF;
|
||||||
|
int a = 0xFF;
|
||||||
|
pixels[width * i + j] = (r << rs) |
|
||||||
|
(g << gs) |
|
||||||
|
(b << bs) |
|
||||||
|
(a << as);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// LowerLeft
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int index = offset + 3 * width * i + 3 * j;
|
||||||
|
int b = bytes[index] & 0xFF;
|
||||||
|
int g = bytes[index + 1] & 0xFF;
|
||||||
|
int r = bytes[index + 2] & 0xFF;
|
||||||
|
int a = 0xFF;
|
||||||
|
pixels[width * (height - i - 1) + j] = (r << rs) |
|
||||||
|
(g << gs) |
|
||||||
|
(b << bs) |
|
||||||
|
(a << as);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
pixels = new int[width * height];
|
||||||
|
if ((descriptor & RIGHT_ORIGIN) != 0) {
|
||||||
|
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||||
|
// UpperRight
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int index = offset + 4 * width * i + 4 * j;
|
||||||
|
int b = bytes[index] & 0xFF;
|
||||||
|
int g = bytes[index + 1] & 0xFF;
|
||||||
|
int r = bytes[index + 2] & 0xFF;
|
||||||
|
int a = bytes[index + 3] & 0xFF;
|
||||||
|
pixels[width * i + (width - j - 1)] = (r << rs) |
|
||||||
|
(g << gs) |
|
||||||
|
(b << bs) |
|
||||||
|
(a << as);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// LowerRight
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int index = offset + 4 * width * i + 4 * j;
|
||||||
|
int b = bytes[index] & 0xFF;
|
||||||
|
int g = bytes[index + 1] & 0xFF;
|
||||||
|
int r = bytes[index + 2] & 0xFF;
|
||||||
|
int a = bytes[index + 3] & 0xFF;
|
||||||
|
pixels[width * (height - i - 1) + (width - j - 1)] = (r << rs) |
|
||||||
|
(g << gs) |
|
||||||
|
(b << bs) |
|
||||||
|
(a << as);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||||
|
// UpperLeft
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int index = offset + 4 * width * i + 4 * j;
|
||||||
|
int b = bytes[index] & 0xFF;
|
||||||
|
int g = bytes[index + 1] & 0xFF;
|
||||||
|
int r = bytes[index + 2] & 0xFF;
|
||||||
|
int a = bytes[index + 3] & 0xFF;
|
||||||
|
pixels[width * i + j] = (r << rs) |
|
||||||
|
(g << gs) |
|
||||||
|
(b << bs) |
|
||||||
|
(a << as);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// LowerLeft
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int index = offset + 4 * width * i + 4 * j;
|
||||||
|
int b = bytes[index] & 0xFF;
|
||||||
|
int g = bytes[index + 1] & 0xFF;
|
||||||
|
int r = bytes[index + 2] & 0xFF;
|
||||||
|
int a = bytes[index + 3] & 0xFF;
|
||||||
|
pixels[width * (height - i - 1) + j] = (r << rs) |
|
||||||
|
(g << gs) |
|
||||||
|
(b << bs) |
|
||||||
|
(a << as);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IOException("Unsupported depth:" + depth);
|
||||||
|
}
|
||||||
|
return pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int[] createPixelsFromGrayscale(int width, int height, int depth, byte[] bytes, int offset, int descriptor, Order order) throws IOException {
|
||||||
|
int[] pixels;
|
||||||
|
int rs = order.redShift;
|
||||||
|
int gs = order.greenShift;
|
||||||
|
int bs = order.blueShift;
|
||||||
|
int as = order.alphaShift;
|
||||||
|
switch (depth) {
|
||||||
|
case 8:
|
||||||
|
pixels = new int[width * height];
|
||||||
|
if ((descriptor & RIGHT_ORIGIN) != 0) {
|
||||||
|
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||||
|
// UpperRight
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int e = bytes[offset + width * i + j] & 0xFF;
|
||||||
|
int a = 0xFF;
|
||||||
|
pixels[width * i + (width - j - 1)] = (e << rs) |
|
||||||
|
(e << gs) |
|
||||||
|
(e << bs) |
|
||||||
|
(a << as);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// LowerRight
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int e = bytes[offset + width * i + j] & 0xFF;
|
||||||
|
int a = 0xFF;
|
||||||
|
pixels[width * (height - i - 1) + (width - j - 1)] = (e << rs) |
|
||||||
|
(e << gs) |
|
||||||
|
(e << bs) |
|
||||||
|
(a << as);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||||
|
// UpperLeft
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int e = bytes[offset + width * i + j] & 0xFF;
|
||||||
|
int a = 0xFF;
|
||||||
|
pixels[width * i + j] = (e << rs) |
|
||||||
|
(e << gs) |
|
||||||
|
(e << bs) |
|
||||||
|
(a << as);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// LowerLeft
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int e = bytes[offset + width * i + j] & 0xFF;
|
||||||
|
int a = 0xFF;
|
||||||
|
pixels[width * (height - i - 1) + j] = (e << rs) |
|
||||||
|
(e << gs) |
|
||||||
|
(e << bs) |
|
||||||
|
(a << as);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
pixels = new int[width * height];
|
||||||
|
if ((descriptor & RIGHT_ORIGIN) != 0) {
|
||||||
|
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||||
|
// UpperRight
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int e = bytes[offset + 2 * width * i + 2 * j] & 0xFF;
|
||||||
|
int a = bytes[offset + 2 * width * i + 2 * j + 1] & 0xFF;
|
||||||
|
pixels[width * i + (width - j - 1)] = (e << rs) |
|
||||||
|
(e << gs) |
|
||||||
|
(e << bs) |
|
||||||
|
(a << as);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// LowerRight
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int e = bytes[offset + 2 * width * i + 2 * j] & 0xFF;
|
||||||
|
int a = bytes[offset + 2 * width * i + 2 * j + 1] & 0xFF;
|
||||||
|
pixels[width * (height - i - 1) + (width - j - 1)] = (e << rs) |
|
||||||
|
(e << gs) |
|
||||||
|
(e << bs) |
|
||||||
|
(a << as);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||||
|
// UpperLeft
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int e = bytes[offset + 2 * width * i + 2 * j] & 0xFF;
|
||||||
|
int a = bytes[offset + 2 * width * i + 2 * j + 1] & 0xFF;
|
||||||
|
pixels[width * i + j] = (e << rs) |
|
||||||
|
(e << gs) |
|
||||||
|
(e << bs) |
|
||||||
|
(a << as);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// LowerLeft
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
for (int j = 0; j < width; j++) {
|
||||||
|
int e = bytes[offset + 2 * width * i + 2 * j] & 0xFF;
|
||||||
|
int a = bytes[offset + 2 * width * i + 2 * j + 1] & 0xFF;
|
||||||
|
pixels[width * (height - i - 1) + j] = (e << rs) |
|
||||||
|
(e << gs) |
|
||||||
|
(e << bs) |
|
||||||
|
(a << as);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IOException("Unsupported depth:" + depth);
|
||||||
|
}
|
||||||
|
return pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TGAReader() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Order {
|
||||||
|
Order(int redShift, int greenShift, int blueShift, int alphaShift) {
|
||||||
|
this.redShift = redShift;
|
||||||
|
this.greenShift = greenShift;
|
||||||
|
this.blueShift = blueShift;
|
||||||
|
this.alphaShift = alphaShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int redShift;
|
||||||
|
public int greenShift;
|
||||||
|
public int blueShift;
|
||||||
|
public int alphaShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package su.xash.engine.workers
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
|
import androidx.documentfile.provider.DocumentFile
|
||||||
|
import androidx.work.CoroutineWorker
|
||||||
|
import androidx.work.WorkerParameters
|
||||||
|
import androidx.work.workDataOf
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
const val KEY_FILE_URI = "KEY_FILE_URI"
|
||||||
|
|
||||||
|
class FileCopyWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx, params) {
|
||||||
|
companion object {
|
||||||
|
const val Input = "Input"
|
||||||
|
const val Progress = "Progress"
|
||||||
|
}
|
||||||
|
|
||||||
|
private var fileCount = 0
|
||||||
|
private var fileCopied = 0
|
||||||
|
|
||||||
|
override suspend fun doWork(): Result {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
val fileUri = inputData.getString(KEY_FILE_URI)
|
||||||
|
setProgress(workDataOf(Input to fileUri))
|
||||||
|
|
||||||
|
val uri = Uri.parse(fileUri)
|
||||||
|
val source = DocumentFile.fromTreeUri(applicationContext, uri)
|
||||||
|
|
||||||
|
fileCount = source?.countDirFiles() ?: return@withContext Result.failure()
|
||||||
|
|
||||||
|
setProgress(workDataOf(Progress to 0f))
|
||||||
|
|
||||||
|
val gamedir = source.name!!
|
||||||
|
val externalFilesDir = DocumentFile.fromFile(applicationContext.getExternalFilesDir(null)!!)
|
||||||
|
|
||||||
|
// create a directory to store staged files
|
||||||
|
val target = externalFilesDir.createDirectory(".$gamedir")!!
|
||||||
|
|
||||||
|
source.copyDirTo(applicationContext, this@FileCopyWorker, target)
|
||||||
|
|
||||||
|
target.renameTo(gamedir)
|
||||||
|
|
||||||
|
setProgress(workDataOf(Progress to 1f))
|
||||||
|
}
|
||||||
|
return Result.success()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun fileCopied(count: Int) {
|
||||||
|
if(count == 0)
|
||||||
|
return
|
||||||
|
|
||||||
|
fileCopied += count
|
||||||
|
val percentage: Float = fileCopied.toFloat() / fileCount.toFloat();
|
||||||
|
setProgress(workDataOf(Progress to percentage))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DocumentFile.countDirFiles(): Int {
|
||||||
|
var count: Int = 0
|
||||||
|
|
||||||
|
listFiles().forEach {
|
||||||
|
if (it.isDirectory)
|
||||||
|
count += it.countDirFiles()
|
||||||
|
else
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DocumentFile.copyFileTo(ctx: Context, file: DocumentFile) {
|
||||||
|
val outFile = file.createFile("application", name!!)!!
|
||||||
|
|
||||||
|
ctx.contentResolver.openOutputStream(outFile.uri).use { os ->
|
||||||
|
ctx.contentResolver.openInputStream(uri).use {
|
||||||
|
it?.copyTo(os!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun DocumentFile.copyDirTo(ctx: Context, worker: FileCopyWorker, dir: DocumentFile) {
|
||||||
|
var count: Int = 0
|
||||||
|
|
||||||
|
listFiles().forEach {
|
||||||
|
if (it.isDirectory) {
|
||||||
|
val outDir = dir.createDirectory(it.name!!)!!
|
||||||
|
it.copyDirTo(ctx, worker, outDir)
|
||||||
|
} else {
|
||||||
|
it.copyFileTo(ctx, dir)
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
worker.fileCopied(count)
|
||||||
|
}
|
||||||
10
android/app/src/main/res/drawable/ic_baseline_add_24.xml
Normal file
10
android/app/src/main/res/drawable/ic_baseline_add_24.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
|
||||||
|
</vector>
|
||||||
10
android/app/src/main/res/drawable/ic_baseline_delete_24.xml
Normal file
10
android/app/src/main/res/drawable/ic_baseline_delete_24.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z" />
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M20,6h-8l-2,-2L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,8c0,-1.1 -0.9,-2 -2,-2zM20,18L4,18L4,8h16v10z" />
|
||||||
|
</vector>
|
||||||
5
android/app/src/main/res/drawable/ic_baseline_key_24.xml
Normal file
5
android/app/src/main/res/drawable/ic_baseline_key_24.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="#000000"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M21,10h-8.35C11.83,7.67 9.61,6 7,6c-3.31,0 -6,2.69 -6,6s2.69,6 6,6c2.61,0 4.83,-1.67 5.65,-4H13l2,2l2,-2l2,2l4,-4.04L21,10zM7,15c-1.65,0 -3,-1.35 -3,-3c0,-1.65 1.35,-3 3,-3s3,1.35 3,3C10,13.65 8.65,15 7,15z"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="#000000"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="#000000"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M8,5v14l11,-7z" />
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.8,11.69 4.8,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z" />
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M20,4H4C2.89,4 2,4.9 2,6v12c0,1.1 0.89,2 2,2h16c1.1,0 2,-0.9 2,-2V6C22,4.9 21.11,4 20,4zM20,18H4V8h16V18zM18,17h-6v-2h6V17zM7.5,17l-1.41,-1.41L8.67,13l-2.59,-2.59L7.5,9l4,4L7.5,17z" />
|
||||||
|
</vector>
|
||||||
15
android/app/src/main/res/drawable/steam_button_gradient.xml
Normal file
15
android/app/src/main/res/drawable/steam_button_gradient.xml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_enabled="true">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<gradient android:endColor="#2D73FF" android:startColor="#06BFFF" />
|
||||||
|
<corners android:radius="4dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item android:state_enabled="false">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<gradient android:endColor="#6D6D6D" android:startColor="#8F8F8F" />
|
||||||
|
<corners android:radius="4dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
9
android/app/src/main/res/drawable/steam_icon.xml
Normal file
9
android/app/src/main/res/drawable/steam_icon.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M12.004,2c-5.25,0 -9.556,4.05 -9.964,9.197l5.36,2.216c0.454,-0.31 1.002,-0.492 1.593,-0.492 0.053,0 0.104,0.003 0.157,0.005l2.384,-3.452v-0.049c0,-2.08 1.69,-3.77 3.77,-3.77 2.079,0 3.77,1.692 3.77,3.772s-1.692,3.771 -3.77,3.771h-0.087l-3.397,2.426c0,0.043 0.003,0.088 0.003,0.133 0,1.562 -1.262,2.83 -2.825,2.83 -1.362,0 -2.513,-0.978 -2.775,-2.273l-3.838,-1.589C3.573,18.922 7.427,22 12.005,22c5.522,0 9.998,-4.477 9.998,-10 0,-5.522 -4.477,-10 -9.999,-10zM7.078,16.667c0.218,0.452 0.595,0.832 1.094,1.041 1.081,0.45 2.328,-0.063 2.777,-1.145 0.22,-0.525 0.22,-1.1 0.004,-1.625 -0.215,-0.525 -0.625,-0.934 -1.147,-1.152 -0.52,-0.217 -1.075,-0.208 -1.565,-0.025l1.269,0.525c0.797,0.333 1.174,1.25 0.84,2.046 -0.33,0.797 -1.247,1.175 -2.044,0.843l-1.228,-0.508zM17.818,9.422c0,-1.385 -1.128,-2.512 -2.513,-2.512 -1.387,0 -2.512,1.127 -2.512,2.512 0,1.388 1.125,2.513 2.512,2.513 1.386,0 2.512,-1.125 2.512,-2.513zM15.31,7.53c1.04,0 1.888,0.845 1.888,1.888s-0.847,1.888 -1.888,1.888c-1.044,0 -1.888,-0.845 -1.888,-1.888s0.845,-1.888 1.888,-1.888z"/>
|
||||||
|
</vector>
|
||||||
33
android/app/src/main/res/drawable/steam_logo.xml
Normal file
33
android/app/src/main/res/drawable/steam_logo.xml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="295.46dp"
|
||||||
|
android:height="90.47dp"
|
||||||
|
android:viewportWidth="295.46"
|
||||||
|
android:viewportHeight="90.47">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="m45.08,1c-23.24,0 -42.28,17.92 -44.08,40.69l23.71,9.8c2.01,-1.37 4.44,-2.18 7.05,-2.18 0.23,0 0.47,0.01 0.7,0.02l10.54,-15.28c0,-0.07 0,-0.14 0,-0.22 0,-9.2 7.48,-16.68 16.68,-16.68 9.2,0 16.68,7.48 16.68,16.68s-7.48,16.68 -16.68,16.68c-0.13,0 -0.25,0 -0.38,-0.01l-15.04,10.73c0.01,0.19 0.01,0.39 0.01,0.59 0,6.91 -5.62,12.52 -12.52,12.52 -6.06,0 -11.13,-4.33 -12.28,-10.06l-16.96,-7.01c5.25,18.57 22.31,32.18 42.56,32.18 24.43,0 44.24,-19.81 44.24,-44.24 0,-24.43 -19.81,-44.24 -44.24,-44.24"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="m28.72,68.12 l-5.43,-2.24c0.96,2.01 2.63,3.68 4.84,4.61 4.78,1.99 10.3,-0.28 12.29,-5.06 0.96,-2.31 0.97,-4.87 0.01,-7.19 -0.95,-2.32 -2.76,-4.13 -5.07,-5.1 -2.3,-0.96 -4.76,-0.92 -6.93,-0.1l5.61,2.32c3.53,1.47 5.2,5.52 3.72,9.05 -1.47,3.53 -5.52,5.2 -9.05,3.72"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="m70.8,33.83c0,-6.13 -4.99,-11.12 -11.12,-11.12 -6.13,0 -11.12,4.99 -11.12,11.12 0,6.13 4.99,11.11 11.12,11.11 6.13,0 11.12,-4.99 11.12,-11.11m-19.45,-0.02c0,-4.61 3.74,-8.35 8.35,-8.35s8.35,3.74 8.35,8.35 -3.74,8.35 -8.35,8.35 -8.35,-3.74 -8.35,-8.35"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="m136.56,31.27 l-2.96,5.21c-2.28,-1.6 -5.38,-2.56 -8.08,-2.56 -3.09,0 -5,1.28 -5,3.57 0,2.78 3.39,3.43 8.44,5.24 5.42,1.92 8.54,4.17 8.54,9.14 0,6.79 -5.34,10.61 -13.02,10.61 -3.74,0 -8.26,-0.97 -11.73,-3.08l2.16,-5.78c2.82,1.49 6.19,2.37 9.2,2.37 4.05,0 5.98,-1.5 5.98,-3.7 0,-2.53 -2.94,-3.29 -7.68,-4.86 -5.4,-1.8 -9.15,-4.17 -9.15,-9.67 0,-6.2 4.96,-9.76 12.1,-9.76 4.98,0 8.98,1.58 11.2,3.26"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="m152.76,61.9v-27.34h-10.13v-5.99h27.21v5.99h-10.1v27.34z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="m197.9,42.05v5.99h-13.36v7.82h15.5v6.04h-22.47v-33.33h22.47v5.97h-15.5v7.51z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="m215.62,55.43 l-2.21,6.47h-7.32l12.49,-33.33h7.03l12.85,33.32h-7.56l-2.25,-6.47h-13.03zM222.07,36.52 L217.51,49.87h9.2z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="m261.22,60.93 l-8.97,-19.3v20.27h-6.68v-33.33h6.67l11.2,24.06 10.8,-24.06h6.73v33.33h-6.68v-20.44l-9.12,19.47z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="m294.46,32.78c0,2.86 -2.15,4.65 -4.61,4.65 -2.47,0 -4.62,-1.78 -4.62,-4.65 0,-2.86 2.15,-4.64 4.62,-4.64 2.46,0 4.61,1.77 4.61,4.64m-8.46,0c0,2.4 1.73,3.9 3.85,3.9 2.11,0 3.83,-1.5 3.83,-3.9 0,-2.4 -1.72,-3.88 -3.83,-3.88 -2.12,0 -3.85,1.5 -3.85,3.88m3.91,-2.37c1.2,0 1.6,0.63 1.6,1.32 0,0.63 -0.37,1.05 -0.82,1.26l1.07,2.01h-0.88l-0.9,-1.78h-0.93v1.78h-0.73v-4.58zM289.05,32.54h0.81c0.53,0 0.84,-0.33 0.84,-0.75 0,-0.42 -0.22,-0.69 -0.84,-0.69h-0.81v1.44z"/>
|
||||||
|
</vector>
|
||||||
35
android/app/src/main/res/layout/activity_main.xml
Normal file
35
android/app/src/main/res/layout/activity_main.xml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/appBarLayout"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/fragmentContainerView"
|
||||||
|
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:defaultNavHost="true"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/appBarLayout"
|
||||||
|
app:navGraph="@navigation/nav_graph"
|
||||||
|
tools:layout="@layout/fragment_library"/>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
111
android/app/src/main/res/layout/card_game.xml
Normal file
111
android/app/src/main/res/layout/card_game.xml
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
style="@style/Widget.Material3.CardView.Filled"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="128dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/gameCover"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
tools:src="@android:mipmap/sym_def_app_icon" />
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
style="@style/Widget.Material3.CardView.Filled"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
app:contentPadding="10dp"
|
||||||
|
app:layout_constrainedWidth="true"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/buttonsContainer"
|
||||||
|
app:layout_constraintHorizontal_bias="0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/gameIcon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/gameTitle"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:src="@android:mipmap/sym_def_app_icon" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/gameTitle"
|
||||||
|
style="@style/TextAppearance.Material3.TitleMedium"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:singleLine="true"
|
||||||
|
app:layout_constrainedWidth="true"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/gameIcon"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="Game Title" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:id="@+id/buttonsContainer"
|
||||||
|
style="@style/Widget.Material3.CardView.Filled"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
|
android:id="@+id/progressIndicator"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:indicatorSize="20dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/launchButton"
|
||||||
|
style="@style/Widget.Material3.Button.IconButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:icon="@drawable/ic_baseline_play_arrow_24"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/settingsButton" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/settingsButton"
|
||||||
|
style="@style/Widget.Material3.Button.IconButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:icon="@drawable/ic_baseline_settings_24"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
30
android/app/src/main/res/layout/edit_text_preference.xml
Normal file
30
android/app/src/main/res/layout/edit_text_preference.xml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<!-- <com.google.android.material.textfield.TextInputLayout-->
|
||||||
|
<!-- android:layout_width="match_parent"-->
|
||||||
|
<!-- android:layout_height="wrap_content"-->
|
||||||
|
<!-- app:layout_constraintTop_toTopOf="parent"-->
|
||||||
|
<!-- app:layout_constraintBottom_toBottomOf="parent">-->
|
||||||
|
|
||||||
|
<!-- <com.google.android.material.textfield.TextInputEditText-->
|
||||||
|
<!-- android:layout_width="match_parent"-->
|
||||||
|
<!-- android:layout_height="wrap_content" />-->
|
||||||
|
<!-- </com.google.android.material.textfield.TextInputLayout>-->
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/summary"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toBottomOf="@android:id/title"
|
||||||
|
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"/>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
14
android/app/src/main/res/layout/fragment_app_settings.xml
Normal file
14
android/app/src/main/res/layout/fragment_app_settings.xml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:paddingHorizontal="8dp">
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/settingsFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:layout="@android:layout/list_content" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
39
android/app/src/main/res/layout/fragment_game_settings.xml
Normal file
39
android/app/src/main/res/layout/fragment_game_settings.xml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/gameCard"
|
||||||
|
layout="@layout/card_game"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
style="@style/Widget.Material3.CardView.Filled"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
app:contentPadding="16dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/gameCard">
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/settingsFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:layout="@android:layout/list_content" />
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
|
android:id="@+id/bottomNavigation"
|
||||||
|
style="@style/Widget.MaterialComponents.BottomNavigationView.Colored"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:menu="@menu/menu_game_settings" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
23
android/app/src/main/res/layout/fragment_library.xml
Normal file
23
android/app/src/main/res/layout/fragment_library.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/swipeRefresh">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/gamesList"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layoutManager="LinearLayoutManager"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingHorizontal="8dp"
|
||||||
|
tools:listitem="@layout/card_game" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
11
android/app/src/main/res/layout/fragment_setup.xml
Normal file
11
android/app/src/main/res/layout/fragment_setup.xml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
|
android:id="@+id/viewPager"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
58
android/app/src/main/res/layout/fragment_steam_login.xml
Normal file
58
android/app/src/main/res/layout/fragment_steam_login.xml
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/steam_background"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:context=".fragment.SteamLoginFragment">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imageView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/steam_logo"
|
||||||
|
app:tint="#C5C3C0" />
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:layout_width="320dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
app:startIconDrawable="@drawable/ic_baseline_person_24">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/steamLogin"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/username"
|
||||||
|
android:inputType="textEmailAddress" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:layout_width="320dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
|
||||||
|
app:startIconDrawable="@drawable/ic_baseline_key_24">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/steamPassword"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/password"
|
||||||
|
android:inputType="textPassword" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/loginButton"
|
||||||
|
style="@style/App.Theme.SteamButton"
|
||||||
|
android:layout_width="240dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="@string/login" />
|
||||||
|
</LinearLayout>
|
||||||
19
android/app/src/main/res/layout/list_preference.xml
Normal file
19
android/app/src/main/res/layout/list_preference.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/summary"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toBottomOf="@android:id/title"
|
||||||
|
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"/>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
51
android/app/src/main/res/layout/page_location.xml
Normal file
51
android/app/src/main/res/layout/page_location.xml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/pagePic"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="64dp"
|
||||||
|
android:layout_marginBottom="32dp"
|
||||||
|
android:src="@drawable/ic_baseline_folder_open_24"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/pageTitle"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/pageTitle"
|
||||||
|
style="@style/TextAppearance.Material3.TitleLarge"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingHorizontal="16dp"
|
||||||
|
android:text="@string/setup_location_title"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/pageMessage"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/pagePic" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/pageMessage"
|
||||||
|
style="@style/TextAppearance.Material3.TitleMedium"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingHorizontal="16dp"
|
||||||
|
android:text="@string/setup_location_message"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/pageButton"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/pageTitle" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/pageButton"
|
||||||
|
android:layout_width="240dp"
|
||||||
|
android:layout_marginBottom="128dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/ok"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/pageMessage" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
51
android/app/src/main/res/layout/page_welcome.xml
Normal file
51
android/app/src/main/res/layout/page_welcome.xml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/pagePic"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="64dp"
|
||||||
|
android:layout_marginBottom="32dp"
|
||||||
|
android:src="@mipmap/ic_launcher"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/pageTitle"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/pageTitle"
|
||||||
|
style="@style/TextAppearance.Material3.TitleLarge"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:paddingHorizontal="16dp"
|
||||||
|
android:text="@string/setup_welcome_title"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/pageMessage"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/pagePic" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/pageMessage"
|
||||||
|
style="@style/TextAppearance.Material3.TitleMedium"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingHorizontal="16dp"
|
||||||
|
android:text="@string/setup_welcome_message"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/pageButton"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/pageTitle" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/pageButton"
|
||||||
|
android:layout_width="240dp"
|
||||||
|
android:layout_marginBottom="128dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/next"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/pageMessage" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user