mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-06 16:44:05 +09:00
Compare commits
667 Commits
gradle-mig
...
jni_light
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af619cda79 | ||
|
|
78bbd9c051 | ||
|
|
3f108a6ea9 | ||
|
|
a831a4d798 | ||
|
|
e3ed712a42 | ||
|
|
daf5c02605 | ||
|
|
e8b39fc668 | ||
|
|
c20d7edb34 | ||
|
|
28f305e76f | ||
|
|
4c3fc2352c | ||
|
|
01094d49eb | ||
|
|
7d3bf0eece | ||
|
|
75f128a8f7 | ||
|
|
514f1e9012 | ||
|
|
60db83eddb | ||
|
|
90a7fcd4d0 | ||
|
|
d93c6de851 | ||
|
|
f603b58307 | ||
|
|
074fe2438d | ||
|
|
69e9fa4b0f | ||
|
|
9373feff34 | ||
|
|
10c188bea7 | ||
|
|
cd1ad9277a | ||
|
|
465ed0d7a4 | ||
|
|
bd1c1bff8a | ||
|
|
8ac5f1dc9e | ||
|
|
268907ee9d | ||
|
|
9937c34d25 | ||
|
|
bdbb30bc58 | ||
|
|
bdbf6cd458 | ||
|
|
e4f456ffa7 | ||
|
|
73a6c844c8 | ||
|
|
84ca954a26 | ||
|
|
66b18bf8c5 | ||
|
|
6d0bff2879 | ||
|
|
14b485dc32 | ||
|
|
a192abd657 | ||
|
|
0d534fd60c | ||
|
|
a4dabbbf37 | ||
|
|
450874540c | ||
|
|
53c45d6829 | ||
|
|
1c839f7135 | ||
|
|
f133406df3 | ||
|
|
ae14026191 | ||
|
|
b9a4e0f64b | ||
|
|
aef601e9b8 | ||
|
|
88db71f780 | ||
|
|
ded9cb1a10 | ||
|
|
afba402c6c | ||
|
|
b027f662ce | ||
|
|
c60b0b42ad | ||
|
|
40580a57cd | ||
|
|
09b4a34d14 | ||
|
|
613b69a20f | ||
|
|
5738418f39 | ||
|
|
10cf3fb007 | ||
|
|
be20fd8328 | ||
|
|
d1a2e6b8f2 | ||
|
|
5bf8b6cad7 | ||
|
|
2c59d60a15 | ||
|
|
68df2a223e | ||
|
|
784a6a13e3 | ||
|
|
9040ff2c87 | ||
|
|
c4510f9c3b | ||
|
|
ebce90aa4b | ||
|
|
25d0e195c3 | ||
|
|
e209967730 | ||
|
|
f689e1de99 | ||
|
|
6e33dbdfaf | ||
|
|
b10e8aa777 | ||
|
|
6a343ae382 | ||
|
|
17b6738308 | ||
|
|
078cdfefa4 | ||
|
|
81f9c92e48 | ||
|
|
8237188dc3 | ||
|
|
7b120020e4 | ||
|
|
f4cd4f49b2 | ||
|
|
09b039c62f | ||
|
|
ff8791f48a | ||
|
|
43bc99548c | ||
|
|
380a14492f | ||
|
|
692e08fc1e | ||
|
|
33ad8520f8 | ||
|
|
9aa8eb395d | ||
|
|
34d50b8d70 | ||
|
|
07e8e21eae | ||
|
|
525273e37f | ||
|
|
34a8113d53 | ||
|
|
4f8cf2cb02 | ||
|
|
8a0abf22da | ||
|
|
9140d6d8b0 | ||
|
|
9133f05b5e | ||
|
|
790d16b85d | ||
|
|
adf60e357e | ||
|
|
f81db26e60 | ||
|
|
655eccbe19 | ||
|
|
5b31b4768f | ||
|
|
425cb82133 | ||
|
|
344e4ebdab | ||
|
|
32afb2e2e5 | ||
|
|
3100a093fd | ||
|
|
fb06200d26 | ||
|
|
1696cc8601 | ||
|
|
4072b9fb09 | ||
|
|
36160a6579 | ||
|
|
4986d570a0 | ||
|
|
1965eabaa3 | ||
|
|
90784afd48 | ||
|
|
258364f37e | ||
|
|
f99531c9d4 | ||
|
|
74cfc05fba | ||
|
|
15868a5a2d | ||
|
|
3abca8989a | ||
|
|
ae9a1ebcb4 | ||
|
|
18a05ace64 | ||
|
|
3b2c38cf0b | ||
|
|
6ecbb672fb | ||
|
|
30954d239a | ||
|
|
edd15a4f79 | ||
|
|
db110d1ca4 | ||
|
|
e3e97000a7 | ||
|
|
ce2d9a271a | ||
|
|
222aef7e3d | ||
|
|
08bbdaf70b | ||
|
|
7300b05442 | ||
|
|
cd13e04658 | ||
|
|
48de42d98b | ||
|
|
35c0c45500 | ||
|
|
6c01aa9b0b | ||
|
|
2335312081 | ||
|
|
abfd9b68fc | ||
|
|
500c72ebc9 | ||
|
|
00fc4f1b8c | ||
|
|
98755fab61 | ||
|
|
09d8702089 | ||
|
|
9080127d38 | ||
|
|
d7664c7f46 | ||
|
|
47da7d5b81 | ||
|
|
ef3690765d | ||
|
|
33c333e7fa | ||
|
|
10128a20a0 | ||
|
|
764945fc30 | ||
|
|
3098c0afd2 | ||
|
|
101c67a107 | ||
|
|
a1661fbb4e | ||
|
|
04c5e32ddf | ||
|
|
b78d488044 | ||
|
|
832e296bc5 | ||
|
|
46e5860143 | ||
|
|
4fa44abd3e | ||
|
|
191a91cb81 | ||
|
|
388d3d6f2f | ||
|
|
b1b29387e3 | ||
|
|
764edea832 | ||
|
|
16e4067d89 | ||
|
|
05a8f47006 | ||
|
|
1f1d6f1eda | ||
|
|
27f79238a1 | ||
|
|
6d553ea583 | ||
|
|
ad8d3ba210 | ||
|
|
e441cdf5f0 | ||
|
|
9c3c35067d | ||
|
|
7a60ae0629 | ||
|
|
258273fd25 | ||
|
|
dc502b2f12 | ||
|
|
803e59a0ee | ||
|
|
e31eaf0241 | ||
|
|
8181bec481 | ||
|
|
7c1d6e6b88 | ||
|
|
7e7e54eed7 | ||
|
|
57c9b7b277 | ||
|
|
984eb4de00 | ||
|
|
c4b4bfd2fc | ||
|
|
cf9bce5bac | ||
|
|
16a7d2abe7 | ||
|
|
a690b46456 | ||
|
|
b55cd415f2 | ||
|
|
4c2b73197d | ||
|
|
1c1ae37f41 | ||
|
|
57fa6de62a | ||
|
|
6f0a923df7 | ||
|
|
4b04bf3781 | ||
|
|
eca0469f32 | ||
|
|
d588f73ed6 | ||
|
|
b40a78b706 | ||
|
|
93a43899e7 | ||
|
|
155ba9eb56 | ||
|
|
4224d56b25 | ||
|
|
cc14218dd5 | ||
|
|
b856829ca9 | ||
|
|
a9bc4f47f8 | ||
|
|
bf9c172206 | ||
|
|
fa86ca2e05 | ||
|
|
9cc0a62188 | ||
|
|
f3b0044d5f | ||
|
|
f5d36e2c92 | ||
|
|
8da80e88a3 | ||
|
|
f21ed3bf0d | ||
|
|
4d0c772dd8 | ||
|
|
f4f0e59811 | ||
|
|
d9f576e4dc | ||
|
|
091f79c7f8 | ||
|
|
8942f352a1 | ||
|
|
1aa90077a4 | ||
|
|
3360ab0dfe | ||
|
|
4eee5ee2b1 | ||
|
|
c7c68187eb | ||
|
|
5c8cdd3162 | ||
|
|
73d1a1bdc5 | ||
|
|
ee3d98662c | ||
|
|
d77b552518 | ||
|
|
5f75288dc7 | ||
|
|
74d76440ee | ||
|
|
e072aff897 | ||
|
|
397b2a8795 | ||
|
|
ae1e99aa3e | ||
|
|
17e550a6a0 | ||
|
|
292de8d56a | ||
|
|
626aa710c1 | ||
|
|
78fc6fc657 | ||
|
|
d2b7c76734 | ||
|
|
4cfd3b8c45 | ||
|
|
e645eaade9 | ||
|
|
af34d94e6a | ||
|
|
98539e698f | ||
|
|
03b642ddd3 | ||
|
|
967eafe8a3 | ||
|
|
69eb2d7a3b | ||
|
|
6d4ac92133 | ||
|
|
b40af8e1b3 | ||
|
|
c381250665 | ||
|
|
497a88c8de | ||
|
|
0bad86bb9d | ||
|
|
eee8a18875 | ||
|
|
24b2e2a2af | ||
|
|
e48731b2e3 | ||
|
|
8f9022827c | ||
|
|
de19f49d26 | ||
|
|
9ade08013f | ||
|
|
6b929ac107 | ||
|
|
108a3e6188 | ||
|
|
07681110c7 | ||
|
|
abd1827182 | ||
|
|
9736d39e04 | ||
|
|
8daf0a2c38 | ||
|
|
6bbfd5d167 | ||
|
|
4664c9ba0d | ||
|
|
fded7f1dfb | ||
|
|
d11fd281f4 | ||
|
|
40423ede52 | ||
|
|
941d9fa107 | ||
|
|
c5fa83b2f4 | ||
|
|
51a2e47430 | ||
|
|
6715308f88 | ||
|
|
35f2cf6b4d | ||
|
|
f45a3d252a | ||
|
|
ade77473c4 | ||
|
|
7cd7b4047f | ||
|
|
f5636fe0d3 | ||
|
|
948f922041 | ||
|
|
6c72bef0de | ||
|
|
fe21340186 | ||
|
|
516314c47f | ||
|
|
55cdac9269 | ||
|
|
a506269906 | ||
|
|
77b563396e | ||
|
|
98a67c80c6 | ||
|
|
a8398765c6 | ||
|
|
6df79b96dd | ||
|
|
83b9f74100 | ||
|
|
d9a01a70c3 | ||
|
|
06949848f8 | ||
|
|
0e1c46f18d | ||
|
|
fe8163c1e4 | ||
|
|
e3ac877c3d | ||
|
|
b560011d2f | ||
|
|
e76458bff6 | ||
|
|
558430b4f3 | ||
|
|
1149311076 | ||
|
|
ef176909b4 | ||
|
|
1d8e66a9cc | ||
|
|
cdf961df09 | ||
|
|
01a32ad00c | ||
|
|
7ffb417618 | ||
|
|
82ddfeb6ee | ||
|
|
e67b97257c | ||
|
|
e6e962ecf7 | ||
|
|
749a82bcf7 | ||
|
|
f9897bc439 | ||
|
|
1c6560797d | ||
|
|
75192bef17 | ||
|
|
05560cf04c | ||
|
|
ee7d51c21b | ||
|
|
2928aa2eb7 | ||
|
|
d0702c9159 | ||
|
|
2bf9acb07a | ||
|
|
25ce7958ae | ||
|
|
64f36d2d7c | ||
|
|
65bc67710c | ||
|
|
86d3a4a08d | ||
|
|
33da9777ea | ||
|
|
07ee987411 | ||
|
|
72b7adcf39 | ||
|
|
c595270faa | ||
|
|
d753365e54 | ||
|
|
116b4cc390 | ||
|
|
a5dd5b9e98 | ||
|
|
f51417e709 | ||
|
|
fd7d724f39 | ||
|
|
528fdc9fc5 | ||
|
|
33a774b5b7 | ||
|
|
58205e5eb5 | ||
|
|
31b7203d01 | ||
|
|
c9932fc81b | ||
|
|
145a4e5e71 | ||
|
|
81529eb215 | ||
|
|
057df6632a | ||
|
|
5499ded796 | ||
|
|
61427b849a | ||
|
|
a53f818ba6 | ||
|
|
d9a3318768 | ||
|
|
d241e5cbb0 | ||
|
|
49a9278c59 | ||
|
|
fc9516fd39 | ||
|
|
6bff02d91e | ||
|
|
bad6ff296a | ||
|
|
1e9c04d7c0 | ||
|
|
3ffdd7233f | ||
|
|
5a5fb45c3b | ||
|
|
1a33c3be5a | ||
|
|
0ad7db3b51 | ||
|
|
8504337da9 | ||
|
|
f2f5cd7daf | ||
|
|
464d30a384 | ||
|
|
009b55481b | ||
|
|
72e7931f4d | ||
|
|
0e4dd79cc1 | ||
|
|
f676938176 | ||
|
|
8a759cb178 | ||
|
|
66e4dcd1c4 | ||
|
|
d9381fc58e | ||
|
|
039ccea58f | ||
|
|
b592b8fa0f | ||
|
|
b82d172d58 | ||
|
|
41f9f4032d | ||
|
|
7b2b6caf82 | ||
|
|
b7fb8ff4da | ||
|
|
2ea3ce0c67 | ||
|
|
9b32cf63ff | ||
|
|
2129cce7f3 | ||
|
|
c8c1bdf836 | ||
|
|
4a54c87826 | ||
|
|
7248616e58 | ||
|
|
33b5a21c26 | ||
|
|
1095cb451f | ||
|
|
4472722c5d | ||
|
|
ab846ad805 | ||
|
|
187277d6a8 | ||
|
|
ad481853bb | ||
|
|
1ecbc57f83 | ||
|
|
41791af764 | ||
|
|
c664755ad8 | ||
|
|
984881421c | ||
|
|
e07e321ee3 | ||
|
|
6e403f97f8 | ||
|
|
87242da9cc | ||
|
|
12c6f6fd04 | ||
|
|
980c92f213 | ||
|
|
8a3c4fd65e | ||
|
|
67ca216243 | ||
|
|
7bd7a6532d | ||
|
|
c5765fc08a | ||
|
|
7f909e3796 | ||
|
|
b4042f0060 | ||
|
|
da2452c84e | ||
|
|
f0a6c36f8a | ||
|
|
fdb9d38e03 | ||
|
|
799a77c929 | ||
|
|
41050337f4 | ||
|
|
85ab2a2066 | ||
|
|
06cbac1cc5 | ||
|
|
50b597de5f | ||
|
|
b96daa7d3d | ||
|
|
80777fcccb | ||
|
|
a601d4c57b | ||
|
|
f7eaa4c4f0 | ||
|
|
f466f6f001 | ||
|
|
5255ae60af | ||
|
|
2a575351d3 | ||
|
|
58b229a7fa | ||
|
|
905ab1004c | ||
|
|
b7ed3dd814 | ||
|
|
ccbf56b322 | ||
|
|
87213e8fbd | ||
|
|
40e48eec21 | ||
|
|
b421dcf187 | ||
|
|
2eb6e7c0a2 | ||
|
|
3de9cedec3 | ||
|
|
f45dc6fde2 | ||
|
|
31954f3ca7 | ||
|
|
4262b02faf | ||
|
|
46fe5fb1e2 | ||
|
|
23cc28d3bd | ||
|
|
9732c6d66f | ||
|
|
566c76c1a2 | ||
|
|
81220fa542 | ||
|
|
572fbb4b9c | ||
|
|
10a99b7db6 | ||
|
|
959873413d | ||
|
|
14dfb5c963 | ||
|
|
86821d2d98 | ||
|
|
c9d786390c | ||
|
|
ade9592d67 | ||
|
|
22ad180e04 | ||
|
|
479c0ce91f | ||
|
|
a9d35678c5 | ||
|
|
cbb4eaad94 | ||
|
|
165ae1777b | ||
|
|
ecf775c664 | ||
|
|
1375f91505 | ||
|
|
c9c761598a | ||
|
|
9a7885fc80 | ||
|
|
9508249533 | ||
|
|
3498a100a4 | ||
|
|
7a3e7546de | ||
|
|
93939f22bf | ||
|
|
253260de6f | ||
|
|
a7dea93744 | ||
|
|
26cbe6970a | ||
|
|
3e54dcab2c | ||
|
|
56b77d1838 | ||
|
|
f4db93ca9e | ||
|
|
a9eb1f579e | ||
|
|
36a7983024 | ||
|
|
ab8f019109 | ||
|
|
ebc8174d2c | ||
|
|
c35ba8201a | ||
|
|
5cd5ebbea3 | ||
|
|
6399c2d66b | ||
|
|
b342e7d042 | ||
|
|
c6e42ffbbe | ||
|
|
e0a23f6089 | ||
|
|
c779baa72d | ||
|
|
aa4fbba711 | ||
|
|
2895f4be6d | ||
|
|
fcd378c51a | ||
|
|
fe94ebbe4a | ||
|
|
8689ab1565 | ||
|
|
4f43fdbd27 | ||
|
|
5fe604cf45 | ||
|
|
f840dbe7de | ||
|
|
532c836553 | ||
|
|
7ebb21124c | ||
|
|
f2ae2d9449 | ||
|
|
6087072d3d | ||
|
|
a47eb41d9a | ||
|
|
47b9b92797 | ||
|
|
037e84d6e2 | ||
|
|
1301121aa9 | ||
|
|
d20190b2bd | ||
|
|
bb797a0910 | ||
|
|
d33d25f384 | ||
|
|
12015669c6 | ||
|
|
671048e1e1 | ||
|
|
c5367f8f1c | ||
|
|
2332239ef2 | ||
|
|
25128d45e5 | ||
|
|
207c90d35e | ||
|
|
1057e7d442 | ||
|
|
5bfc5c3a38 | ||
|
|
84f91e6a7a | ||
|
|
4363bd4ba2 | ||
|
|
48315daa7d | ||
|
|
cd710de280 | ||
|
|
816502df3d | ||
|
|
b6290134a9 | ||
|
|
1e3ffd2272 | ||
|
|
1f59082c15 | ||
|
|
2e11676ee6 | ||
|
|
f919b45e18 | ||
|
|
24de647284 | ||
|
|
accf1cf584 | ||
|
|
6bea8af9db | ||
|
|
d3547e47ca | ||
|
|
208fd2ba15 | ||
|
|
72204fd5cd | ||
|
|
41da296bce | ||
|
|
114bfe395f | ||
|
|
2491a03c99 | ||
|
|
3d91023011 | ||
|
|
ff817c25e6 | ||
|
|
f47c66db44 | ||
|
|
bc4fd8866a | ||
|
|
0113ca5d09 | ||
|
|
920d8085cd | ||
|
|
a10134db2e | ||
|
|
edb2f5ce11 | ||
|
|
a22d27408c | ||
|
|
dac69f504c | ||
|
|
dfd71435de | ||
|
|
76fcb5b12f | ||
|
|
e9572488be | ||
|
|
08417be027 | ||
|
|
edd97b45a7 | ||
|
|
0a0aea9589 | ||
|
|
f5db4cb2fb | ||
|
|
75ab8c6558 | ||
|
|
63ec3a8917 | ||
|
|
4c8ceaf301 | ||
|
|
6d8f9d2901 | ||
|
|
efd3284e30 | ||
|
|
b29e6af643 | ||
|
|
96c6cb2cc6 | ||
|
|
bdba27d776 | ||
|
|
71091cce98 | ||
|
|
679a65a12e | ||
|
|
a3445d631a | ||
|
|
b23f848d95 | ||
|
|
3b7e88b0af | ||
|
|
d7b49b0f9d | ||
|
|
0180c7cf0a | ||
|
|
b33f179a9b | ||
|
|
c48308efe1 | ||
|
|
076c5ba1f1 | ||
|
|
d7576ce844 | ||
|
|
1c0b969078 | ||
|
|
5d7349386e | ||
|
|
3065d642b5 | ||
|
|
d028593842 | ||
|
|
5c4036e73f | ||
|
|
a9b00bd909 | ||
|
|
add2be7109 | ||
|
|
226ae77ab4 | ||
|
|
5799cc39ce | ||
|
|
afe197caf7 | ||
|
|
cc01ff62e6 | ||
|
|
bd58c9e40b | ||
|
|
9ddf0dee63 | ||
|
|
ad68309bc5 | ||
|
|
0a2bf64bff | ||
|
|
e66304bea0 | ||
|
|
8e7b61ea0c | ||
|
|
bb33d9e381 | ||
|
|
65dec9661c | ||
|
|
2c9906888b | ||
|
|
2f7eaea6b8 | ||
|
|
abad2eb1a6 | ||
|
|
12b04fabdf | ||
|
|
dbdee14481 | ||
|
|
172e5752ca | ||
|
|
c60a967050 | ||
|
|
361f322d78 | ||
|
|
8b111ef262 | ||
|
|
df5f4771a1 | ||
|
|
2d34db3022 | ||
|
|
5a76b1cc13 | ||
|
|
9aab3d3664 | ||
|
|
c5b452f779 | ||
|
|
95ea8d9b7c | ||
|
|
f02c931715 | ||
|
|
225f2f2235 | ||
|
|
1b83e7deb7 | ||
|
|
e951a6285e | ||
|
|
0717b883b4 | ||
|
|
6c94dc9632 | ||
|
|
54b52b1b6e | ||
|
|
4acc797fee | ||
|
|
5db3aadaf4 | ||
|
|
02f38eab3c | ||
|
|
b08060bffc | ||
|
|
fdecb83ebf | ||
|
|
e139fb891f | ||
|
|
efbb654b45 | ||
|
|
ea4c4bdb2b | ||
|
|
e9c7ef4930 | ||
|
|
1f1e2f6899 | ||
|
|
e7276513d7 | ||
|
|
8ae07c8d20 | ||
|
|
bac246cd9a | ||
|
|
ec73d2ea1e | ||
|
|
213831ad31 | ||
|
|
b52d6f89f7 | ||
|
|
dfb769c982 | ||
|
|
9e9bca3442 | ||
|
|
b1686ec5ab | ||
|
|
d076676a2f | ||
|
|
1e89ddfec7 | ||
|
|
1c5ee6f32c | ||
|
|
083197f4cb | ||
|
|
135f8f86e8 | ||
|
|
f7d055806b | ||
|
|
5944a215df | ||
|
|
0f8f64cddf | ||
|
|
0b7485fd57 | ||
|
|
e499c24c0d | ||
|
|
aab8da6ac7 | ||
|
|
ea73ff3153 | ||
|
|
4b54fb3b67 | ||
|
|
4d8ff11ece | ||
|
|
3eb1fe98cd | ||
|
|
df8c0813c3 | ||
|
|
ae97310bf7 | ||
|
|
0c2cb48135 | ||
|
|
f5f0fcb077 | ||
|
|
d3080ffb78 | ||
|
|
d1f01a203d | ||
|
|
da06e0fa93 | ||
|
|
0b024dcf70 | ||
|
|
ac05b5edf1 | ||
|
|
9a8090038e | ||
|
|
0e60380718 | ||
|
|
71294a6bd1 | ||
|
|
f4332afd3c | ||
|
|
f7365ea47b | ||
|
|
63bc018550 | ||
|
|
bc36cc946d | ||
|
|
767802e75f | ||
|
|
a6bbf256f0 | ||
|
|
e253641471 | ||
|
|
2e2e4a0281 | ||
|
|
433612ebdb | ||
|
|
f06c6f7502 | ||
|
|
81e9539381 | ||
|
|
e88124f065 | ||
|
|
35a723ee0f | ||
|
|
d0109a88af | ||
|
|
5e2cb526ee | ||
|
|
8e6fc55f46 | ||
|
|
ae45cf32a7 | ||
|
|
a9a2b93341 | ||
|
|
639f1c158e | ||
|
|
1362f6921e | ||
|
|
611b78ffa5 | ||
|
|
c1e7b3537d | ||
|
|
72e348b5e5 | ||
|
|
e76f8840ba | ||
|
|
656aa07e8b | ||
|
|
4548a2fe3d | ||
|
|
70d85398ce | ||
|
|
dd60448cae | ||
|
|
8c8a0cbb23 | ||
|
|
e0665db121 | ||
|
|
aeb377a857 | ||
|
|
e501b356cd | ||
|
|
01def757e9 | ||
|
|
ea1e90b035 | ||
|
|
0db1130b41 | ||
|
|
1ad9f2611d | ||
|
|
9c7e7ed266 | ||
|
|
56530a6041 | ||
|
|
af8516be68 | ||
|
|
9df31df54f | ||
|
|
b66b02ceeb | ||
|
|
7a7fac776a | ||
|
|
d179d090c5 | ||
|
|
174a0f9101 | ||
|
|
fd7a629757 | ||
|
|
a5ca82f2c7 | ||
|
|
4552d7b7db | ||
|
|
fe994621c0 | ||
|
|
5dc99f5612 | ||
|
|
1d1769a2c3 | ||
|
|
7078ecfed4 | ||
|
|
1dd156d172 | ||
|
|
22bb5d83e1 | ||
|
|
e1642c799c | ||
|
|
870c9b36ff |
24
.gitignore
vendored
24
.gitignore
vendored
@@ -1,15 +1,33 @@
|
||||
# Build-related
|
||||
out/*
|
||||
bin/*
|
||||
build/*
|
||||
.gradle/*
|
||||
|
||||
# Java native errors
|
||||
hs_err_pid*
|
||||
|
||||
# OS files
|
||||
Thumbs.db
|
||||
*.jar
|
||||
.DS_Store
|
||||
~$*
|
||||
|
||||
# Resources that should not be tracked
|
||||
*.jar
|
||||
assets/mods/basegame/demoworld
|
||||
assets/mods/basegame/demoworld.gz
|
||||
#assets/mods/basegame/demoworld.gz
|
||||
external_resource_packs.zip
|
||||
|
||||
# IntelliJ
|
||||
workspace.xml
|
||||
|
||||
# Temporary files
|
||||
.tmp*
|
||||
tmp_*
|
||||
~$*
|
||||
|
||||
# Eclipse MAT heap files
|
||||
*.hprof
|
||||
*.bin
|
||||
*.index
|
||||
*.threads
|
||||
*_Leak_Suspects.zip
|
||||
@@ -1,6 +1,6 @@
|
||||
*Terrarum*
|
||||
|
||||
Copyright (C) 2013-2018 Minjaesong (Torvald)
|
||||
Copyright (C) 2013-2019 Minjaesong (Torvald)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*Terrarum Sans Bitmap*
|
||||
|
||||
Copyright (c) 2017 Minjae Song (Torvald) and the contributors
|
||||
Copyright (c) 2017-2019 Minjae Song (Torvald) and the contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
|0..4095|Tiles (4096 possible)|
|
||||
|4096..8191|Walls (4096 possible)|
|
||||
|8192..8447|Wires (256 possible)|
|
||||
|8448..32767|Items (static) (24320 possible)|
|
||||
|32768..0x0FFF_FFFF|Items (dynamic\*) (268M possible)|
|
||||
|0x1000_0000..0x7FFF_FFFF|Actors|
|
||||
|-2147483648..-1 (all negative numbers)|Faction|
|
||||
|8448..0x0F_FFFF|Items (static) (1M possible)|
|
||||
|0x10_0000..0x0FFF_FFFF|Items (dynamic\*) (267M possible)|
|
||||
|0x1000_0000..0x7FFF_FFFF|Actors (1879M possible)|
|
||||
|-2147483648..-1 (all negative numbers)|Faction (2147M possible)|
|
||||
|
||||
* dynamic items have own properties that will persist through savegame.
|
||||
|
||||
@@ -14,7 +14,8 @@ Actors range in-depth
|
||||
|
||||
|Range|Description|
|
||||
|-----|-----------|
|
||||
|0x1000_0000..0x1FFF_FFFF|Rendered behind (e.g. tapestries)
|
||||
|0x2000_0000..0x5FFF_FFFF|Regular actors (e.g. almost all of them)
|
||||
|0x6000_0000..0x6FFF_FFFF|Special (e.g. weapon swung, bullets, dropped item, particles)
|
||||
|0x7000_0000..0x7FFF_FFFF|Rendered front (e.g. fake tile)
|
||||
|0x1000_0000..0x1FFF_FFFF|Rendered behind (e.g. tapestries)|
|
||||
|0x2000_0000..0x4FFF_FFFF|Regular actors (e.g. almost all of them)|
|
||||
|0x5000_0000..0x5FFF_FFFF|Special (e.g. weapon swung, bullets, dropped item, particles)|
|
||||
|0x6000_0000..0x6FFF_FFFF|Rendered front (e.g. fake tile)|
|
||||
|0x7000_0000..0x7FFF_FFFF|Rendered as screen overlay, not affected by light nor environment overlays|
|
||||
BIN
assets/appicon128.png
Normal file
BIN
assets/appicon128.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 462 B |
BIN
assets/appicon16.png
Normal file
BIN
assets/appicon16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 366 B |
BIN
assets/appicon256.png
Normal file
BIN
assets/appicon256.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 559 B |
BIN
assets/appicon32.png
Normal file
BIN
assets/appicon32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 387 B |
BIN
assets/appicon64.png
Normal file
BIN
assets/appicon64.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 418 B |
@@ -1,4 +1,4 @@
|
||||
#version 100
|
||||
#version 120
|
||||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
@@ -71,7 +71,7 @@ The control is omnidirectional. In other words, \emph{not} cell-based.
|
||||
\subsubsection{ISO\slash ANSI\slash JIS pedalboards}
|
||||
Your default moving around uses ESDF (qwerty)\slash FRST (colemak)\slash .OEW (dvorak) pedals for default `WASD', in order for you to provide more modifier pedals---QAZ (qwerty\slash colemak), /A; (dvorak)---that are pressed with your little finger and more comfort to some pedalboards with Topre actuators.\footnote{Writers of this book would recommend you to use pedalboard with Cherry MX Red actuators, though any decent pedalboard should be sufficient.}
|
||||
|
||||
\subsubsection{Joypads}
|
||||
\subsubsection{gamepads}
|
||||
Your moving around uses left stick, and direction of the movement is \emph{not} limited to 8 directions, hence the term, “omni\-direc\-tion\-al”.
|
||||
|
||||
\section{World}
|
||||
|
||||
15
assets/graphics/! PSD to TGA imagemagick.bat
Normal file
15
assets/graphics/! PSD to TGA imagemagick.bat
Normal file
@@ -0,0 +1,15 @@
|
||||
SET basefilename=%~d1%~p1%~n1
|
||||
SET inputextension=%~x1
|
||||
rem inputextension should be dot-psd
|
||||
rem color space must be Lab16
|
||||
|
||||
IF "%inputextension%" NEQ ".psd" goto fail
|
||||
|
||||
convert %1 -colorspace sRGB -write mpr:temp -background black -alpha Remove mpr:temp -compose Copy_Opacity -composite "%basefilename%.tga"
|
||||
|
||||
exit
|
||||
|
||||
:fail
|
||||
echo "File not PSD"
|
||||
pause
|
||||
exit /b 1
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -10,9 +10,9 @@ uniform sampler2D u_texture;
|
||||
|
||||
|
||||
// "steps" of R, G and B. Must be integer && equal or greater than 2
|
||||
uniform float rcount = 32.0;
|
||||
uniform float gcount = 32.0;
|
||||
uniform float bcount = 32.0;
|
||||
uniform float rcount = 64.0;
|
||||
uniform float gcount = 64.0;
|
||||
uniform float bcount = 64.0;
|
||||
uniform float acount = 1.0;
|
||||
|
||||
int bayer[14 * 14] = int[](131,187,8,78,50,18,134,89,155,102,29,95,184,73,22,86,113,171,142,105,34,166,9,60,151,128,40,110,168,137,45,28,64,188,82,54,124,189,80,13,156,56,7,61,186,121,154,6,108,177,24,100,38,176,93,123,83,148,96,17,88,133,44,145,69,161,139,72,30,181,115,27,163,47,178,65,164,14,120,48,5,127,153,52,190,58,126,81,116,21,106,77,173,92,191,63,99,12,76,144,4,185,37,149,192,39,135,23,117,31,170,132,35,172,103,66,129,79,3,97,57,159,70,141,53,94,114,20,49,158,19,146,169,122,183,11,104,180,2,165,152,87,182,118,91,42,67,25,84,147,43,85,125,68,16,136,71,10,193,112,160,138,51,111,162,26,194,46,174,107,41,143,33,74,1,101,195,15,75,140,109,90,32,62,157,98,167,119,179,59,36,130,175,55,0,150);
|
||||
|
||||
@@ -2053,7 +2053,7 @@
|
||||
},
|
||||
{
|
||||
"n": "MENU_LABEL_MAINMENU",
|
||||
"s": "메뉴"
|
||||
"s": "메인 메뉴"
|
||||
},
|
||||
{
|
||||
"n": "MENU_LABEL_MORE",
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
Air tile (tile 0,0) must have colour of 0x00000000, NOT 0xFFFFFF00. You can modify the tga file directly to correct bad exporter behaviour.
|
||||
Air tile (tile 0,0) must have colour of 0x00000000, NOT 0xFFFFFF00. You can modify the tga file directly to correct bad exporter behaviour.
|
||||
|
||||
All TGA must have alpha premultiplied.
|
||||
@@ -1,182 +1,158 @@
|
||||
"id";"drop";"name" ; "shdr"; "shdg"; "shdb"; "shduv";"strength";"dsty";"mate";"fluid";"solid";"clear";"wall"; "lumr"; "lumg"; "lumb";"lumuv";"fall";"dlfn";"vscs";"fv";"friction"
|
||||
"0"; "0";"BLOCK_AIR" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "1";"null"; "0"; "0"; "1"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"4"
|
||||
"16"; "17";"BLOCK_STONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"17"; "17";"BLOCK_STONE_QUARRIED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"18"; "18";"BLOCK_STONE_TILE_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"19"; "19";"BLOCK_STONE_BRICKS" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"32"; "32";"BLOCK_DIRT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"dirt"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"33"; "32";"BLOCK_GRASS" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"grss"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"34"; "34";"BLOCK_GRASSWALL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"grss"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"35"; "35";"BLOCK_FOLIAGE_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"grss"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"36"; "36";"BLOCK_FOLIAGE_LIME" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"grss"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"37"; "37";"BLOCK_FOLIAGE_GOLD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"grss"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"38"; "38";"BLOCK_FOLIAGE_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"grss"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"39"; "39";"BLOCK_FOLIAGE_ICEBLUE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"grss"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"40"; "40";"BLOCK_FOLIAGE_PURPLE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"grss"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"48"; "48";"BLOCK_PLANK_NORMAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "16"; "740";"wood"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"49"; "49";"BLOCK_PLANK_EBONY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "19";"1200";"wood"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"50"; "50";"BLOCK_PLANK_BIRCH" ;"0.1252";"0.1252";"0.1252";"0.1252"; "15"; "670";"wood"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"51"; "51";"BLOCK_PLANK_BLOODROSE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "17"; "900";"wood"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"64"; "64";"BLOCK_TRUNK_NORMAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "16"; "740";"wood"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"65"; "65";"BLOCK_TRUNK_EBONY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "19";"1200";"wood"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"66"; "66";"BLOCK_TRUNK_BIRCH" ;"0.1252";"0.1252";"0.1252";"0.1252"; "15"; "670";"wood"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"67"; "67";"BLOCK_TRUNK_BLOODROSE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "17"; "900";"wood"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"80"; "80";"BLOCK_SAND" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"sand"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "1"; "0"; "N/A"; "0";"16"
|
||||
"81"; "81";"BLOCK_SAND_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"sand"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "1"; "0"; "N/A"; "0";"16"
|
||||
"82"; "82";"BLOCK_SAND_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"sand"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "1"; "0"; "N/A"; "0";"16"
|
||||
"83"; "83";"BLOCK_SAND_DESERT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"sand"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "1"; "0"; "N/A"; "0";"16"
|
||||
"84"; "84";"BLOCK_SAND_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"sand"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "1"; "0"; "N/A"; "0";"16"
|
||||
"85"; "85";"BLOCK_SAND_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"sand"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "1"; "0"; "N/A"; "0";"16"
|
||||
"96"; "96";"BLOCK_GRAVEL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"grvl"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "1"; "0"; "N/A"; "0";"16"
|
||||
"97"; "97";"BLOCK_GRAVEL_GREY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"grvl"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "1"; "0"; "N/A"; "0";"16"
|
||||
"112"; "112";"BLOCK_ORE_MALACHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"113"; "113";"BLOCK_ORE_HEMATITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"114"; "114";"BLOCK_ORE_NATURAL_GOLD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"115"; "115";"BLOCK_ORE_NATURAL_SILVER" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"116"; "116";"BLOCK_ORE_RUTILE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"117"; "117";"BLOCK_ORE_AURICHALCUMITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"128"; "128";"BLOCK_GEM_RUBY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"129"; "129";"BLOCK_GEM_EMERALD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"130"; "130";"BLOCK_GEM_SAPPHIRE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"131"; "131";"BLOCK_GEM_TOPAZ" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"132"; "132";"BLOCK_GEM_DIAMOND" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"133"; "133";"BLOCK_GEM_AMETHYST" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"144"; "144";"BLOCK_SNOW" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24"; "500";"snow"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"145"; "0";"BLOCK_ICE_FRAGILE" ;"0.0508";"0.0508";"0.0508";"0.0508"; "5"; "930";"icei"; "0"; "1"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0"; "4"
|
||||
"146"; "146";"BLOCK_ICE_NATURAL" ;"0.1016";"0.1016";"0.1016";"0.1016"; "35"; "930";"icei"; "0"; "1"; "1"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0"; "4"
|
||||
"147"; "147";"BLOCK_ICE_CLEAR_MAGICAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"3720";"icex"; "0"; "1"; "1"; "1";"0.0744";"0.1252";"0.2268";"0.0000"; "0"; "0"; "N/A"; "0"; "4"
|
||||
"148"; "148";"BLOCK_GLASS_CRUDE" ;"0.0120";"0.0040";"0.0120";"0.0080"; "5";"2500";"glas"; "0"; "1"; "1"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"149"; "149";"BLOCK_GLASS_CLEAN" ;"0.0040";"0.0040";"0.0040";"0.0020"; "5";"2203";"glas"; "0"; "1"; "1"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"160"; "160";"BLOCK_PLATFORM_STONE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"rock"; "0"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"161"; "161";"BLOCK_PLATFORM_WOODEN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"wood"; "0"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"162"; "162";"BLOCK_PLATFORM_EBONY" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"wood"; "0"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"163"; "163";"BLOCK_PLATFORM_BIRCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"wood"; "0"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"164"; "164";"BLOCK_PLATFORM_BLOODROSE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"wood"; "0"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"176"; "176";"BLOCK_TORCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"fxtr"; "0"; "0"; "1"; "0";"1.0000";"0.6372";"0.0000";"0.0000"; "0"; "1"; "N/A"; "0";"16"
|
||||
"177"; "177";"BLOCK_TORCH_FROST" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"fxtr"; "0"; "0"; "1"; "0";"0.3048";"0.4848";"1.0000";"0.0000"; "0"; "1"; "N/A"; "0";"16"
|
||||
"192"; "176";"BLOCK_TORCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"fxtr"; "0"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"193"; "177";"BLOCK_TORCH_FROST" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"fxtr"; "0"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"208"; "208";"BLOCK_ILLUMINATOR_WHITE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.9270";"0.9414";"0.8519";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"209"; "209";"BLOCK_ILLUMINATOR_YELLOW" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"1.0000";"0.8408";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"210"; "210";"BLOCK_ILLUMINATOR_ORANGE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"1.0000";"0.5294";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"211"; "211";"BLOCK_ILLUMINATOR_RED" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.9188";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"212"; "212";"BLOCK_ILLUMINATOR_FUCHSIA" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.9188";"0.0000";"0.7156";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"213"; "213";"BLOCK_ILLUMINATOR_PURPLE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.7156";"0.0000";"0.9188";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"214"; "214";"BLOCK_ILLUMINATOR_BLUE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.1996";"0.9188";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"215"; "215";"BLOCK_ILLUMINATOR_CYAN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.4621";"1.4188";"1.2368";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"216"; "216";"BLOCK_ILLUMINATOR_GREEN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.2112";"1.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"217"; "217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.1252";"0.4068";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"218"; "218";"BLOCK_ILLUMINATOR_BROWN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.3324";"0.1252";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"219"; "219";"BLOCK_ILLUMINATOR_TAN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.5864";"0.4068";"0.2032";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"220"; "220";"BLOCK_ILLUMINATOR_GREY_LIGHT";"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.7392";"0.7392";"0.7392";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"221"; "221";"BLOCK_ILLUMINATOR_GREY_MED" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.4576";"0.4576";"0.4576";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"222"; "222";"BLOCK_ILLUMINATOR_GREY_DARK" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.2540";"0.2540";"0.2540";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"223"; "223";"BLOCK_ILLUMINATOR_BLACK" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.2140";"0.0000";"0.4932";"3.7499"; "0"; "0"; "N/A"; "0";"16"
|
||||
"224"; "208";"BLOCK_ILLUMINATOR_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"225"; "209";"BLOCK_ILLUMINATOR_YELLOW" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"226"; "210";"BLOCK_ILLUMINATOR_ORANGE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"227"; "211";"BLOCK_ILLUMINATOR_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"228"; "212";"BLOCK_ILLUMINATOR_FUCHSIA" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"229"; "213";"BLOCK_ILLUMINATOR_PURPLE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"230"; "214";"BLOCK_ILLUMINATOR_BLUE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"231"; "215";"BLOCK_ILLUMINATOR_CYAN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"232"; "216";"BLOCK_ILLUMINATOR_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"233"; "217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"234"; "218";"BLOCK_ILLUMINATOR_BROWN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"235"; "219";"BLOCK_ILLUMINATOR_TAN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"236"; "220";"BLOCK_ILLUMINATOR_GREY_LIGHT";"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"237"; "221";"BLOCK_ILLUMINATOR_GREY_MED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"238"; "222";"BLOCK_ILLUMINATOR_GREY_DARK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"239"; "223";"BLOCK_ILLUMINATOR_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"240"; "240";"BLOCK_SANDSTONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"241"; "241";"BLOCK_SANDSTONE_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"242"; "242";"BLOCK_SANDSTONE_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"243"; "243";"BLOCK_SANDSTONE_DESERT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"244"; "244";"BLOCK_SANDSTONE_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"245"; "245";"BLOCK_SANDSTONE_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"256"; "256";"BLOCK_LANTERN_IRON_REGULAR" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"fxtr"; "0"; "0"; "1"; "0";"1.0000";"0.6372";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"257"; "257";"BLOCK_SUNSTONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "2"; "N/A"; "0";"16"
|
||||
"258"; "258";"BLOCK_DAYLIGHT_CAPACITOR" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "3"; "N/A"; "0";"16"
|
||||
"4064"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
|
||||
"4065"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
|
||||
"4066"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
|
||||
"4067"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
|
||||
"4068"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
|
||||
"4069"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
|
||||
"4070"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
|
||||
"4071"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
|
||||
"4072"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
|
||||
"4073"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
|
||||
"4074"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
|
||||
"4075"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
|
||||
"4076"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
|
||||
"4077"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
|
||||
"4078"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
|
||||
"4079"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
|
||||
"4080"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
|
||||
"4081"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
|
||||
"4082"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
|
||||
"4083"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
|
||||
"4084"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
|
||||
"4085"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
|
||||
"4086"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
|
||||
"4087"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
|
||||
"4088"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
|
||||
"4089"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
|
||||
"4090"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
|
||||
"4091"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
|
||||
"4092"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
|
||||
"4093"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
|
||||
"4094"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
|
||||
"4095"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
|
||||
"-1"; "0";"BLOCK_NULL" ;"4.0000";"4.0000";"4.0000";"4.0000"; "-1";"2600";"null"; "0"; "0"; "1"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||
"id";"drop";"name" ; "shdr"; "shdg"; "shdb"; "shduv";"str";"dsty";"mate";"solid";"plat";"clear";"wall";"fall";"dlfn";"vscs";"fv";"fr"; "lumr"; "lumg"; "lumb"; "lumuv"
|
||||
"0"; "0";"BLOCK_AIR" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "1";"NULL"; "0"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"1"; "1";"BLOCK_MIASMA" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "1";"NULL"; "0"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"16"; "17";"BLOCK_STONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"17"; "17";"BLOCK_STONE_QUARRIED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"18"; "18";"BLOCK_STONE_TILE_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"19"; "19";"BLOCK_STONE_BRICKS" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"32"; "32";"BLOCK_DIRT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"DIRT"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"33"; "32";"BLOCK_GRASS" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"34"; "34";"BLOCK_GRASSWALL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"35"; "35";"BLOCK_FOLIAGE_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"36"; "36";"BLOCK_FOLIAGE_LIME" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"37"; "37";"BLOCK_FOLIAGE_GOLD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"38"; "38";"BLOCK_FOLIAGE_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"39"; "39";"BLOCK_FOLIAGE_ICEBLUE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"40"; "40";"BLOCK_FOLIAGE_PURPLE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"48"; "48";"BLOCK_PLANK_NORMAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "16"; "740";"WOOD"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"49"; "49";"BLOCK_PLANK_EBONY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "19";"1200";"WOOD"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"50"; "50";"BLOCK_PLANK_BIRCH" ;"0.1252";"0.1252";"0.1252";"0.1252"; "15"; "670";"WOOD"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"51"; "51";"BLOCK_PLANK_BLOODROSE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "17"; "900";"WOOD"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"64"; "64";"BLOCK_TRUNK_NORMAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "16"; "740";"WOOD"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"65"; "65";"BLOCK_TRUNK_EBONY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "19";"1200";"WOOD"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"66"; "66";"BLOCK_TRUNK_BIRCH" ;"0.1252";"0.1252";"0.1252";"0.1252"; "15"; "670";"WOOD"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"67"; "67";"BLOCK_TRUNK_BLOODROSE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "17"; "900";"WOOD"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"80"; "80";"BLOCK_SAND" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"81"; "81";"BLOCK_SAND_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"82"; "82";"BLOCK_SAND_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"83"; "83";"BLOCK_SAND_DESERT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"84"; "84";"BLOCK_SAND_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"85"; "85";"BLOCK_SAND_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"96"; "96";"BLOCK_GRAVEL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"GRVL"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"97"; "97";"BLOCK_GRAVEL_GREY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"GRVL"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"112"; "112";"BLOCK_ORE_MALACHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"113"; "113";"BLOCK_ORE_HEMATITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"114"; "114";"BLOCK_ORE_NATURAL_GOLD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"115"; "115";"BLOCK_ORE_NATURAL_SILVER" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"116"; "116";"BLOCK_ORE_RUTILE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"117"; "117";"BLOCK_ORE_AURICHALCUMITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"128"; "128";"BLOCK_GEM_RUBY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"129"; "129";"BLOCK_GEM_EMERALD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"130"; "130";"BLOCK_GEM_SAPPHIRE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"131"; "131";"BLOCK_GEM_TOPAZ" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"132"; "132";"BLOCK_GEM_DIAMOND" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"133"; "133";"BLOCK_GEM_AMETHYST" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"144"; "144";"BLOCK_SNOW" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24"; "500";"SNOW"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"145"; "0";"BLOCK_ICE_FRAGILE" ;"0.0508";"0.0508";"0.0508";"0.0508"; "5"; "930";"ICEI"; "1"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"146"; "146";"BLOCK_ICE_NATURAL" ;"0.1016";"0.1016";"0.1016";"0.1016"; "35"; "930";"ICEI"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"147"; "147";"BLOCK_ICE_CLEAR_MAGICAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"3720";"ICEX"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0744";"0.1252";"0.2268";"0.0000"
|
||||
"148"; "148";"BLOCK_GLASS_CRUDE" ;"0.0876";"0.0424";"0.0876";"0.1252"; "5";"2500";"GLAS"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"149"; "149";"BLOCK_GLASS_CLEAN" ;"0.0424";"0.0424";"0.0424";"0.0636"; "5";"2203";"GLAS"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"160"; "160";"BLOCK_PLATFORM_STONE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"ROCK"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"161"; "161";"BLOCK_PLATFORM_WOODEN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"162"; "162";"BLOCK_PLATFORM_EBONY" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"163"; "163";"BLOCK_PLATFORM_BIRCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"164"; "164";"BLOCK_PLATFORM_BLOODROSE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"176"; "176";"BLOCK_TORCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "1"; "N/A"; "0";"16";"1.0000";"0.6372";"0.0000";"0.0000"
|
||||
"177"; "177";"BLOCK_TORCH_FROST" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "1"; "N/A"; "0";"16";"0.3048";"0.4848";"1.0000";"0.0000"
|
||||
"192"; "176";"BLOCK_TORCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"193"; "177";"BLOCK_TORCH_FROST" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"208"; "208";"BLOCK_ILLUMINATOR_WHITE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.9270";"0.9414";"0.8519";"0.0000"
|
||||
"209"; "209";"BLOCK_ILLUMINATOR_YELLOW" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"1.0000";"0.8408";"0.0000";"0.0000"
|
||||
"210"; "210";"BLOCK_ILLUMINATOR_ORANGE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"1.0000";"0.5294";"0.0000";"0.0000"
|
||||
"211"; "211";"BLOCK_ILLUMINATOR_RED" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.9188";"0.0000";"0.0000";"0.0000"
|
||||
"212"; "212";"BLOCK_ILLUMINATOR_FUCHSIA" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.9188";"0.0000";"0.7156";"0.0000"
|
||||
"213"; "213";"BLOCK_ILLUMINATOR_PURPLE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.7156";"0.0000";"0.9188";"0.0000"
|
||||
"214"; "214";"BLOCK_ILLUMINATOR_BLUE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.1996";"0.9188";"0.0000"
|
||||
"215"; "215";"BLOCK_ILLUMINATOR_CYAN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.4621";"1.4188";"1.2368";"0.0000"
|
||||
"216"; "216";"BLOCK_ILLUMINATOR_GREEN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.2112";"1.0000";"0.0000";"0.0000"
|
||||
"217"; "217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.1252";"0.4068";"0.0000";"0.0000"
|
||||
"218"; "218";"BLOCK_ILLUMINATOR_BROWN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.3324";"0.1252";"0.0000";"0.0000"
|
||||
"219"; "219";"BLOCK_ILLUMINATOR_TAN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.5864";"0.4068";"0.2032";"0.0000"
|
||||
"220"; "220";"BLOCK_ILLUMINATOR_GREY_LIGHT";"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.7392";"0.7392";"0.7392";"0.0000"
|
||||
"221"; "221";"BLOCK_ILLUMINATOR_GREY_MED" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.4576";"0.4576";"0.4576";"0.0000"
|
||||
"222"; "222";"BLOCK_ILLUMINATOR_GREY_DARK" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.2540";"0.2540";"0.2540";"0.0000"
|
||||
"223"; "223";"BLOCK_ILLUMINATOR_BLACK" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.2140";"0.0000";"0.4932";"3.7499"
|
||||
"224"; "208";"BLOCK_ILLUMINATOR_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"225"; "209";"BLOCK_ILLUMINATOR_YELLOW" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"226"; "210";"BLOCK_ILLUMINATOR_ORANGE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"227"; "211";"BLOCK_ILLUMINATOR_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"228"; "212";"BLOCK_ILLUMINATOR_FUCHSIA" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"229"; "213";"BLOCK_ILLUMINATOR_PURPLE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"230"; "214";"BLOCK_ILLUMINATOR_BLUE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"231"; "215";"BLOCK_ILLUMINATOR_CYAN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"232"; "216";"BLOCK_ILLUMINATOR_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"233"; "217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"234"; "218";"BLOCK_ILLUMINATOR_BROWN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"235"; "219";"BLOCK_ILLUMINATOR_TAN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"236"; "220";"BLOCK_ILLUMINATOR_GREY_LIGHT";"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"237"; "221";"BLOCK_ILLUMINATOR_GREY_MED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"238"; "222";"BLOCK_ILLUMINATOR_GREY_DARK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"239"; "223";"BLOCK_ILLUMINATOR_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"240"; "240";"BLOCK_SANDSTONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"241"; "241";"BLOCK_SANDSTONE_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"242"; "242";"BLOCK_SANDSTONE_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"243"; "243";"BLOCK_SANDSTONE_DESERT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"244"; "244";"BLOCK_SANDSTONE_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"245"; "245";"BLOCK_SANDSTONE_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"256"; "256";"BLOCK_LANTERN_IRON_REGULAR" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"1.0000";"0.6372";"0.0000";"0.0000"
|
||||
"257"; "257";"BLOCK_SUNSTONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"ROCK"; "1"; "0"; "0"; "0"; "0"; "2"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"258"; "258";"BLOCK_DAYLIGHT_CAPACITOR" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "0"; "0"; "3"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"4096"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0826";"100";"1000";"WATR"; "0"; "0"; "1"; "0"; "0"; "0"; "16"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"4097"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696";"100";"2600";"ROCK"; "0"; "0"; "1"; "0"; "0"; "0"; "32"; "0";"16";"0.7664";"0.2032";"0.0000";"0.0000"
|
||||
"-1"; "0";"BLOCK_NULL" ;"4.0000";"4.0000";"4.0000";"4.0000"; "-1";"2600";"NULL"; "0"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
|
||||
## Notes ##
|
||||
|
||||
# id: Block ID
|
||||
#
|
||||
# Lava/Water props are left for future references, do not delete them until FluidCodex is built #
|
||||
#
|
||||
# id: Block ID. ID equal to or greater than 4096 is for fluids, mainly for lighting calculation.
|
||||
# drop: Drop ID
|
||||
|
||||
#
|
||||
# shdr/g/b, lumr/g/b: Shade RGB/ Lum RGB.
|
||||
# valid range: float of 0..4; 1.0 for 255
|
||||
|
||||
# Friction: 0: frictionless, <16: slippery, 16: regular, >16: sticky
|
||||
|
||||
#
|
||||
# solid: whether the tile has full collision (affects physics; flowers are not solid, glass is solid)
|
||||
# clear: whether the tile has trnasparency (affects render; flowers AND glass is clear)
|
||||
|
||||
# clear: [PENDING FOR REMOVAL] whether the tile has trnasparency (affects render; flowers AND glass is clear)
|
||||
# plat: if the block is a Platform (applicable target: actual platforms, furniture filler block that collision == PLATFORM)
|
||||
#
|
||||
# vscs: viscosity, (velocity) / (1 + (n/16)), 16 halves movement speed, can be used to non-fluid tiles (sticky hazard, tarmac road in Terraria)
|
||||
|
||||
#
|
||||
# str: strength
|
||||
#
|
||||
# dsty: density. As we are putting water an 1000, it is identical to specific gravity. [g/l]
|
||||
|
||||
#
|
||||
# dlfn: dynamic luminosity function.
|
||||
# 0-static, 1-torch flicker, 2-current global light (sun, star, moon), 3-daylight at noon,
|
||||
# 4-slow breath, 5-pulsate
|
||||
|
||||
#
|
||||
# mate: material, four-letter code
|
||||
|
||||
#
|
||||
# fv: vertical friction (boolean)
|
||||
|
||||
|
||||
# fr: horizontal friction. 0: frictionless, <16: slippery, 16: regular, >16: sticky
|
||||
#
|
||||
#
|
||||
## Illuminators ##
|
||||
|
||||
# Illuminator white: Mercury Lamp; CIELAB of (94, -5.131, 10.613), which is made out of CIEXYZ of (0.947638, 1.146481, 0.482263), measured with ColorMunki Spectrometer (If you want high CRI lamp, collect a daylight!)
|
||||
#
|
||||
# Illuminator white: Mercury Lamp; CIELAB of (94, -5.131, 10.613), which is made out of CIEXYZ of (0.947638, 1.146481, 0.482263), measured with ColorMunki Spectrometer (If you don't want green tinge, collect a daylight!)
|
||||
# Illuminator orange: Sodium Lamp; CIE xy of (0.5375, 0.4153), CIEXYZ of (352.531139, 272.379377, 30.980339), measured with ColorMunki Spectrometer
|
||||
# Defalut torch : Y 64 x 0.55183 y 0.40966 (Planckian ~1 770 K); real candlelight colour taken from Spyder5 colorimeter (for I couldn't afford i1DisplayPro/Colormunki)
|
||||
# Defalut torch : Y 64 x 0.55183 y 0.40966 (Planckian ~1 770 K); real candlelight colour taken from Spyder5 colorimeter (for I couldn't afford i1DisplayPro/Colormunki -- at least back then!)
|
||||
# Sunstone: Artificial sunlight, change colour over time in sync with sunlight. The light is set by game's code.
|
||||
# Sunlight capacitor: daylight at noon. Set by game's code.
|
||||
|
||||
#
|
||||
# BLOCK_ILLUMINATOR_CYAN is actually a SUPER_LUMINATOR, cyan colour is used as:
|
||||
# 1. It has quite a brightness on RGB colour space
|
||||
# 2. Helmholz-Kohlraush effect
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
## Tiles ##
|
||||
|
||||
#
|
||||
# 16 colour palette : games's 16-colour palette
|
||||
# Magical ice: theoretical __metallic__ ice that might form under super-high pressure (> 5 TPa). Its density is a wild guess.
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
## References ##
|
||||
|
||||
#
|
||||
# * Density of various woods : http://www.engineeringtoolbox.com/wood-density-d_40.html
|
||||
# * Density of various phases of ice : http://www1.lsbu.ac.uk/water/ice_phases.html
|
||||
#
|
||||
|
Can't render this file because it contains an unexpected character in line 1 and column 20.
|
157
assets/mods/basegame/blocks/blocks_old.csv
Normal file
157
assets/mods/basegame/blocks/blocks_old.csv
Normal file
@@ -0,0 +1,157 @@
|
||||
"id";"drop";"name" ; "shdr"; "shdg"; "shdb"; "shduv";"str";"dsty";"mate";"solid";"plat";"clear";"wall";"fall";"dlfn";"vscs";"fv";"fr"; "lumr"; "lumg"; "lumb"; "lumuv"
|
||||
"0"; "0";"BLOCK_AIR" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "1";"NULL"; "0"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"16"; "17";"BLOCK_STONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"17"; "17";"BLOCK_STONE_QUARRIED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"18"; "18";"BLOCK_STONE_TILE_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"19"; "19";"BLOCK_STONE_BRICKS" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"32"; "32";"BLOCK_DIRT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"DIRT"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"33"; "32";"BLOCK_GRASS" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"34"; "34";"BLOCK_GRASSWALL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"35"; "35";"BLOCK_FOLIAGE_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"36"; "36";"BLOCK_FOLIAGE_LIME" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"37"; "37";"BLOCK_FOLIAGE_GOLD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"38"; "38";"BLOCK_FOLIAGE_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"39"; "39";"BLOCK_FOLIAGE_ICEBLUE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"40"; "40";"BLOCK_FOLIAGE_PURPLE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"48"; "48";"BLOCK_PLANK_NORMAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "16"; "740";"WOOD"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"49"; "49";"BLOCK_PLANK_EBONY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "19";"1200";"WOOD"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"50"; "50";"BLOCK_PLANK_BIRCH" ;"0.1252";"0.1252";"0.1252";"0.1252"; "15"; "670";"WOOD"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"51"; "51";"BLOCK_PLANK_BLOODROSE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "17"; "900";"WOOD"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"64"; "64";"BLOCK_TRUNK_NORMAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "16"; "740";"WOOD"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"65"; "65";"BLOCK_TRUNK_EBONY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "19";"1200";"WOOD"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"66"; "66";"BLOCK_TRUNK_BIRCH" ;"0.1252";"0.1252";"0.1252";"0.1252"; "15"; "670";"WOOD"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"67"; "67";"BLOCK_TRUNK_BLOODROSE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "17"; "900";"WOOD"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"80"; "80";"BLOCK_SAND" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"81"; "81";"BLOCK_SAND_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"82"; "82";"BLOCK_SAND_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"83"; "83";"BLOCK_SAND_DESERT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"84"; "84";"BLOCK_SAND_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"85"; "85";"BLOCK_SAND_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"96"; "96";"BLOCK_GRAVEL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"GRVL"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"97"; "97";"BLOCK_GRAVEL_GREY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"GRVL"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"112"; "112";"BLOCK_ORE_MALACHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"113"; "113";"BLOCK_ORE_HEMATITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"114"; "114";"BLOCK_ORE_NATURAL_GOLD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"115"; "115";"BLOCK_ORE_NATURAL_SILVER" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"116"; "116";"BLOCK_ORE_RUTILE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"117"; "117";"BLOCK_ORE_AURICHALCUMITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"128"; "128";"BLOCK_GEM_RUBY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"129"; "129";"BLOCK_GEM_EMERALD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"130"; "130";"BLOCK_GEM_SAPPHIRE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"131"; "131";"BLOCK_GEM_TOPAZ" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"132"; "132";"BLOCK_GEM_DIAMOND" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"133"; "133";"BLOCK_GEM_AMETHYST" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"144"; "144";"BLOCK_SNOW" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24"; "500";"SNOW"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"145"; "0";"BLOCK_ICE_FRAGILE" ;"0.0508";"0.0508";"0.0508";"0.0508"; "5"; "930";"ICEI"; "1"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"146"; "146";"BLOCK_ICE_NATURAL" ;"0.1016";"0.1016";"0.1016";"0.1016"; "35"; "930";"ICEI"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"147"; "147";"BLOCK_ICE_CLEAR_MAGICAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"3720";"ICEX"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0744";"0.1252";"0.2268";"0.0000"
|
||||
"148"; "148";"BLOCK_GLASS_CRUDE" ;"0.0120";"0.0040";"0.0120";"0.0080"; "5";"2500";"GLAS"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"149"; "149";"BLOCK_GLASS_CLEAN" ;"0.0040";"0.0040";"0.0040";"0.0020"; "5";"2203";"GLAS"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"160"; "160";"BLOCK_PLATFORM_STONE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"ROCK"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"161"; "161";"BLOCK_PLATFORM_WOODEN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"162"; "162";"BLOCK_PLATFORM_EBONY" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"163"; "163";"BLOCK_PLATFORM_BIRCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"164"; "164";"BLOCK_PLATFORM_BLOODROSE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"176"; "176";"BLOCK_TORCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "1"; "N/A"; "0";"16";"1.0000";"0.6372";"0.0000";"0.0000"
|
||||
"177"; "177";"BLOCK_TORCH_FROST" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "1"; "N/A"; "0";"16";"0.3048";"0.4848";"1.0000";"0.0000"
|
||||
"192"; "176";"BLOCK_TORCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"193"; "177";"BLOCK_TORCH_FROST" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"208"; "208";"BLOCK_ILLUMINATOR_WHITE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.9270";"0.9414";"0.8519";"0.0000"
|
||||
"209"; "209";"BLOCK_ILLUMINATOR_YELLOW" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"1.0000";"0.8408";"0.0000";"0.0000"
|
||||
"210"; "210";"BLOCK_ILLUMINATOR_ORANGE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"1.0000";"0.5294";"0.0000";"0.0000"
|
||||
"211"; "211";"BLOCK_ILLUMINATOR_RED" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.9188";"0.0000";"0.0000";"0.0000"
|
||||
"212"; "212";"BLOCK_ILLUMINATOR_FUCHSIA" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.9188";"0.0000";"0.7156";"0.0000"
|
||||
"213"; "213";"BLOCK_ILLUMINATOR_PURPLE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.7156";"0.0000";"0.9188";"0.0000"
|
||||
"214"; "214";"BLOCK_ILLUMINATOR_BLUE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.1996";"0.9188";"0.0000"
|
||||
"215"; "215";"BLOCK_ILLUMINATOR_CYAN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.4621";"1.4188";"1.2368";"0.0000"
|
||||
"216"; "216";"BLOCK_ILLUMINATOR_GREEN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.2112";"1.0000";"0.0000";"0.0000"
|
||||
"217"; "217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.1252";"0.4068";"0.0000";"0.0000"
|
||||
"218"; "218";"BLOCK_ILLUMINATOR_BROWN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.3324";"0.1252";"0.0000";"0.0000"
|
||||
"219"; "219";"BLOCK_ILLUMINATOR_TAN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.5864";"0.4068";"0.2032";"0.0000"
|
||||
"220"; "220";"BLOCK_ILLUMINATOR_GREY_LIGHT";"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.7392";"0.7392";"0.7392";"0.0000"
|
||||
"221"; "221";"BLOCK_ILLUMINATOR_GREY_MED" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.4576";"0.4576";"0.4576";"0.0000"
|
||||
"222"; "222";"BLOCK_ILLUMINATOR_GREY_DARK" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.2540";"0.2540";"0.2540";"0.0000"
|
||||
"223"; "223";"BLOCK_ILLUMINATOR_BLACK" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.2140";"0.0000";"0.4932";"3.7499"
|
||||
"224"; "208";"BLOCK_ILLUMINATOR_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"225"; "209";"BLOCK_ILLUMINATOR_YELLOW" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"226"; "210";"BLOCK_ILLUMINATOR_ORANGE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"227"; "211";"BLOCK_ILLUMINATOR_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"228"; "212";"BLOCK_ILLUMINATOR_FUCHSIA" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"229"; "213";"BLOCK_ILLUMINATOR_PURPLE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"230"; "214";"BLOCK_ILLUMINATOR_BLUE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"231"; "215";"BLOCK_ILLUMINATOR_CYAN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"232"; "216";"BLOCK_ILLUMINATOR_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"233"; "217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"234"; "218";"BLOCK_ILLUMINATOR_BROWN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"235"; "219";"BLOCK_ILLUMINATOR_TAN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"236"; "220";"BLOCK_ILLUMINATOR_GREY_LIGHT";"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"237"; "221";"BLOCK_ILLUMINATOR_GREY_MED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"238"; "222";"BLOCK_ILLUMINATOR_GREY_DARK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"239"; "223";"BLOCK_ILLUMINATOR_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"240"; "240";"BLOCK_SANDSTONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"241"; "241";"BLOCK_SANDSTONE_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"242"; "242";"BLOCK_SANDSTONE_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"243"; "243";"BLOCK_SANDSTONE_DESERT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"244"; "244";"BLOCK_SANDSTONE_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"245"; "245";"BLOCK_SANDSTONE_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"256"; "256";"BLOCK_LANTERN_IRON_REGULAR" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"1.0000";"0.6372";"0.0000";"0.0000"
|
||||
"257"; "257";"BLOCK_SUNSTONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"ROCK"; "1"; "0"; "0"; "0"; "0"; "2"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"258"; "258";"BLOCK_DAYLIGHT_CAPACITOR" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "0"; "0"; "3"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"4094"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696";"100";"2600";"ROCK"; "0"; "0"; "1"; "0"; "0"; "0"; "32"; "0";"16";"0.7664";"0.2032";"0.0000";"0.0000"
|
||||
"4095"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508";"100";"1000";"WATR"; "0"; "0"; "1"; "0"; "0"; "0"; "16"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
"-1"; "0";"BLOCK_NULL" ;"4.0000";"4.0000";"4.0000";"4.0000"; "-1";"2600";"NULL"; "0"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
|
||||
|
||||
## Notes ##
|
||||
#
|
||||
# Lava/Water props are left for future references, do not delete them until FluidCodex is built #
|
||||
#
|
||||
# id: Block ID
|
||||
# drop: Drop ID
|
||||
#
|
||||
# shdr/g/b, lumr/g/b: Shade RGB/ Lum RGB.
|
||||
# valid range: float of 0..4; 1.0 for 255
|
||||
#
|
||||
# solid: whether the tile has full collision (affects physics; flowers are not solid, glass is solid)
|
||||
# clear: [PENDING FOR REMOVAL] whether the tile has trnasparency (affects render; flowers AND glass is clear)
|
||||
# plat: if the block is a Platform (applicable target: actual platforms, furniture filler block that collision == PLATFORM)
|
||||
#
|
||||
# vscs: viscosity, (velocity) / (1 + (n/16)), 16 halves movement speed, can be used to non-fluid tiles (sticky hazard, tarmac road in Terraria)
|
||||
#
|
||||
# str: strength
|
||||
#
|
||||
# dsty: density. As we are putting water an 1000, it is identical to specific gravity. [g/l]
|
||||
#
|
||||
# dlfn: dynamic luminosity function.
|
||||
# 0-static, 1-torch flicker, 2-current global light (sun, star, moon), 3-daylight at noon,
|
||||
# 4-slow breath, 5-pulsate
|
||||
#
|
||||
# mate: material, four-letter code
|
||||
#
|
||||
# fv: vertical friction (boolean)
|
||||
# fr: horizontal friction. 0: frictionless, <16: slippery, 16: regular, >16: sticky
|
||||
#
|
||||
#
|
||||
## Illuminators ##
|
||||
#
|
||||
# Illuminator white: Mercury Lamp; CIELAB of (94, -5.131, 10.613), which is made out of CIEXYZ of (0.947638, 1.146481, 0.482263), measured with ColorMunki Spectrometer (If you don't want green tinge, collect a daylight!)
|
||||
# Illuminator orange: Sodium Lamp; CIE xy of (0.5375, 0.4153), CIEXYZ of (352.531139, 272.379377, 30.980339), measured with ColorMunki Spectrometer
|
||||
# Defalut torch : Y 64 x 0.55183 y 0.40966 (Planckian ~1 770 K); real candlelight colour taken from Spyder5 colorimeter (for I couldn't afford i1DisplayPro/Colormunki -- at least back then!)
|
||||
# Sunstone: Artificial sunlight, change colour over time in sync with sunlight. The light is set by game's code.
|
||||
# Sunlight capacitor: daylight at noon. Set by game's code.
|
||||
#
|
||||
# BLOCK_ILLUMINATOR_CYAN is actually a SUPER_LUMINATOR, cyan colour is used as:
|
||||
# 1. It has quite a brightness on RGB colour space
|
||||
# 2. Helmholz-Kohlraush effect
|
||||
#
|
||||
#
|
||||
## Tiles ##
|
||||
#
|
||||
# 16 colour palette : games's 16-colour palette
|
||||
# Magical ice: theoretical __metallic__ ice that might form under super-high pressure (> 5 TPa). Its density is a wild guess.
|
||||
#
|
||||
#
|
||||
## References ##
|
||||
#
|
||||
# * Density of various woods : http://www.engineeringtoolbox.com/wood-density-d_40.html
|
||||
# * Density of various phases of ice : http://www1.lsbu.ac.uk/water/ice_phases.html
|
||||
#
|
||||
|
Can't render this file because it contains an unexpected character in line 1 and column 20.
|
BIN
assets/mods/basegame/blocks/fluids.tga.gz
LFS
Normal file
BIN
assets/mods/basegame/blocks/fluids.tga.gz
LFS
Normal file
Binary file not shown.
Binary file not shown.
BIN
assets/mods/basegame/blocks/terrain_autumn.tga.gz
LFS
Normal file
BIN
assets/mods/basegame/blocks/terrain_autumn.tga.gz
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/blocks/terrain_spring.tga.gz
LFS
Normal file
BIN
assets/mods/basegame/blocks/terrain_spring.tga.gz
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/blocks/terrain_winter.tga.gz
LFS
Normal file
BIN
assets/mods/basegame/blocks/terrain_winter.tga.gz
LFS
Normal file
Binary file not shown.
@@ -8,22 +8,22 @@
|
||||
"multithread": true,
|
||||
|
||||
|
||||
"joypadkeyn": 4,
|
||||
"joypadkeyw": 1,
|
||||
"joypadkeys": 2,
|
||||
"joypadkeye": 3,
|
||||
"gamepadkeyn": 4,
|
||||
"gamepadkeyw": 1,
|
||||
"gamepadkeys": 2,
|
||||
"gamepadkeye": 3,
|
||||
|
||||
"joypadlup": 4,
|
||||
"joypadrup": 5,
|
||||
"joypadldown": 6,
|
||||
"joypadrdown": 7,
|
||||
"gamepadlup": 4,
|
||||
"gamepadrup": 5,
|
||||
"gamepadldown": 6,
|
||||
"gamepadrdown": 7,
|
||||
|
||||
"joypadlstickx": 0,
|
||||
"joypadlsticky": 1,
|
||||
"joypadrstickx": 2,
|
||||
"joypadrsticky": 3,
|
||||
"gamepadlstickx": 0,
|
||||
"gamepadlsticky": 1,
|
||||
"gamepadrstickx": 2,
|
||||
"gamepadrsticky": 3,
|
||||
|
||||
"joypadlabelstyle": "msxb360",
|
||||
"gamepadlabelstyle": "msxb360",
|
||||
|
||||
|
||||
"keyup": 33,
|
||||
|
||||
BIN
assets/mods/basegame/demoworld.gz
LFS
Normal file
BIN
assets/mods/basegame/demoworld.gz
LFS
Normal file
Binary file not shown.
Binary file not shown.
BIN
assets/mods/basegame/fonts/watch_new.tga
LFS
Normal file
BIN
assets/mods/basegame/fonts/watch_new.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/gui/old_watchface_atlas.tga
LFS
Normal file
BIN
assets/mods/basegame/gui/old_watchface_atlas.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/gui/old_watchface_atlas_floatey.tga
LFS
Normal file
BIN
assets/mods/basegame/gui/old_watchface_atlas_floatey.tga
LFS
Normal file
Binary file not shown.
Binary file not shown.
@@ -1,13 +1,13 @@
|
||||
"idst";"dsty";"forcemod";"endurance";"comments"
|
||||
"rock";"2400"; "1"; "0.42";
|
||||
"cupr";"1000"; "2"; "1.00";"copper"
|
||||
"egls";"2500"; "4"; "0.82";"elven glass"
|
||||
"iron";"1000"; "5"; "1.42";
|
||||
"argn";"1000"; "9"; "0.91";"argentum/silver"
|
||||
"stal";"1000"; "14"; "1.73";"steel"
|
||||
"eaur";"1000"; "21"; "1.36";"elven aurichalcum"
|
||||
"tial";"1000"; "33"; "2.16";"titanium alloy (Ti6Al4V)"
|
||||
"admt";"1000"; "71"; "3.42";"adamant"
|
||||
"ROCK";"2400"; "1"; "0.42";
|
||||
"CUPR";"1000"; "2"; "1.00";"copper"
|
||||
"EGLS";"2500"; "4"; "0.82";"elven glass"
|
||||
"IRON";"1000"; "5"; "1.42";
|
||||
"ARGN";"1000"; "9"; "0.91";"argentum/silver"
|
||||
"STAL";"1000"; "14"; "1.73";"steel"
|
||||
"EAUR";"1000"; "21"; "1.36";"elven aurichalcum"
|
||||
"TIAL";"1000"; "33"; "2.16";"titanium alloy (Ti6Al4V)"
|
||||
"ADMT";"1000"; "71"; "3.42";"adamant"
|
||||
|
||||
# idst: ID_STRING
|
||||
|
||||
|
||||
|
Binary file not shown.
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_arm_rest_left.tga
LFS
Normal file
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_arm_rest_left.tga
LFS
Normal file
Binary file not shown.
Binary file not shown.
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_foot_left.tga
LFS
Normal file
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_foot_left.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_foot_right.tga
LFS
Normal file
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_foot_right.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_hair.tga
LFS
Normal file
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_hair.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_hair_fore.tga
LFS
Normal file
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_hair_fore.tga
LFS
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_head.tga
LFS
Normal file
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_head.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_leg_rest_left.tga
LFS
Normal file
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_leg_rest_left.tga
LFS
Normal file
Binary file not shown.
Binary file not shown.
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_lower_torso.tga
LFS
Normal file
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_lower_torso.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_upper_torso.tga
LFS
Normal file
BIN
assets/mods/basegame/sprites/sprite_assembler_test_assets/test_upper_torso.tga
LFS
Normal file
Binary file not shown.
35
assets/mods/basegame/sprites/test_sprite.properties
Normal file
35
assets/mods/basegame/sprites/test_sprite.properties
Normal file
@@ -0,0 +1,35 @@
|
||||
# complete file name is: SPRITESHEET + bodypart name + EXTENSION
|
||||
SPRITESHEET=mods/basegame/sprites/sprite_assembler_test_assets/test_
|
||||
EXTENSION=.tga
|
||||
# defines frame size and origin point. Origin point is given as: (originx, size.y - 1)
|
||||
CONFIG=SIZE 48,56;ORIGINX 29
|
||||
|
||||
# note to self: don't implement skeleton hierarchy: there's too many exceptions
|
||||
# besides, you have "ALL" key.
|
||||
|
||||
! a skeleton also defines what body parts (images) be used.
|
||||
! you can also write multiline text using reverse solidus; this is a feature of .properties
|
||||
! skeleton joints are ordered: foremost-drawn object comes first, which means lowermost object IN THIS LIST
|
||||
! are painted first, and any object that comes before it will paint over it. In other words, this list is
|
||||
! first reversed then being iterated.
|
||||
! Joints' original point is defined in the document sprite_joints.psd. It also has visual representations.
|
||||
# TODO right now accessory points are explicitly defined. Should they be injected in run-time?
|
||||
SKELETON_STAND=HEADGEAR 0,32;HAIR_FORE 0,32;\
|
||||
ARM_REST_RIGHT -7,23;HAND_REST_RIGHT -6,11;HELD_ITEM -6,11;\
|
||||
HAIR 0,32;HEAD 0,32;\
|
||||
UPPER_TORSO 0,23;LOWER_TORSO 0,15;\
|
||||
FOOT_RIGHT -2,2;LEG_REST_RIGHT -2,7;\
|
||||
FOOT_LEFT 2,2;LEG_REST_LEFT 2,7;\
|
||||
ARM_REST_LEFT 5,24;HAND_REST_LEFT 6,12
|
||||
|
||||
# skeleton_stand is used for testing purpose
|
||||
ANIM_RUN=DELAY 0.15;ROW 2;SKELETON SKELETON_STAND
|
||||
ANIM_RUN_1=LEG_REST_RIGHT 1,1;FOOT_RIGHT 1,1;LEG_REST_LEFT -1,0;FOOT_LEFT -1,0
|
||||
ANIM_RUN_2=ALL 0,1;LEG_REST_RIGHT 0,-1;FOOT_RIGHT 0,-1;LEG_REST_LEFT 0,1;FOOT_LEFT 0,1
|
||||
ANIM_RUN_3=LEG_REST_RIGHT -1,0;FOOT_RIGHT -1,0;LEG_REST_LEFT 1,1;FOOT_LEFT 1,1
|
||||
ANIM_RUN_4=ALL 0,1;LEG_REST_RIGHT 0,1;FOOT_RIGHT 0,1;LEG_REST_LEFT 0,-1;FOOT_LEFT 0,-1
|
||||
|
||||
ANIM_IDLE=DELAY 2;ROW 1;SKELETON SKELETON_STAND
|
||||
ANIM_IDLE_1=
|
||||
! ANIM_IDLE_1 will not make any transformation
|
||||
ANIM_IDLE_2=UPPER_TORSO 0,-1;HEAD 0,-1;HAIR 0,-1;HELD_ITEM 0,-1;ARM_REST_LEFT 0,-1;ARM_REST_RIGHT 0,-1;HAND_REST_LEFT 0,-1;HAND_REST_RIGHT 0,-1;HAIR_FORE 0,-1;HEADGEAR 0,-1
|
||||
Binary file not shown.
@@ -10,5 +10,5 @@ uniform sampler2D u_texture;
|
||||
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = texture2D(u_texture, v_texCoords);
|
||||
gl_FragColor = vec4(texture2D(u_texture, v_texCoords).rgb, 1.0);
|
||||
}
|
||||
108
assets/raytracelight.frag
Normal file
108
assets/raytracelight.frag
Normal file
@@ -0,0 +1,108 @@
|
||||
#version 120
|
||||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
varying vec4 v_color;
|
||||
varying vec2 v_texCoords;
|
||||
|
||||
// all 3 must have the same dimension!
|
||||
// the divisor of 2 input and an output must be the same. I.e. either divide all by 4, or not.
|
||||
uniform sampler2D shades;
|
||||
uniform sampler2D lights;
|
||||
// WARNING -- Gdx.Color.toIntBits returns ABGR, but GLSL expects RGBA. Use the function Color.toRGBA() in LightmapRenderNew
|
||||
uniform sampler2D u_texture;
|
||||
uniform vec2 outSize;
|
||||
uniform float multiplier = 4.0; // if divided by four, put 4.0 in there
|
||||
|
||||
#define TRAVERSE_SIZE 128 // should be good for screen size up to 1920 for tile size of 16
|
||||
|
||||
vec4 sampleFrom(sampler2D from, vec2 which) {
|
||||
return texture2D(from, which / outSize);
|
||||
}
|
||||
|
||||
int traceRayCount(vec2 delta) {
|
||||
vec2 absDelta = abs(delta);
|
||||
int arraySize = int(max(absDelta.x, absDelta.y));
|
||||
return arraySize + 1;
|
||||
}
|
||||
|
||||
vec2[TRAVERSE_SIZE] traceRay(int arraySize, vec2 from, vec2 to) {
|
||||
vec2 delta = to - from;
|
||||
vec2[TRAVERSE_SIZE] returnArray;
|
||||
int arri = 0;
|
||||
|
||||
// if the line is not vertical...
|
||||
if (delta.x != 0) {
|
||||
float deltaError = abs(delta.y / delta.x);
|
||||
float error = 0.0;
|
||||
float traceY = from.y;
|
||||
|
||||
for (float traceX = from.x; traceX <= to.x; traceX++) {
|
||||
// plot(traceX, traceY)
|
||||
returnArray[arri] = vec2(traceX, traceY);
|
||||
arri = arri + 1;
|
||||
|
||||
error = error + deltaError;
|
||||
if (error >= 0.5) {
|
||||
traceY = traceY + sign(delta.y);
|
||||
error = error - 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (float traceY = from.y; traceY <= to.y; traceY++) {
|
||||
returnArray[arri] = vec2(from.x, traceY);
|
||||
}
|
||||
}
|
||||
|
||||
return returnArray;
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
// this code will produce y-flipped image. It's your job to flip it again (e.g. using y-flipped fullscreen quad)
|
||||
|
||||
// Nice try, but it kills GPU :(
|
||||
// reason: looks like traceRayCount() returns value greater than TRAVERSE_SIZE.
|
||||
// even if I make traceRayCount() to return constant 3, I get less than 1 fps on GTX 970.
|
||||
|
||||
vec4 outColor = vec4(0.0,0.0,0.0,0.0);
|
||||
|
||||
// 1. pick a light source
|
||||
for (int y = 0; y < int(outSize.y); y++) {
|
||||
for (int x = 0; x < int(outSize.x); x++) {
|
||||
vec2 from = vec2(x + 0.5, y + 0.5); // +0.5 is used because gl_FragCoord does
|
||||
vec2 to = gl_FragCoord.xy;
|
||||
vec2 delta = to - from;
|
||||
int traceCount = traceRayCount(delta);
|
||||
vec4 light = sampleFrom(lights, from);
|
||||
|
||||
// 2. get a trace path
|
||||
vec2[TRAVERSE_SIZE] returnArray = traceRay(traceCount, from, to);
|
||||
|
||||
// 2.1 get angular darkening coefficient
|
||||
vec2 unitVec = delta / max(delta.x, delta.y);
|
||||
float angularDimming = sqrt(unitVec.x * unitVec.x + unitVec.y * unitVec.y);
|
||||
//float angularDimming = 1.0; // TODO depends on the angle of (lightPos, gl_FragCoord.x)
|
||||
|
||||
// 3. traverse the light path to dim the "light"
|
||||
// var "light" will be attenuated after this loop
|
||||
for (int i = 0; i < traceCount; i++) {
|
||||
vec4 shade = sampleFrom(shades, returnArray[i]) * angularDimming;
|
||||
|
||||
light = light - shade;
|
||||
}
|
||||
|
||||
// 4. mix the incoming light into the light buffer.
|
||||
outColor = max(outColor, light);
|
||||
}
|
||||
}
|
||||
|
||||
gl_FragColor = outColor * multiplier;
|
||||
//gl_FragColor = vec4(0,1,0,1);
|
||||
|
||||
//gl_FragColor = sampleFrom(lights, gl_FragCoord.xy) * multiplier;
|
||||
|
||||
|
||||
}
|
||||
@@ -1,3 +1,13 @@
|
||||
/*
|
||||
|
||||
Texture binding:
|
||||
|
||||
0 <- Tiles atlas
|
||||
1 <- Tiles buffer that holds tiles to be drawn
|
||||
2 <- Fluid tiles atlas
|
||||
|
||||
*/
|
||||
|
||||
#version 120
|
||||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
@@ -16,10 +26,11 @@ uniform vec2 screenDimension;
|
||||
uniform vec2 tilesInAxes; // vec2(tiles_in_horizontal, tiles_in_vertical)
|
||||
|
||||
uniform ivec2 tilemapDimension;
|
||||
uniform sampler2D tilemap; // RGB888, A is optional and will be completely ignored
|
||||
uniform sampler2D tilemap; // RGBA8888
|
||||
|
||||
uniform sampler2D tilesAtlas;
|
||||
uniform sampler2D backgroundTexture;
|
||||
uniform sampler2D tilesAtlas; // terrain, wire, fluids, etc.
|
||||
uniform sampler2D tilesBlendAtlas; // weather mix (e.g. yellowed grass)
|
||||
uniform float tilesBlend = 0.0; // percentage of blending [0f..1f]. 0: draws tilesAtlas, 1: draws tilesBlendAtlas
|
||||
|
||||
uniform ivec2 tilesInAtlas = ivec2(256, 256);
|
||||
uniform ivec2 atlasTexSize = ivec2(4096, 4096);
|
||||
@@ -34,18 +45,18 @@ ivec2 getTileXY(int tileNumber) {
|
||||
return ivec2(tileNumber % int(tilesInAtlas.x), tileNumber / int(tilesInAtlas.x));
|
||||
}
|
||||
|
||||
// return: int=0xrrggbb
|
||||
// return: int=0xaarrggbb
|
||||
int _colToInt(vec4 color) {
|
||||
return int(color.b * 255) | (int(color.g * 255) << 8) | (int(color.r * 255) << 16);
|
||||
return int(color.b * 255) | (int(color.g * 255) << 8) | (int(color.r * 255) << 16) | (int(color.a * 255) << 24);
|
||||
}
|
||||
|
||||
// 0x0rggbb where int=0xaarrggbb
|
||||
// return: [0..1048575]
|
||||
int getTileFromColor(vec4 color) {
|
||||
return _colToInt(color) & 0x0FFFFF;
|
||||
return _colToInt(color) & 0xFFFFF;
|
||||
}
|
||||
|
||||
// 0xr00000 where int=0xaarrggbb
|
||||
// 0x00r00000 where int=0xaarrggbb
|
||||
// return: [0..15]
|
||||
int getBreakageFromColor(vec4 color) {
|
||||
return (_colToInt(color) >> 20) & 0xF;
|
||||
@@ -56,6 +67,7 @@ void main() {
|
||||
// READ THE FUCKING MANUAL, YOU DONKEY !! //
|
||||
// This code purposedly uses flipped fragcoord. //
|
||||
// Make sure you don't use gl_FragCoord unknowingly! //
|
||||
// Remember, if there's a compile error, shader SILENTLY won't do anything //
|
||||
|
||||
|
||||
// default gl_FragCoord takes half-integer (represeting centre of the pixel) -- could be useful for phys solver?
|
||||
@@ -75,25 +87,31 @@ void main() {
|
||||
ivec2 breakageXY = getTileXY(breakage + 5); // +5 is hard-coded constant that depends on the atlas
|
||||
|
||||
|
||||
mediump vec2 coordInTile = mod(pxCoord, tileSizeInPx) / tileSizeInPx; // 0..1 regardless of tile position in atlas
|
||||
vec2 coordInTile = mod(pxCoord, tileSizeInPx) / tileSizeInPx; // 0..1 regardless of tile position in atlas
|
||||
|
||||
// don't really need highp here; read the GLES spec
|
||||
mediump vec2 singleTileSizeInUV = vec2(1) / tilesInAtlas; // constant 0.00390625 for unmodified default uniforms
|
||||
vec2 singleTileSizeInUV = vec2(1) / tilesInAtlas; // constant 0.00390625 for unmodified default uniforms
|
||||
|
||||
mediump vec2 uvCoordForTile = coordInTile * singleTileSizeInUV; // 0..0.00390625 regardless of tile position in atlas
|
||||
vec2 uvCoordForTile = coordInTile * singleTileSizeInUV; // 0..0.00390625 regardless of tile position in atlas
|
||||
|
||||
mediump vec2 uvCoordOffsetTile = tileXY * singleTileSizeInUV; // where the tile starts in the atlas, using uv coord (0..1)
|
||||
mediump vec2 uvCoordOffsetBreakage = breakageXY * singleTileSizeInUV;
|
||||
vec2 uvCoordOffsetTile = tileXY * singleTileSizeInUV; // where the tile starts in the atlas, using uv coord (0..1)
|
||||
vec2 uvCoordOffsetBreakage = breakageXY * singleTileSizeInUV;
|
||||
|
||||
mediump vec2 finalUVCoordForTile = uvCoordForTile + uvCoordOffsetTile;// where we should be actually looking for in atlas, using UV coord (0..1)
|
||||
mediump vec2 finalUVCoordForBreakage = uvCoordForTile + uvCoordOffsetBreakage;
|
||||
vec2 finalUVCoordForTile = uvCoordForTile + uvCoordOffsetTile;// where we should be actually looking for in atlas, using UV coord (0..1)
|
||||
vec2 finalUVCoordForBreakage = uvCoordForTile + uvCoordOffsetBreakage;
|
||||
|
||||
|
||||
// blending a breakage tex with main tex
|
||||
|
||||
vec4 finalTile = texture2D(tilesAtlas, finalUVCoordForTile);
|
||||
vec4 tileCol = texture2D(tilesAtlas, finalUVCoordForTile);
|
||||
vec4 tileAltCol = texture2D(tilesBlendAtlas, finalUVCoordForTile);
|
||||
|
||||
vec4 finalTile = mix(tileCol, tileAltCol, tilesBlend);
|
||||
|
||||
vec4 finalBreakage = texture2D(tilesAtlas, finalUVCoordForBreakage);
|
||||
|
||||
gl_FragColor = colourFilter * (mix(finalTile, finalBreakage, finalBreakage.a));
|
||||
vec4 finalColor = vec4(mix(finalTile.rgb, finalBreakage.rgb, finalBreakage.a), finalTile.a);
|
||||
|
||||
gl_FragColor = colourFilter * finalColor;
|
||||
|
||||
}
|
||||
|
||||
32
build.gradle
32
build.gradle
@@ -42,4 +42,34 @@ compileTestKotlin {
|
||||
jar {
|
||||
baseName = 'Terrarum'
|
||||
version = '0.2'
|
||||
}
|
||||
}
|
||||
|
||||
// should be same as plain old 'gradlew run'
|
||||
task game(type: JavaExec) {
|
||||
classpath sourceSets.main.runtimeClasspath
|
||||
main = 'net.torvald.terrarum.AppLoader'
|
||||
group = "Application"
|
||||
description = "Launches the game. Should be the same as 'gradlew run'."
|
||||
}
|
||||
|
||||
task gamedebug(type: JavaExec) {
|
||||
classpath sourceSets.main.runtimeClasspath
|
||||
main = 'net.torvald.terrarum.AppLoader'
|
||||
group = "Application"
|
||||
description = "Launches the game with debuy key."
|
||||
args = ["isdev=true"]
|
||||
}
|
||||
|
||||
task spriteassembler(type: JavaExec) {
|
||||
classpath sourceSets.main.runtimeClasspath
|
||||
main = 'net.torvald.spriteassembler.SpriteAssemblerAppKt'
|
||||
group = "Application"
|
||||
description = "Launches the Sprite Assembler."
|
||||
}
|
||||
|
||||
task csveditor(type: JavaExec) {
|
||||
classpath sourceSets.main.runtimeClasspath
|
||||
main = 'net.torvald.terrarum.debuggerapp.CSVEditor'
|
||||
group = "Application"
|
||||
description = "Launches the CSV Editor. (for Blocks?)"
|
||||
}
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
lib/gdx-nightly-20190112.zip
Normal file
BIN
lib/gdx-nightly-20190112.zip
Normal file
Binary file not shown.
BIN
lib/gdx.jar
BIN
lib/gdx.jar
Binary file not shown.
BIN
lib/kotlin-stdlib-sources.jar
Normal file
BIN
lib/kotlin-stdlib-sources.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
743
src/com/badlogic/gdx/backends/lwjgl/LwjglGraphics.java
Normal file
743
src/com/badlogic/gdx/backends/lwjgl/LwjglGraphics.java
Normal file
@@ -0,0 +1,743 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2011 See AUTHORS file.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
package com.badlogic.gdx.backends.lwjgl;
|
||||
|
||||
import com.badlogic.gdx.Application;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Graphics;
|
||||
import com.badlogic.gdx.graphics.Cursor.SystemCursor;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.GL30;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.Pixmap.Format;
|
||||
import com.badlogic.gdx.graphics.glutils.GLVersion;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||
import com.badlogic.gdx.utils.SharedLibraryLoader;
|
||||
import org.lwjgl.LWJGLException;
|
||||
import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.ContextAttribs;
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.PixelFormat;
|
||||
|
||||
import java.awt.*;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/** An implementation of the {@link Graphics} interface based on Lwjgl.
|
||||
* @author mzechner */
|
||||
public class LwjglGraphics implements Graphics {
|
||||
|
||||
/** The suppored OpenGL extensions */
|
||||
static Array<String> extensions;
|
||||
static GLVersion glVersion;
|
||||
|
||||
GL20 gl20;
|
||||
GL30 gl30;
|
||||
long frameId = -1;
|
||||
float deltaTime = 0;
|
||||
long frameStart = 0;
|
||||
int frames = 0;
|
||||
int fps;
|
||||
long lastTime = System.nanoTime();
|
||||
Canvas canvas;
|
||||
boolean vsync = false;
|
||||
boolean resize = false;
|
||||
LwjglApplicationConfiguration config;
|
||||
BufferFormat bufferFormat = new BufferFormat(8, 8, 8, 8, 16, 8, 0, false);
|
||||
volatile boolean isContinuous = true;
|
||||
volatile boolean requestRendering = false;
|
||||
boolean softwareMode;
|
||||
boolean usingGL30;
|
||||
|
||||
// deltaTime kalman filter related variables
|
||||
private float kalmanEstimate = 1.0f/60.0f;
|
||||
private float kalmanErrorCovariance = 1.0f;
|
||||
private final float kalmanErrorRate = 0.2f; // 0.2: empirical value
|
||||
private final float kalmanUpdateThreshold = 0.1f;
|
||||
private final float getMagnitudeDifferenceEpsilon = 0.00001f;
|
||||
|
||||
LwjglGraphics (LwjglApplicationConfiguration config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
LwjglGraphics (Canvas canvas) {
|
||||
this.config = new LwjglApplicationConfiguration();
|
||||
config.width = canvas.getWidth();
|
||||
config.height = canvas.getHeight();
|
||||
this.canvas = canvas;
|
||||
}
|
||||
|
||||
LwjglGraphics (Canvas canvas, LwjglApplicationConfiguration config) {
|
||||
this.config = config;
|
||||
this.canvas = canvas;
|
||||
}
|
||||
|
||||
|
||||
public int getHeight () {
|
||||
if (canvas != null)
|
||||
return Math.max(1, canvas.getHeight());
|
||||
else
|
||||
return (int)(Display.getHeight() * Display.getPixelScaleFactor());
|
||||
}
|
||||
|
||||
public int getWidth () {
|
||||
if (canvas != null)
|
||||
return Math.max(1, canvas.getWidth());
|
||||
else
|
||||
return (int)(Display.getWidth() * Display.getPixelScaleFactor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBackBufferWidth () {
|
||||
return getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBackBufferHeight () {
|
||||
return getHeight();
|
||||
}
|
||||
|
||||
|
||||
public long getFrameId () {
|
||||
return frameId;
|
||||
}
|
||||
|
||||
public float getDeltaTime () {
|
||||
return kalmanEstimate;
|
||||
}
|
||||
|
||||
private void resetDeltaSmoothingHistory() {
|
||||
kalmanEstimate = 1.0f/60.0f;
|
||||
kalmanErrorCovariance = 1.0f;
|
||||
}
|
||||
|
||||
// only for a > 0 && b > 0
|
||||
private float getMagnitudeDifference(float a, float b) {
|
||||
if (a < getMagnitudeDifferenceEpsilon || b < getMagnitudeDifferenceEpsilon) {
|
||||
return (a + b) / getMagnitudeDifferenceEpsilon;
|
||||
}
|
||||
|
||||
if (a > b) {
|
||||
return a / b;
|
||||
}
|
||||
else {
|
||||
return b / a;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateKalmanRenderDelta() {
|
||||
// The problem with this kalman filter is that it assumes most simplistic situation:
|
||||
// 1. the actual delta (measured delta - noise) is constant (that is, not constantly increasing or something)
|
||||
// 2. everything is linear
|
||||
// We may need to implement Extended Kalman Filter but what is Jacobian, I suck at maths.
|
||||
//
|
||||
// Instead, this implementation will reset itself when difference in magnitude between
|
||||
// old and new is greater than set value.
|
||||
//
|
||||
// It's not perfect but it works, much better than averaging.
|
||||
|
||||
if (getMagnitudeDifference(deltaTime, kalmanEstimate) >= 2.0) {
|
||||
resetDeltaSmoothingHistory();
|
||||
}
|
||||
|
||||
// measurement value
|
||||
float observation = deltaTime;
|
||||
|
||||
if (observation <= kalmanUpdateThreshold) {
|
||||
// time update
|
||||
float priorEstimate = kalmanEstimate;
|
||||
float priorError = kalmanErrorCovariance;
|
||||
|
||||
// measurement update
|
||||
float gain = priorError / (priorError + kalmanErrorRate);
|
||||
float newEstimate = priorEstimate + gain * (observation - priorEstimate);
|
||||
float newError = (1.0f - gain) * priorError;
|
||||
|
||||
kalmanEstimate = newEstimate;
|
||||
kalmanErrorCovariance = newError;
|
||||
}
|
||||
}
|
||||
|
||||
public float getRawDeltaTime () {
|
||||
return deltaTime;
|
||||
}
|
||||
|
||||
public GraphicsType getType () {
|
||||
return GraphicsType.LWJGL;
|
||||
}
|
||||
|
||||
public GLVersion getGLVersion () {
|
||||
return glVersion;
|
||||
}
|
||||
|
||||
public boolean isGL20Available () {
|
||||
return gl20 != null;
|
||||
}
|
||||
|
||||
public GL20 getGL20 () {
|
||||
return gl20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGL20 (GL20 gl20) {
|
||||
this.gl20 = gl20;
|
||||
if (gl30 == null) {
|
||||
Gdx.gl = gl20;
|
||||
Gdx.gl20 = gl20;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGL30Available () {
|
||||
return gl30 != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GL30 getGL30 () {
|
||||
return gl30;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGL30 (GL30 gl30) {
|
||||
this.gl30 = gl30;
|
||||
if (gl30 != null) {
|
||||
this.gl20 = gl30;
|
||||
|
||||
Gdx.gl = gl20;
|
||||
Gdx.gl20 = gl20;
|
||||
Gdx.gl30 = gl30;
|
||||
}
|
||||
}
|
||||
|
||||
public int getFramesPerSecond () {
|
||||
return fps;
|
||||
}
|
||||
|
||||
void updateTime () {
|
||||
long time = System.nanoTime();
|
||||
deltaTime = (time - lastTime) / 1000000000.0f;
|
||||
lastTime = time;
|
||||
|
||||
if (time - frameStart >= 1000000000) {
|
||||
fps = frames;
|
||||
frames = 0;
|
||||
frameStart = time;
|
||||
}
|
||||
frames++;
|
||||
|
||||
updateKalmanRenderDelta();
|
||||
}
|
||||
|
||||
void setupDisplay () throws LWJGLException {
|
||||
if (config.useHDPI) {
|
||||
System.setProperty("org.lwjgl.opengl.Display.enableHighDPI", "true");
|
||||
}
|
||||
|
||||
if (canvas != null) {
|
||||
Display.setParent(canvas);
|
||||
} else {
|
||||
boolean displayCreated = false;
|
||||
|
||||
if(!config.fullscreen) {
|
||||
displayCreated = setWindowedMode(config.width, config.height);
|
||||
} else {
|
||||
DisplayMode bestMode = null;
|
||||
for(DisplayMode mode: getDisplayModes()) {
|
||||
if(mode.width == config.width && mode.height == config.height) {
|
||||
if(bestMode == null || bestMode.refreshRate < this.getDisplayMode().refreshRate) {
|
||||
bestMode = mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bestMode == null) {
|
||||
bestMode = this.getDisplayMode();
|
||||
}
|
||||
displayCreated = setFullscreenMode(bestMode);
|
||||
}
|
||||
if (!displayCreated) {
|
||||
if (config.setDisplayModeCallback != null) {
|
||||
config = config.setDisplayModeCallback.onFailure(config);
|
||||
if (config != null) {
|
||||
displayCreated = setWindowedMode(config.width, config.height);
|
||||
}
|
||||
}
|
||||
if (!displayCreated) {
|
||||
throw new GdxRuntimeException("Couldn't set display mode " + config.width + "x" + config.height + ", fullscreen: "
|
||||
+ config.fullscreen);
|
||||
}
|
||||
}
|
||||
if (config.iconPaths.size > 0) {
|
||||
ByteBuffer[] icons = new ByteBuffer[config.iconPaths.size];
|
||||
for (int i = 0, n = config.iconPaths.size; i < n; i++) {
|
||||
Pixmap pixmap = new Pixmap(Gdx.files.getFileHandle(config.iconPaths.get(i), config.iconFileTypes.get(i)));
|
||||
if (pixmap.getFormat() != Format.RGBA8888) {
|
||||
Pixmap rgba = new Pixmap(pixmap.getWidth(), pixmap.getHeight(), Format.RGBA8888);
|
||||
rgba.drawPixmap(pixmap, 0, 0);
|
||||
pixmap.dispose();
|
||||
pixmap = rgba;
|
||||
}
|
||||
icons[i] = ByteBuffer.allocateDirect(pixmap.getPixels().limit());
|
||||
icons[i].put(pixmap.getPixels()).flip();
|
||||
pixmap.dispose();
|
||||
}
|
||||
Display.setIcon(icons);
|
||||
}
|
||||
}
|
||||
Display.setTitle(config.title);
|
||||
Display.setResizable(config.resizable);
|
||||
Display.setInitialBackground(config.initialBackgroundColor.r, config.initialBackgroundColor.g,
|
||||
config.initialBackgroundColor.b);
|
||||
|
||||
Display.setLocation(config.x, config.y);
|
||||
createDisplayPixelFormat(config.useGL30, config.gles30ContextMajorVersion, config.gles30ContextMinorVersion);
|
||||
initiateGL();
|
||||
}
|
||||
|
||||
/**
|
||||
* Only needed when setupDisplay() is not called.
|
||||
*/
|
||||
void initiateGL() {
|
||||
extractVersion();
|
||||
extractExtensions();
|
||||
initiateGLInstances();
|
||||
}
|
||||
|
||||
private static void extractVersion () {
|
||||
String versionString = org.lwjgl.opengl.GL11.glGetString(GL11.GL_VERSION);
|
||||
String vendorString = org.lwjgl.opengl.GL11.glGetString(GL11.GL_VENDOR);
|
||||
String rendererString = org.lwjgl.opengl.GL11.glGetString(GL11.GL_RENDERER);
|
||||
glVersion = new GLVersion(Application.ApplicationType.Desktop, versionString, vendorString, rendererString);
|
||||
}
|
||||
|
||||
private static void extractExtensions () {
|
||||
extensions = new Array<String>();
|
||||
if (glVersion.isVersionEqualToOrHigher(3, 2)) {
|
||||
int numExtensions = GL11.glGetInteger(GL30.GL_NUM_EXTENSIONS);
|
||||
for (int i = 0; i < numExtensions; ++i)
|
||||
extensions.add(org.lwjgl.opengl.GL30.glGetStringi(GL20.GL_EXTENSIONS, i));
|
||||
} else {
|
||||
extensions.addAll(org.lwjgl.opengl.GL11.glGetString(GL20.GL_EXTENSIONS).split(" "));
|
||||
}
|
||||
}
|
||||
|
||||
/** @return whether the supported OpenGL (not ES) version is compatible with OpenGL ES 3.x. */
|
||||
private static boolean fullCompatibleWithGLES3 () {
|
||||
// OpenGL ES 3.0 is compatible with OpenGL 4.3 core, see http://en.wikipedia.org/wiki/OpenGL_ES#OpenGL_ES_3.0
|
||||
return glVersion.isVersionEqualToOrHigher(4, 3);
|
||||
}
|
||||
|
||||
/** @return whether the supported OpenGL (not ES) version is compatible with OpenGL ES 2.x. */
|
||||
private static boolean fullCompatibleWithGLES2 () {
|
||||
// OpenGL ES 2.0 is compatible with OpenGL 4.1 core
|
||||
// see https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt
|
||||
return glVersion.isVersionEqualToOrHigher(4, 1) || extensions.contains("GL_ARB_ES2_compatibility", false);
|
||||
}
|
||||
|
||||
private static boolean supportsFBO () {
|
||||
// FBO is in core since OpenGL 3.0, see https://www.opengl.org/wiki/Framebuffer_Object
|
||||
return glVersion.isVersionEqualToOrHigher(3, 0) || extensions.contains("GL_EXT_framebuffer_object", false)
|
||||
|| extensions.contains("GL_ARB_framebuffer_object", false);
|
||||
}
|
||||
|
||||
private void createDisplayPixelFormat (boolean useGL30, int gles30ContextMajor, int gles30ContextMinor) {
|
||||
try {
|
||||
if (useGL30) {
|
||||
ContextAttribs context = new ContextAttribs(gles30ContextMajor, gles30ContextMinor).withForwardCompatible(false)
|
||||
.withProfileCore(true);
|
||||
try {
|
||||
Display.create(new PixelFormat(config.r + config.g + config.b, config.a, config.depth, config.stencil,
|
||||
config.samples), context);
|
||||
} catch (Exception e) {
|
||||
System.out.println("LwjglGraphics: OpenGL " + gles30ContextMajor + "." + gles30ContextMinor
|
||||
+ "+ core profile (GLES 3.0) not supported.");
|
||||
createDisplayPixelFormat(false, gles30ContextMajor, gles30ContextMinor);
|
||||
return;
|
||||
}
|
||||
System.out.println("LwjglGraphics: created OpenGL " + gles30ContextMajor + "." + gles30ContextMinor
|
||||
+ "+ core profile (GLES 3.0) context. This is experimental!");
|
||||
usingGL30 = true;
|
||||
} else {
|
||||
Display
|
||||
.create(new PixelFormat(config.r + config.g + config.b, config.a, config.depth, config.stencil, config.samples));
|
||||
usingGL30 = false;
|
||||
}
|
||||
bufferFormat = new BufferFormat(config.r, config.g, config.b, config.a, config.depth, config.stencil, config.samples,
|
||||
false);
|
||||
} catch (Exception ex) {
|
||||
Display.destroy();
|
||||
try {
|
||||
Thread.sleep(200);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
try {
|
||||
Display.create(new PixelFormat(0, 16, 8));
|
||||
if (getDisplayMode().bitsPerPixel == 16) {
|
||||
bufferFormat = new BufferFormat(5, 6, 5, 0, 16, 8, 0, false);
|
||||
}
|
||||
if (getDisplayMode().bitsPerPixel == 24) {
|
||||
bufferFormat = new BufferFormat(8, 8, 8, 0, 16, 8, 0, false);
|
||||
}
|
||||
if (getDisplayMode().bitsPerPixel == 32) {
|
||||
bufferFormat = new BufferFormat(8, 8, 8, 8, 16, 8, 0, false);
|
||||
}
|
||||
} catch (Exception ex2) {
|
||||
Display.destroy();
|
||||
try {
|
||||
Thread.sleep(200);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
try {
|
||||
Display.create(new PixelFormat());
|
||||
} catch (Exception ex3) {
|
||||
if (!softwareMode && config.allowSoftwareMode) {
|
||||
softwareMode = true;
|
||||
System.setProperty("org.lwjgl.opengl.Display.allowSoftwareOpenGL", "true");
|
||||
createDisplayPixelFormat(useGL30, gles30ContextMajor, gles30ContextMinor);
|
||||
return;
|
||||
}
|
||||
throw new GdxRuntimeException("OpenGL is not supported by the video driver.", ex3);
|
||||
}
|
||||
if (getDisplayMode().bitsPerPixel == 16) {
|
||||
bufferFormat = new BufferFormat(5, 6, 5, 0, 8, 0, 0, false);
|
||||
}
|
||||
if (getDisplayMode().bitsPerPixel == 24) {
|
||||
bufferFormat = new BufferFormat(8, 8, 8, 0, 8, 0, 0, false);
|
||||
}
|
||||
if (getDisplayMode().bitsPerPixel == 32) {
|
||||
bufferFormat = new BufferFormat(8, 8, 8, 8, 8, 0, 0, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void initiateGLInstances () {
|
||||
if (usingGL30) {
|
||||
gl30 = new LwjglGL30();
|
||||
gl20 = gl30;
|
||||
} else {
|
||||
gl20 = new LwjglGL20();
|
||||
}
|
||||
|
||||
if (!glVersion.isVersionEqualToOrHigher(2, 0))
|
||||
throw new GdxRuntimeException("OpenGL 2.0 or higher with the FBO extension is required. OpenGL version: "
|
||||
+ GL11.glGetString(GL11.GL_VERSION) + "\n" + glVersion.getDebugVersionString());
|
||||
|
||||
if (!supportsFBO()) {
|
||||
throw new GdxRuntimeException("OpenGL 2.0 or higher with the FBO extension is required. OpenGL version: "
|
||||
+ GL11.glGetString(GL11.GL_VERSION) + ", FBO extension: false\n" + glVersion.getDebugVersionString());
|
||||
}
|
||||
|
||||
Gdx.gl = gl20;
|
||||
Gdx.gl20 = gl20;
|
||||
Gdx.gl30 = gl30;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getPpiX () {
|
||||
return Toolkit.getDefaultToolkit().getScreenResolution();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getPpiY () {
|
||||
return Toolkit.getDefaultToolkit().getScreenResolution();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getPpcX () {
|
||||
return (Toolkit.getDefaultToolkit().getScreenResolution() / 2.54f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getPpcY () {
|
||||
return (Toolkit.getDefaultToolkit().getScreenResolution() / 2.54f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getDensity () {
|
||||
if (config.overrideDensity != -1) return config.overrideDensity / 160f;
|
||||
return (Toolkit.getDefaultToolkit().getScreenResolution() / 160f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsDisplayModeChange () {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Monitor getPrimaryMonitor () {
|
||||
return new LwjglMonitor(0, 0, "Primary Monitor");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Monitor getMonitor () {
|
||||
return getPrimaryMonitor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Monitor[] getMonitors () {
|
||||
return new Monitor[] { getPrimaryMonitor() };
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisplayMode[] getDisplayModes (Monitor monitor) {
|
||||
return getDisplayModes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisplayMode getDisplayMode (Monitor monitor) {
|
||||
return getDisplayMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setFullscreenMode (DisplayMode displayMode) {
|
||||
org.lwjgl.opengl.DisplayMode mode = ((LwjglDisplayMode)displayMode).mode;
|
||||
try {
|
||||
if (!mode.isFullscreenCapable()) {
|
||||
Display.setDisplayMode(mode);
|
||||
} else {
|
||||
Display.setDisplayModeAndFullscreen(mode);
|
||||
}
|
||||
float scaleFactor = Display.getPixelScaleFactor();
|
||||
config.width = (int)(mode.getWidth() * scaleFactor);
|
||||
config.height = (int)(mode.getHeight() * scaleFactor);
|
||||
if (Gdx.gl != null) Gdx.gl.glViewport(0, 0, config.width, config.height);
|
||||
resize = true;
|
||||
return true;
|
||||
} catch (LWJGLException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Kindly stolen from http://lwjgl.org/wiki/index.php?title=LWJGL_Basics_5_(Fullscreen), not perfect but will do. */
|
||||
@Override
|
||||
public boolean setWindowedMode (int width, int height) {
|
||||
if (getWidth() == width && getHeight() == height && !Display.isFullscreen()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
org.lwjgl.opengl.DisplayMode targetDisplayMode = null;
|
||||
boolean fullscreen = false;
|
||||
|
||||
if (fullscreen) {
|
||||
org.lwjgl.opengl.DisplayMode[] modes = Display.getAvailableDisplayModes();
|
||||
int freq = 0;
|
||||
|
||||
for (int i = 0; i < modes.length; i++) {
|
||||
org.lwjgl.opengl.DisplayMode current = modes[i];
|
||||
|
||||
if ((current.getWidth() == width) && (current.getHeight() == height)) {
|
||||
if ((targetDisplayMode == null) || (current.getFrequency() >= freq)) {
|
||||
if ((targetDisplayMode == null) || (current.getBitsPerPixel() > targetDisplayMode.getBitsPerPixel())) {
|
||||
targetDisplayMode = current;
|
||||
freq = targetDisplayMode.getFrequency();
|
||||
}
|
||||
}
|
||||
|
||||
// if we've found a match for bpp and frequence against the
|
||||
// original display mode then it's probably best to go for this one
|
||||
// since it's most likely compatible with the monitor
|
||||
if ((current.getBitsPerPixel() == Display.getDesktopDisplayMode().getBitsPerPixel())
|
||||
&& (current.getFrequency() == Display.getDesktopDisplayMode().getFrequency())) {
|
||||
targetDisplayMode = current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
targetDisplayMode = new org.lwjgl.opengl.DisplayMode(width, height);
|
||||
}
|
||||
|
||||
if (targetDisplayMode == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean resizable = !fullscreen && config.resizable;
|
||||
|
||||
Display.setDisplayMode(targetDisplayMode);
|
||||
Display.setFullscreen(fullscreen);
|
||||
// Workaround for bug in LWJGL whereby resizable state is lost on DisplayMode change
|
||||
if (resizable == Display.isResizable()) {
|
||||
Display.setResizable(!resizable);
|
||||
}
|
||||
Display.setResizable(resizable);
|
||||
|
||||
float scaleFactor = Display.getPixelScaleFactor();
|
||||
config.width = (int)(targetDisplayMode.getWidth() * scaleFactor);
|
||||
config.height = (int)(targetDisplayMode.getHeight() * scaleFactor);
|
||||
if (Gdx.gl != null) Gdx.gl.glViewport(0, 0, config.width, config.height);
|
||||
resize = true;
|
||||
return true;
|
||||
} catch (LWJGLException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisplayMode[] getDisplayModes () {
|
||||
try {
|
||||
org.lwjgl.opengl.DisplayMode[] availableDisplayModes = Display.getAvailableDisplayModes();
|
||||
DisplayMode[] modes = new DisplayMode[availableDisplayModes.length];
|
||||
|
||||
int idx = 0;
|
||||
for (org.lwjgl.opengl.DisplayMode mode : availableDisplayModes) {
|
||||
if (mode.isFullscreenCapable()) {
|
||||
modes[idx++] = new LwjglDisplayMode(mode.getWidth(), mode.getHeight(), mode.getFrequency(),
|
||||
mode.getBitsPerPixel(), mode);
|
||||
}
|
||||
}
|
||||
|
||||
return modes;
|
||||
} catch (LWJGLException e) {
|
||||
throw new GdxRuntimeException("Couldn't fetch available display modes", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisplayMode getDisplayMode () {
|
||||
org.lwjgl.opengl.DisplayMode mode = Display.getDesktopDisplayMode();
|
||||
return new LwjglDisplayMode(mode.getWidth(), mode.getHeight(), mode.getFrequency(), mode.getBitsPerPixel(), mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle (String title) {
|
||||
Display.setTitle(title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display must be reconfigured via {@link #setWindowedMode(int, int)} for the changes to take
|
||||
* effect.
|
||||
*/
|
||||
@Override
|
||||
public void setUndecorated (boolean undecorated) {
|
||||
System.setProperty("org.lwjgl.opengl.Window.undecorated", undecorated ? "true" : "false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Display must be reconfigured via {@link #setWindowedMode(int, int)} for the changes to take
|
||||
* effect.
|
||||
*/
|
||||
@Override
|
||||
public void setResizable (boolean resizable) {
|
||||
this.config.resizable = resizable;
|
||||
Display.setResizable(resizable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferFormat getBufferFormat () {
|
||||
return bufferFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVSync (boolean vsync) {
|
||||
this.vsync = vsync;
|
||||
Display.setVSyncEnabled(vsync);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsExtension (String extension) {
|
||||
return extensions.contains(extension, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContinuousRendering (boolean isContinuous) {
|
||||
this.isContinuous = isContinuous;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isContinuousRendering () {
|
||||
return isContinuous;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestRendering () {
|
||||
synchronized (this) {
|
||||
requestRendering = true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean shouldRender () {
|
||||
synchronized (this) {
|
||||
boolean rq = requestRendering;
|
||||
requestRendering = false;
|
||||
return rq || isContinuous || Display.isDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullscreen () {
|
||||
return Display.isFullscreen();
|
||||
}
|
||||
|
||||
public boolean isSoftwareMode () {
|
||||
return softwareMode;
|
||||
}
|
||||
|
||||
/** A callback used by LwjglApplication when trying to create the display */
|
||||
public interface SetDisplayModeCallback {
|
||||
/** If the display creation fails, this method will be called. Suggested usage is to modify the passed configuration to use a
|
||||
* common width and height, and set fullscreen to false.
|
||||
* @return the configuration to be used for a second attempt at creating a display. A null value results in NOT attempting
|
||||
* to create the display a second time */
|
||||
public LwjglApplicationConfiguration onFailure (LwjglApplicationConfiguration initialConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.badlogic.gdx.graphics.Cursor newCursor (Pixmap pixmap, int xHotspot, int yHotspot) {
|
||||
return new LwjglCursor(pixmap, xHotspot, yHotspot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCursor (com.badlogic.gdx.graphics.Cursor cursor) {
|
||||
if (canvas != null && SharedLibraryLoader.isMac) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Mouse.setNativeCursor(((LwjglCursor)cursor).lwjglCursor);
|
||||
} catch (LWJGLException e) {
|
||||
throw new GdxRuntimeException("Could not set cursor image.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSystemCursor (SystemCursor systemCursor) {
|
||||
if (canvas != null && SharedLibraryLoader.isMac) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Mouse.setNativeCursor(null);
|
||||
} catch (LWJGLException e) {
|
||||
throw new GdxRuntimeException("Couldn't set system cursor");
|
||||
}
|
||||
}
|
||||
|
||||
private class LwjglDisplayMode extends DisplayMode {
|
||||
org.lwjgl.opengl.DisplayMode mode;
|
||||
|
||||
public LwjglDisplayMode (int width, int height, int refreshRate, int bitsPerPixel, org.lwjgl.opengl.DisplayMode mode) {
|
||||
super(width, height, refreshRate, bitsPerPixel);
|
||||
this.mode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
private class LwjglMonitor extends Monitor {
|
||||
protected LwjglMonitor (int virtualX, int virtualY, String name) {
|
||||
super(virtualX, virtualY, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
116
src/com/badlogic/gdx/graphics/PixmapIO2.java
Normal file
116
src/com/badlogic/gdx/graphics/PixmapIO2.java
Normal file
@@ -0,0 +1,116 @@
|
||||
package com.badlogic.gdx.graphics;
|
||||
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.utils.StreamUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2019-01-07.
|
||||
*/
|
||||
public class PixmapIO2 {
|
||||
|
||||
// REMEMBER: to the GL's perspective, this game's FBOs are always Y-flipped. //
|
||||
|
||||
public static void writeTGAHappy(FileHandle file, Pixmap pixmap, boolean flipY) throws IOException {
|
||||
OutputStream output = file.write(false);
|
||||
|
||||
try {
|
||||
_writeTGA(output, pixmap, false, flipY);
|
||||
} finally {
|
||||
StreamUtils.closeQuietly(output);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeTGA(FileHandle file, Pixmap pixmap, boolean flipY) throws IOException {
|
||||
OutputStream output = file.write(false);
|
||||
|
||||
try {
|
||||
_writeTGA(output, pixmap, true, flipY);
|
||||
} finally {
|
||||
StreamUtils.closeQuietly(output);
|
||||
}
|
||||
}
|
||||
|
||||
private static void _writeTGA(OutputStream out, Pixmap pixmap, boolean verbatim, boolean flipY) throws IOException {
|
||||
byte[] width = toShortLittle(pixmap.getWidth());
|
||||
byte[] height = toShortLittle(pixmap.getHeight());
|
||||
byte[] zero = toShortLittle(0);
|
||||
|
||||
out.write(0); // ID field: empty
|
||||
out.write(0); // no colour map, but should be ignored anyway as it being unmapped RGB
|
||||
out.write(2); // 2 means unmapped RGB
|
||||
out.write(new byte[]{0,0,0,0,0}); // color map spec: empty
|
||||
out.write(zero); // x origin: 0
|
||||
out.write(zero); // y origin: 0
|
||||
out.write(width); // width
|
||||
out.write(height); // height
|
||||
out.write(32); // image pixel size: we're writing 32-bit image (8bpp BGRA)
|
||||
out.write(8); // image descriptor: dunno, Photoshop writes 8 in there
|
||||
|
||||
// write actual image data
|
||||
// since we're following Photoshop's conventional header, we also follows Photoshop's
|
||||
// TGA saving scheme, that is:
|
||||
// 1. BGRA order
|
||||
// 2. Y-Flipped but not X-Flipped
|
||||
|
||||
if (!flipY) {
|
||||
for (int y = pixmap.getHeight() - 1; y >= 0; y--) {
|
||||
for (int x = 0; x < pixmap.getWidth(); x++) {
|
||||
writeTga(x, y, verbatim, pixmap, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int y = 0; y < pixmap.getHeight(); y++) {
|
||||
for (int x = 0; x < pixmap.getWidth(); x++) {
|
||||
writeTga(x, y, verbatim, pixmap, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// write footer
|
||||
// 00 00 00 00 00 00 00 00 TRUEVISION-XFILE 2E 00
|
||||
out.write(new byte[]{0,0,0,0,0,0,0,0});
|
||||
if (verbatim)
|
||||
out.write("TRUEVISION-XFILE".getBytes());
|
||||
else
|
||||
out.write("TerrarumHappyTGA".getBytes());
|
||||
out.write(new byte[]{0x2E,0});
|
||||
|
||||
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
|
||||
private static byte[] zeroalpha = new byte[]{0,0,0,0};
|
||||
private static void writeTga(int x, int y, boolean verbatim, Pixmap pixmap, OutputStream out) throws IOException {
|
||||
int color = pixmap.getPixel(x, y);
|
||||
|
||||
// if alpha == 0, write special value instead
|
||||
if (verbatim && (color & 0xFF) == 0) {
|
||||
out.write(zeroalpha);
|
||||
}
|
||||
else {
|
||||
out.write(RGBAtoBGRA(color));
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] toShortLittle(int i) {
|
||||
return new byte[]{
|
||||
(byte) (i & 0xFF),
|
||||
(byte) ((i >>> 8) & 0xFF)
|
||||
};
|
||||
}
|
||||
|
||||
private static byte[] RGBAtoBGRA(int rgba) {
|
||||
return new byte[]{
|
||||
(byte) ((rgba >>> 8) & 0xFF),
|
||||
(byte) ((rgba >>> 16) & 0xFF),
|
||||
(byte) ((rgba >>> 24) & 0xFF),
|
||||
(byte) (rgba & 0xFF)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.torvald.colourutil
|
||||
|
||||
import com.jme3.math.FastMath
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.jme3.math.FastMath
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2017-01-12.
|
||||
@@ -11,25 +11,27 @@ object CIEXYZUtil {
|
||||
/**
|
||||
* 0..255 -> 0.0..1.0
|
||||
*/
|
||||
private val rgbLineariseLUT = Array<Float>(257, {
|
||||
val step = minOf(it, 255) / 255f
|
||||
private val rgbLinLUT = FloatArray(256) {
|
||||
val step = it / 255f
|
||||
|
||||
if (step > 0.04045f)
|
||||
((step + 0.055f) / 1.055f).powerOf(2.4f)
|
||||
else step / 12.92f
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 0..255 -> 0.0..1.0
|
||||
*/
|
||||
private val rgbUnLineariseLUT = Array<Float>(257, {
|
||||
val step = minOf(it, 255) / 255f
|
||||
private val rgbUnLinLUT = FloatArray(256) {
|
||||
val step = it / 255f
|
||||
|
||||
if (step > 0.0031308f)
|
||||
1.055f * step.powerOf(1f / 2.4f) - 0.055f
|
||||
else
|
||||
step * 12.92f
|
||||
})
|
||||
}
|
||||
|
||||
private val rgbToXyzLut_XR = FloatArray(256) { 0.4124564f * (it / 255f) }
|
||||
|
||||
|
||||
|
||||
@@ -65,8 +67,35 @@ object CIEXYZUtil {
|
||||
|
||||
fun Color.toXYZ(): CIEXYZ = RGB(this).toXYZ()
|
||||
|
||||
/**
|
||||
* "Linearise" the sRGB triads. This use lookup table to speed up calculation.
|
||||
* Integer values (1/255, 2/255, .. , 254/255, 255/255) are accurate but any values in between are
|
||||
* linearly interpolated and thus slightly less accurate. Visually there's little-to-no difference,
|
||||
* but may not optimal for rigorous maths.
|
||||
*/
|
||||
fun RGB.linearise(): RGB {
|
||||
/*val newR = if (r > 0.04045f)
|
||||
val out = floatArrayOf(0f, 0f, 0f)
|
||||
for (i in 0..2) {
|
||||
val value = when (i) {
|
||||
0 -> this.r
|
||||
1 -> this.g
|
||||
2 -> this.b
|
||||
else -> throw InternalError("Fuck you")
|
||||
}
|
||||
val step = value.clampOne() * 255f // 0.0 .. 255.0
|
||||
val intStep = step.toInt() // 0 .. 255
|
||||
val NeXTSTEP = minOf(intStep + 1, 255) // 1 .. 255
|
||||
|
||||
out[i] = interpolateLinear(step - intStep, rgbLinLUT[intStep], rgbLinLUT[NeXTSTEP])
|
||||
}
|
||||
|
||||
|
||||
return RGB(out[0], out[1], out[2], alpha)
|
||||
}
|
||||
|
||||
/** Suitable for rigorous maths but slower */
|
||||
fun RGB.lineariseSuper(): RGB {
|
||||
val newR = if (r > 0.04045f)
|
||||
((r + 0.055f) / 1.055f).powerOf(2.4f)
|
||||
else r / 12.92f
|
||||
val newG = if (g > 0.04045f)
|
||||
@@ -77,28 +106,38 @@ object CIEXYZUtil {
|
||||
else b / 12.92f
|
||||
|
||||
|
||||
return RGB(newR, newG, newB, alpha)*/
|
||||
return RGB(newR, newG, newB, alpha)
|
||||
}
|
||||
|
||||
/**
|
||||
* "Un-linearise" the RGB triads. That is, codes the linear RGB into sRGB. This use lookup table to speed up calculation.
|
||||
* Integer values (1/255, 2/255, .. , 254/255, 255/255) are accurate but any values in between are
|
||||
* linearly interpolated and thus slightly less accurate. Visually there's little-to-no difference,
|
||||
* but may not optimal for rigorous maths.
|
||||
*/
|
||||
fun RGB.unLinearise(): RGB {
|
||||
val out = floatArrayOf(0f, 0f, 0f)
|
||||
for (i in 0..2) {
|
||||
val value = when (i) {
|
||||
0 -> this.r
|
||||
1 -> this.g
|
||||
2 -> this.b
|
||||
else -> throw Exception("Fuck you")
|
||||
else -> throw InternalError("Fuck you")
|
||||
}
|
||||
val step = value.clampOne() * 255f
|
||||
val intStep = step.toInt()
|
||||
val step = value.clampOne() * 255f // 0.0 .. 255.0
|
||||
val intStep = step.toInt() // 0 .. 255
|
||||
val NeXTSTEP = minOf(intStep + 1, 255) // 1 .. 255
|
||||
|
||||
out[i] = interpolateLinear(step - intStep, rgbLineariseLUT[intStep], rgbLineariseLUT[intStep + 1])
|
||||
out[i] = interpolateLinear(step - intStep, rgbUnLinLUT[intStep], rgbUnLinLUT[NeXTSTEP])
|
||||
}
|
||||
|
||||
|
||||
return RGB(out[0], out[1], out[2], alpha)
|
||||
}
|
||||
|
||||
fun RGB.unLinearise(): RGB {
|
||||
/*val newR = if (r > 0.0031308f)
|
||||
/** Suitable for rigorous maths but slower */
|
||||
fun RGB.unLineariseSuper(): RGB {
|
||||
val newR = if (r > 0.0031308f)
|
||||
1.055f * r.powerOf(1f / 2.4f) - 0.055f
|
||||
else
|
||||
r * 12.92f
|
||||
@@ -112,24 +151,7 @@ object CIEXYZUtil {
|
||||
b * 12.92f
|
||||
|
||||
|
||||
return RGB(newR, newG, newB, alpha)*/
|
||||
|
||||
val out = floatArrayOf(0f, 0f, 0f)
|
||||
for (i in 0..2) {
|
||||
val value = when (i) {
|
||||
0 -> this.r
|
||||
1 -> this.g
|
||||
2 -> this.b
|
||||
else -> throw Exception("Fuck you")
|
||||
}
|
||||
val step = value.clampOne() * 255f
|
||||
val intStep = step.toInt()
|
||||
|
||||
out[i] = interpolateLinear(step - intStep, rgbUnLineariseLUT[intStep], rgbUnLineariseLUT[intStep + 1])
|
||||
}
|
||||
|
||||
|
||||
return RGB(out[0], out[1], out[2], alpha)
|
||||
return RGB(newR, newG, newB, alpha)
|
||||
}
|
||||
|
||||
fun RGB.toXYZ(): CIEXYZ {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package net.torvald.colourutil
|
||||
|
||||
import com.jme3.math.FastMath
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.colourutil.CIEXYZUtil.linearise
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2016-07-26.
|
||||
@@ -20,4 +21,17 @@ object ColourUtil {
|
||||
|
||||
return Color(r, g, b, a)
|
||||
}
|
||||
|
||||
/** Get luminosity level using CIEXYZ colour space. Slow but accurate. */
|
||||
fun RGB.getLuminosity(): Float {
|
||||
val new = this.linearise()
|
||||
return 0.2126729f * new.r + 0.7151522f * new.g + 0.0721750f * new.b // from RGB.toXYZ
|
||||
}
|
||||
/** Get luminosity level using CIEXYZ colour space. Slow but accurate. */
|
||||
fun Color.getLuminosity() = RGB(this).getLuminosity()
|
||||
|
||||
/** Get luminosity level using NTSC standard. Fast, less accurate but should be good enough. */
|
||||
fun RGB.getLuminosityQuick() = 0.3f * this.r + 0.59f * this.g + 0.11f * this.b // NTSC standard
|
||||
/** Get luminosity level using NTSC standard. Fast, less accurate but should be good enough. */
|
||||
fun Color.getLuminosityQuick() = 0.3f * this.r + 0.59f * this.g + 0.11f * this.b // NTSC standard
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package net.torvald.dataclass
|
||||
|
||||
|
||||
/**
|
||||
* buffer[head] contains the most recent item, whereas buffer[tail] contains the oldest one.
|
||||
*
|
||||
* Notes for particle storage:
|
||||
* Particles does not need to be removed, just let it overwrite as their operation is rather
|
||||
* lightweight. So, just flagDespawn = true if it need to be "deleted" so that it won't update
|
||||
@@ -12,57 +14,67 @@ package net.torvald.dataclass
|
||||
class CircularArray<T>(val size: Int) {
|
||||
|
||||
val buffer: Array<T> = arrayOfNulls<Any>(size) as Array<T>
|
||||
var tail: Int = 0
|
||||
var head: Int = 0
|
||||
var tail: Int = 0; private set
|
||||
var head: Int = -1; private set
|
||||
|
||||
private var unreliableAddCount = 0
|
||||
|
||||
val lastIndex = size - 1
|
||||
|
||||
/**
|
||||
* Number of elements that forEach() or fold() would iterate.
|
||||
*/
|
||||
val elemCount: Int
|
||||
get() = if (tail >= head) tail - head else size
|
||||
get() = minOf(unreliableAddCount, size)
|
||||
|
||||
fun add(item: T) {
|
||||
buffer[tail] = item // overwrites oldest item when eligible
|
||||
tail = (tail + 1) % size
|
||||
if (tail == head) {
|
||||
head = (head + 1) % size
|
||||
if (unreliableAddCount <= size) unreliableAddCount += 1
|
||||
|
||||
head = (head + 1) % size
|
||||
if (unreliableAddCount > size) {
|
||||
tail = (tail + 1) % size
|
||||
}
|
||||
|
||||
buffer[head] = item // overwrites oldest item when eligible
|
||||
|
||||
|
||||
//println("$this $unreliableAddCount")
|
||||
}
|
||||
|
||||
inline fun forEach(action: (T) -> Unit) {
|
||||
fun getHeadElem(): T = buffer[head]
|
||||
fun getTailElem(): T = buffer[tail]
|
||||
|
||||
/**
|
||||
* Iterates the array with oldest element first.
|
||||
*/
|
||||
fun forEach(action: (T) -> Unit) {
|
||||
// has slightly better iteration performance than lambda
|
||||
if (tail >= head) {
|
||||
for (i in head..tail - 1)
|
||||
if (unreliableAddCount <= size) {
|
||||
for (i in 0..head)
|
||||
action(buffer[i])
|
||||
}
|
||||
else {
|
||||
for (i in 0..size - 1)
|
||||
action(buffer[(i + head) % size])
|
||||
action(buffer[(i + tail) % size])
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME not working as intended
|
||||
inline fun <R> fold(initial: R, operation: (R, T) -> R): R {
|
||||
fun <R> fold(initial: R, operation: (R, T) -> R): R {
|
||||
var accumulator = initial
|
||||
//for (element in buffer) accumulator = operation(accumulator, element)
|
||||
if (tail >= head) {
|
||||
for (i in head..tail - 1)
|
||||
operation(accumulator, buffer[i])
|
||||
if (unreliableAddCount <= size) {
|
||||
for (i in 0..head)
|
||||
accumulator = operation(accumulator, buffer[i])
|
||||
}
|
||||
else {
|
||||
for (i in 0..size - 1)
|
||||
operation(accumulator, buffer[(i + head) % size])
|
||||
accumulator = operation(accumulator, buffer[(i + tail) % size])
|
||||
}
|
||||
|
||||
return accumulator
|
||||
}
|
||||
|
||||
inline fun forEachConcurrent(action: (T) -> Unit) {
|
||||
TODO()
|
||||
}
|
||||
|
||||
inline fun forEachConcurrentWaitFor(action: (T) -> Unit) {
|
||||
TODO()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "CircularArray(size=" + buffer.size + ", head=" + head + ", tail=" + tail + ")"
|
||||
|
||||
59
src/net/torvald/spriteanimation/Animatable.kt
Normal file
59
src/net/torvald/spriteanimation/Animatable.kt
Normal file
@@ -0,0 +1,59 @@
|
||||
package net.torvald.spriteanimation
|
||||
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import net.torvald.spriteassembler.ADProperties
|
||||
import net.torvald.spriteassembler.AssembleSheetPixmap
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2019-01-18.
|
||||
*/
|
||||
interface HasAssembledSprite {
|
||||
|
||||
var animDesc: FileHandle
|
||||
|
||||
// FIXME sometimes the animmation is invisible (row and nFrames mismatch -- row is changed to 1 but it's drawing 3rd frame?)
|
||||
|
||||
fun reassembleSprite(sprite: SpriteAnimation) {
|
||||
_rebuild(ADProperties(animDesc.read()), sprite)
|
||||
}
|
||||
|
||||
/*fun rebuild(animDesc: String, spriteAnimation: SpriteAnimation) {
|
||||
_rebuild(ADProperties(StringReader(animDesc)), spriteAnimation)
|
||||
}
|
||||
|
||||
fun rebuild(animDesc: FileHandle, spriteAnimation: SpriteAnimation) {
|
||||
_rebuild(ADProperties(animDesc.read()), spriteAnimation)
|
||||
}
|
||||
|
||||
fun rebuild(javaProp: Properties, spriteAnimation: SpriteAnimation) {
|
||||
_rebuild(ADProperties(javaProp), spriteAnimation)
|
||||
}*/
|
||||
|
||||
|
||||
private fun _rebuild(ad: ADProperties, sprite: SpriteAnimation) {
|
||||
// TODO injecting held item/armour pictures? Would it be AssembleSheetPixmap's job?
|
||||
|
||||
val pixmap = AssembleSheetPixmap(ad)
|
||||
val texture = Texture(pixmap)
|
||||
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
|
||||
pixmap.dispose()
|
||||
val regionPack = TextureRegionPack(texture, ad.frameWidth, ad.frameHeight)
|
||||
|
||||
val newAnimDelays = FloatArray(ad.animations.size)
|
||||
val newAnimFrames = IntArray(ad.animations.size)
|
||||
|
||||
ad.animations.forEach { t, u ->
|
||||
val index = u.row - 1
|
||||
newAnimDelays[index] = u.delay
|
||||
newAnimFrames[index] = u.frames
|
||||
}
|
||||
|
||||
sprite.setSpriteImage(regionPack)
|
||||
sprite.delays = newAnimDelays
|
||||
sprite.nFrames = newAnimFrames
|
||||
sprite.nRows = newAnimDelays.size
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,21 +7,39 @@ package net.torvald.spriteanimation
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.terrarum.Second
|
||||
import net.torvald.terrarum.gameactors.ActorWBMovable
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
|
||||
class SpriteAnimation(val parentActor: ActorWBMovable) {
|
||||
|
||||
private lateinit var textureRegion: TextureRegionPack
|
||||
lateinit var textureRegion: TextureRegionPack; private set
|
||||
|
||||
var currentFrame = 0
|
||||
var currentRow = 0
|
||||
var nFrames: Int = 1
|
||||
private set
|
||||
|
||||
var nFrames: IntArray = intArrayOf(1)
|
||||
internal set
|
||||
var nRows: Int = 1
|
||||
private set
|
||||
var delay = 200f
|
||||
internal set
|
||||
|
||||
private val currentDelay: Second
|
||||
get() = delays[currentRow]
|
||||
|
||||
/**
|
||||
* Sets delays for each rows. Array size must be the same as the rows of the sheet
|
||||
*/
|
||||
var delays: FloatArray = floatArrayOf(0.2f)
|
||||
set(value) {
|
||||
if (value.filter { it <= 0f }.isNotEmpty()) {
|
||||
throw IllegalArgumentException("Delay array contains zero or negative value: $delays")
|
||||
}
|
||||
|
||||
field = value
|
||||
}
|
||||
|
||||
private var delta = 0f
|
||||
|
||||
val looping = true
|
||||
private var animationRunning = true
|
||||
var flipHorizontal = false
|
||||
@@ -53,7 +71,15 @@ class SpriteAnimation(val parentActor: ActorWBMovable) {
|
||||
*/
|
||||
fun setRowsAndFrames(nRows: Int, nFrames: Int) {
|
||||
this.nRows = nRows
|
||||
this.nFrames = nFrames
|
||||
this.nFrames = IntArray(nRows) { nFrames }
|
||||
}
|
||||
|
||||
fun setFramesOf(row: Int, frameCount: Int) {
|
||||
nFrames[row] = frameCount
|
||||
}
|
||||
|
||||
fun setFramesCount(framesCount: IntArray) {
|
||||
nFrames = framesCount
|
||||
}
|
||||
|
||||
fun update(delta: Float) {
|
||||
@@ -61,17 +87,23 @@ class SpriteAnimation(val parentActor: ActorWBMovable) {
|
||||
//skip this if animation is stopped
|
||||
this.delta += delta
|
||||
|
||||
//println("delta accumulation: $delta, currentDelay: $currentDelay")
|
||||
|
||||
//check if it's time to advance the frame
|
||||
if (this.delta >= this.delay) {
|
||||
//if set to not loop, keep the frame at the last frame
|
||||
if (this.currentFrame == this.nFrames && !this.looping) {
|
||||
this.currentFrame = this.nFrames - 1
|
||||
while (this.delta >= currentDelay) {
|
||||
// advance frame
|
||||
if (looping) { // looping, wrap around
|
||||
currentFrame = (currentFrame + 1) % nFrames[currentRow]
|
||||
}
|
||||
else if (currentFrame < nFrames[currentRow] - 1) { // not looping and haven't reached the end
|
||||
currentFrame += 1
|
||||
}
|
||||
|
||||
//advance one frame, then reset delta counter
|
||||
this.currentFrame = this.currentFrame % this.nFrames
|
||||
this.delta = 0f
|
||||
// discount counter
|
||||
this.delta -= currentDelay
|
||||
}
|
||||
|
||||
//println("row, frame: $currentRow, $currentFrame")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,13 +118,13 @@ class SpriteAnimation(val parentActor: ActorWBMovable) {
|
||||
* *
|
||||
* @param scale
|
||||
*/
|
||||
@JvmOverloads fun render(batch: SpriteBatch, posX: Float, posY: Float, scale: Float = 1f) {
|
||||
fun render(batch: SpriteBatch, posX: Float, posY: Float, scale: Float = 1f) {
|
||||
if (cellWidth == 0 || cellHeight == 0) {
|
||||
throw Error("Sprite width or height is set to zero! ($cellWidth, $cellHeight); master: $parentActor")
|
||||
}
|
||||
|
||||
if (visible) {
|
||||
val region = textureRegion.get(currentRow, currentFrame)
|
||||
val region = textureRegion.get(currentFrame, currentRow)
|
||||
batch.color = colorFilter
|
||||
|
||||
if (flipHorizontal && flipVertical) {
|
||||
@@ -131,20 +163,9 @@ class SpriteAnimation(val parentActor: ActorWBMovable) {
|
||||
}
|
||||
|
||||
fun switchRow(newRow: Int) {
|
||||
currentRow = newRow % nRows
|
||||
|
||||
//if beyond the frame index then reset
|
||||
if (currentFrame > nFrames) {
|
||||
reset()
|
||||
}
|
||||
}
|
||||
|
||||
fun setSpriteDelay(newDelay: Float) {
|
||||
if (newDelay > 0) {
|
||||
delay = newDelay
|
||||
}
|
||||
else {
|
||||
throw IllegalArgumentException("Delay equal or less than zero")
|
||||
if (newRow != currentRow) {
|
||||
currentRow = newRow
|
||||
currentFrame = 1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
314
src/net/torvald/spriteassembler/ADProperties.kt
Normal file
314
src/net/torvald/spriteassembler/ADProperties.kt
Normal file
@@ -0,0 +1,314 @@
|
||||
package net.torvald.spriteassembler
|
||||
|
||||
import net.torvald.terrarum.linearSearchBy
|
||||
import java.io.InputStream
|
||||
import java.io.Reader
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.collections.HashSet
|
||||
|
||||
internal data class Joint(val name: String, val position: ADPropertyObject.Vector2i) {
|
||||
override fun toString() = "$name $position"
|
||||
}
|
||||
|
||||
internal data class Skeleton(val name: String, val joints: List<Joint>) {
|
||||
override fun toString() = "$name=$joints"
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name You know it
|
||||
* @param delay Delay between each frame in seconds
|
||||
* @param row STARTS AT ONE! Row in the final spritesheet, also act as the animation index.
|
||||
* @param frames number of frames this animation has
|
||||
* @param skeleton list of joints to be transformed
|
||||
*/
|
||||
internal data class Animation(val name: String, val delay: Float, val row: Int, val frames: Int, val skeleton: Skeleton) {
|
||||
override fun toString() = "$name delay: $delay, row: $row, frames: $frames, skeleton: ${skeleton.name}"
|
||||
}
|
||||
|
||||
/** Later the 'translate' can be changed so that it represents affine transformation (Matrix2d) */
|
||||
internal data class Transform(val joint: Joint, val translate: ADPropertyObject.Vector2i) {
|
||||
override fun toString() = "$joint transform: $translate"
|
||||
}
|
||||
|
||||
class ADProperties {
|
||||
private val javaProp = Properties()
|
||||
|
||||
/** Every key is CAPITALISED */
|
||||
private val propTable = HashMap<String, List<ADPropertyObject>>()
|
||||
|
||||
/** list of bodyparts used by all the skeletons (HEAD, UPPER_TORSO, LOWER_TORSO) */
|
||||
lateinit var bodyparts: List<String>; private set
|
||||
lateinit var bodypartFiles: List<String>; private set
|
||||
/** properties that are being used as skeletons (SKELETON_STAND) */
|
||||
internal lateinit var skeletons: HashMap<String, Skeleton>; private set
|
||||
/** properties that are recognised as animations (ANIM_RUN, ANIM)IDLE) */
|
||||
internal lateinit var animations: HashMap<String, Animation>; private set
|
||||
/** an "animation frame" property (ANIM_RUN_1, ANIM_RUN_2) */
|
||||
internal lateinit var transforms: HashMap<String, List<Transform>>; private set
|
||||
|
||||
private val reservedProps = listOf("SPRITESHEET", "EXTENSION")
|
||||
private val animMustContain = listOf("DELAY", "ROW", "SKELETON")
|
||||
|
||||
lateinit var baseFilename: String; private set
|
||||
lateinit var extension: String; private set
|
||||
var frameWidth: Int = -1; private set
|
||||
var frameHeight: Int = -1; private set
|
||||
var originX: Int = -1; private set
|
||||
var originY: Int = -1; private set
|
||||
internal val origin: ADPropertyObject.Vector2i
|
||||
get() = ADPropertyObject.Vector2i(originX, originY)
|
||||
|
||||
private val animFrameSuffixRegex = Regex("""_[0-9]+""")
|
||||
|
||||
private val ALL_JOINT = Joint(ALL_JOINT_SELECT_KEY, ADPropertyObject.Vector2i(0, 0))
|
||||
|
||||
var rows = -1; private set
|
||||
var cols = -1; private set
|
||||
|
||||
companion object {
|
||||
const val ALL_JOINT_SELECT_KEY = "ALL"
|
||||
}
|
||||
|
||||
constructor(reader: Reader) {
|
||||
javaProp.load(reader)
|
||||
continueLoad()
|
||||
}
|
||||
|
||||
constructor(inputStream: InputStream) {
|
||||
javaProp.load(inputStream)
|
||||
continueLoad()
|
||||
}
|
||||
|
||||
constructor(javaProp: Properties) {
|
||||
this.javaProp.putAll(javaProp.toMap())
|
||||
}
|
||||
|
||||
private fun continueLoad() {
|
||||
javaProp.keys.forEach { propName ->
|
||||
val propsStr = javaProp.getProperty(propName as String)
|
||||
val propsList = propsStr.split(';').map { ADPropertyObject(it) }
|
||||
|
||||
propTable[propName.toUpperCase()] = propsList
|
||||
}
|
||||
|
||||
// set reserved values for the animation: filename, extension
|
||||
baseFilename = get("SPRITESHEET")[0].name
|
||||
extension = get("EXTENSION")[0].name
|
||||
val frameSizeVec = get("CONFIG").linearSearchBy { it.name == "SIZE" }!!.input as ADPropertyObject.Vector2i
|
||||
frameWidth = frameSizeVec.x
|
||||
frameHeight = frameSizeVec.y
|
||||
originX = (get("CONFIG").linearSearchBy { it.name == "ORIGINX" }!!.input as Float).toInt()
|
||||
originY = frameHeight - 1
|
||||
|
||||
var maxColFinder = -1
|
||||
var maxRowFinder = -1
|
||||
val bodyparts = HashSet<String>()
|
||||
val skeletons = HashMap<String, Skeleton>()
|
||||
val animations = HashMap<String, Animation>()
|
||||
val animFrames = HashMap<String, Int>()
|
||||
val transforms = HashMap<String, List<Transform>>()
|
||||
// scan every props, write down anim frames for later use
|
||||
propTable.keys.forEach {
|
||||
if (animFrameSuffixRegex.containsMatchIn(it)) {
|
||||
val animName = getAnimNameFromFrame(it)
|
||||
val frameNumber = getFrameNumberFromName(it)
|
||||
|
||||
// if animFrames does not have our entry, add it.
|
||||
// otherwise, max() against the existing value
|
||||
if (animFrames.containsKey(animName)) {
|
||||
animFrames[animName] = maxOf(animFrames[animName]!!, frameNumber)
|
||||
}
|
||||
else {
|
||||
animFrames[animName] = frameNumber
|
||||
}
|
||||
|
||||
maxColFinder = maxOf(maxColFinder, frameNumber)
|
||||
}
|
||||
}
|
||||
// populate skeletons and animations
|
||||
forEach { s, list ->
|
||||
// Map-ify. If it has variable == "SKELETON", the 's' is likely an animation
|
||||
// and thus, uses whatever the "input" used by the SKELETON is a skeleton
|
||||
val propsHashMap = HashMap<String, Any?>()
|
||||
list.forEach {
|
||||
propsHashMap[it.name.toUpperCase()] = it.input
|
||||
}
|
||||
|
||||
// if it is indeed anim, populate animations list
|
||||
if (propsHashMap.containsKey("SKELETON")) {
|
||||
val skeletonName = propsHashMap["SKELETON"] as String
|
||||
val skeletonDef = get(skeletonName)
|
||||
|
||||
skeletons[skeletonName] = Skeleton(skeletonName, skeletonDef.toJoints())
|
||||
animations[s] = Animation(
|
||||
s,
|
||||
propsHashMap["DELAY"] as Float,
|
||||
(propsHashMap["ROW"] as Float).toInt(),
|
||||
animFrames[s]!!,
|
||||
Skeleton(skeletonName, skeletonDef.toJoints())
|
||||
)
|
||||
|
||||
maxRowFinder = maxOf(maxRowFinder, animations[s]!!.row)
|
||||
}
|
||||
}
|
||||
|
||||
// populate the bodyparts using skeletons
|
||||
skeletons.forEach { (_, prop: Skeleton) ->
|
||||
prop.joints.forEach {
|
||||
bodyparts.add(it.name)
|
||||
}
|
||||
}
|
||||
|
||||
// populate transforms
|
||||
animations.forEach { t, u ->
|
||||
for (fc in 1..u.frames) {
|
||||
val frameName = "${t}_$fc"
|
||||
val prop = get(frameName)
|
||||
|
||||
var emptyList = prop.size == 1 && prop[0].name.isEmpty()
|
||||
|
||||
val transformList = if (!emptyList) {
|
||||
List(prop.size) { index ->
|
||||
val jointNameToSearch = prop[index].name.toUpperCase()
|
||||
val joint = if (jointNameToSearch == "ALL")
|
||||
ALL_JOINT
|
||||
else
|
||||
u.skeleton.joints.linearSearchBy { it.name == jointNameToSearch }
|
||||
?: throw NullPointerException("No such joint: $jointNameToSearch")
|
||||
val translate = prop[index].input as ADPropertyObject.Vector2i
|
||||
|
||||
Transform(joint, translate)
|
||||
}
|
||||
}
|
||||
else {
|
||||
// to make real empty list
|
||||
List(0) { Transform(ALL_JOINT, ADPropertyObject.Vector2i(0, 0)) }
|
||||
}
|
||||
|
||||
transforms[frameName] = transformList
|
||||
}
|
||||
}
|
||||
|
||||
this.bodyparts = bodyparts.toList().sorted()
|
||||
this.skeletons = skeletons
|
||||
this.animations = animations
|
||||
this.bodypartFiles = this.bodyparts.map { toFilename(it) }
|
||||
this.transforms = transforms
|
||||
|
||||
cols = maxColFinder
|
||||
rows = maxRowFinder
|
||||
}
|
||||
|
||||
operator fun get(identifier: String) = propTable[identifier.toUpperCase()]!!
|
||||
val keys
|
||||
get() = propTable.keys
|
||||
fun containsKey(key: String) = propTable.containsKey(key)
|
||||
fun forEach(predicate: (String, List<ADPropertyObject>) -> Unit) = propTable.forEach(predicate)
|
||||
|
||||
fun toFilename(partName: String) =
|
||||
"${this.baseFilename}${partName.toLowerCase()}${this.extension}"
|
||||
|
||||
internal fun getAnimByFrameName(frameName: String) = animations[getAnimNameFromFrame(frameName)]!!
|
||||
internal fun getFrameNumberFromName(frameName: String) = frameName.substring(frameName.lastIndexOf('_') + 1 until frameName.length).toInt()
|
||||
|
||||
internal fun getSkeleton(name: String) = skeletons[name]!!
|
||||
internal fun getTransform(name: String) = transforms[name]!!
|
||||
|
||||
private fun getAnimNameFromFrame(s: String) = s.substring(0 until s.lastIndexOf('_'))
|
||||
|
||||
private fun List<ADPropertyObject>.toJoints() = List(this.size) {
|
||||
Joint(this[it].name.toUpperCase(), this[it].input!! as ADPropertyObject.Vector2i)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param propertyRaw example inputs:
|
||||
* - ```DELAY 0.15```
|
||||
* - ```LEG_RIGHT 0,-1```
|
||||
*
|
||||
* Created by minjaesong on 2019-01-05.
|
||||
*/
|
||||
class ADPropertyObject(propertyRaw: String) {
|
||||
|
||||
/** If the input is like ```UPPER_TORSO``` (that is, not a variable-input pair), this holds the string UPPER_TORSO. */
|
||||
val name: String
|
||||
val input: Any?
|
||||
get() = when (type) {
|
||||
ADPropertyType.IVEC2 -> field!! as Vector2i
|
||||
ADPropertyType.FLOAT -> field!! as Float
|
||||
ADPropertyType.STRING_PAIR -> field!! as String
|
||||
else -> null
|
||||
}
|
||||
val type: ADPropertyType
|
||||
|
||||
|
||||
init {
|
||||
val propPair = propertyRaw.split(variableInputSepRegex)
|
||||
|
||||
if (isADvariable(propertyRaw)) {
|
||||
name = propPair[0]
|
||||
val inputStr = propPair[1]
|
||||
|
||||
if (isADivec2(inputStr)) {
|
||||
type = ADPropertyType.IVEC2
|
||||
input = toADivec2(inputStr)
|
||||
}
|
||||
else if (isADfloat(inputStr)) {
|
||||
type = ADPropertyType.FLOAT
|
||||
input = toADfloat(inputStr)
|
||||
}
|
||||
else {
|
||||
type = ADPropertyType.STRING_PAIR
|
||||
input = inputStr
|
||||
}
|
||||
}
|
||||
else {
|
||||
name = propertyRaw
|
||||
input = null
|
||||
type = ADPropertyType.NAME_ONLY
|
||||
}
|
||||
}
|
||||
|
||||
internal companion object {
|
||||
private val floatRegex = Regex("""-?[0-9]+(\.[0-9]*)?""")
|
||||
private val ivec2Regex = Regex("""-?[0-9]+,-?[0-9]+""")
|
||||
private val variableInputSepRegex = Regex(""" +""")
|
||||
|
||||
fun isADivec2(s: String) = ivec2Regex.matches(s)
|
||||
fun isADfloat(s: String) = floatRegex.matches(s) && !ivec2Regex.containsMatchIn(s)
|
||||
|
||||
fun toADivec2(s: String) = if (isADivec2(s))
|
||||
Vector2i(s.substringBefore(',').toInt(), s.substringAfter(',').toInt())
|
||||
else throw IllegalArgumentException("Input not in ivec2 format: $s")
|
||||
fun toADfloat(s: String) = if (isADfloat(s))
|
||||
s.toFloat()
|
||||
else throw IllegalArgumentException("Input not in ivec2 format: $s")
|
||||
|
||||
/** example valid input: ```LEG_RIGHT 0,1``` */
|
||||
fun isADvariable(property: String) = variableInputSepRegex.containsMatchIn(property)
|
||||
/** example valid input: ```sprites/test``` */
|
||||
fun isADstring(property: String) = !isADvariable(property)
|
||||
}
|
||||
|
||||
internal data class Vector2i(var x: Int, var y: Int) {
|
||||
override fun toString() = "($x, $y)"
|
||||
|
||||
operator fun plus(other: Vector2i) = Vector2i(this.x + other.x, this.y + other.y)
|
||||
operator fun minus(other: Vector2i) = Vector2i(this.x - other.x, this.y - other.y)
|
||||
|
||||
fun invertY() = Vector2i(this.x, -this.y)
|
||||
}
|
||||
|
||||
enum class ADPropertyType {
|
||||
NAME_ONLY, // "sprite/test.tga" to nothing
|
||||
IVEC2, // "LEG_RIGHT" to (1,-1)
|
||||
FLOAT, // "DELAY" to 0.15
|
||||
STRING_PAIR // "SKELETON" to "SKELETON_DEFAULT"
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "$name ${input ?: ""}: ${type.toString().toLowerCase()}"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
## Animation Description Language
|
||||
|
||||
This is a text version of my drawing of same name. 2018-01-04 CuriousTorvald
|
||||
|
||||
Author's node: yet another non-JSON domain-specific language because why not?
|
||||
|
||||
## Objective
|
||||
|
||||
* Java .properties-compatible
|
||||
* Case insensitive
|
||||
|
||||
## Example code
|
||||
|
||||
```
|
||||
SPRITESHEET=sprites/test
|
||||
EXTENSION=.tga.gz
|
||||
|
||||
ANIM_RUN=DELAY 0.15;ROW 2
|
||||
ANIM_RUN_BODYPARTS=HEAD;UPPER_TORSO;LOWER_TORSO;ARM_FWD_LEFT;ARM_FWD_RIGHT;LEG_LEFT;LEG_RIGHT
|
||||
ANIM_RUN_1=LEG_RIGHT 1,-1;LEG_LEFT -1,0
|
||||
ANIM_RUN_2=ALL 0,-1;LEG_RIGHT 0,1;LEG_LEFT 0,-1
|
||||
ANIM_RUN_3=LEG_RIGHT -1,0;LEG_LEFT 1,-1
|
||||
ANIM_RUN_4=ALL 0,-1;LEG_RIGHT 0,-1;LEG_LEFT 0,1
|
||||
|
||||
ANIM_IDLE=DELAY 2;ROW 1
|
||||
ANIM_IDLE_BODYPARTS=HEAD;UPPER_TORSO;LOWER_TORSO;ARM_REST_LEFT;ARM_REST_RIGHT;LEG_LEFT;LEG_RIGHT
|
||||
ANIM_IDLE_1=
|
||||
! ANIM_IDLE_1 will not make any transformation
|
||||
ANIM_IDLE_2=UPPER_TORSO 0,-1
|
||||
|
||||
ANIM_CROUCH=DELAY 1;ROW 3
|
||||
ANIM_CROUCH_BODYPARTS=HEAD;UPPER_TORSO;LOWER_TORSO;ARM_FWD_LEFT;ARM_FWD_RIGHT;LEG_CROUCH_LEFT;LEG_CROUCH_RIGHT
|
||||
ANIM_CROUCH_1=
|
||||
...
|
||||
```
|
||||
|
||||
### In-detail
|
||||
|
||||
```
|
||||
ANIM_RUN=DELAY 0.15;ROW 2
|
||||
```
|
||||
|
||||
Each line defines one property. A property is a field-value pair. In this code, field is ```ANIM_RUN```, and the value is ```DELAY 0.15;ROW 2```
|
||||
|
||||
The values are further parsed using ```;``` (semicolon with NO spaces attached) as a separator.
|
||||
|
||||
```
|
||||
In this example, ANIM_RUN contains two variables:
|
||||
|
||||
DELAY = 0.15
|
||||
ROW = 2
|
||||
```
|
||||
|
||||
A value of the field is consisted of zero or more variable-input pairs. Variable and the input are separated with one or more connected spaces.
|
||||
|
||||
#### Variables
|
||||
|
||||
Variables can have only one of the two types: ```float``` and ```ivec2```. Single integer value ('2' in the ROW) are regarded as a float.
|
||||
|
||||
Float and Ivec2 are determined by:
|
||||
|
||||
* Ivec2: inputs that are matched by the regex ```-?[0-9]+,-?[0-9]+``` (we call this "ivec2 regex")
|
||||
* Float: inputs that are matched by the regex ```-?[0-9]+(\.[0-9]*)?```, but not even partially matched by the ivec2 regex.
|
||||
|
||||
Any argument to the body parts takes ivec2, to move the parts accordingly.
|
||||
|
||||
#### Just one exception: SPRITESHEET and EXTENSION
|
||||
|
||||
SPRITESHEET and EXTENSION property is not parsed as a property, it's just a single string like the original .properties
|
||||
|
||||
### Naming convention of properties
|
||||
|
||||
If a field is recognised as an animation (in this case ANIM_RUN), the assembler will look for the fields named like ANIM_RUN_1, ANIM_RUN_2, ... , ANIM_RUN_9, ANIM_RUN_10 and beyond.
|
||||
|
||||
### Naming convention of files
|
||||
|
||||
If the animation specifies a "body part" (in this example LEG_LEFT and LEG_RIGHT), the assembler will look for a file ```sprites/test_leg_left.tga.gz``` and ```sprites/test_leg_right.tga.gz``` respectively. Filenames are advised to be kept all lowercase.
|
||||
|
||||
### Reserved keywords
|
||||
|
||||
These values must exist so that the file can be parsed successfully.
|
||||
|
||||
#### Root
|
||||
|
||||
|Name|Type|Meaning|
|
||||
|---|---|---|
|
||||
|SPRITESHEET|properties: NAME_ONLY|Base file name of the images|
|
||||
|EXTENSION|properties: NAME_ONLY|Extension of the base file|
|
||||
|CONFIG|properties: 2 variables|Frame size and origin-x position, 0 being left|
|
||||
|
||||
#### Animation
|
||||
|
||||
Remember that 'variables' are contained within 'properties'
|
||||
|
||||
|Name|Type|Meaning|
|
||||
|---|---|---|
|
||||
|DELAY|variable: float|Delay between frames, in seconds|
|
||||
|ROW|variable: float|which row the animation goes in the spritesheet|
|
||||
|SKELETON|variable: string_pair|Which skeleton this animation uses
|
||||
|
||||
#### Transforms
|
||||
|
||||
Things like ```LEG_RIGHT -1,0``` within ```ANIM_RUN_3``` are called 'Transform'
|
||||
|
||||
|Name|Type|Meaning|
|
||||
|---|---|---|
|
||||
|ALL|variable: ivec2|Shifts (translates) everything by set value|
|
||||
|
||||
### Notes
|
||||
|
||||
* All indices are one-based
|
||||
|
||||
## Operation
|
||||
|
||||
* Each line describes transformation
|
||||
* Transformation are applied sequentially from left to right. In other words, their order matters. Be wary of the clipping that may occur! (really?)
|
||||
* The Field is an identifier the game code -- sprite assembler -- recognises.
|
||||
* The Field of animation's name is the name the game code looks for. Example: ```this.setAnim("ANIM_RUN")```
|
||||
* Coord system is Y-Up, meaning Y=0 is the bottommost position.
|
||||
125
src/net/torvald/spriteassembler/AssembleFrameGdx.kt
Normal file
125
src/net/torvald/spriteassembler/AssembleFrameGdx.kt
Normal file
@@ -0,0 +1,125 @@
|
||||
package net.torvald.spriteassembler
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.linearSearch
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Assembles the single frame of the animation, outputs GDX Pixmap.
|
||||
*
|
||||
* The entire rendering is done by using pixmap. That is, no GPU access.
|
||||
*
|
||||
* Created by minjaesong on 2019-01-06.
|
||||
*/
|
||||
object AssembleSheetPixmap {
|
||||
|
||||
operator fun invoke(properties: ADProperties): Pixmap {
|
||||
val canvas = Pixmap(properties.cols * properties.frameWidth, properties.rows * properties.frameHeight, Pixmap.Format.RGBA8888)
|
||||
canvas.blending = Pixmap.Blending.SourceOver
|
||||
|
||||
|
||||
// actually draw
|
||||
properties.transforms.forEach { t, _ ->
|
||||
drawThisFrame(t, canvas, properties)
|
||||
}
|
||||
|
||||
return canvas
|
||||
}
|
||||
|
||||
private fun drawThisFrame(frameName: String,
|
||||
canvas: Pixmap,
|
||||
properties: ADProperties
|
||||
) {
|
||||
val theAnim = properties.getAnimByFrameName(frameName)
|
||||
val skeleton = theAnim.skeleton.joints.reversed()
|
||||
val transforms = properties.getTransform(frameName)
|
||||
val bodyparts = Array<Pixmap?>(skeleton.size) {
|
||||
// if file does not exist, null it
|
||||
val file = File("assets/" + properties.toFilename(skeleton[it].name))
|
||||
|
||||
//printdbg(this, "Loading file ${file.absolutePath}, exists: ${file.exists()}")
|
||||
|
||||
/*return*/if (file.exists()) {
|
||||
Pixmap(Gdx.files.internal(file.path))
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
}
|
||||
val transformList = AssembleFrameBase.makeTransformList(skeleton, transforms)
|
||||
|
||||
val animRow = theAnim.row
|
||||
val animFrame = properties.getFrameNumberFromName(frameName)
|
||||
|
||||
AppLoader.printdbg(this, "Frame to draw: $frameName (R$animRow C$animFrame)")
|
||||
|
||||
drawFrame(animRow, animFrame, canvas, properties, bodyparts, transformList)
|
||||
|
||||
bodyparts.forEach { it?.dispose() }
|
||||
}
|
||||
|
||||
private fun drawFrame(row: Int, column: Int,
|
||||
canvas: Pixmap,
|
||||
props: ADProperties,
|
||||
bodyparts: Array<Pixmap?>,
|
||||
transformList: List<Pair<String, ADPropertyObject.Vector2i>>
|
||||
) {
|
||||
val tmpFrame = Pixmap(props.frameWidth, props.frameHeight, Pixmap.Format.RGBA8888)
|
||||
|
||||
bodyparts.forEachIndexed { index, image ->
|
||||
if (image != null) {
|
||||
val imgCentre = AssembleFrameBase.getCentreOf(image)
|
||||
val drawPos = transformList[index].second.invertY() + props.origin - imgCentre
|
||||
|
||||
tmpFrame.drawPixmap(image, drawPos.x, drawPos.y)
|
||||
}
|
||||
}
|
||||
|
||||
canvas.drawPixmap(
|
||||
tmpFrame,
|
||||
(column - 1) * props.frameWidth,
|
||||
(row - 1) * props.frameHeight
|
||||
)
|
||||
|
||||
tmpFrame.dispose()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal object AssembleFrameBase {
|
||||
/**
|
||||
* Returns joints list with tranform applied.
|
||||
* @param skeleton list of joints
|
||||
* @param transform ordered list of transforms should be applied. First come first serve.
|
||||
* @return List of pairs that contains joint name on left, final transform value on right
|
||||
*/
|
||||
fun makeTransformList(joints: List<Joint>, transforms: List<Transform>): List<Pair<String, ADPropertyObject.Vector2i>> {
|
||||
// make our mutable list
|
||||
val out = ArrayList<Pair<String, ADPropertyObject.Vector2i>>()
|
||||
joints.forEach {
|
||||
out.add(it.name to it.position)
|
||||
}
|
||||
|
||||
// process transform queue
|
||||
transforms.forEach { transform ->
|
||||
if (transform.joint.name == ADProperties.ALL_JOINT_SELECT_KEY) {
|
||||
// transform applies to all joints
|
||||
for (c in 0 until out.size) {
|
||||
out[c] = out[c].first to (out[c].second + transform.translate)
|
||||
}
|
||||
}
|
||||
else {
|
||||
val i = out.linearSearch { it.first == transform.joint.name }!!
|
||||
// transform applies to one specific joint in the list (one specific joint is a search result)
|
||||
out[i] = out[i].first to (out[i].second + transform.translate)
|
||||
}
|
||||
}
|
||||
|
||||
return out.toList()
|
||||
}
|
||||
|
||||
fun getCentreOf(pixmap: Pixmap) = ADPropertyObject.Vector2i(pixmap.width / 2, pixmap.height / 2)
|
||||
}
|
||||
322
src/net/torvald/spriteassembler/SpriteAssemblerApp.kt
Normal file
322
src/net/torvald/spriteassembler/SpriteAssemblerApp.kt
Normal file
@@ -0,0 +1,322 @@
|
||||
package net.torvald.spriteassembler
|
||||
|
||||
import com.badlogic.gdx.Game
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplication
|
||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.PixmapIO2
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import net.torvald.terrarum.gdxClearAndSetBlend
|
||||
import net.torvald.terrarum.inUse
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Font
|
||||
import java.awt.event.MouseAdapter
|
||||
import java.awt.event.MouseEvent
|
||||
import java.io.StringReader
|
||||
import java.util.*
|
||||
import javax.swing.*
|
||||
import javax.swing.tree.DefaultMutableTreeNode
|
||||
import javax.swing.tree.DefaultTreeModel
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2019-01-05.
|
||||
*/
|
||||
class SpriteAssemblerApp(val gdxWindow: SpriteAssemblerPreview) : JFrame() {
|
||||
|
||||
private val panelProperties = JTree()
|
||||
private val panelAnimationsList = JList<String>()
|
||||
private val panelBodypartsList = JList<String>()
|
||||
private val panelImageFilesList = JList<String>()
|
||||
private val panelSkeletonsList = JList<String>()
|
||||
private val panelTransformsList = JList<String>()
|
||||
private val panelStatList = JList<String>()
|
||||
private val panelCode = JTextPane()
|
||||
private val statBar = JTextArea("Null.")
|
||||
|
||||
private lateinit var adProperties: ADProperties
|
||||
|
||||
private val props = Properties()
|
||||
private val lang = Properties()
|
||||
|
||||
private val captionProperties = "" + // dummy string to make IDE happy with the auto indent
|
||||
|
||||
"id=ID of this block\n" +
|
||||
"drop=ID of the block this very block should drop when mined\n" +
|
||||
"name=String identifier of the block\n" +
|
||||
"shdr=Shade Red (light absorption). Valid range 0.0-4.0\n" +
|
||||
"shdg=Shade Green (light absorption). Valid range 0.0-4.0\n" +
|
||||
"shdb=Shade Blue (light absorption). Valid range 0.0-4.0\n" +
|
||||
"shduv=Shade UV (light absorbtion). Valid range 0.0-4.0\n" +
|
||||
"lumr=Luminosity Red (light intensity). Valid range 0.0-4.0\n" +
|
||||
"lumg=Luminosity Green (light intensity). Valid range 0.0-4.0\n" +
|
||||
"lumb=Luminosity Blue (light intensity). Valid range 0.0-4.0\n" +
|
||||
"lumuv=Luminosity UV (light intensity). Valid range 0.0-4.0\n" +
|
||||
"str=Strength of the block\n" +
|
||||
"dsty=Density of the block. Water have 1000 in the in-game scale\n" +
|
||||
"mate=Material of the block\n" +
|
||||
"solid=Whether the file has full collision\n" +
|
||||
"plat=Whether the block should behave like a platform\n" +
|
||||
"wall=Whether the block can be used as a wall\n" +
|
||||
"fall=Whether the block should fall through the empty space\n" +
|
||||
"dlfn=Dynamic Light Function. 0=Static. Please see <strong>notes</strong>\n" +
|
||||
"fv=Vertical friction when player slide on the cliff. 0 means not slide-able\n" +
|
||||
"fr=Horizontal friction. <16:slippery 16:regular >16:sticky\n"
|
||||
|
||||
/**
|
||||
* ¤ is used as a \n marker
|
||||
*/
|
||||
private val translations = "" +
|
||||
"WARNING_CONTINUE=Continue?\n" +
|
||||
"WARNING_YOUR_DATA_WILL_GONE=Existing edits will be lost.\n" +
|
||||
"OPERATION_CANCELLED=Operation cancelled.\n" +
|
||||
"NO_SUCH_FILE=No such file exists, operation cancelled.\n" +
|
||||
"NEW_ROWS=Enter the number of rows to initialise the new CSV.¤Remember, you can always add or delete rows later.\n" +
|
||||
"ADD_ROWS=Enter the number of rows to add:\n" +
|
||||
"WRITE_FAIL=Writing to file has failed:\n" +
|
||||
"STAT_INIT=Creating a new CSV. You can still open existing file.\n" +
|
||||
"STAT_SAVE_TGA_SUCCESSFUL=Spritesheet exported successfully.\n" +
|
||||
"STAT_LOAD_SUCCESSFUL=File loaded successfully.\n" +
|
||||
"ERROR_INTERNAL=Something went wrong.\n" +
|
||||
"ERROR_PARSE_FAIL=Parsing failed\n" +
|
||||
"SPRITE_DEF_LOAD_SUCCESSFUL=Sprite definition loaded.\n" +
|
||||
"SPRITE_ASSEMBLE_SUCCESSFUL=Sprite assembled."
|
||||
|
||||
init {
|
||||
// setup application properties //
|
||||
try {
|
||||
props.load(StringReader(captionProperties))
|
||||
lang.load(StringReader(translations))
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
|
||||
}
|
||||
|
||||
panelCode.font = Font(Font.MONOSPACED, Font.PLAIN, 12)
|
||||
|
||||
panelAnimationsList.model = DefaultListModel()
|
||||
panelBodypartsList.model = DefaultListModel()
|
||||
panelImageFilesList.model = DefaultListModel()
|
||||
panelSkeletonsList.model = DefaultListModel()
|
||||
panelTransformsList.model = DefaultListModel()
|
||||
panelStatList.model = DefaultListModel()
|
||||
|
||||
val panelPartsList = JTabbedPane(JTabbedPane.TOP)
|
||||
panelPartsList.add("Animations", JScrollPane(panelAnimationsList))
|
||||
panelPartsList.add("Bodyparts", JScrollPane(panelBodypartsList))
|
||||
panelPartsList.add("Images", JScrollPane(panelImageFilesList))
|
||||
panelPartsList.add("Skeletons", JScrollPane(panelSkeletonsList))
|
||||
panelPartsList.add("Transforms", JScrollPane(panelTransformsList))
|
||||
panelPartsList.add("Stats", JScrollPane(panelStatList))
|
||||
|
||||
val panelDataView = JSplitPane(JSplitPane.VERTICAL_SPLIT, JScrollPane(panelProperties), panelPartsList)
|
||||
panelDataView.resizeWeight = 0.333
|
||||
|
||||
// to disable text wrap
|
||||
//val panelCodeNoWrap = JPanel(BorderLayout())
|
||||
//panelCodeNoWrap.add(panelCode)
|
||||
|
||||
val panelMain = JSplitPane(JSplitPane.HORIZONTAL_SPLIT, JScrollPane(panelCode), panelDataView)
|
||||
panelMain.resizeWeight = 0.666
|
||||
|
||||
val menu = JMenuBar()
|
||||
menu.add(JMenu("Parse")).addMouseListener(object : MouseAdapter() {
|
||||
override fun mousePressed(e: MouseEvent?) {
|
||||
try {
|
||||
adProperties = ADProperties(StringReader(panelCode.text))
|
||||
statBar.text = lang.getProperty("SPRITE_DEF_LOAD_SUCCESSFUL")
|
||||
|
||||
val propRoot = DefaultMutableTreeNode("Properties")
|
||||
|
||||
adProperties.forEach { s, list ->
|
||||
// build tree node for the properties display
|
||||
val propNode = DefaultMutableTreeNode(s)
|
||||
propRoot.add(propNode)
|
||||
list.forEach {
|
||||
propNode.add(DefaultMutableTreeNode(it.toString()))
|
||||
}
|
||||
}
|
||||
|
||||
panelProperties.model = DefaultTreeModel(propRoot)
|
||||
|
||||
// clean the data views
|
||||
panelAnimationsList.model = DefaultListModel()
|
||||
panelBodypartsList.model = DefaultListModel()
|
||||
panelImageFilesList.model = DefaultListModel()
|
||||
panelSkeletonsList.model = DefaultListModel()
|
||||
panelTransformsList.model = DefaultListModel()
|
||||
panelStatList.model = DefaultListModel()
|
||||
|
||||
// populate animations view
|
||||
adProperties.animations.forEach {
|
||||
(panelAnimationsList.model as DefaultListModel).addElement("${it.value}")
|
||||
}
|
||||
// populate bodyparts view
|
||||
adProperties.bodyparts.forEach { partName ->
|
||||
(panelBodypartsList.model as DefaultListModel).addElement(partName)
|
||||
}
|
||||
// populate image file list view
|
||||
adProperties.bodypartFiles.forEach { partName ->
|
||||
(panelImageFilesList.model as DefaultListModel).addElement(partName)
|
||||
}
|
||||
// populate skeletons view
|
||||
adProperties.skeletons.forEach {
|
||||
(panelSkeletonsList.model as DefaultListModel).addElement("${it.value}")
|
||||
}
|
||||
// populate transforms view
|
||||
adProperties.transforms.forEach {
|
||||
(panelTransformsList.model as DefaultListModel).addElement("$it")
|
||||
}
|
||||
// populate stats
|
||||
(panelStatList.model as DefaultListModel).addElement("Spritesheet rows: ${adProperties.rows}")
|
||||
(panelStatList.model as DefaultListModel).addElement("Spritesheet columns: ${adProperties.cols}")
|
||||
(panelStatList.model as DefaultListModel).addElement("Frame size: ${adProperties.frameWidth}, ${adProperties.frameHeight}")
|
||||
(panelStatList.model as DefaultListModel).addElement("Origin position: ${adProperties.originX}, ${adProperties.originY}")
|
||||
}
|
||||
catch (fehler: Throwable) {
|
||||
displayError("ERROR_PARSE_FAIL", fehler)
|
||||
fehler.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
menu.add(JMenu("Run")).addMouseListener(object : MouseAdapter() {
|
||||
override fun mousePressed(e: MouseEvent?) {
|
||||
try {
|
||||
gdxWindow.requestAssemblyTest(adProperties)
|
||||
statBar.text = lang.getProperty("SPRITE_ASSEMBLE_SUCCESSFUL")
|
||||
}
|
||||
catch (fehler: Throwable) {
|
||||
displayError("ERROR_PARSE_FAIL", fehler)
|
||||
fehler.printStackTrace()
|
||||
}
|
||||
}
|
||||
})
|
||||
menu.add(JMenu("Export")).addMouseListener(object : MouseAdapter() {
|
||||
override fun mousePressed(e: MouseEvent?) {
|
||||
val fileChooser = JFileChooser()
|
||||
fileChooser.showSaveDialog(null)
|
||||
|
||||
if (fileChooser.selectedFile != null) {
|
||||
gdxWindow.requestExport(fileChooser.selectedFile.absolutePath)
|
||||
statBar.text = lang.getProperty("STAT_SAVE_TGA_SUCCESSFUL")
|
||||
} // else, do nothing
|
||||
}
|
||||
})
|
||||
|
||||
this.layout = BorderLayout()
|
||||
this.add(menu, BorderLayout.NORTH)
|
||||
this.add(panelMain, BorderLayout.CENTER)
|
||||
this.add(statBar, BorderLayout.SOUTH)
|
||||
this.title = "Terrarum Sprite Assembler and Viewer"
|
||||
this.isVisible = true
|
||||
this.setSize(1154, 768)
|
||||
this.defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE
|
||||
}
|
||||
|
||||
private fun displayMessage(messageKey: String) {
|
||||
JOptionPane.showOptionDialog(
|
||||
null,
|
||||
lang.getProperty(messageKey), null,
|
||||
JOptionPane.DEFAULT_OPTION,
|
||||
JOptionPane.INFORMATION_MESSAGE, null,
|
||||
arrayOf("OK", "Cancel"),
|
||||
"Cancel"
|
||||
)
|
||||
}
|
||||
|
||||
private fun displayError(messageKey: String, cause: Throwable) {
|
||||
JOptionPane.showOptionDialog(null,
|
||||
lang.getProperty(messageKey) + "\n" + cause.toString(), null,
|
||||
JOptionPane.DEFAULT_OPTION,
|
||||
JOptionPane.ERROR_MESSAGE, null,
|
||||
arrayOf("OK", "Cancel"),
|
||||
"Cancel"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class SpriteAssemblerPreview: Game() {
|
||||
private lateinit var batch: SpriteBatch
|
||||
|
||||
private lateinit var renderTexture: Texture
|
||||
private var image: Pixmap? = null
|
||||
set(value) {
|
||||
renderTexture.dispose()
|
||||
field?.dispose()
|
||||
|
||||
field = value
|
||||
renderTexture = Texture(field)
|
||||
}
|
||||
|
||||
override fun create() {
|
||||
Gdx.graphics.setTitle("Sprite Assembler Preview")
|
||||
batch = SpriteBatch()
|
||||
renderTexture = Texture(1, 1, Pixmap.Format.RGBA8888)
|
||||
}
|
||||
|
||||
private val bgCol = Color(.62f,.79f,1f,1f)
|
||||
|
||||
private var doAssemble = false
|
||||
private lateinit var assembleProp: ADProperties
|
||||
|
||||
private var doExport = false
|
||||
private lateinit var exportPath: String
|
||||
|
||||
override fun render() {
|
||||
if (doAssemble) {
|
||||
// assembly requires GL context
|
||||
doAssemble = false
|
||||
assembleImage(assembleProp)
|
||||
}
|
||||
|
||||
if (doExport && image != null) {
|
||||
doExport = false
|
||||
PixmapIO2.writeTGAHappy(Gdx.files.absolute(exportPath), image, false)
|
||||
}
|
||||
|
||||
|
||||
gdxClearAndSetBlend(.62f,.79f,1f,1f)
|
||||
|
||||
|
||||
batch.inUse {
|
||||
batch.color = Color.WHITE
|
||||
batch.draw(renderTexture, 0f, 0f)
|
||||
}
|
||||
}
|
||||
|
||||
private fun assembleImage(prop: ADProperties) {
|
||||
image = AssembleSheetPixmap(prop)
|
||||
}
|
||||
|
||||
// TODO rename to requestAssembly
|
||||
fun requestAssemblyTest(prop: ADProperties) {
|
||||
doAssemble = true
|
||||
assembleProp = prop
|
||||
}
|
||||
|
||||
fun requestExport(path: String) {
|
||||
doExport = true
|
||||
exportPath = path
|
||||
}
|
||||
|
||||
override fun resize(width: Int, height: Int) {
|
||||
super.resize(width, height)
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val appConfig = LwjglApplicationConfiguration()
|
||||
appConfig.resizable = true
|
||||
appConfig.width = 512
|
||||
appConfig.height = 512
|
||||
appConfig.foregroundFPS = 5
|
||||
appConfig.backgroundFPS = 5
|
||||
|
||||
val gdxWindow = SpriteAssemblerPreview()
|
||||
|
||||
LwjglApplication(gdxWindow, appConfig)
|
||||
SpriteAssemblerApp(gdxWindow)
|
||||
}
|
||||
35
src/net/torvald/spriteassembler/test_sprite.properties
Normal file
35
src/net/torvald/spriteassembler/test_sprite.properties
Normal file
@@ -0,0 +1,35 @@
|
||||
# complete file name is: SPRITESHEET + bodypart name + EXTENSION
|
||||
SPRITESHEET=mods/basegame/sprites/sprite_assembler_test_assets/test_
|
||||
EXTENSION=.tga
|
||||
# defines frame size and origin point. Origin point is given as: (originx, size.y - 1)
|
||||
CONFIG=SIZE 48,56;ORIGINX 29
|
||||
|
||||
# note to self: don't implement skeleton hierarchy: there's too many exceptions
|
||||
# besides, you have "ALL" key.
|
||||
|
||||
! a skeleton also defines what body parts (images) be used.
|
||||
! you can also write multiline text using reverse solidus; this is a feature of .properties
|
||||
! skeleton joints are ordered: foremost-drawn object comes first, which means lowermost object IN THIS LIST
|
||||
! are painted first, and any object that comes before it will paint over it. In other words, this list is
|
||||
! first reversed then being iterated.
|
||||
! Joints' original point is defined in the document sprite_joints.psd. It also has visual representations.
|
||||
# TODO right now accessory points are explicitly defined. Should they be injected in run-time?
|
||||
SKELETON_STAND=HEADGEAR 0,32;HAIR_FORE 0,32;\
|
||||
ARM_REST_RIGHT -7,23;HAND_REST_RIGHT -6,11;HELD_ITEM -6,11;\
|
||||
HAIR 0,32;HEAD 0,32;\
|
||||
UPPER_TORSO 0,23;LOWER_TORSO 0,15;\
|
||||
FOOT_RIGHT -2,2;LEG_REST_RIGHT -2,7;\
|
||||
FOOT_LEFT 2,2;LEG_REST_LEFT 2,7;\
|
||||
ARM_REST_LEFT 5,24;HAND_REST_LEFT 6,12
|
||||
|
||||
# skeleton_stand is used for testing purpose
|
||||
ANIM_RUN=DELAY 0.15;ROW 2;SKELETON SKELETON_STAND
|
||||
ANIM_RUN_1=LEG_REST_RIGHT 1,1;FOOT_RIGHT 1,1;LEG_REST_LEFT -1,0;FOOT_LEFT -1,0
|
||||
ANIM_RUN_2=ALL 0,1;LEG_REST_RIGHT 0,-1;FOOT_RIGHT 0,-1;LEG_REST_LEFT 0,1;FOOT_LEFT 0,1
|
||||
ANIM_RUN_3=LEG_REST_RIGHT -1,0;FOOT_RIGHT -1,0;LEG_REST_LEFT 1,1;FOOT_LEFT 1,1
|
||||
ANIM_RUN_4=ALL 0,1;LEG_REST_RIGHT 0,1;FOOT_RIGHT 0,1;LEG_REST_LEFT 0,-1;FOOT_LEFT 0,-1
|
||||
|
||||
ANIM_IDLE=DELAY 2;ROW 1;SKELETON SKELETON_STAND
|
||||
ANIM_IDLE_1=
|
||||
! ANIM_IDLE_1 will not make any transformation
|
||||
ANIM_IDLE_2=UPPER_TORSO 0,-1;HEAD 0,-1;HAIR 0,-1;HELD_ITEM 0,-1;ARM_REST_LEFT 0,-1;ARM_REST_RIGHT 0,-1;HAND_REST_LEFT 0,-1;HAND_REST_RIGHT 0,-1;HAIR_FORE 0,-1;HEADGEAR 0,-1
|
||||
@@ -1,8 +1,8 @@
|
||||
package net.torvald.terrarum;
|
||||
|
||||
import com.badlogic.gdx.ApplicationListener;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Screen;
|
||||
import com.badlogic.gdx.*;
|
||||
import com.badlogic.gdx.assets.AssetManager;
|
||||
import com.badlogic.gdx.audio.AudioDevice;
|
||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
|
||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
|
||||
import com.badlogic.gdx.graphics.*;
|
||||
@@ -10,13 +10,32 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
|
||||
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
|
||||
import com.badlogic.gdx.utils.ScreenUtils;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import net.torvald.dataclass.ArrayListMap;
|
||||
import net.torvald.getcpuname.GetCpuName;
|
||||
import net.torvald.terrarum.gamecontroller.KeyToggler;
|
||||
import net.torvald.terrarum.imagefont.TinyAlphNum;
|
||||
import net.torvald.terrarum.modulebasegame.Ingame;
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer;
|
||||
import net.torvald.terrarum.utils.JsonFetcher;
|
||||
import net.torvald.terrarum.utils.JsonWriter;
|
||||
import net.torvald.terrarum.worlddrawer.BlocksDrawer;
|
||||
import net.torvald.terrarum.worlddrawer.LightmapRenderer;
|
||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase;
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack;
|
||||
import org.lwjgl.input.Controller;
|
||||
import org.lwjgl.input.Controllers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
import static net.torvald.terrarum.TerrarumKt.gdxClearAndSetBlend;
|
||||
|
||||
/**
|
||||
* The framework's Application Loader
|
||||
*
|
||||
@@ -30,19 +49,62 @@ public class AppLoader implements ApplicationListener {
|
||||
* AA: Major version
|
||||
* BB: Minor version
|
||||
* XXXX: Revision (Repository commits, or something arbitrary)
|
||||
*
|
||||
* e.g. 0x02010034 can be translated as 2.1.52
|
||||
* <p>
|
||||
* e.g. 0x02010034 will be translated as 2.1.52
|
||||
*/
|
||||
public static final int VERSION_RAW = 0x00_02_027C;
|
||||
public static final boolean IS_DEVELOPMENT_BUILD = true;
|
||||
|
||||
|
||||
public static final int VERSION_RAW = 0x00_02_04B1;
|
||||
|
||||
public static final String getVERSION_STRING() {
|
||||
return String.format("%d.%d.%d", VERSION_RAW >>> 24, (VERSION_RAW & 0xff0000) >>> 16, VERSION_RAW & 0xFFFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* when FALSE, some assertion and print code will not execute
|
||||
*/
|
||||
public static boolean IS_DEVELOPMENT_BUILD = false;
|
||||
|
||||
|
||||
/**
|
||||
* Singleton instance
|
||||
*/
|
||||
private static AppLoader INSTANCE = null;
|
||||
|
||||
private AppLoader() { }
|
||||
/**
|
||||
* Screen injected at init, so that you run THAT screen instead of the main game.
|
||||
*/
|
||||
private static Screen injectScreen = null;
|
||||
|
||||
/**
|
||||
* Initialise the application with the alternative Screen you choose
|
||||
*
|
||||
* @param appConfig LWJGL(2) Application Configuration
|
||||
* @param injectScreen GDX Screen you want to run
|
||||
*/
|
||||
public AppLoader(LwjglApplicationConfiguration appConfig, Screen injectScreen) {
|
||||
AppLoader.injectScreen = injectScreen;
|
||||
AppLoader.appConfig = appConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the application with default game screen
|
||||
*
|
||||
* @param appConfig LWJGL(2) Application Configuration
|
||||
*/
|
||||
public AppLoader(LwjglApplicationConfiguration appConfig) {
|
||||
AppLoader.appConfig = appConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default null constructor. Don't use it.
|
||||
*/
|
||||
private AppLoader() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton pattern implementation in Java.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static AppLoader getINSTANCE() {
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = new AppLoader();
|
||||
@@ -51,9 +113,29 @@ public class AppLoader implements ApplicationListener {
|
||||
}
|
||||
|
||||
public static final String GAME_NAME = "Terrarum";
|
||||
public static final String COPYRIGHT_DATE_NAME = "Copyright 2013-2018 Torvald (minjaesong)";
|
||||
public static final String COPYRIGHT_DATE_NAME = "Copyright 2013-2019 Torvald (minjaesong)";
|
||||
public static String GAME_LOCALE = System.getProperty("user.language") + System.getProperty("user.country");
|
||||
|
||||
public static final String systemArch = System.getProperty("os.arch");
|
||||
public static String processor;
|
||||
public static String processorVendor;
|
||||
public static String renderer;
|
||||
public static String rendererVendor;
|
||||
|
||||
public static final boolean is32BitJVM = !System.getProperty("sun.arch.data.model").contains("64");
|
||||
|
||||
|
||||
public static final float TV_SAFE_GRAPHICS = 0.05f; // as per EBU recommendation (https://tech.ebu.ch/docs/r/r095.pdf)
|
||||
public static final float TV_SAFE_ACTION = 0.035f; // as per EBU recommendation (https://tech.ebu.ch/docs/r/r095.pdf)
|
||||
|
||||
public static int getTvSafeGraphicsWidth() { return Math.round(screenW * TV_SAFE_GRAPHICS); }
|
||||
public static int getTvSafeGraphicsHeight() { return Math.round(screenH * TV_SAFE_GRAPHICS); }
|
||||
public static int getTvSafeActionWidth() { return Math.round(screenW * TV_SAFE_ACTION); }
|
||||
public static int getTvSafeActionHeight() { return Math.round(screenH * TV_SAFE_ACTION); }
|
||||
|
||||
/**
|
||||
* These languages won't distinguish regional differences (e.g. enUS and enUK, frFR and frCA)
|
||||
*/
|
||||
private static final String[] localeSimple = {"de", "en", "es", "it"}; // must be sorted!!
|
||||
|
||||
public static String getSysLang() {
|
||||
@@ -81,13 +163,19 @@ public class AppLoader implements ApplicationListener {
|
||||
}
|
||||
}
|
||||
|
||||
public static final String getVERSION_STRING() {
|
||||
return String.format("%d.%d.%d", VERSION_RAW >>> 24, (VERSION_RAW & 0xff0000) >>> 16, VERSION_RAW & 0xFFFF);
|
||||
}
|
||||
private static boolean splashDisplayed = false;
|
||||
private static boolean postInitFired = false;
|
||||
private static boolean screenshotRequested = false;
|
||||
private static boolean resizeRequested = false;
|
||||
private static Point2i resizeReqSize;
|
||||
|
||||
public static LwjglApplicationConfiguration appConfig;
|
||||
|
||||
public static GameFontBase fontGame;
|
||||
public static TinyAlphNum fontSmallNumbers;
|
||||
|
||||
/** A gamepad. Multiple gamepads may controll this single virtualised gamepad. */
|
||||
public static org.lwjgl.input.Controller gamepad = null;
|
||||
public static float gamepadDeadzone = 0.1f;
|
||||
|
||||
/**
|
||||
* For the events depends on rendering frame (e.g. flicker on post-hit invincibility)
|
||||
@@ -95,37 +183,79 @@ public class AppLoader implements ApplicationListener {
|
||||
public static int GLOBAL_RENDER_TIMER = new Random().nextInt(1020) + 1;
|
||||
|
||||
|
||||
public static ArrayListMap debugTimers = new ArrayListMap<String, Long>();
|
||||
|
||||
public static final int defaultW = 1110;
|
||||
public static final int defaultH = 740;
|
||||
public static final int minimumW = 1080;
|
||||
public static final int minimumH = 720;
|
||||
|
||||
public static void main(String[] args) {
|
||||
// load configs
|
||||
getDefaultDirectory();
|
||||
createDirs();
|
||||
readConfigJson();
|
||||
|
||||
|
||||
try { processor = GetCpuName.getModelName(); }
|
||||
catch (IOException e1) { processor = "Unknown"; }
|
||||
try { processorVendor = GetCpuName.getCPUID(); }
|
||||
catch (IOException e2) { processorVendor = "Unknown"; }
|
||||
|
||||
|
||||
ShaderProgram.pedantic = false;
|
||||
|
||||
appConfig = new LwjglApplicationConfiguration();
|
||||
appConfig.vSyncEnabled = false;
|
||||
LwjglApplicationConfiguration appConfig = new LwjglApplicationConfiguration();
|
||||
//appConfig.useGL30 = true; // used: loads GL 3.2, unused: loads GL 4.6; what the fuck?
|
||||
appConfig.vSyncEnabled = getConfigBoolean("usevsync");
|
||||
appConfig.resizable = false;//true;
|
||||
//appConfig.width = 1072; // IMAX ratio
|
||||
//appConfig.height = 742; // IMAX ratio
|
||||
appConfig.width = 1110; // photographic ratio (1.5:1)
|
||||
appConfig.height = 740; // photographic ratio (1.5:1)
|
||||
appConfig.backgroundFPS = 9999;
|
||||
appConfig.foregroundFPS = 9999;
|
||||
//appConfig.width = 1110; // photographic ratio (1.5:1)
|
||||
//appConfig.height = 740; // photographic ratio (1.5:1)
|
||||
appConfig.width = getConfigInt("screenwidth");
|
||||
appConfig.height = getConfigInt("screenheight");
|
||||
appConfig.backgroundFPS = getConfigInt("displayfps");
|
||||
appConfig.foregroundFPS = getConfigInt("displayfps");
|
||||
appConfig.title = GAME_NAME;
|
||||
appConfig.forceExit = false;
|
||||
|
||||
new LwjglApplication(new AppLoader(), appConfig);
|
||||
// load app icon
|
||||
int[] appIconSizes = new int[]{256,128,64,32,16};
|
||||
for (int size : appIconSizes) {
|
||||
String name = "assets/appicon" + size + ".png";
|
||||
if (new File("./" + name).exists()) {
|
||||
appConfig.addIcon(name, Files.FileType.Internal);
|
||||
}
|
||||
}
|
||||
|
||||
if (args.length == 1 && args[0].equals("isdev=true")) {
|
||||
IS_DEVELOPMENT_BUILD = true;
|
||||
// safe area box
|
||||
//KeyToggler.INSTANCE.forceSet(Input.Keys.F11, true);
|
||||
}
|
||||
|
||||
new LwjglApplication(new AppLoader(appConfig), appConfig);
|
||||
}
|
||||
|
||||
|
||||
private static ShaderProgram shaderBayerSkyboxFill;
|
||||
public static ShaderProgram shaderHicolour;
|
||||
public static ShaderProgram shaderPassthru;
|
||||
public static ShaderProgram shaderColLUT;
|
||||
|
||||
public static Mesh fullscreenQuad;
|
||||
private OrthographicCamera camera;
|
||||
private SpriteBatch logoBatch;
|
||||
public static TextureRegion logo;
|
||||
public static AudioDevice audioDevice;
|
||||
|
||||
private Color gradWhiteTop = new Color(0xf8f8f8ff);
|
||||
private Color gradWhiteBottom = new Color(0xd8d8d8ff);
|
||||
|
||||
public Screen screen;
|
||||
public static int screenW = 0;
|
||||
public static int screenH = 0;
|
||||
|
||||
public static Texture textureWhiteSquare;
|
||||
|
||||
private void initViewPort(int width, int height) {
|
||||
// Set Y to point downwards
|
||||
@@ -138,26 +268,34 @@ public class AppLoader implements ApplicationListener {
|
||||
Gdx.gl20.glViewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
public static final double UPDATE_RATE = 1.0 / 60.0; // TODO set it like 1/100, because apparent framerate is limited by update rate
|
||||
|
||||
private float loadTimer = 0f;
|
||||
private final float showupTime = 100f / 1000f;
|
||||
|
||||
private FrameBuffer renderFBO;
|
||||
|
||||
public static AssetManager assetManager;
|
||||
|
||||
@Override
|
||||
public void create() {
|
||||
assetManager = new AssetManager();
|
||||
|
||||
// set basis of draw
|
||||
logoBatch = new SpriteBatch();
|
||||
camera = new OrthographicCamera(((float) appConfig.width), ((float) appConfig.height));
|
||||
|
||||
|
||||
initViewPort(appConfig.width, appConfig.height);
|
||||
|
||||
// logo here :p
|
||||
logo = new TextureRegion(new Texture(Gdx.files.internal("assets/graphics/logo_placeholder.tga")));
|
||||
logo.flip(false, true);
|
||||
|
||||
shaderBayerSkyboxFill = new ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/4096_bayer_skyboxfill.frag"));
|
||||
shaderHicolour = new ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/hicolour.frag"));
|
||||
shaderColLUT = new ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/passthru.frag"));
|
||||
|
||||
|
||||
|
||||
// set GL graphics constants
|
||||
shaderBayerSkyboxFill = loadShader("assets/4096.vert", "assets/4096_bayer_skyboxfill.frag");
|
||||
shaderHicolour = loadShader("assets/4096.vert", "assets/hicolour.frag");
|
||||
shaderPassthru = loadShader("assets/4096.vert", "assets/passthru.frag");
|
||||
shaderColLUT = loadShader("assets/4096.vert", "assets/passthru.frag");
|
||||
|
||||
fullscreenQuad = new Mesh(
|
||||
true, 4, 6,
|
||||
@@ -165,40 +303,58 @@ public class AppLoader implements ApplicationListener {
|
||||
VertexAttribute.ColorUnpacked(),
|
||||
VertexAttribute.TexCoords(0)
|
||||
);
|
||||
updateFullscreenQuad(appConfig.width, appConfig.height);
|
||||
|
||||
fullscreenQuad.setVertices(new float[]{
|
||||
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f,
|
||||
((float) appConfig.width), 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f,
|
||||
((float) appConfig.width), ((float) appConfig.height), 0f, 1f, 1f, 1f, 1f, 1f, 0f,
|
||||
0f, ((float) appConfig.height), 0f, 1f, 1f, 1f, 1f, 0f, 0f
|
||||
});
|
||||
fullscreenQuad.setIndices(new short[]{0, 1, 2, 2, 3, 0});
|
||||
// enlist suitable gamepads
|
||||
try {
|
||||
Controllers.create();
|
||||
|
||||
printdbg(this, "Available gamepads: " + Controllers.getControllerCount());
|
||||
for (int x = 0; x < Controllers.getControllerCount(); x++) {
|
||||
Controller gamepad = Controllers.getController(x);
|
||||
printdbg(this, String.format("Gamepad #%d: %s", x + 1, gamepad.getName()));
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
printdbg(this, "Exception occured while creating controllers -- there will be no gamepads available.");
|
||||
printdbg(this, e);
|
||||
}
|
||||
|
||||
|
||||
logo = new TextureRegion(new Texture(Gdx.files.internal("assets/graphics/logo_placeholder.tga")));
|
||||
logo.flip(false, true);
|
||||
// set up renderer info variables
|
||||
renderer = Gdx.graphics.getGLVersion().getRendererString();
|
||||
rendererVendor = Gdx.graphics.getGLVersion().getVendorString();
|
||||
|
||||
|
||||
TextureRegionPack.Companion.setGlobalFlipY(true);
|
||||
fontGame = new GameFontBase("assets/graphics/fonts/terrarum-sans-bitmap", false, true, Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest, false, 128, false);
|
||||
|
||||
// make loading list
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @link http://bilgin.esme.org/BitsAndBytes/KalmanFilterforDummies
|
||||
*/
|
||||
private void updateKalmanRenderDelta() {
|
||||
// moved to LwjglGraphics
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
Gdx.gl.glDisable(GL20.GL_DITHER);
|
||||
|
||||
if (splashDisplayed && !postInitFired) {
|
||||
postInitFired = true;
|
||||
postInit();
|
||||
}
|
||||
|
||||
FrameBufferManager.begin(renderFBO);
|
||||
Gdx.gl.glClearColor(.094f, .094f, .094f, 0f);
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D);
|
||||
Gdx.gl.glEnable(GL20.GL_BLEND);
|
||||
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
|
||||
Gdx.gl.glBlendEquation(GL20.GL_FUNC_ADD);
|
||||
FrameBufferManager.end();
|
||||
|
||||
|
||||
FrameBufferManager.begin(renderFBO);
|
||||
gdxClearAndSetBlend(.094f, .094f, .094f, 0f);
|
||||
setCameraPosition(0, 0);
|
||||
|
||||
// draw splash screen when predefined screen is null
|
||||
// because in normal operation, the only time screen == null is when the app is cold-launched
|
||||
// you can't have a text drawn here :v
|
||||
if (screen == null) {
|
||||
shaderBayerSkyboxFill.begin();
|
||||
shaderBayerSkyboxFill.setUniformMatrix("u_projTrans", camera.combined);
|
||||
@@ -224,91 +380,187 @@ public class AppLoader implements ApplicationListener {
|
||||
loadTimer += Gdx.graphics.getRawDeltaTime();
|
||||
|
||||
if (loadTimer >= showupTime) {
|
||||
Terrarum.INSTANCE.setScreenW(appConfig.width);
|
||||
Terrarum.INSTANCE.setScreenH(appConfig.height);
|
||||
// hand over the scene control to this single class; Terrarum must call
|
||||
// 'AppLoader.getINSTANCE().screen.render(delta)', this is not redundant at all!
|
||||
setScreen(Terrarum.INSTANCE);
|
||||
}
|
||||
}
|
||||
// draw the screen
|
||||
else {
|
||||
screen.render(Gdx.graphics.getDeltaTime());
|
||||
screen.render((float) UPDATE_RATE);
|
||||
}
|
||||
|
||||
KeyToggler.INSTANCE.update(screen instanceof Ingame);
|
||||
|
||||
// nested FBOs are just not a thing in GL!
|
||||
net.torvald.terrarum.FrameBufferManager.end();
|
||||
|
||||
PostProcessor.INSTANCE.draw(camera.combined, renderFBO);
|
||||
|
||||
|
||||
// process resize request
|
||||
if (resizeRequested) {
|
||||
resizeRequested = false;
|
||||
resize(resizeReqSize.getX(), resizeReqSize.getY());
|
||||
}
|
||||
|
||||
|
||||
// process screenshot request
|
||||
if (screenshotRequested) {
|
||||
screenshotRequested = false;
|
||||
|
||||
try {
|
||||
Pixmap p = ScreenUtils.getFrameBufferPixmap(0, 0, appConfig.width, appConfig.height);
|
||||
PixmapIO2.writeTGA(Gdx.files.absolute(defaultDir + "/Screenshot.tga"), p, true);
|
||||
p.dispose();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
splashDisplayed = true;
|
||||
GLOBAL_RENDER_TIMER += 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(int width, int height) {
|
||||
printdbg(this, "Resize called");
|
||||
for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {
|
||||
printdbg(this, stackTraceElement);
|
||||
}
|
||||
|
||||
//initViewPort(width, height);
|
||||
|
||||
Terrarum.INSTANCE.resize(width, height);
|
||||
if (screen != null) screen.resize(Terrarum.INSTANCE.getWIDTH(), Terrarum.INSTANCE.getHEIGHT());
|
||||
screenW = width;
|
||||
screenH = height;
|
||||
|
||||
if (screenW % 2 == 1) screenW -= 1;
|
||||
if (screenH % 2 == 1) screenH -= 1;
|
||||
|
||||
if (screen != null) screen.resize(screenW, screenH);
|
||||
|
||||
|
||||
if (renderFBO == null ||
|
||||
(renderFBO.getWidth() != Terrarum.INSTANCE.getWIDTH() ||
|
||||
renderFBO.getHeight() != Terrarum.INSTANCE.getHEIGHT())
|
||||
) {
|
||||
(renderFBO.getWidth() != screenW ||
|
||||
renderFBO.getHeight() != screenH)
|
||||
) {
|
||||
renderFBO = new FrameBuffer(
|
||||
Pixmap.Format.RGBA8888,
|
||||
Terrarum.INSTANCE.getWIDTH(),
|
||||
Terrarum.INSTANCE.getHEIGHT(),
|
||||
screenW,
|
||||
screenH,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
appConfig.width = Terrarum.INSTANCE.getWIDTH();
|
||||
appConfig.height = Terrarum.INSTANCE.getHEIGHT();
|
||||
appConfig.width = screenW;
|
||||
appConfig.height = screenH;
|
||||
|
||||
printdbg(this, "Resize event");
|
||||
updateFullscreenQuad(screenW, screenH);
|
||||
|
||||
printdbg(this, "Resize end");
|
||||
}
|
||||
|
||||
public static void resizeScreen(int width, int height) {
|
||||
resizeRequested = true;
|
||||
resizeReqSize = new Point2i(Math.max(width, minimumW), Math.max(height, minimumH));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose () {
|
||||
if (screen != null) screen.hide();
|
||||
|
||||
public void dispose() {
|
||||
System.out.println("Goodbye !");
|
||||
|
||||
|
||||
if (screen != null) {
|
||||
screen.hide();
|
||||
screen.dispose();
|
||||
}
|
||||
|
||||
IngameRenderer.INSTANCE.dispose();
|
||||
if (Controllers.isCreated()) Controllers.destroy();
|
||||
|
||||
Terrarum.INSTANCE.dispose();
|
||||
|
||||
shaderBayerSkyboxFill.dispose();
|
||||
shaderHicolour.dispose();
|
||||
shaderColLUT.dispose();
|
||||
|
||||
assetManager.dispose();
|
||||
fullscreenQuad.dispose();
|
||||
|
||||
fontGame.dispose();
|
||||
fontSmallNumbers.dispose();
|
||||
|
||||
// delete temp files
|
||||
new File("./tmp_wenquanyi.tga").delete();
|
||||
new File("./tmp_wenquanyi.tga").delete(); // FIXME this is pretty much ad-hoc
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pause () {
|
||||
public void pause() {
|
||||
if (screen != null) screen.pause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resume () {
|
||||
public void resume() {
|
||||
if (screen != null) screen.resume();
|
||||
}
|
||||
|
||||
public void setScreen(Screen screen) {
|
||||
printdbg(this, "Changing screen to " + screen.getClass().getCanonicalName());
|
||||
|
||||
if (this.screen != null) this.screen.hide();
|
||||
// this whole thing is directtly copied from com.badlogic.gdx.Game
|
||||
|
||||
if (this.screen != null) {
|
||||
this.screen.hide();
|
||||
this.screen.dispose();
|
||||
}
|
||||
this.screen = screen;
|
||||
if (this.screen != null) {
|
||||
this.screen.show();
|
||||
this.screen.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
||||
}
|
||||
|
||||
System.gc();
|
||||
|
||||
printdbg(this, "Screen transisiton complete: " + this.screen.getClass().getCanonicalName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Init stuffs which needs GL context
|
||||
*/
|
||||
private void postInit() {
|
||||
textureWhiteSquare = new Texture(Gdx.files.internal("assets/graphics/ortho_line_tex_2px.tga"));
|
||||
textureWhiteSquare.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
|
||||
|
||||
TextureRegionPack.Companion.setGlobalFlipY(true);
|
||||
fontGame = new GameFontBase("assets/graphics/fonts/terrarum-sans-bitmap", false, true,
|
||||
Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest, false, 256, false
|
||||
);
|
||||
fontSmallNumbers = TinyAlphNum.INSTANCE;
|
||||
|
||||
audioDevice = Gdx.audio.newAudioDevice(48000, false);
|
||||
|
||||
// if there is a predefined screen, open that screen after my init process
|
||||
if (injectScreen != null) {
|
||||
setScreen(injectScreen);
|
||||
}
|
||||
|
||||
|
||||
BlocksDrawer.INSTANCE.getWorld(); // will initialize the BlocksDrawer by calling dummy method
|
||||
LightmapRenderer.INSTANCE.hdr(0f);
|
||||
|
||||
|
||||
printdbg(this, "PostInit done");
|
||||
}
|
||||
|
||||
|
||||
private void setCameraPosition(float newX, float newY) {
|
||||
camera.position.set((-newX + appConfig.width / 2), (-newY + appConfig.height / 2), 0f);
|
||||
camera.update();
|
||||
logoBatch.setProjectionMatrix(camera.combined);
|
||||
}
|
||||
|
||||
private void updateFullscreenQuad(int WIDTH, int HEIGHT) {
|
||||
private void updateFullscreenQuad(int WIDTH, int HEIGHT) { // NOT y-flipped quads!
|
||||
fullscreenQuad.setVertices(new float[]{
|
||||
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f,
|
||||
WIDTH, 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f,
|
||||
@@ -318,15 +570,272 @@ public class AppLoader implements ApplicationListener {
|
||||
fullscreenQuad.setIndices(new short[]{0, 1, 2, 2, 3, 0});
|
||||
}
|
||||
|
||||
public static void requestScreenshot() {
|
||||
screenshotRequested = true;
|
||||
}
|
||||
|
||||
public static final void printdbg(Object obj, Object message) {
|
||||
if (IS_DEVELOPMENT_BUILD) {
|
||||
System.out.println("["+obj.getClass().getSimpleName()+"] "+message.toString());
|
||||
// DEFAULT DIRECTORIES //
|
||||
|
||||
public static String OSName = System.getProperty("os.name");
|
||||
public static String OSVersion = System.getProperty("os.version");
|
||||
public static String operationSystem;
|
||||
/** %appdata%/Terrarum, without trailing slash */
|
||||
public static String defaultDir;
|
||||
/** defaultDir + "/Saves", without trailing slash */
|
||||
public static String defaultSaveDir;
|
||||
/** defaultDir + "/config.json" */
|
||||
public static String configDir;
|
||||
public static RunningEnvironment environment;
|
||||
|
||||
private static void getDefaultDirectory() {
|
||||
String OS = OSName.toUpperCase();
|
||||
if (OS.contains("WIN")) {
|
||||
operationSystem = "WINDOWS";
|
||||
defaultDir = System.getenv("APPDATA") + "/Terrarum";
|
||||
}
|
||||
else if (OS.contains("OS X")) {
|
||||
operationSystem = "OSX";
|
||||
defaultDir = System.getProperty("user.home") + "/Library/Application Support/Terrarum";
|
||||
}
|
||||
else if (OS.contains("NUX") || OS.contains("NIX") || OS.contains("BSD")) {
|
||||
operationSystem = "LINUX";
|
||||
defaultDir = System.getProperty("user.home") + "/.Terrarum";
|
||||
}
|
||||
else if (OS.contains("SUNOS")) {
|
||||
operationSystem = "SOLARIS";
|
||||
defaultDir = System.getProperty("user.home") + "/.Terrarum";
|
||||
}
|
||||
/*else if (System.getProperty("java.runtime.name").toUpperCase().contains("ANDROID")) {
|
||||
operationSystem = "ANDROID";
|
||||
defaultDir = System.getProperty("user.home") + "/.Terrarum";
|
||||
environment = RunningEnvironment.MOBILE;
|
||||
}*/
|
||||
else {
|
||||
operationSystem = "UNKNOWN";
|
||||
defaultDir = System.getProperty("user.home") + "/.Terrarum";
|
||||
}
|
||||
|
||||
defaultSaveDir = defaultDir + "/Saves";
|
||||
configDir = defaultDir + "/config.json";
|
||||
|
||||
System.out.println(String.format("os.name = %s (with identifier %s)", OSName, operationSystem));
|
||||
System.out.println(String.format("os.version = %s", OSVersion));
|
||||
System.out.println(String.format("default directory: %s", defaultDir));
|
||||
}
|
||||
|
||||
private static void createDirs() {
|
||||
File[] dirs = {new File(defaultSaveDir)};
|
||||
|
||||
for (File it : dirs) {
|
||||
if (!it.exists())
|
||||
it.mkdirs();
|
||||
}
|
||||
|
||||
//dirs.forEach { if (!it.exists()) it.mkdirs() }
|
||||
}
|
||||
|
||||
|
||||
// CONFIG //
|
||||
|
||||
private static KVHashMap gameConfig = new KVHashMap();
|
||||
|
||||
private static void createConfigJson() throws IOException {
|
||||
File configFile = new File(configDir);
|
||||
|
||||
if (!configFile.exists() || configFile.length() == 0L) {
|
||||
JsonWriter.INSTANCE.writeToFile(DefaultConfig.INSTANCE.fetch(), configDir);
|
||||
}
|
||||
}
|
||||
public static final void printdbgerr(Object obj, Object message) {
|
||||
if (IS_DEVELOPMENT_BUILD) {
|
||||
System.err.println("["+obj.getClass().getSimpleName()+"] "+message.toString());
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true on successful, false on failure.
|
||||
*/
|
||||
private static Boolean readConfigJson() {
|
||||
try {
|
||||
// read from disk and build config from it
|
||||
JsonObject jsonObject = JsonFetcher.INSTANCE.invoke(configDir);
|
||||
|
||||
// make config
|
||||
jsonObject.entrySet().forEach((entry) ->
|
||||
gameConfig.set(entry.getKey(), entry.getValue())
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (java.nio.file.NoSuchFileException e) {
|
||||
// write default config to game dir. Call this method again to read config from it.
|
||||
try {
|
||||
createConfigJson();
|
||||
}
|
||||
catch (IOException e1) {
|
||||
System.out.println("[AppLoader] Unable to write config.json file");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return config from config set. If the config does not exist, default value will be returned.
|
||||
* @param key
|
||||
* *
|
||||
* @return Config from config set or default config if it does not exist.
|
||||
* *
|
||||
* @throws NullPointerException if the specified config simply does not exist.
|
||||
*/
|
||||
public static int getConfigInt(String key) {
|
||||
Object cfg = getConfigMaster(key);
|
||||
if (cfg instanceof JsonPrimitive)
|
||||
return ((JsonPrimitive) cfg).getAsInt();
|
||||
else
|
||||
return Integer.parseInt(((String) cfg));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return config from config set. If the config does not exist, default value will be returned.
|
||||
* @param key
|
||||
* *
|
||||
* @return Config from config set or default config if it does not exist.
|
||||
* *
|
||||
* @throws NullPointerException if the specified config simply does not exist.
|
||||
*/
|
||||
public static String getConfigString(String key) {
|
||||
Object cfg = getConfigMaster(key);
|
||||
if (cfg instanceof JsonPrimitive)
|
||||
return ((JsonPrimitive) cfg).getAsString();
|
||||
else
|
||||
return ((String) cfg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return config from config set. If the config does not exist, default value will be returned.
|
||||
* @param key
|
||||
* *
|
||||
* @return Config from config set or default config if it does not exist. If the default value is undefined, will return false.
|
||||
*/
|
||||
public static boolean getConfigBoolean(String key) {
|
||||
try {
|
||||
Object cfg = getConfigMaster(key);
|
||||
if (cfg instanceof JsonPrimitive)
|
||||
return ((JsonPrimitive) cfg).getAsBoolean();
|
||||
else
|
||||
return ((boolean) cfg);
|
||||
}
|
||||
catch (NullPointerException keyNotFound) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int[] getConfigIntArray(String key) {
|
||||
Object cfg = getConfigMaster(key);
|
||||
if (cfg instanceof JsonArray) {
|
||||
JsonArray jsonArray = ((JsonArray) cfg).getAsJsonArray();
|
||||
//return IntArray(jsonArray.size(), { i -> jsonArray[i].asInt })
|
||||
int[] intArray = new int[jsonArray.size()];
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
intArray[i] = jsonArray.get(i).getAsInt();
|
||||
}
|
||||
return intArray;
|
||||
}
|
||||
else
|
||||
return ((int[]) cfg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get config from config file. If the entry does not exist, get from defaults; if the entry is not in the default, NullPointerException will be thrown
|
||||
*/
|
||||
private static JsonObject getDefaultConfig() {
|
||||
return DefaultConfig.INSTANCE.fetch();
|
||||
}
|
||||
|
||||
private static Object getConfigMaster(String key1) {
|
||||
String key = key1.toLowerCase();
|
||||
|
||||
Object config;
|
||||
try {
|
||||
config = gameConfig.get(key);
|
||||
}
|
||||
catch (NullPointerException e) {
|
||||
config = null;
|
||||
}
|
||||
|
||||
Object defaults;
|
||||
try {
|
||||
defaults = getDefaultConfig().get(key);
|
||||
}
|
||||
catch (NullPointerException e) {
|
||||
defaults = null;
|
||||
}
|
||||
|
||||
if (config == null) {
|
||||
if (defaults == null) {
|
||||
throw new NullPointerException("key not found: '" + key + "'");
|
||||
}
|
||||
else {
|
||||
return defaults;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setConfig(String key, Object value) {
|
||||
gameConfig.set(key, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// //
|
||||
|
||||
public static void printdbg(Object obj, Object message) {
|
||||
if (IS_DEVELOPMENT_BUILD) {
|
||||
System.out.println("[" + obj.getClass().getSimpleName() + "] " + message.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void printdbgerr(Object obj, Object message) {
|
||||
if (IS_DEVELOPMENT_BUILD) {
|
||||
System.err.println("[" + obj.getClass().getSimpleName() + "] " + message.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static ShaderProgram loadShader(String vert, String frag) {
|
||||
ShaderProgram s = new ShaderProgram(Gdx.files.internal(vert), Gdx.files.internal(frag));
|
||||
|
||||
if (s.getLog().toLowerCase().contains("error")) {
|
||||
throw new Error(String.format("Shader program loaded with %s, %s failed:\n%s", vert, frag, s.getLog()));
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
public static void measureDebugTime(String name, kotlin.jvm.functions.Function0<kotlin.Unit> block) {
|
||||
if (IS_DEVELOPMENT_BUILD) {
|
||||
//debugTimers.put(name, kotlin.system.TimingKt.measureNanoTime(block));
|
||||
|
||||
long start = System.nanoTime();
|
||||
block.invoke();
|
||||
debugTimers.put(name, System.nanoTime() - start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setDebugTime(String name, long value) {
|
||||
if (IS_DEVELOPMENT_BUILD) {
|
||||
debugTimers.put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addDebugTime(String target, String... targets) {
|
||||
if (IS_DEVELOPMENT_BUILD) {
|
||||
long l = 0L;
|
||||
for (String s : targets) {
|
||||
l += ((long) debugTimers.get(s));
|
||||
}
|
||||
debugTimers.put(target, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,34 +14,36 @@ object DefaultConfig {
|
||||
val jsonObject = JsonObject()
|
||||
|
||||
jsonObject.addProperty("displayfps", 0) // 0: no limit, non-zero: limit
|
||||
jsonObject.addProperty("usevsync", true)
|
||||
jsonObject.addProperty("usevsync", false)
|
||||
jsonObject.addProperty("screenwidth", AppLoader.defaultW)
|
||||
jsonObject.addProperty("screenheight", AppLoader.defaultH)
|
||||
|
||||
|
||||
jsonObject.addProperty("imtooyoungtodie", false) // no perma-death
|
||||
jsonObject.addProperty("language", AppLoader.getSysLang())
|
||||
jsonObject.addProperty("notificationshowuptime", 6500)
|
||||
jsonObject.addProperty("notificationshowuptime", 4000)
|
||||
jsonObject.addProperty("multithread", true) // experimental!
|
||||
jsonObject.addProperty("multithreadedlight", false) // experimental!
|
||||
|
||||
|
||||
|
||||
// control-gamepad
|
||||
jsonObject.addProperty("joypadkeyn", 4)
|
||||
jsonObject.addProperty("joypadkeyw", 1)
|
||||
jsonObject.addProperty("joypadkeys", 2)
|
||||
jsonObject.addProperty("joypadkeye", 3) // logitech indices
|
||||
jsonObject.addProperty("gamepadkeyn", 4)
|
||||
jsonObject.addProperty("gamepadkeyw", 1)
|
||||
jsonObject.addProperty("gamepadkeys", 2)
|
||||
jsonObject.addProperty("gamepadkeye", 3) // logitech indices
|
||||
|
||||
jsonObject.addProperty("joypadlup", 4)
|
||||
jsonObject.addProperty("joypadrup", 5)
|
||||
jsonObject.addProperty("joypadldown", 6)
|
||||
jsonObject.addProperty("joypadrdown", 7) // logitech indices
|
||||
jsonObject.addProperty("gamepadlup", 4)
|
||||
jsonObject.addProperty("gamepadrup", 5)
|
||||
jsonObject.addProperty("gamepadldown", 6)
|
||||
jsonObject.addProperty("gamepadrdown", 7) // logitech indices
|
||||
|
||||
jsonObject.addProperty("joypadlstickx", 0)
|
||||
jsonObject.addProperty("joypadlsticky", 1)
|
||||
jsonObject.addProperty("joypadrstickx", 2)
|
||||
jsonObject.addProperty("joypadrsticky", 3) // 0-1-2-3 but sometimes 3-2-1-0 ?! what the actual fuck?
|
||||
jsonObject.addProperty("gamepadlstickx", 0)
|
||||
jsonObject.addProperty("gamepadlsticky", 1)
|
||||
jsonObject.addProperty("gamepadrstickx", 2)
|
||||
jsonObject.addProperty("gamepadrsticky", 3) // 0-1-2-3 but sometimes 3-2-1-0 ?! what the actual fuck?
|
||||
|
||||
jsonObject.addProperty("joypadlabelstyle", "msxb360") // "nwii", "logitech", "sonyps", "msxb360", "generic"
|
||||
jsonObject.addProperty("gamepadlabelstyle", "msxb360") // "nwii", "logitech", "sonyps", "msxb360", "generic"
|
||||
|
||||
|
||||
|
||||
@@ -66,8 +68,8 @@ object DefaultConfig {
|
||||
|
||||
jsonObject.addProperty("keyjump", Input.Keys.SPACE)
|
||||
|
||||
val keyquickbars = JsonArray(); for (i in Input.Keys.NUMPAD_1..Input.Keys.NUMPAD_9) keyquickbars.add(i); keyquickbars.add(Input.Keys.NUMPAD_0) // NUM_1 to NUM_0
|
||||
jsonObject.add("keyquickbars", keyquickbars)
|
||||
val keyquickslots = JsonArray(); for (i in Input.Keys.NUM_1..Input.Keys.NUM_9) keyquickslots.add(i); keyquickslots.add(Input.Keys.NUM_0) // NUM_1 to NUM_0
|
||||
jsonObject.add("keyquickslots", keyquickslots)
|
||||
|
||||
jsonObject.addProperty("mouseprimary", Input.Buttons.LEFT) // left mouse
|
||||
jsonObject.addProperty("mousesecondary", Input.Buttons.RIGHT) // right mouse
|
||||
@@ -75,23 +77,17 @@ object DefaultConfig {
|
||||
|
||||
jsonObject.addProperty("pcgamepadenv", "console")
|
||||
|
||||
jsonObject.addProperty("safetywarning", true)
|
||||
//jsonObject.addProperty("safetywarning", true)
|
||||
|
||||
|
||||
jsonObject.addProperty("maxparticles", 768)
|
||||
|
||||
|
||||
jsonObject.addProperty("fullframelightupdate", false)
|
||||
|
||||
jsonObject.addProperty("temperatureunit", 1) // -1: american, 0: kelvin, 1: celcius
|
||||
|
||||
|
||||
// "fancy" graphics settings
|
||||
jsonObject.addProperty("fxdither", true)
|
||||
jsonObject.addProperty("fx3dlut", false)
|
||||
|
||||
|
||||
jsonObject.addProperty("__debug", false)
|
||||
//jsonObject.addProperty("fx3dlut", false)
|
||||
|
||||
|
||||
return jsonObject
|
||||
|
||||
@@ -3,7 +3,6 @@ package net.torvald.terrarum
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.Screen
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.GL20
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
@@ -39,8 +38,7 @@ object ErrorDisp : Screen {
|
||||
}
|
||||
|
||||
override fun render(delta: Float) {
|
||||
Gdx.gl.glClearColor(.094f, .094f, .094f, 0f)
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
||||
gdxClearAndSetBlend(.094f, .094f, .094f, 0f)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
* list of Actors that is sorted by Actors' referenceID
|
||||
*/
|
||||
//val ACTORCONTAINER_INITIAL_SIZE = 64
|
||||
val PARTICLES_MAX = Terrarum.getConfigInt("maxparticles")
|
||||
val PARTICLES_MAX = AppLoader.getConfigInt("maxparticles")
|
||||
//val actorContainer = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
|
||||
//val actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
|
||||
val particlesContainer = CircularArray<ParticleBase>(PARTICLES_MAX)
|
||||
@@ -362,14 +362,14 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
width = 900,
|
||||
height = Terrarum.HEIGHT - 160,
|
||||
categoryWidth = 210,
|
||||
toggleKeyLiteral = Terrarum.getConfigInt("keyinventory")
|
||||
toggleKeyLiteral = AppLoader.getConfigInt("keyinventory")
|
||||
)*/
|
||||
/*uiInventoryPlayer.setPosition(
|
||||
-uiInventoryPlayer.width,
|
||||
70
|
||||
)*/
|
||||
uiInventoryPlayer = UIInventoryFull(player,
|
||||
toggleKeyLiteral = Terrarum.getConfigInt("keyinventory")
|
||||
toggleKeyLiteral = AppLoader.getConfigInt("keyinventory")
|
||||
)
|
||||
uiInventoryPlayer.setPosition(0, 0)
|
||||
|
||||
@@ -464,7 +464,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
override fun run() {
|
||||
var updateTries = 0
|
||||
while (ingame.updateDeltaCounter >= ingame.updateRate) {
|
||||
ingame.updateGame(Terrarum.deltaTime)
|
||||
ingame.updateGame(AppLoader.UPDATE_RATE.toFloat())
|
||||
ingame.updateDeltaCounter -= ingame.updateRate
|
||||
updateTries++
|
||||
|
||||
@@ -515,7 +515,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
|
||||
|
||||
if (false && Terrarum.getConfigBoolean("multithread")) { // NO MULTITHREADING: camera don't like concurrent modification (jittery actor movements)
|
||||
if (false && AppLoader.getConfigBoolean("multithread")) { // NO MULTITHREADING: camera don't like concurrent modification (jittery actor movements)
|
||||
if (firstTimeRun || updateThreadWrapper.state == Thread.State.TERMINATED) {
|
||||
updateThreadWrapper = Thread(ingameUpdateThread, "Terrarum UpdateThread")
|
||||
updateThreadWrapper.start()
|
||||
@@ -529,7 +529,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
while (updateDeltaCounter >= updateRate) {
|
||||
|
||||
//updateGame(delta)
|
||||
Terrarum.debugTimers["Ingame.update"] = measureNanoTime { updateGame(delta) }
|
||||
AppLoader.measureDebugTime("Ingame.update") { updateGame(delta) }
|
||||
|
||||
updateDeltaCounter -= updateRate
|
||||
updateTries++
|
||||
@@ -544,7 +544,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
/** RENDER CODE GOES HERE */
|
||||
//renderGame(batch)
|
||||
Terrarum.debugTimers["Ingame.render"] = measureNanoTime { renderGame(batch) }
|
||||
AppLoader.measureDebugTime("Ingame.render") { renderGame(batch) }
|
||||
}
|
||||
|
||||
protected fun updateGame(delta: Float) {
|
||||
@@ -1090,7 +1090,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
}
|
||||
|
||||
playableActorDelegate = newActor
|
||||
WorldSimulator(player, Terrarum.deltaTime)
|
||||
WorldSimulator(player, AppLoader.UPDATE_RATE.toFloat())
|
||||
}
|
||||
|
||||
private fun changePossession(refid: Int) {
|
||||
@@ -1107,7 +1107,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
// accept new delegate
|
||||
playableActorDelegate = PlayableActorDelegate(getActorByID(refid) as ActorHumanoid)
|
||||
playableActorDelegate!!.actor.collisionType = ActorWithPhysics.COLLISION_KINEMATIC
|
||||
WorldSimulator(player, Terrarum.deltaTime)
|
||||
WorldSimulator(player, AppLoader.UPDATE_RATE.toFloat())
|
||||
}
|
||||
|
||||
/** Send message to notifier UI and toggle the UI as opened. */
|
||||
|
||||
@@ -17,9 +17,9 @@ class GdxColorMap {
|
||||
height = pixmap.height
|
||||
is2D = pixmap.height > 1
|
||||
|
||||
data = kotlin.IntArray(pixmap.width * pixmap.height, {
|
||||
data = kotlin.IntArray(pixmap.width * pixmap.height) {
|
||||
pixmap.getPixel(it % pixmap.width, it / pixmap.width)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
AppLoader.printdbg(this, "Loading colormap from ${imageFile.name()}; PixmapFormat: ${pixmap.format}; Dimension: $width x $height")
|
||||
@@ -55,4 +55,40 @@ class GdxColorMap {
|
||||
fun getRaw(x: Int, y: Int): RGBA8888 = data[y * width + x]
|
||||
fun getRaw(x: Int): RGBA8888 = if (is2D) throw OperationNotSupportedException("This is 2D color map") else data[x]
|
||||
|
||||
override fun toString(): String {
|
||||
val sb = StringBuilder()
|
||||
|
||||
sb.append("ColorMap ${width}x$height:\n")
|
||||
|
||||
var yi = 0
|
||||
var xi = 0
|
||||
for (y in ((0 until height).take(2) + (0 until height).toList().takeLast(2)).distinct()) {
|
||||
|
||||
if (y - yi > 1) {
|
||||
sb.append(when (width) {
|
||||
in 1..4 -> ".......... ".repeat(width) + '\n'
|
||||
else -> ".......... .......... ... .......... .......... \n"
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
for (x in ((0 until width).take(2) + (0 until width).toList().takeLast(2)).distinct()) {
|
||||
if (x - xi > 1) {
|
||||
sb.append("... ")
|
||||
}
|
||||
|
||||
sb.append("0x")
|
||||
sb.append(getRaw(x, y).toLong().and(0xFFFFFFFF).toString(16).toUpperCase().padStart(8, '0'))
|
||||
sb.append(' ')
|
||||
|
||||
xi = x
|
||||
}
|
||||
|
||||
sb.append('\n')
|
||||
|
||||
yi = y
|
||||
}
|
||||
|
||||
return sb.toString()
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,13 @@ package net.torvald.terrarum
|
||||
|
||||
import com.badlogic.gdx.Screen
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.badlogic.gdx.utils.Queue
|
||||
import net.torvald.terrarum.gameactors.Actor
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.ui.ConsoleWindow
|
||||
import java.util.ArrayList
|
||||
import java.util.*
|
||||
import java.util.concurrent.locks.Lock
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import javax.swing.JOptionPane
|
||||
@@ -23,7 +25,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
||||
|
||||
open lateinit var consoleHandler: ConsoleWindow
|
||||
|
||||
open lateinit var world: GameWorld
|
||||
open var world: GameWorld = GameWorld.makeNullWorld()
|
||||
/** how many different planets/stages/etc. are thenre. Whole stages must be manually managed by YOU. */
|
||||
var gameworldCount = 0
|
||||
/** The actor the game is currently allowing you to control.
|
||||
@@ -36,14 +38,25 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
||||
*/
|
||||
open var actorNowPlaying: ActorHumanoid? = null
|
||||
|
||||
open var gameInitialised = false
|
||||
internal set
|
||||
open var gameFullyLoaded = false
|
||||
internal set
|
||||
|
||||
val ACTORCONTAINER_INITIAL_SIZE = 64
|
||||
val actorContainer = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
|
||||
val actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
|
||||
|
||||
protected val terrainChangeQueue = Queue<BlockChangeQueueItem>()
|
||||
protected val wallChangeQueue = Queue<BlockChangeQueueItem>()
|
||||
protected val wireChangeQueue = Queue<BlockChangeQueueItem>()
|
||||
|
||||
override fun hide() {
|
||||
}
|
||||
|
||||
override fun show() {
|
||||
// the very basic show() implementation
|
||||
gameInitialised = true
|
||||
}
|
||||
|
||||
override fun render(delta: Float) {
|
||||
@@ -89,6 +102,33 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
||||
open fun worldSecondaryClickEnd(delta: Float) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Event for triggering fixture update when something is placed/removed on the world.
|
||||
* Normally only called by GameWorld.setTileTerrain
|
||||
*
|
||||
* Queueing schema is used to make sure things are synchronised.
|
||||
*/
|
||||
open fun queueTerrainChangedEvent(old: Int, new: Int, position: Long) {
|
||||
val (x, y) = LandUtil.resolveBlockAddr(world, position)
|
||||
terrainChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y))
|
||||
}
|
||||
|
||||
/**
|
||||
* Wall version of terrainChanged() event
|
||||
*/
|
||||
open fun queueWallChangedEvent(old: Int, new: Int, position: Long) {
|
||||
val (x, y) = LandUtil.resolveBlockAddr(world, position)
|
||||
wallChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y))
|
||||
}
|
||||
|
||||
/**
|
||||
* Wire version of terrainChanged() event
|
||||
*/
|
||||
open fun queueWireChangedEvent(old: Int, new: Int, position: Long) {
|
||||
val (x, y) = LandUtil.resolveBlockAddr(world, position)
|
||||
wireChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y))
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////
|
||||
@@ -197,7 +237,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
||||
|
||||
|
||||
fun insertionSortLastElem(arr: ArrayList<Actor>) {
|
||||
lock(ReentrantLock()) {
|
||||
ReentrantLock().lock {
|
||||
var j = arr.lastIndex - 1
|
||||
val x = arr.last()
|
||||
while (j >= 0 && arr[j] > x) {
|
||||
@@ -208,13 +248,16 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
||||
}
|
||||
}
|
||||
|
||||
inline fun lock(lock: Lock, body: () -> Unit) {
|
||||
lock.lock()
|
||||
try {
|
||||
body()
|
||||
}
|
||||
finally {
|
||||
lock.unlock()
|
||||
}
|
||||
|
||||
data class BlockChangeQueueItem(val old: Int, val new: Int, val posX: Int, val posY: Int)
|
||||
}
|
||||
|
||||
inline fun Lock.lock(body: () -> Unit) {
|
||||
this.lock()
|
||||
try {
|
||||
body()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import com.google.gson.JsonPrimitive
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
typealias ItemValue = KVHashMap
|
||||
typealias GameConfig = KVHashMap
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2015-12-30.
|
||||
|
||||
@@ -2,19 +2,21 @@ package net.torvald.terrarum
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.ScreenAdapter
|
||||
import com.badlogic.gdx.graphics.*
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.dataclass.HistoryArray
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.modulebasegame.Ingame
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2017-07-13.
|
||||
*/
|
||||
object LoadScreen : ScreenAdapter() {
|
||||
|
||||
var screenToLoad: Ingame? = null
|
||||
var screenToLoad: IngameInstance? = null
|
||||
private lateinit var screenLoadingThread: Thread
|
||||
|
||||
|
||||
@@ -123,12 +125,10 @@ object LoadScreen : ScreenAdapter() {
|
||||
|
||||
|
||||
|
||||
Gdx.gl.glClearColor(.094f, .094f, .094f, 0f)
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
||||
gdxClearAndSetBlend(.094f, .094f, .094f, 0f)
|
||||
|
||||
textFbo.inAction(null, null) {
|
||||
Gdx.gl.glClearColor(0f, 0f, 0f, 0f)
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
||||
gdxClearAndSetBlend(0f, 0f, 0f, 0f)
|
||||
}
|
||||
|
||||
// update arrow object
|
||||
@@ -161,7 +161,7 @@ object LoadScreen : ScreenAdapter() {
|
||||
Terrarum.batch.inUse {
|
||||
|
||||
|
||||
blendNormal()
|
||||
blendNormal(Terrarum.batch)
|
||||
Terrarum.fontGame
|
||||
it.color = Color.WHITE
|
||||
|
||||
@@ -169,7 +169,7 @@ object LoadScreen : ScreenAdapter() {
|
||||
Terrarum.fontGame.draw(it, textToPrint, ((textFbo.width - textWidth) / 2).toInt().toFloat(), 0f)
|
||||
|
||||
|
||||
blendMul()
|
||||
blendMul(Terrarum.batch)
|
||||
// draw colour overlay, flipped
|
||||
it.draw(textOverlayTex,
|
||||
(textFbo.width - textWidth) / 2f,
|
||||
@@ -184,7 +184,7 @@ object LoadScreen : ScreenAdapter() {
|
||||
Terrarum.batch.inUse {
|
||||
initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT) // dunno, no render without this
|
||||
it.projectionMatrix = camera.combined
|
||||
blendNormal()
|
||||
blendNormal(Terrarum.batch)
|
||||
|
||||
|
||||
// almost black background
|
||||
@@ -239,7 +239,7 @@ object LoadScreen : ScreenAdapter() {
|
||||
for (i in 0 until messages.elemCount) {
|
||||
Terrarum.fontGame.draw(it,
|
||||
messages[i] ?: "",
|
||||
40f,
|
||||
AppLoader.getTvSafeGraphicsWidth() + 16f,
|
||||
80f + (messages.size - i - 1) * Terrarum.fontGame.lineHeight
|
||||
)
|
||||
}
|
||||
@@ -251,7 +251,7 @@ object LoadScreen : ScreenAdapter() {
|
||||
|
||||
initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT) // dunno, no render without this
|
||||
it.projectionMatrix = camera.combined
|
||||
blendNormal()
|
||||
blendNormal(Terrarum.batch)
|
||||
|
||||
|
||||
|
||||
@@ -264,7 +264,7 @@ object LoadScreen : ScreenAdapter() {
|
||||
for (i in 0 until messages.elemCount) {
|
||||
Terrarum.fontGame.draw(it,
|
||||
messages[i] ?: "",
|
||||
40f,
|
||||
AppLoader.getTvSafeGraphicsWidth() + 16f,
|
||||
80f + (messages.size - i - 1) * Terrarum.fontGame.lineHeight
|
||||
)
|
||||
}
|
||||
@@ -313,7 +313,6 @@ object LoadScreen : ScreenAdapter() {
|
||||
}
|
||||
|
||||
override fun hide() {
|
||||
dispose()
|
||||
}
|
||||
|
||||
override fun resize(width: Int, height: Int) {
|
||||
|
||||
@@ -229,6 +229,8 @@ object ModMgr {
|
||||
val className = it["classname"].toString()
|
||||
val itemID = it["id"].toInt()
|
||||
|
||||
printdbg(this, "Reading item #$itemID with className $className")
|
||||
|
||||
val loadedClass = Class.forName(className)
|
||||
val loadedClassConstructor = loadedClass.getConstructor(ItemID::class.java)
|
||||
val loadedClassInstance = loadedClassConstructor.newInstance(itemID)
|
||||
|
||||
@@ -53,3 +53,5 @@ data class Point2d(var x: Double, var y: Double) : Cloneable {
|
||||
fun distSqr(other: Point2d) = ((this.x - other.x).sqr() + (this.y - other.y).sqr())
|
||||
|
||||
}
|
||||
|
||||
data class Point2i(val x: Int, val y: Int)
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.Input
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.GL20
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||
import com.badlogic.gdx.graphics.glutils.ShaderProgram
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
|
||||
import com.badlogic.gdx.math.Matrix4
|
||||
import kotlin.system.measureNanoTime
|
||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||
import net.torvald.terrarum.ui.BasicDebugInfoWindow
|
||||
|
||||
/**
|
||||
* Must be called by the App Loader
|
||||
@@ -16,57 +20,139 @@ import kotlin.system.measureNanoTime
|
||||
object PostProcessor {
|
||||
|
||||
private lateinit var batch: SpriteBatch // not nulling to save some lines of code
|
||||
//private lateinit var camera: OrthographicCamera
|
||||
private var textureRegion: TextureRegion? = null
|
||||
|
||||
private lateinit var shapeRenderer: ShapeRenderer
|
||||
private lateinit var camera: OrthographicCamera
|
||||
|
||||
private lateinit var lutTex: Texture
|
||||
|
||||
private var init = false
|
||||
|
||||
fun reloadLUT(filename: String) {
|
||||
lutTex = Texture(Gdx.files.internal("assets/clut/$filename"))
|
||||
}
|
||||
|
||||
private val defaultResCol = Color(0x66ffff66)
|
||||
private val safeAreaCol = Color(0xffffff66.toInt())
|
||||
private val safeAreaCol2 = Color(0xffffff44.toInt())
|
||||
|
||||
private val debugUI = BasicDebugInfoWindow()
|
||||
|
||||
fun draw(projMat: Matrix4, fbo: FrameBuffer) {
|
||||
|
||||
if (textureRegion == null) {
|
||||
textureRegion = TextureRegion(fbo.colorBufferTexture)
|
||||
// init
|
||||
if (!init) {
|
||||
init = true
|
||||
|
||||
debugUI.setPosition(0, 0)
|
||||
|
||||
batch = SpriteBatch()
|
||||
camera = OrthographicCamera(AppLoader.screenW.toFloat(), AppLoader.screenH.toFloat())
|
||||
camera.setToOrtho(true)
|
||||
|
||||
batch.projectionMatrix = camera.combined
|
||||
|
||||
shapeRenderer = ShapeRenderer()
|
||||
Gdx.gl20.glViewport(0, 0, AppLoader.appConfig.width, AppLoader.appConfig.height)
|
||||
}
|
||||
|
||||
|
||||
debugUI.update(Gdx.graphics.deltaTime)
|
||||
|
||||
|
||||
Terrarum.debugTimers["Renderer.PostProcessor"] = measureNanoTime {
|
||||
AppLoader.measureDebugTime("Renderer.PostProcessor") {
|
||||
|
||||
Gdx.gl.glClearColor(.094f, .094f, .094f, 0f)
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
||||
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D)
|
||||
Gdx.gl.glEnable(GL20.GL_BLEND)
|
||||
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA)
|
||||
gdxClearAndSetBlend(.094f, .094f, .094f, 0f)
|
||||
|
||||
val shader: ShaderProgram? =
|
||||
if (Terrarum.getConfigBoolean("fxdither"))
|
||||
AppLoader.shaderHicolour
|
||||
else
|
||||
null
|
||||
|
||||
fbo.colorBufferTexture.bind(0)
|
||||
|
||||
shader?.begin()
|
||||
shader?.setUniformf("resolution", AppLoader.appConfig.width.toFloat(), AppLoader.appConfig.height.toFloat())
|
||||
shader?.setUniformMatrix("u_projTrans", projMat)
|
||||
shader?.setUniformi("u_texture", 0)
|
||||
AppLoader.fullscreenQuad.render(shader, GL20.GL_TRIANGLES)
|
||||
shader?.end()
|
||||
|
||||
|
||||
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it
|
||||
postShader(projMat, fbo)
|
||||
|
||||
if (AppLoader.IS_DEVELOPMENT_BUILD && KeyToggler.isOn(Input.Keys.F11)) {
|
||||
drawSafeArea()
|
||||
}
|
||||
|
||||
if (KeyToggler.isOn(Input.Keys.F3)) {
|
||||
if (!debugUI.isOpened && !debugUI.isOpening) debugUI.setAsOpen()
|
||||
batch.inUse { debugUI.renderUI(batch, camera) }
|
||||
}
|
||||
else {
|
||||
if (!debugUI.isClosed && !debugUI.isClosing) debugUI.setAsClose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun postShader(projMat: Matrix4, fbo: FrameBuffer) {
|
||||
val shader: ShaderProgram? =
|
||||
if (AppLoader.getConfigBoolean("fxdither"))
|
||||
AppLoader.shaderHicolour
|
||||
else
|
||||
AppLoader.shaderPassthru
|
||||
|
||||
fbo.colorBufferTexture.bind(0)
|
||||
|
||||
shader?.begin()
|
||||
shader?.setUniformMatrix("u_projTrans", projMat)
|
||||
shader?.setUniformi("u_texture", 0)
|
||||
AppLoader.fullscreenQuad.render(shader, GL20.GL_TRIANGLES)
|
||||
shader?.end()
|
||||
|
||||
|
||||
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it
|
||||
|
||||
}
|
||||
|
||||
private fun drawSafeArea() {
|
||||
val tvSafeAreaW = AppLoader.getTvSafeGraphicsWidth().toFloat()
|
||||
val tvSafeAreaH = AppLoader.getTvSafeGraphicsHeight().toFloat()
|
||||
val tvSafeArea2W = AppLoader.getTvSafeActionWidth().toFloat()
|
||||
val tvSafeArea2H = AppLoader.getTvSafeActionHeight().toFloat()
|
||||
|
||||
shapeRenderer.inUse(ShapeRenderer.ShapeType.Line) {
|
||||
shapeRenderer.color = safeAreaCol2
|
||||
shapeRenderer.rect(
|
||||
tvSafeArea2W, tvSafeArea2H, AppLoader.screenW - 2 * tvSafeArea2W, AppLoader.screenH - 2 * tvSafeArea2H
|
||||
)
|
||||
|
||||
shapeRenderer.color = safeAreaCol
|
||||
shapeRenderer.rect(
|
||||
tvSafeAreaW, tvSafeAreaH, AppLoader.screenW - 2 * tvSafeAreaW, AppLoader.screenH - 2 * tvSafeAreaH
|
||||
)
|
||||
|
||||
shapeRenderer.color = defaultResCol
|
||||
shapeRenderer.rect(
|
||||
(AppLoader.screenW - AppLoader.minimumW).div(2).toFloat(),
|
||||
(AppLoader.screenH - AppLoader.minimumH).div(2).toFloat(),
|
||||
AppLoader.minimumW.toFloat(),
|
||||
AppLoader.minimumH.toFloat()
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
batch.inUse {
|
||||
batch.color = safeAreaCol
|
||||
AppLoader.fontSmallNumbers.draw(
|
||||
batch, safeAreaStr,
|
||||
tvSafeAreaW, tvSafeAreaH - 10
|
||||
)
|
||||
|
||||
batch.color = defaultResCol
|
||||
AppLoader.fontSmallNumbers.draw(
|
||||
batch, defaultResStr,
|
||||
(AppLoader.screenW - AppLoader.minimumW).div(2).toFloat(),
|
||||
(AppLoader.screenH - AppLoader.minimumH).div(2).minus(10).toFloat()
|
||||
)
|
||||
}
|
||||
}
|
||||
catch (doNothing: NullPointerException) { }
|
||||
finally {
|
||||
// one-time call, caused by catching NPE before batch ends
|
||||
if (batch.isDrawing) {
|
||||
batch.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val defaultResStr = "${AppLoader.minimumW}x${AppLoader.minimumH}"
|
||||
private val safeAreaStr = "TV Safe Area"
|
||||
|
||||
/**
|
||||
* Camera will be moved so that (newX, newY) would be sit on the top-left edge.
|
||||
*/
|
||||
|
||||
72
src/net/torvald/terrarum/QNDTreeNode.kt
Normal file
72
src/net/torvald/terrarum/QNDTreeNode.kt
Normal file
@@ -0,0 +1,72 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class QNDTreeNode<T>(var data: T? = null, var parent: QNDTreeNode<T>? = null) {
|
||||
var children = ArrayList<QNDTreeNode<T>>()
|
||||
|
||||
|
||||
private fun traverse1(node: QNDTreeNode<T>, action: (QNDTreeNode<T>, Int) -> Unit, depth: Int = 0) {
|
||||
//if (node == null) return
|
||||
action(node, depth)
|
||||
node.children.forEach { traverse1(it, action, depth + 1) }
|
||||
}
|
||||
|
||||
private fun traverse2(node: QNDTreeNode<T>, action: (QNDTreeNode<T>, Int) -> Unit, depth: Int = 0) {
|
||||
//if (node == null) return
|
||||
node.children.forEach { traverse2(it, action, depth + 1) }
|
||||
action(node, depth)
|
||||
}
|
||||
|
||||
/**
|
||||
* (QNDTreeNode, Int) is Node-depth pair, starting from zero.
|
||||
*/
|
||||
fun traversePreorder(action: (QNDTreeNode<T>, Int) -> Unit) {
|
||||
this.traverse1(this, action)
|
||||
}
|
||||
|
||||
/**
|
||||
* (QNDTreeNode, Int) is Node-depth pair, starting from zero.
|
||||
*/
|
||||
fun traversePostorder(action: (QNDTreeNode<T>, Int) -> Unit) {
|
||||
this.traverse2(this, action)
|
||||
}
|
||||
|
||||
/**
|
||||
* (QNDTreeNode, Int) is Node-depth pair, starting from zero.
|
||||
*/
|
||||
fun traverseLevelorder(action: (QNDTreeNode<T>, Int) -> Unit) {
|
||||
val q = ArrayList<Pair<QNDTreeNode<T>, Int>>() // node, depth
|
||||
q.add(this to 0)
|
||||
while (q.isNotEmpty()) {
|
||||
val node = q.removeAt(0)
|
||||
action(node.first, node.second)
|
||||
node.first.children.forEach {
|
||||
q.add(it to node.second + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves data in the node in a specific depth (level).
|
||||
* Probably only useful for level = 1
|
||||
*/
|
||||
fun getLevelData(level: Int): List<T?> {
|
||||
val list = ArrayList<T?>()
|
||||
|
||||
traversePreorder { node, i ->
|
||||
if (i == level) {
|
||||
list.add(node.data)
|
||||
}
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
override fun toString() = data.toString()
|
||||
|
||||
fun print() {
|
||||
TODO()
|
||||
}
|
||||
}
|
||||
@@ -3,26 +3,23 @@ package net.torvald.terrarum
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.Screen
|
||||
import com.badlogic.gdx.assets.AssetManager
|
||||
import com.badlogic.gdx.graphics.*
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.GL20
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||
import com.badlogic.gdx.graphics.glutils.ShaderProgram
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.dataclass.ArrayListMap
|
||||
import net.torvald.dataclass.CircularArray
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.AppLoader.printdbg
|
||||
import net.torvald.terrarum.AppLoader.printdbgerr
|
||||
import net.torvald.terrarum.AppLoader.*
|
||||
import net.torvald.terrarum.gameactors.Actor
|
||||
import net.torvald.terrarum.gameactors.ActorID
|
||||
import net.torvald.terrarum.imagefont.TinyAlphNum
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||
import net.torvald.terrarum.utils.JsonFetcher
|
||||
import net.torvald.terrarum.utils.JsonWriter
|
||||
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
|
||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase
|
||||
@@ -30,8 +27,7 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
import org.lwjgl.BufferUtils
|
||||
import org.lwjgl.input.Controllers
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import net.torvald.getcpuname.GetCpuName
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
|
||||
|
||||
@@ -50,11 +46,6 @@ object Terrarum : Screen {
|
||||
*/
|
||||
const val PLAYER_REF_ID: Int = 0x91A7E2
|
||||
|
||||
val debugTimers = ArrayListMap<String, Long>()
|
||||
|
||||
var screenW = 0
|
||||
var screenH = 0
|
||||
|
||||
lateinit var batch: SpriteBatch
|
||||
lateinit var shapeRender: ShapeRenderer // DO NOT USE!! for very limited applications e.g. WeatherMixer
|
||||
inline fun inShapeRenderer(shapeRendererType: ShapeRenderer.ShapeType = ShapeRenderer.ShapeType.Filled, action: (ShapeRenderer) -> Unit) {
|
||||
@@ -69,9 +60,9 @@ object Terrarum : Screen {
|
||||
//////////////////////////////
|
||||
|
||||
val WIDTH: Int
|
||||
get() = if (screenW % 2 == 0) screenW else screenW - 1
|
||||
get() = AppLoader.screenW
|
||||
val HEIGHT: Int
|
||||
get() = if (screenH % 2 == 0) screenH else screenH - 1
|
||||
get() = AppLoader.screenH
|
||||
|
||||
//val WIDTH_MIN = 800
|
||||
//val HEIGHT_MIN = 600
|
||||
@@ -82,44 +73,22 @@ object Terrarum : Screen {
|
||||
get() = HEIGHT.ushr(1)
|
||||
|
||||
/**
|
||||
* To be used with physics simulator
|
||||
* To be used with physics simulator. This is a magic number.
|
||||
*/
|
||||
val TARGET_FPS: Double = 26.0 + (2.0 / 3.0)
|
||||
val PHYS_TIME_FRAME: Double = 26.0 + (2.0 / 3.0)
|
||||
// 26.0 + (2.0 / 3.0) // lower value == faster gravity response (IT WON'T HOTSWAP!!)
|
||||
// protip: using METER, game unit and SI unit will have same number
|
||||
|
||||
/**
|
||||
* To be used with render, to achieve smooth frame drawing
|
||||
* TARGET_INTERNAL_FPS > TARGET_FPS for smooth frame drawing
|
||||
*/
|
||||
val TARGET_INTERNAL_FPS: Double = 60.0
|
||||
|
||||
internal val UPDATE_CATCHUP_MAX_TRIES = 10
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var previousScreen: Screen? = null // to be used with temporary states like StateMonitorCheck
|
||||
|
||||
|
||||
var ingame: IngameInstance? = null
|
||||
private val gameConfig = GameConfig()
|
||||
|
||||
val OSName = System.getProperty("os.name")
|
||||
val OSVersion = System.getProperty("os.version")
|
||||
lateinit var OperationSystem: String // all caps "WINDOWS, "OSX", "LINUX", "SOLARIS", "UNKNOWN"
|
||||
private set
|
||||
lateinit var defaultDir: String
|
||||
private set
|
||||
lateinit var defaultSaveDir: String
|
||||
private set
|
||||
|
||||
|
||||
|
||||
private val javaHeapCircularArray = CircularArray<Int>(128)
|
||||
private val nativeHeapCircularArray = CircularArray<Int>(128)
|
||||
private val javaHeapCircularArray = CircularArray<Int>(64)
|
||||
private val nativeHeapCircularArray = CircularArray<Int>(64)
|
||||
private val updateRateCircularArray = CircularArray<Double>(16)
|
||||
|
||||
val memJavaHeap: Int
|
||||
get() {
|
||||
@@ -139,30 +108,35 @@ object Terrarum : Screen {
|
||||
}
|
||||
val memXmx: Int
|
||||
get() = (Runtime.getRuntime().maxMemory() shr 20).toInt()
|
||||
val updateRateStr: String
|
||||
get() {
|
||||
updateRateCircularArray.add(updateRate)
|
||||
|
||||
var environment: RunningEnvironment
|
||||
private set
|
||||
var acc = 0.0
|
||||
updateRateCircularArray.forEach { acc = maxOf(acc, it) }
|
||||
return String.format("%.2f", acc)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
val fontGame: GameFontBase = AppLoader.fontGame
|
||||
lateinit var fontSmallNumbers: TinyAlphNum
|
||||
val fontSmallNumbers: TinyAlphNum = AppLoader.fontSmallNumbers
|
||||
|
||||
var joypadLabelStart: Char = 0xE000.toChar() // lateinit
|
||||
var joypadLableSelect: Char = 0xE000.toChar() // lateinit
|
||||
var joypadLabelNinA: Char = 0xE000.toChar() // lateinit TODO
|
||||
var joypadLabelNinB: Char = 0xE000.toChar() // lateinit TODO
|
||||
var joypadLabelNinX: Char = 0xE000.toChar() // lateinit TODO
|
||||
var joypadLabelNinY: Char = 0xE000.toChar() // lateinit TODO
|
||||
var joypadLabelNinL: Char = 0xE000.toChar() // lateinit TODO
|
||||
var joypadLabelNinR: Char = 0xE000.toChar() // lateinit TODO
|
||||
var joypadLabelNinZL: Char = 0xE000.toChar() // lateinit TODO
|
||||
var joypadLabelNinZR: Char = 0xE000.toChar() // lateinit TODO
|
||||
val joypadLabelLEFT = 0xE068.toChar()
|
||||
val joypadLabelDOWN = 0xE069.toChar()
|
||||
val joypadLabelUP = 0xE06A.toChar()
|
||||
val joypadLabelRIGHT = 0xE06B.toChar()
|
||||
var gamepadLabelStart: Char = 0xE000.toChar() // lateinit
|
||||
var gamepadLableSelect: Char = 0xE000.toChar() // lateinit
|
||||
var gamepadLabelNinA: Char = 0xE000.toChar() // lateinit TODO
|
||||
var gamepadLabelNinB: Char = 0xE000.toChar() // lateinit TODO
|
||||
var gamepadLabelNinX: Char = 0xE000.toChar() // lateinit TODO
|
||||
var gamepadLabelNinY: Char = 0xE000.toChar() // lateinit TODO
|
||||
var gamepadLabelNinL: Char = 0xE000.toChar() // lateinit TODO
|
||||
var gamepadLabelNinR: Char = 0xE000.toChar() // lateinit TODO
|
||||
var gamepadLabelNinZL: Char = 0xE000.toChar() // lateinit TODO
|
||||
var gamepadLabelNinZR: Char = 0xE000.toChar() // lateinit TODO
|
||||
val gamepadLabelLEFT = 0xE068.toChar()
|
||||
val gamepadLabelDOWN = 0xE069.toChar()
|
||||
val gamepadLabelUP = 0xE06A.toChar()
|
||||
val gamepadLabelRIGHT = 0xE06B.toChar()
|
||||
|
||||
// 0x0 - 0xF: Game-related
|
||||
// 0x10 - 0x1F: Config
|
||||
@@ -185,12 +159,8 @@ object Terrarum : Screen {
|
||||
val STATE_ID_TOOL_NOISEGEN = 0x200
|
||||
val STATE_ID_TOOL_RUMBLE_DIAGNOSIS = 0x201
|
||||
|
||||
var controller: org.lwjgl.input.Controller? = null
|
||||
private set
|
||||
val CONTROLLER_DEADZONE = 0.1f
|
||||
|
||||
/** Available CPU threads */
|
||||
val THREADS = Runtime.getRuntime().availableProcessors()
|
||||
val THREADS = Runtime.getRuntime().availableProcessors() + 1
|
||||
|
||||
/**
|
||||
* If the game is multithreading.
|
||||
@@ -199,20 +169,11 @@ object Terrarum : Screen {
|
||||
* THREADS >= 2 and config "multithread" is true
|
||||
*/
|
||||
val MULTITHREAD: Boolean
|
||||
get() = THREADS >= 2 && getConfigBoolean("multithread")
|
||||
|
||||
private lateinit var configDir: String
|
||||
get() = THREADS >= 3 && getConfigBoolean("multithread")
|
||||
|
||||
const val NAME = AppLoader.GAME_NAME
|
||||
|
||||
|
||||
val systemArch = System.getProperty("os.arch")
|
||||
val processor = GetCpuName.getModelName()
|
||||
val processorVendor = GetCpuName.getCPUID()
|
||||
|
||||
val is32BitJVM = !System.getProperty("sun.arch.data.model").contains("64")
|
||||
|
||||
|
||||
lateinit var shaderBlur: ShaderProgram
|
||||
lateinit var shaderBayer: ShaderProgram
|
||||
lateinit var shaderSkyboxFill: ShaderProgram
|
||||
@@ -220,10 +181,6 @@ object Terrarum : Screen {
|
||||
lateinit var shaderRGBOnly: ShaderProgram
|
||||
lateinit var shaderAtoGrey: ShaderProgram
|
||||
|
||||
|
||||
lateinit var textureWhiteSquare: Texture
|
||||
|
||||
|
||||
lateinit var testTexture: Texture
|
||||
|
||||
|
||||
@@ -231,8 +188,6 @@ object Terrarum : Screen {
|
||||
val fullscreenQuad = AppLoader.fullscreenQuad
|
||||
|
||||
|
||||
val deltaTime: Float; get() = Gdx.graphics.rawDeltaTime
|
||||
|
||||
|
||||
lateinit var assetManager: AssetManager // TODO
|
||||
|
||||
@@ -243,16 +198,6 @@ object Terrarum : Screen {
|
||||
println("LibGDX version ${com.badlogic.gdx.Version.VERSION}")
|
||||
|
||||
|
||||
getDefaultDirectory()
|
||||
createDirs()
|
||||
|
||||
|
||||
// read config i guess...?
|
||||
val readFromDisk = readConfigJson()
|
||||
if (!readFromDisk) readConfigJson() // what's this for?
|
||||
|
||||
|
||||
|
||||
println("os.arch = $systemArch") // debug info
|
||||
|
||||
if (is32BitJVM) {
|
||||
@@ -264,12 +209,12 @@ object Terrarum : Screen {
|
||||
println("vendor = $processorVendor")
|
||||
|
||||
|
||||
joypadLabelStart = when (getConfigString("joypadlabelstyle")) {
|
||||
gamepadLabelStart = when (getConfigString("gamepadlabelstyle")) {
|
||||
"nwii" -> 0xE04B.toChar() // + mark
|
||||
"logitech" -> 0xE05A.toChar() // number 10
|
||||
else -> 0xE042.toChar() // |> mark (sonyps, msxb360, generic)
|
||||
}
|
||||
joypadLableSelect = when (getConfigString("joypadlabelstyle")) {
|
||||
gamepadLableSelect = when (getConfigString("gamepadlabelstyle")) {
|
||||
"nwii" -> 0xE04D.toChar() // - mark
|
||||
"logitech" -> 0xE059.toChar() // number 9
|
||||
"sonyps" -> 0xE043.toChar() // solid rectangle
|
||||
@@ -278,17 +223,19 @@ object Terrarum : Screen {
|
||||
}
|
||||
|
||||
|
||||
|
||||
environment = try {
|
||||
Controllers.getController(0) // test if controller exists
|
||||
if (getConfigString("pcgamepadenv") == "console")
|
||||
RunningEnvironment.CONSOLE
|
||||
else
|
||||
// setting environment as MOBILE precedes this code
|
||||
//if (environment != RunningEnvironment.MOBILE) {
|
||||
environment = try {
|
||||
Controllers.getController(0) // test if controller exists
|
||||
if (getConfigString("pcgamepadenv") == "console")
|
||||
RunningEnvironment.CONSOLE
|
||||
else
|
||||
RunningEnvironment.PC
|
||||
}
|
||||
catch (e: IndexOutOfBoundsException) {
|
||||
RunningEnvironment.PC
|
||||
}
|
||||
catch (e: IndexOutOfBoundsException) {
|
||||
RunningEnvironment.PC
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
@@ -314,20 +261,17 @@ object Terrarum : Screen {
|
||||
val MINIMAL_GL_MAX_TEXTURE_SIZE = 4096
|
||||
|
||||
override fun show() {
|
||||
if (environment != RunningEnvironment.MOBILE) {
|
||||
Gdx.gl.glDisable(GL20.GL_DITHER)
|
||||
}
|
||||
|
||||
|
||||
assetManager = AssetManager()
|
||||
|
||||
|
||||
testTexture = Texture(Gdx.files.internal("./assets/test_texture.tga"))
|
||||
|
||||
|
||||
val glInfo = Gdx.graphics.glVersion.debugVersionString
|
||||
|
||||
println("GL_VERSION = $GL_VERSION")
|
||||
println("GL_MAX_TEXTURE_SIZE = $GL_MAX_TEXTURE_SIZE")
|
||||
println("GL info:\n${Gdx.graphics.glVersion.debugVersionString}") // debug info
|
||||
println("GL info:\n$glInfo") // debug info
|
||||
|
||||
|
||||
if (GL_VERSION < MINIMAL_GL_VERSION || GL_MAX_TEXTURE_SIZE < MINIMAL_GL_MAX_TEXTURE_SIZE) {
|
||||
@@ -345,27 +289,19 @@ object Terrarum : Screen {
|
||||
shapeRender = ShapeRenderer()
|
||||
|
||||
|
||||
//fontGame = GameFontBase("assets/graphics/fonts/terrarum-sans-bitmap", flipY = true)
|
||||
fontSmallNumbers = TinyAlphNum
|
||||
|
||||
|
||||
textureWhiteSquare = Texture(Gdx.files.internal("assets/graphics/ortho_line_tex_2px.tga"))
|
||||
textureWhiteSquare.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
|
||||
|
||||
|
||||
ShaderProgram.pedantic = false
|
||||
shaderBlur = ShaderProgram(Gdx.files.internal("assets/blur.vert"), Gdx.files.internal("assets/blur.frag"))
|
||||
shaderBlur = AppLoader.loadShader("assets/blur.vert", "assets/blur.frag")
|
||||
|
||||
|
||||
if (getConfigBoolean("fxdither")) {
|
||||
shaderBayer = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/4096_bayer.frag"))
|
||||
shaderBayer = AppLoader.loadShader("assets/4096.vert", "assets/4096_bayer.frag")
|
||||
shaderBayer.begin()
|
||||
shaderBayer.setUniformf("rcount", 64f)
|
||||
shaderBayer.setUniformf("gcount", 64f)
|
||||
shaderBayer.setUniformf("bcount", 64f)
|
||||
shaderBayer.end()
|
||||
|
||||
shaderSkyboxFill = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/4096_bayer_skyboxfill.frag"))
|
||||
shaderSkyboxFill = AppLoader.loadShader("assets/4096.vert", "assets/4096_bayer_skyboxfill.frag")
|
||||
shaderSkyboxFill.begin()
|
||||
shaderSkyboxFill.setUniformf("rcount", 64f)
|
||||
shaderSkyboxFill.setUniformf("gcount", 64f)
|
||||
@@ -373,15 +309,15 @@ object Terrarum : Screen {
|
||||
shaderSkyboxFill.end()
|
||||
}
|
||||
else {
|
||||
shaderBayer = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/passthru.frag"))
|
||||
shaderSkyboxFill = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/skyboxfill.frag"))
|
||||
shaderBayer = AppLoader.loadShader("assets/4096.vert", "assets/passthru.frag")
|
||||
shaderSkyboxFill = AppLoader.loadShader("assets/4096.vert", "assets/skyboxfill.frag")
|
||||
}
|
||||
|
||||
|
||||
shaderBlendGlow = ShaderProgram(Gdx.files.internal("assets/blendGlow.vert"), Gdx.files.internal("assets/blendGlow.frag"))
|
||||
shaderBlendGlow = AppLoader.loadShader("assets/blendGlow.vert", "assets/blendGlow.frag")
|
||||
|
||||
shaderRGBOnly = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/rgbonly.frag"))
|
||||
shaderAtoGrey = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/aonly.frag"))
|
||||
shaderRGBOnly = AppLoader.loadShader("assets/4096.vert", "assets/rgbonly.frag")
|
||||
shaderAtoGrey = AppLoader.loadShader("assets/4096.vert", "assets/aonly.frag")
|
||||
|
||||
|
||||
if (!shaderBlendGlow.isCompiled) {
|
||||
@@ -419,18 +355,18 @@ object Terrarum : Screen {
|
||||
|
||||
|
||||
|
||||
// jump right into the ingame
|
||||
/*ingame = Ingame(batch)
|
||||
ingame!!.gameLoadInfoPayload = Ingame.NewWorldParameters(2400, 800, HQRNG().nextLong())
|
||||
ingame!!.gameLoadMode = Ingame.GameLoadMode.CREATE_NEW
|
||||
LoadScreen.screenToLoad = ingame!!
|
||||
super.setScreen(LoadScreen)*/
|
||||
// jump straight into the ingame
|
||||
/*val ingame = Ingame(batch)
|
||||
ingame.gameLoadInfoPayload = Ingame.NewWorldParameters(2400, 800, HQRNG().nextLong())
|
||||
ingame.gameLoadMode = Ingame.GameLoadMode.CREATE_NEW
|
||||
LoadScreen.screenToLoad = ingame
|
||||
this.ingame = ingame
|
||||
setScreen(LoadScreen)*/
|
||||
|
||||
|
||||
|
||||
// title screen
|
||||
AppLoader.getINSTANCE().setScreen(TitleScreen(batch))
|
||||
//appLoader.setScreen(FuckingWorldRenderer(batch))
|
||||
}
|
||||
|
||||
fun setScreen(screen: Screen) {
|
||||
@@ -438,10 +374,9 @@ object Terrarum : Screen {
|
||||
}
|
||||
|
||||
override fun render(delta: Float) {
|
||||
Terrarum.debugTimers["GDX.delta"] = delta.times(1000_000_000f).toLong()
|
||||
AppLoader.getINSTANCE().screen.render(deltaTime)
|
||||
//GLOBAL_RENDER_TIMER += 1
|
||||
// moved to AppLoader; global event must be place at the apploader to prevent ACCIDENTAL forgot-to-update type of bug.
|
||||
AppLoader.setDebugTime("GDX.rawDelta", Gdx.graphics.rawDeltaTime.times(1000_000_000f).toLong())
|
||||
AppLoader.setDebugTime("GDX.smtDelta", Gdx.graphics.deltaTime.times(1000_000_000f).toLong())
|
||||
AppLoader.getINSTANCE().screen.render(delta)
|
||||
}
|
||||
|
||||
override fun pause() {
|
||||
@@ -452,231 +387,30 @@ object Terrarum : Screen {
|
||||
AppLoader.getINSTANCE().screen.resume()
|
||||
}
|
||||
|
||||
/** Don't call this! Call AppLoader.dispose() */
|
||||
override fun dispose() {
|
||||
AppLoader.getINSTANCE().screen.dispose()
|
||||
|
||||
fontGame.dispose()
|
||||
fontSmallNumbers.dispose()
|
||||
|
||||
|
||||
//dispose any other resources used in this level
|
||||
|
||||
|
||||
shaderBayer.dispose()
|
||||
shaderSkyboxFill.dispose()
|
||||
shaderBlur.dispose()
|
||||
shaderBlendGlow.dispose()
|
||||
|
||||
|
||||
shapeRender.dispose()
|
||||
batch.dispose()
|
||||
ingame?.dispose()
|
||||
}
|
||||
|
||||
override fun hide() {
|
||||
AppLoader.getINSTANCE().screen.hide()
|
||||
}
|
||||
|
||||
/** For the actual resize, call AppLoader.resize() */
|
||||
override fun resize(width: Int, height: Int) {
|
||||
//var width = maxOf(width, WIDTH_MIN)
|
||||
//var height = maxOf(height, HEIGHT_MIN)
|
||||
|
||||
var width = width
|
||||
var height = height
|
||||
|
||||
if (width % 2 == 1) width -= 1
|
||||
if (height % 2 == 1) height -= 1
|
||||
|
||||
screenW = width
|
||||
screenH = height
|
||||
|
||||
|
||||
try {
|
||||
AppLoader.getINSTANCE().screen.resize(screenW, screenH)
|
||||
}
|
||||
catch (e: NullPointerException) { }
|
||||
|
||||
// re-calculate fullscreen quad
|
||||
//updateFullscreenQuad(screenW, screenH)
|
||||
|
||||
//appLoader.resize(width, height)
|
||||
//Gdx.graphics.setWindowedMode(width, height)
|
||||
ingame?.resize(width, height)
|
||||
|
||||
printdbg(this, "newsize: ${Gdx.graphics.width}x${Gdx.graphics.height} | internal: ${width}x$height")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private fun getDefaultDirectory() {
|
||||
val OS = System.getProperty("os.name").toUpperCase()
|
||||
if (OS.contains("WIN")) {
|
||||
OperationSystem = "WINDOWS"
|
||||
defaultDir = System.getenv("APPDATA") + "/Terrarum"
|
||||
}
|
||||
else if (OS.contains("OS X")) {
|
||||
OperationSystem = "OSX"
|
||||
defaultDir = System.getProperty("user.home") + "/Library/Application Support/Terrarum"
|
||||
}
|
||||
else if (OS.contains("NUX") || OS.contains("NIX") || OS.contains("BSD")) {
|
||||
OperationSystem = "LINUX"
|
||||
defaultDir = System.getProperty("user.home") + "/.Terrarum"
|
||||
}
|
||||
else if (OS.contains("SUNOS")) {
|
||||
OperationSystem = "SOLARIS"
|
||||
defaultDir = System.getProperty("user.home") + "/.Terrarum"
|
||||
}
|
||||
else if (System.getProperty("java.runtime.name").toUpperCase().contains("ANDROID")) {
|
||||
OperationSystem = "ANDROID"
|
||||
defaultDir = System.getProperty("user.home") + "/.Terrarum"
|
||||
environment = RunningEnvironment.MOBILE
|
||||
}
|
||||
else {
|
||||
OperationSystem = "UNKNOWN"
|
||||
defaultDir = System.getProperty("user.home") + "/.Terrarum"
|
||||
}
|
||||
|
||||
defaultSaveDir = defaultDir + "/Saves"
|
||||
configDir = defaultDir + "/config.json"
|
||||
|
||||
println("os.name = $OSName (with identifier $OperationSystem)")
|
||||
println("os.version = $OSVersion")
|
||||
println("default directory: $defaultDir")
|
||||
}
|
||||
|
||||
private fun createDirs() {
|
||||
val dirs = arrayOf(File(defaultSaveDir))
|
||||
dirs.forEach { if (!it.exists()) it.mkdirs() }
|
||||
}
|
||||
|
||||
private fun createConfigJson() {
|
||||
val configFile = File(configDir)
|
||||
|
||||
if (!configFile.exists() || configFile.length() == 0L) {
|
||||
JsonWriter.writeToFile(DefaultConfig.fetch(), configDir)
|
||||
}
|
||||
}
|
||||
|
||||
private fun readConfigJson(): Boolean {
|
||||
try {
|
||||
// read from disk and build config from it
|
||||
val jsonObject = JsonFetcher(configDir)
|
||||
|
||||
// make config
|
||||
jsonObject.entrySet().forEach { entry -> gameConfig[entry.key] = entry.value }
|
||||
|
||||
return true
|
||||
}
|
||||
catch (e: IOException) {
|
||||
// write default config to game dir. Call this method again to read config from it.
|
||||
try {
|
||||
createConfigJson()
|
||||
}
|
||||
catch (e1: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return config from config set. If the config does not exist, default value will be returned.
|
||||
* @param key
|
||||
* *
|
||||
* @return Config from config set or default config if it does not exist.
|
||||
* *
|
||||
* @throws NullPointerException if the specified config simply does not exist.
|
||||
*/
|
||||
fun getConfigInt(key: String): Int {
|
||||
val cfg = getConfigMaster(key)
|
||||
if (cfg is JsonPrimitive)
|
||||
return cfg.asInt
|
||||
else
|
||||
return cfg as Int
|
||||
}
|
||||
|
||||
/**
|
||||
* Return config from config set. If the config does not exist, default value will be returned.
|
||||
* @param key
|
||||
* *
|
||||
* @return Config from config set or default config if it does not exist.
|
||||
* *
|
||||
* @throws NullPointerException if the specified config simply does not exist.
|
||||
*/
|
||||
fun getConfigString(key: String): String {
|
||||
val cfg = getConfigMaster(key)
|
||||
if (cfg is JsonPrimitive)
|
||||
return cfg.asString
|
||||
else
|
||||
return cfg as String
|
||||
}
|
||||
|
||||
/**
|
||||
* Return config from config set. If the config does not exist, default value will be returned.
|
||||
* @param key
|
||||
* *
|
||||
* @return Config from config set or default config if it does not exist.
|
||||
* *
|
||||
* @throws NullPointerException if the specified config simply does not exist.
|
||||
*/
|
||||
fun getConfigBoolean(key: String): Boolean {
|
||||
val cfg = getConfigMaster(key)
|
||||
if (cfg is JsonPrimitive)
|
||||
return cfg.asBoolean
|
||||
else
|
||||
return cfg as Boolean
|
||||
}
|
||||
|
||||
fun getConfigIntArray(key: String): IntArray {
|
||||
val cfg = getConfigMaster(key)
|
||||
if (cfg is JsonArray) {
|
||||
val jsonArray = cfg.asJsonArray
|
||||
return IntArray(jsonArray.size(), { i -> jsonArray[i].asInt })
|
||||
}
|
||||
else
|
||||
return cfg as IntArray
|
||||
}
|
||||
|
||||
/**
|
||||
* Get config from config file. If the entry does not exist, get from defaults; if the entry is not in the default, NullPointerException will be thrown
|
||||
*/
|
||||
private val defaultConfig = DefaultConfig.fetch()
|
||||
|
||||
private fun getConfigMaster(key: String): Any {
|
||||
val key = key.toLowerCase()
|
||||
|
||||
val config = try {
|
||||
gameConfig[key]
|
||||
}
|
||||
catch (e: NullPointerException) {
|
||||
null
|
||||
}
|
||||
|
||||
val defaults = try {
|
||||
defaultConfig.get(key)
|
||||
}
|
||||
catch (e: NullPointerException) {
|
||||
null
|
||||
}
|
||||
|
||||
if (config == null) {
|
||||
if (defaults == null) {
|
||||
throw NullPointerException("key not found: '$key'")
|
||||
}
|
||||
else {
|
||||
return defaults
|
||||
}
|
||||
}
|
||||
else {
|
||||
return config
|
||||
}
|
||||
}
|
||||
|
||||
fun setConfig(key: String, value: Any) {
|
||||
gameConfig[key] = value
|
||||
}
|
||||
|
||||
val currentSaveDir: File
|
||||
get() {
|
||||
val file = File(defaultSaveDir + "/test")
|
||||
@@ -688,30 +422,36 @@ object Terrarum : Screen {
|
||||
}
|
||||
|
||||
/** Position of the cursor in the world */
|
||||
inline val mouseX: Double
|
||||
val mouseX: Double
|
||||
get() = WorldCamera.x + Gdx.input.x / (ingame?.screenZoom ?: 1f).toDouble()
|
||||
/** Position of the cursor in the world */
|
||||
inline val mouseY: Double
|
||||
val mouseY: Double
|
||||
get() = WorldCamera.y + Gdx.input.y / (ingame?.screenZoom ?: 1f).toDouble()
|
||||
/** Position of the cursor in the world */
|
||||
@JvmStatic inline val mouseTileX: Int
|
||||
val oldMouseX: Double
|
||||
get() = WorldCamera.x + (Gdx.input.x - Gdx.input.deltaX) / (ingame?.screenZoom ?: 1f).toDouble()
|
||||
/** Position of the cursor in the world */
|
||||
val oldMouseY: Double
|
||||
get() = WorldCamera.y + (Gdx.input.y - Gdx.input.deltaY) / (ingame?.screenZoom ?: 1f).toDouble()
|
||||
/** Position of the cursor in the world */
|
||||
@JvmStatic val mouseTileX: Int
|
||||
get() = (mouseX / FeaturesDrawer.TILE_SIZE).floorInt()
|
||||
/** Position of the cursor in the world */
|
||||
@JvmStatic inline val mouseTileY: Int
|
||||
@JvmStatic val mouseTileY: Int
|
||||
get() = (mouseY / FeaturesDrawer.TILE_SIZE).floorInt()
|
||||
/** Position of the cursor in the world */
|
||||
@JvmStatic val oldMouseTileX: Int
|
||||
get() = (oldMouseX / FeaturesDrawer.TILE_SIZE).floorInt()
|
||||
/** Position of the cursor in the world */
|
||||
@JvmStatic val oldMouseTileY: Int
|
||||
get() = (oldMouseY / FeaturesDrawer.TILE_SIZE).floorInt()
|
||||
inline val mouseScreenX: Int
|
||||
get() = Gdx.input.x
|
||||
inline val mouseScreenY: Int
|
||||
get() = Gdx.input.y
|
||||
/** Bigger than 1.0 */
|
||||
/** Delta converted as it it was a FPS */
|
||||
inline val updateRate: Double
|
||||
get() = 1.0 / Gdx.graphics.deltaTime
|
||||
val updateRateStr: String
|
||||
get() = String.format("%.2f", updateRate)
|
||||
/** Smaller than 1.0 */
|
||||
val renderRate = 1.0 / TARGET_INTERNAL_FPS
|
||||
val renderRateStr = TARGET_INTERNAL_FPS.toString()
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
*
|
||||
@@ -727,6 +467,7 @@ object Terrarum : Screen {
|
||||
Actor.RenderOrder.MIDDLE -> Actor.RANGE_MIDDLE
|
||||
Actor.RenderOrder.MIDTOP -> Actor.RANGE_MIDTOP
|
||||
Actor.RenderOrder.FRONT -> Actor.RANGE_FRONT
|
||||
Actor.RenderOrder.OVERLAY-> Actor.RANDE_OVERLAY
|
||||
}
|
||||
}
|
||||
catch (gameNotInitialisedException: KotlinNullPointerException) {
|
||||
@@ -780,9 +521,9 @@ fun Float.round(): Float {
|
||||
|
||||
// ShapeRenderer alternative for rects
|
||||
fun SpriteBatch.fillRect(x: Float, y: Float, w: Float, h: Float) {
|
||||
this.draw(Terrarum.textureWhiteSquare, x, y, w, h)
|
||||
this.draw(AppLoader.textureWhiteSquare, x, y, w, h)
|
||||
}
|
||||
inline fun SpriteBatch.drawStraightLine(x: Float, y: Float, otherEnd: Float, thickness: Float, isVertical: Boolean) {
|
||||
fun SpriteBatch.drawStraightLine(x: Float, y: Float, otherEnd: Float, thickness: Float, isVertical: Boolean) {
|
||||
if (!isVertical)
|
||||
this.fillRect(x, y, otherEnd - x, thickness)
|
||||
else
|
||||
@@ -792,38 +533,80 @@ inline fun SpriteBatch.drawStraightLine(x: Float, y: Float, otherEnd: Float, thi
|
||||
|
||||
|
||||
infix fun Color.mul(other: Color): Color = this.cpy().mul(other)
|
||||
infix fun Color.mulAndAssign(other: Color): Color {
|
||||
this.r *= other.r
|
||||
this.g *= other.g
|
||||
this.b *= other.b
|
||||
this.a *= other.a
|
||||
|
||||
|
||||
|
||||
/*inline fun Color.toRGB10(): RGB10 {
|
||||
val bits = this.toIntBits() // ABGR
|
||||
// 0bxxRRRRRRRRRRGGGGGGGGGGBBBBBBBBBB
|
||||
// 0bAAAAAAAABBBBBBBBGGGGGGGGRRRRRRRR
|
||||
return bits.and(0x0000FF).shl(20) or bits.and(0x00FF00).shl(2) or bits.and(0xFF0000).ushr(16)
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
fun blendMul(batch: SpriteBatch? = null) {
|
||||
(batch ?: Terrarum.batch).enableBlending()
|
||||
(batch ?: Terrarum.batch).setBlendFunction(GL20.GL_DST_COLOR, GL20.GL_ONE_MINUS_SRC_ALPHA)
|
||||
Gdx.gl.glBlendEquation(GL20.GL_FUNC_ADD) // batch.flush does not touch blend equation
|
||||
return this
|
||||
}
|
||||
|
||||
fun blendNormal(batch: SpriteBatch? = null) {
|
||||
(batch ?: Terrarum.batch).enableBlending()
|
||||
(batch ?: Terrarum.batch).setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA)
|
||||
Gdx.gl.glBlendEquation(GL20.GL_FUNC_ADD) // batch.flush does not touch blend equation
|
||||
|
||||
fun blendMul(batch: SpriteBatch) {
|
||||
// will break if the colour image contains semitransparency
|
||||
batch.enableBlending()
|
||||
batch.setBlendFunction(GL20.GL_DST_COLOR, GL20.GL_ONE_MINUS_SRC_ALPHA)
|
||||
}
|
||||
|
||||
fun blendScreen(batch: SpriteBatch? = null) {
|
||||
(batch ?: Terrarum.batch).enableBlending()
|
||||
(batch ?: Terrarum.batch).setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_COLOR)
|
||||
Gdx.gl.glBlendEquation(GL20.GL_FUNC_ADD) // batch.flush does not touch blend equation
|
||||
fun blendScreen(batch: SpriteBatch) {
|
||||
// will break if the colour image contains semitransparency
|
||||
batch.enableBlending()
|
||||
batch.setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_COLOR)
|
||||
}
|
||||
|
||||
fun blendDisable(batch: SpriteBatch? = null) {
|
||||
(batch ?: Terrarum.batch).disableBlending()
|
||||
fun blendDisable(batch: SpriteBatch) {
|
||||
batch.disableBlending()
|
||||
}
|
||||
|
||||
fun blendNormal(batch: SpriteBatch) {
|
||||
batch.enableBlending()
|
||||
batch.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_SRC_ALPHA, GL20.GL_ONE)
|
||||
|
||||
// ALPHA *MUST BE* PREMULTIPLIED //
|
||||
|
||||
// One way to tell:
|
||||
// 1. Check (RGB) and (A) values.
|
||||
// 2. If there exist a pixel such that max(R,G,B) > (A), then the image is NOT premultiplied.
|
||||
// Easy way:
|
||||
// Base game (mods/basegame/blocks/terrain.tga.gz) has impure window glass. When looking at the RGB channel only:
|
||||
// premultipied if the glass looks very dark.
|
||||
// not premultipied if the glass looks VERY GREEN.
|
||||
|
||||
// helpful links:
|
||||
// - https://gamedev.stackexchange.com/questions/82741/normal-blend-mode-with-opengl-trouble
|
||||
// - https://www.andersriggelsen.dk/glblendfunc.php
|
||||
}
|
||||
|
||||
fun gdxClearAndSetBlend(r: Float, g: Float, b: Float, a: Float) {
|
||||
Gdx.gl.glClearColor(r,g,b,a)
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
||||
gdxSetBlend()
|
||||
}
|
||||
|
||||
fun gdxSetBlend() {
|
||||
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D)
|
||||
Gdx.gl.glEnable(GL20.GL_BLEND)
|
||||
}
|
||||
|
||||
fun gdxSetBlendNormal() {
|
||||
gdxSetBlend()
|
||||
Gdx.gl.glBlendFuncSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_SRC_ALPHA, GL20.GL_ONE)
|
||||
//Gdx.gl.glBlendEquationSeparate(GL20.GL_FUNC_ADD, GL30.GL_MAX) // batch.flush does not touch blend equation
|
||||
|
||||
// ALPHA *MUST BE* PREMULTIPLIED //
|
||||
|
||||
// One way to tell:
|
||||
// 1. Check (RGB) and (A) values.
|
||||
// 2. If there exist a pixel such that max(R,G,B) > (A), then the image is NOT premultiplied.
|
||||
// Easy way:
|
||||
// Base game (mods/basegame/blocks/terrain.tga.gz) has impure window glass. When looking at the RGB channel only:
|
||||
// premultipied if the glass looks very dark.
|
||||
// not premultipied if the glass looks VERY GREEN.
|
||||
|
||||
// helpful links:
|
||||
// - https://gamedev.stackexchange.com/questions/82741/normal-blend-mode-with-opengl-trouble
|
||||
// - https://www.andersriggelsen.dk/glblendfunc.php
|
||||
}
|
||||
|
||||
object BlendMode {
|
||||
@@ -832,11 +615,11 @@ object BlendMode {
|
||||
const val NORMAL = "normal"
|
||||
//const val MAX = "GL_MAX" // not supported by GLES -- use shader
|
||||
|
||||
fun resolve(mode: String) {
|
||||
fun resolve(mode: String, batch: SpriteBatch) {
|
||||
when (mode) {
|
||||
SCREEN -> blendScreen()
|
||||
MULTIPLY -> blendMul()
|
||||
NORMAL -> blendNormal()
|
||||
SCREEN -> blendScreen(batch)
|
||||
MULTIPLY -> blendMul(batch)
|
||||
NORMAL -> blendNormal(batch)
|
||||
//MAX -> blendLightenOnly() // not supported by GLES -- use shader
|
||||
else -> throw Error("Unknown blend mode: $mode")
|
||||
}
|
||||
@@ -844,7 +627,7 @@ object BlendMode {
|
||||
}
|
||||
|
||||
enum class RunningEnvironment {
|
||||
PC, CONSOLE, MOBILE
|
||||
PC, CONSOLE//, MOBILE
|
||||
}
|
||||
|
||||
infix fun Color.screen(other: Color) = Color(
|
||||
@@ -890,23 +673,24 @@ val ccK = GameFontBase.toColorCode(0x888F)
|
||||
|
||||
typealias Second = Float
|
||||
|
||||
inline fun Int.sqr(): Int = this * this
|
||||
inline fun Double.floorInt() = Math.floor(this).toInt()
|
||||
inline fun Float.floorInt() = FastMath.floor(this)
|
||||
inline fun Float.floor() = FastMath.floor(this).toFloat()
|
||||
inline fun Double.ceilInt() = Math.ceil(this).toInt()
|
||||
inline fun Float.ceil(): Float = FastMath.ceil(this).toFloat()
|
||||
inline fun Float.ceilInt() = FastMath.ceil(this)
|
||||
inline fun Double.round() = Math.round(this).toDouble()
|
||||
inline fun Double.floor() = Math.floor(this)
|
||||
inline fun Double.ceil() = this.floor() + 1.0
|
||||
inline fun Double.roundInt(): Int = Math.round(this).toInt()
|
||||
inline fun Float.roundInt(): Int = Math.round(this)
|
||||
inline fun Double.abs() = Math.abs(this)
|
||||
inline fun Double.sqr() = this * this
|
||||
inline fun Double.sqrt() = Math.sqrt(this)
|
||||
inline fun Float.sqrt() = FastMath.sqrt(this)
|
||||
inline fun Int.abs() = if (this < 0) -this else this
|
||||
fun Int.sqr(): Int = this * this
|
||||
fun Double.floorInt() = Math.floor(this).toInt()
|
||||
fun Float.floorInt() = FastMath.floor(this)
|
||||
fun Float.floor() = FastMath.floor(this).toFloat()
|
||||
fun Double.ceilInt() = Math.ceil(this).toInt()
|
||||
fun Float.ceil(): Float = FastMath.ceil(this).toFloat()
|
||||
fun Float.ceilInt() = FastMath.ceil(this)
|
||||
fun Double.round() = Math.round(this).toDouble()
|
||||
fun Double.floor() = Math.floor(this)
|
||||
fun Double.ceil() = this.floor() + 1.0
|
||||
fun Double.roundInt(): Int = Math.round(this).toInt()
|
||||
fun Float.roundInt(): Int = Math.round(this)
|
||||
fun Double.abs() = Math.abs(this)
|
||||
fun Double.sqr() = this * this
|
||||
fun Float.sqr() = this * this
|
||||
fun Double.sqrt() = Math.sqrt(this)
|
||||
fun Float.sqrt() = FastMath.sqrt(this)
|
||||
fun Int.abs() = this.absoluteValue
|
||||
fun Double.bipolarClamp(limit: Double) =
|
||||
this.coerceIn(-limit, limit)
|
||||
|
||||
@@ -938,4 +722,19 @@ fun interpolateLinear(scale: Double, startValue: Double, endValue: Double): Doub
|
||||
return endValue
|
||||
}
|
||||
return (1.0 - scale) * startValue + scale * endValue
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> List<T>.linearSearch(selector: (T) -> Boolean): Int? {
|
||||
this.forEachIndexed { index, it ->
|
||||
if (selector.invoke(it)) return index
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
fun <T> List<T>.linearSearchBy(selector: (T) -> Boolean): T? {
|
||||
this.forEach {
|
||||
if (selector.invoke(it)) return it
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ package net.torvald.terrarum
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.InputAdapter
|
||||
import com.badlogic.gdx.Screen
|
||||
import com.badlogic.gdx.graphics.*
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||
@@ -18,14 +21,17 @@ import net.torvald.terrarum.gameworld.fmod
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.modulebasegame.Ingame
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.*
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.HumanoidNPC
|
||||
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
|
||||
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIRemoCon
|
||||
import net.torvald.terrarum.serialise.ReadLayerData
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
import net.torvald.terrarum.modulebasegame.ui.UITitleRemoConYaml
|
||||
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
|
||||
import net.torvald.terrarum.worlddrawer.*
|
||||
import net.torvald.terrarum.serialise.ReadLayerData
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
|
||||
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||
import java.io.FileInputStream
|
||||
|
||||
/**
|
||||
@@ -49,7 +55,7 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
|
||||
}
|
||||
|
||||
|
||||
private var loadDone = false
|
||||
//private var loadDone = false // not required; draw-while-loading is implemented in the AppLoader
|
||||
|
||||
private lateinit var demoWorld: GameWorldExtension
|
||||
private lateinit var cameraNodes: FloatArray // camera Y-pos
|
||||
@@ -124,18 +130,19 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
|
||||
|
||||
|
||||
demoWorld = ReadLayerData(FileInputStream(ModMgr.getFile("basegame", "demoworld")))
|
||||
|
||||
// set time to summer
|
||||
demoWorld.time.addTime(WorldTime.DAY_LENGTH * 32)
|
||||
|
||||
// construct camera nodes
|
||||
val nodeCount = 100
|
||||
cameraNodes = kotlin.FloatArray(nodeCount, { it ->
|
||||
cameraNodes = kotlin.FloatArray(nodeCount) { it ->
|
||||
val tileXPos = (demoWorld.width.toFloat() * it / nodeCount).floorInt()
|
||||
var travelDownCounter = 0
|
||||
while (!BlockCodex[demoWorld.getTileFromTerrain(tileXPos, travelDownCounter)].isSolid) {
|
||||
travelDownCounter += 4
|
||||
}
|
||||
travelDownCounter * FeaturesDrawer.TILE_SIZE.toFloat()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
cameraPlayer = object : HumanoidNPC(cameraAI, born = 0, usePhysics = false, forceAssignRefID = Terrarum.PLAYER_REF_ID) {
|
||||
@@ -164,7 +171,7 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
|
||||
|
||||
uiContainer.add(uiMenu)
|
||||
|
||||
loadDone = true
|
||||
//loadDone = true
|
||||
}
|
||||
|
||||
|
||||
@@ -172,7 +179,7 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
|
||||
}
|
||||
|
||||
override fun show() {
|
||||
printdbg(this, "atrniartsientsarinoetsar")
|
||||
printdbg(this, "show() called")
|
||||
|
||||
initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT)
|
||||
|
||||
@@ -184,40 +191,40 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
|
||||
|
||||
|
||||
worldFBO = FrameBuffer(Pixmap.Format.RGBA8888, Terrarum.WIDTH, Terrarum.HEIGHT, false)
|
||||
|
||||
loadThingsWhileIntroIsVisible()
|
||||
|
||||
printdbg(this, "show() exit")
|
||||
}
|
||||
|
||||
|
||||
private val introUncoverTime: Second = 0.3f
|
||||
private var introUncoverDeltaCounter = 0f
|
||||
private var updateDeltaCounter = 0.0
|
||||
protected val renderRate = Terrarum.renderRate
|
||||
private var updateAkku = 0.0
|
||||
|
||||
override fun render(delta: Float) {
|
||||
if (!loadDone) {
|
||||
loadThingsWhileIntroIsVisible()
|
||||
}
|
||||
else {
|
||||
// async update
|
||||
updateDeltaCounter += delta
|
||||
var updateTries = 0
|
||||
while (updateDeltaCounter >= renderRate) {
|
||||
updateScreen(delta)
|
||||
updateDeltaCounter -= renderRate
|
||||
updateTries++
|
||||
// async update and render
|
||||
|
||||
if (updateTries >= Terrarum.UPDATE_CATCHUP_MAX_TRIES) {
|
||||
break
|
||||
}
|
||||
}
|
||||
val dt = Gdx.graphics.deltaTime
|
||||
updateAkku += dt
|
||||
|
||||
// render? just do it anyway
|
||||
renderScreen()
|
||||
var i = 0L
|
||||
while (updateAkku >= delta) {
|
||||
AppLoader.measureDebugTime("Ingame.update") { updateScreen(delta) }
|
||||
updateAkku -= delta
|
||||
i += 1
|
||||
}
|
||||
AppLoader.setDebugTime("Ingame.updateCounter", i)
|
||||
|
||||
|
||||
// render? just do it anyway
|
||||
AppLoader.measureDebugTime("Ingame.render") { renderScreen() }
|
||||
AppLoader.setDebugTime("Ingame.render-Light",
|
||||
(AppLoader.debugTimers["Ingame.render"] as Long) - ((AppLoader.debugTimers["Renderer.LightTotal"] as? Long) ?: 0)
|
||||
)
|
||||
}
|
||||
|
||||
fun updateScreen(delta: Float) {
|
||||
//Gdx.graphics.setTitle(Ingame.getCanonicalTitle())
|
||||
|
||||
demoWorld.globalLight = WeatherMixer.globalLightNow
|
||||
demoWorld.updateWorldTime(delta)
|
||||
WeatherMixer.update(delta, cameraPlayer, demoWorld)
|
||||
@@ -236,12 +243,13 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
|
||||
}
|
||||
|
||||
fun renderScreen() {
|
||||
Gdx.graphics.setTitle(Ingame.getCanonicalTitle())
|
||||
|
||||
|
||||
//camera.setToOrtho(true, Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT.toFloat())
|
||||
|
||||
// render world
|
||||
Gdx.gl.glClearColor(.64f, .754f, .84f, 1f)
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
||||
gdxClearAndSetBlend(.64f, .754f, .84f, 1f)
|
||||
|
||||
|
||||
IngameRenderer.invoke(world = demoWorld, uisToDraw = uiContainer)
|
||||
@@ -257,7 +265,7 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
|
||||
|
||||
private fun renderOverlayTexts() {
|
||||
setCameraPosition(0f, 0f)
|
||||
blendNormal()
|
||||
blendNormal(batch)
|
||||
batch.shader = null
|
||||
|
||||
batch.color = Color.LIGHT_GRAY
|
||||
@@ -289,22 +297,24 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
|
||||
}
|
||||
|
||||
override fun resize(width: Int, height: Int) {
|
||||
printdbg(this, "resize() called")
|
||||
|
||||
// Set up viewport when window is resized
|
||||
initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT)
|
||||
|
||||
BlocksDrawer.resize(Terrarum.WIDTH, Terrarum.HEIGHT)
|
||||
LightmapRenderer.resize(Terrarum.WIDTH, Terrarum.HEIGHT)
|
||||
|
||||
if (loadDone) {
|
||||
// resize UI by re-creating it (!!)
|
||||
uiMenu.resize(Terrarum.WIDTH, Terrarum.HEIGHT)
|
||||
//uiMenu.setPosition(0, UITitleRemoConRoot.menubarOffY)
|
||||
uiMenu.setPosition(0, 0) // shitty hack. Could be:
|
||||
// 1: Init code and resize code are different
|
||||
// 2: The UI is coded shit
|
||||
}
|
||||
// resize UI by re-creating it (!!)
|
||||
uiMenu.resize(Terrarum.WIDTH, Terrarum.HEIGHT)
|
||||
// TODO I forgot what the fuck kind of hack I was talking about
|
||||
//uiMenu.setPosition(0, UITitleRemoConRoot.menubarOffY)
|
||||
uiMenu.setPosition(0, 0) // shitty hack. Could be:
|
||||
// 1: Init code and resize code are different
|
||||
// 2: The UI is coded shit
|
||||
|
||||
|
||||
IngameRenderer.resize(Terrarum.WIDTH, Terrarum.HEIGHT)
|
||||
|
||||
printdbg(this, "resize() exit")
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
|
||||
@@ -6,7 +6,9 @@ import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull
|
||||
import net.torvald.terrarum.ui.*
|
||||
import net.torvald.terrarum.ui.UIItem
|
||||
import net.torvald.terrarum.ui.UIItemImageButton
|
||||
import net.torvald.terrarum.ui.UIUtils
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2017-10-20.
|
||||
@@ -18,6 +20,12 @@ class UIItemInventoryCatBar(
|
||||
override val width: Int
|
||||
) : UIItem(parentUI) {
|
||||
|
||||
// deal with the moving position
|
||||
override var oldPosX = posX
|
||||
override var oldPosY = posY
|
||||
|
||||
private val parentInventory = parentUI
|
||||
|
||||
private val catIcons = parentUI.catIcons
|
||||
private val catArrangement = parentUI.catArrangement
|
||||
|
||||
@@ -91,15 +99,23 @@ class UIItemInventoryCatBar(
|
||||
private val underlineColour = Color(0xeaeaea_40.toInt())
|
||||
private val underlineHighlightColour = mainButtons[0].highlightCol
|
||||
|
||||
private var highlighterXPos = mainButtons[selectedIndex].posX.toDouble()
|
||||
private var highlighterXPos = mainButtons[selectedIndex].posX.toFloat()
|
||||
private var highlighterXStart = highlighterXPos
|
||||
private var highlighterXEnd = highlighterXPos
|
||||
|
||||
private val highlighterYPos = catIcons.tileH + 4f
|
||||
private var highlighterMoving = false
|
||||
private val highlighterMoveDuration: Second = 0.1f
|
||||
private val highlighterMoveDuration: Second = 0.15f
|
||||
private var highlighterMoveTimer: Second = 0f
|
||||
|
||||
private var transitionFired = false
|
||||
|
||||
/**
|
||||
* 0: map, 1: inventory caticons, 2: menu
|
||||
*/
|
||||
var selectedPanel = 1
|
||||
private set
|
||||
|
||||
// set up underlined indicator
|
||||
init {
|
||||
// procedurally generate texture
|
||||
@@ -134,8 +150,8 @@ class UIItemInventoryCatBar(
|
||||
highlighterXPos = UIUtils.moveQuick(
|
||||
highlighterXStart,
|
||||
highlighterXEnd,
|
||||
highlighterMoveTimer.toDouble(),
|
||||
highlighterMoveDuration.toDouble()
|
||||
highlighterMoveTimer,
|
||||
highlighterMoveDuration
|
||||
)
|
||||
|
||||
if (highlighterMoveTimer > highlighterMoveDuration) {
|
||||
@@ -150,23 +166,61 @@ class UIItemInventoryCatBar(
|
||||
mainButtons.forEachIndexed { index, btn ->
|
||||
btn.update(delta)
|
||||
|
||||
if (btn.mousePushed && selectedPanel != 1) {
|
||||
transitionFired = true
|
||||
selectedPanel = 1
|
||||
}
|
||||
|
||||
if (btn.mousePushed && index != selectedIndex) {
|
||||
// normal stuffs
|
||||
val oldIndex = selectedIndex
|
||||
|
||||
highlighterXStart = mainButtons[selectedIndex].posX.toDouble() // using old selectedIndex
|
||||
highlighterXStart = mainButtons[selectedIndex].posX.toFloat() // using old selectedIndex
|
||||
selectedIndex = index
|
||||
highlighterMoving = true
|
||||
highlighterXEnd = mainButtons[selectedIndex].posX.toDouble() // using new selectedIndex
|
||||
highlighterXEnd = mainButtons[selectedIndex].posX.toFloat() // using new selectedIndex
|
||||
|
||||
selectionChangeListener?.invoke(oldIndex, index)
|
||||
}
|
||||
btn.highlighted = (index == selectedIndex) // forcibly highlight if this.highlighted != null
|
||||
|
||||
if (selectedPanel == 1) {
|
||||
btn.highlighted = (index == selectedIndex) // forcibly highlight if this.highlighted != null
|
||||
|
||||
sideButtons[0].highlighted = false
|
||||
sideButtons[3].highlighted = false
|
||||
}
|
||||
}
|
||||
|
||||
sideButtons[0].update(delta)
|
||||
sideButtons[3].update(delta)
|
||||
|
||||
|
||||
// more transition stuffs
|
||||
if (sideButtons[0].mousePushed) {
|
||||
if (selectedPanel != 0) transitionFired = true
|
||||
mainButtons.forEach { it.highlighted = false }
|
||||
selectedPanel = 0
|
||||
parentInventory.requestTransition(0)
|
||||
|
||||
sideButtons[0].highlighted = true
|
||||
sideButtons[3].highlighted = false
|
||||
}
|
||||
else if (sideButtons[3].mousePushed) {
|
||||
if (selectedPanel != 2) transitionFired = true
|
||||
mainButtons.forEach { it.highlighted = false }
|
||||
selectedPanel = 2
|
||||
parentInventory.requestTransition(2)
|
||||
transitionFired = true
|
||||
|
||||
sideButtons[0].highlighted = false
|
||||
sideButtons[3].highlighted = true
|
||||
}
|
||||
|
||||
|
||||
if (transitionFired) {
|
||||
transitionFired = false
|
||||
parentInventory.requestTransition(2 - selectedPanel)
|
||||
}
|
||||
}
|
||||
|
||||
override fun render(batch: SpriteBatch, camera: Camera) {
|
||||
@@ -186,8 +240,12 @@ class UIItemInventoryCatBar(
|
||||
batch.drawStraightLine(posX.toFloat(), posY + height - 1f, posX + width.toFloat(), 1f, false)
|
||||
|
||||
// indicator
|
||||
batch.color = underlineHighlightColour
|
||||
batch.draw(underlineIndTex, (highlighterXPos - buttonGapSize / 2).toFloat().round(), posY + highlighterYPos)
|
||||
if (selectedPanel == 1) {
|
||||
batch.color = underlineHighlightColour
|
||||
batch.draw(underlineIndTex, (highlighterXPos - buttonGapSize / 2).toFloat().round(), posY + highlighterYPos)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import net.torvald.terrarum.itemproperties.GameItem
|
||||
import net.torvald.terrarum.modulebasegame.Ingame
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellBase
|
||||
import net.torvald.terrarum.ui.*
|
||||
import net.torvald.terrarum.ui.UIItemTextButton
|
||||
|
||||
/***
|
||||
* Note that the UI will not render if either item or itemImage is null.
|
||||
@@ -36,6 +36,10 @@ class UIItemInventoryElem(
|
||||
val drawBackOnNull: Boolean = true
|
||||
) : UIItemInventoryCellBase(parentUI, posX, posY, item, amount, itemImage, quickslot, equippedSlot) {
|
||||
|
||||
// deal with the moving position
|
||||
override var oldPosX = posX
|
||||
override var oldPosY = posY
|
||||
|
||||
companion object {
|
||||
val height = 48
|
||||
val UNIQUE_ITEM_HAS_NO_AMOUNT = -1
|
||||
@@ -74,12 +78,12 @@ class UIItemInventoryElem(
|
||||
if (item != null || drawBackOnNull) {
|
||||
// do not highlight even if drawBackOnNull is true
|
||||
if (mouseUp && item != null) {
|
||||
BlendMode.resolve(mouseoverBackBlendMode)
|
||||
BlendMode.resolve(mouseoverBackBlendMode, batch)
|
||||
batch.color = mouseoverBackCol
|
||||
}
|
||||
// if drawBackOnNull, just draw background
|
||||
else {
|
||||
BlendMode.resolve(backBlendMode)
|
||||
BlendMode.resolve(backBlendMode, batch)
|
||||
batch.color = backCol
|
||||
}
|
||||
batch.fillRect(posX.toFloat(), posY.toFloat(), width.toFloat(), height.toFloat())
|
||||
@@ -87,7 +91,7 @@ class UIItemInventoryElem(
|
||||
|
||||
|
||||
if (item != null && itemImage != null) {
|
||||
blendNormal()
|
||||
blendNormal(batch)
|
||||
|
||||
// item image
|
||||
batch.color = Color.WHITE
|
||||
@@ -136,14 +140,14 @@ class UIItemInventoryElem(
|
||||
}
|
||||
|
||||
override fun keyDown(keycode: Int): Boolean {
|
||||
if (item != null && Terrarum.ingame != null && keycode in Input.Keys.NUM_1..Input.Keys.NUM_0) {
|
||||
if (item != null && Terrarum.ingame != null && keycode in Input.Keys.NUM_0..Input.Keys.NUM_9) {
|
||||
val player = (Terrarum.ingame!! as Ingame).actorNowPlaying
|
||||
|
||||
if (player == null) return false
|
||||
|
||||
val inventory = player.inventory
|
||||
val slot = if (keycode == Input.Keys.NUM_0) 9 else keycode - Input.Keys.NUM_1
|
||||
val currentSlotItem = inventory?.getQuickBar(slot)
|
||||
val currentSlotItem = inventory?.getQuickslot(slot)
|
||||
|
||||
|
||||
inventory.setQuickBar(
|
||||
@@ -157,13 +161,13 @@ class UIItemInventoryElem(
|
||||
// search for duplicates in the quickbar, except mine
|
||||
// if there is, unregister the other
|
||||
(0..9).minus(slot).forEach {
|
||||
if (inventory.getQuickBar(it)?.item == item) {
|
||||
if (inventory.getQuickslot(it)?.item == item) {
|
||||
inventory.setQuickBar(it, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
return super.keyDown(keycode)
|
||||
}
|
||||
|
||||
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
||||
@@ -171,6 +175,10 @@ class UIItemInventoryElem(
|
||||
|
||||
// equip da shit
|
||||
val itemEquipSlot = item!!.equipPosition
|
||||
if (itemEquipSlot == GameItem.EquipPosition.NULL) {
|
||||
TODO("Equip position is NULL, does this mean it's single-consume items like a potion?")
|
||||
}
|
||||
|
||||
val player = (Terrarum.ingame!! as Ingame).actorNowPlaying
|
||||
|
||||
if (player == null) return false
|
||||
@@ -185,12 +193,11 @@ class UIItemInventoryElem(
|
||||
|
||||
inventoryUI.rebuildList()
|
||||
|
||||
return true
|
||||
return super.touchDown(screenX, screenY, pointer, button)
|
||||
}
|
||||
|
||||
|
||||
override fun dispose() {
|
||||
itemImage?.texture?.dispose()
|
||||
}
|
||||
|
||||
override fun keyUp(keycode: Int): Boolean {
|
||||
|
||||
@@ -9,7 +9,7 @@ import net.torvald.terrarum.itemproperties.GameItem
|
||||
import net.torvald.terrarum.modulebasegame.Ingame
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellBase
|
||||
import net.torvald.terrarum.ui.*
|
||||
import net.torvald.terrarum.ui.UIItemTextButton
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2017-10-20.
|
||||
@@ -33,6 +33,10 @@ class UIItemInventoryElemSimple(
|
||||
val drawBackOnNull: Boolean = true
|
||||
) : UIItemInventoryCellBase(parentUI, posX, posY, item, amount, itemImage, quickslot, equippedSlot) {
|
||||
|
||||
// deal with the moving position
|
||||
override var oldPosX = posX
|
||||
override var oldPosY = posY
|
||||
|
||||
companion object {
|
||||
val height = UIItemInventoryElem.height
|
||||
}
|
||||
@@ -56,12 +60,12 @@ class UIItemInventoryElemSimple(
|
||||
if (item != null || drawBackOnNull) {
|
||||
// do not highlight even if drawBackOnNull is true
|
||||
if (mouseUp && item != null || equippedSlot != null) { // "equippedSlot != null": also highlight back if equipped
|
||||
BlendMode.resolve(mouseoverBackBlendMode)
|
||||
BlendMode.resolve(mouseoverBackBlendMode, batch)
|
||||
batch.color = mouseoverBackCol
|
||||
}
|
||||
// if drawBackOnNull, just draw background
|
||||
else {
|
||||
BlendMode.resolve(backBlendMode)
|
||||
BlendMode.resolve(backBlendMode, batch)
|
||||
batch.color = backCol
|
||||
}
|
||||
batch.fillRect(posX.toFloat(), posY.toFloat(), width.toFloat(), height.toFloat())
|
||||
@@ -72,7 +76,7 @@ class UIItemInventoryElemSimple(
|
||||
// and you can clearly see the quickslot UI anyway
|
||||
|
||||
if (item != null && itemImage != null) {
|
||||
blendNormal()
|
||||
blendNormal(batch)
|
||||
|
||||
// item image
|
||||
batch.color = Color.WHITE
|
||||
@@ -96,8 +100,8 @@ class UIItemInventoryElemSimple(
|
||||
batch.drawStraightLine(barOffset, posY + height - thickness, barOffset + barFullLen * (item!!.durability / item!!.maxDurability), thickness, false)
|
||||
}
|
||||
}
|
||||
else {
|
||||
// draw item count
|
||||
// draw item count when applicable
|
||||
else if (item!!.stackable) {
|
||||
val amountString = amount.toString()
|
||||
|
||||
// highlight item count (blocks/walls) if the item is equipped
|
||||
@@ -121,15 +125,14 @@ class UIItemInventoryElemSimple(
|
||||
}
|
||||
|
||||
override fun keyDown(keycode: Int): Boolean {
|
||||
if (item != null && Terrarum.ingame != null && keycode in Input.Keys.NUM_1..Input.Keys.NUM_0) {
|
||||
println("keydown elemgrid")
|
||||
if (item != null && Terrarum.ingame != null && keycode in Input.Keys.NUM_0..Input.Keys.NUM_9) {
|
||||
|
||||
val player = (Terrarum.ingame!! as Ingame).actorNowPlaying
|
||||
if (player == null) return false
|
||||
|
||||
val inventory = player.inventory
|
||||
val slot = if (keycode == Input.Keys.NUM_0) 9 else keycode - Input.Keys.NUM_1
|
||||
val currentSlotItem = inventory.getQuickBar(slot)
|
||||
val currentSlotItem = inventory.getQuickslot(slot)
|
||||
|
||||
|
||||
inventory.setQuickBar(
|
||||
@@ -143,13 +146,13 @@ class UIItemInventoryElemSimple(
|
||||
// search for duplicates in the quickbar, except mine
|
||||
// if there is, unregister the other
|
||||
(0..9).minus(slot).forEach {
|
||||
if (inventory.getQuickBar(it)?.item == item) {
|
||||
if (inventory.getQuickslot(it)?.item == item) {
|
||||
inventory.setQuickBar(it, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
return super.keyDown(keycode)
|
||||
}
|
||||
|
||||
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
||||
@@ -172,12 +175,11 @@ class UIItemInventoryElemSimple(
|
||||
|
||||
inventoryUI.rebuildList()
|
||||
|
||||
return true
|
||||
return super.touchDown(screenX, screenY, pointer, button)
|
||||
}
|
||||
|
||||
|
||||
override fun dispose() {
|
||||
itemImage?.texture?.dispose()
|
||||
}
|
||||
|
||||
override fun keyUp(keycode: Int): Boolean {
|
||||
|
||||
200
src/net/torvald/terrarum/Yaml.kt
Normal file
200
src/net/torvald/terrarum/Yaml.kt
Normal file
@@ -0,0 +1,200 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Simplified version of YAML, only for the representation of a text tree.
|
||||
*
|
||||
* Example code:
|
||||
* ```
|
||||
* - File
|
||||
* - New : Ctrl-N
|
||||
* - Open : Ctrl-O
|
||||
* - Open Recent
|
||||
* - yaml_example.yaml
|
||||
* - Yaml.kt
|
||||
* - Close : Ctrl-W
|
||||
* - Settings
|
||||
* - Line Separators
|
||||
* - CRLF
|
||||
* - CR
|
||||
* - LF
|
||||
* - Edit
|
||||
* - Undo : Ctrl-Z
|
||||
* - Redo : Shift-Ctrl-Z
|
||||
* - Cut : Ctrl-X
|
||||
* - Copy : Ctrl-C
|
||||
* - Paste : Ctrl-V
|
||||
* - Find
|
||||
* - Find : Ctrl-F
|
||||
* - Replace : Shift-Ctrl-F
|
||||
* - Convert Indents
|
||||
* - To Spaces
|
||||
* - Set Project Indentation
|
||||
* - To Tabs
|
||||
* - Refactor
|
||||
* - Refactor This
|
||||
* - Rename : Shift-Ctrl-R
|
||||
* - Extract
|
||||
* - Variable
|
||||
* - Property
|
||||
* - Function
|
||||
* ```
|
||||
*
|
||||
* - All lines are indented with one space
|
||||
* - All entries are preceded by '- ' (dash and a space)
|
||||
* - All propery are separated by ' : ' (space colon space)
|
||||
* - A line that does not start with '- ' are simply ignored, so you can freely make empty lines and/or comments.
|
||||
*
|
||||
* Any deviation to the above rule will cause a parse failure, because it's simple and dumb as that.
|
||||
*
|
||||
* Created by minjaesong on 2018-12-08.
|
||||
*/
|
||||
inline class Yaml(val text: String) {
|
||||
|
||||
companion object {
|
||||
val SEPARATOR = Regex(" : ")
|
||||
}
|
||||
|
||||
fun parse(): QNDTreeNode<String> {
|
||||
var currentIndentLevel = -1
|
||||
val root = QNDTreeNode<String>()
|
||||
var currentNode = root
|
||||
val nodesStack = Stack<QNDTreeNode<String>>()
|
||||
val validLineStartRe = Regex(""" *\- """)
|
||||
|
||||
nodesStack.push(currentNode)
|
||||
|
||||
text.split('\n') .forEach {
|
||||
if (validLineStartRe.containsMatchIn(it)) { // take partial match; do the task if the text's line is valid
|
||||
val indentLevel = it.countSpaces()
|
||||
val it = it.trimIndent()
|
||||
if (it.startsWith("- ")) { // just double check if indent-trimmed line looks valid
|
||||
val nodeName = it.drop(2)
|
||||
|
||||
if (indentLevel == currentIndentLevel) {
|
||||
val sibling = QNDTreeNode(nodeName, currentNode.parent)
|
||||
currentNode.parent!!.children.add(sibling)
|
||||
currentNode = sibling
|
||||
}
|
||||
else if (indentLevel > currentIndentLevel) {
|
||||
val childNode = QNDTreeNode(nodeName, currentNode)
|
||||
currentNode.children.add(childNode)
|
||||
nodesStack.push(currentNode)
|
||||
currentNode = childNode
|
||||
currentIndentLevel = indentLevel
|
||||
}
|
||||
else {
|
||||
repeat(currentIndentLevel - indentLevel) { currentNode = nodesStack.pop() }
|
||||
currentIndentLevel = indentLevel
|
||||
val sibling = QNDTreeNode(nodeName, currentNode.parent)
|
||||
currentNode.parent!!.children.add(sibling)
|
||||
currentNode = sibling
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// test traverse resulting tree
|
||||
/*root.traversePreorder { node, depth ->
|
||||
repeat(depth + 1) { print("-") }
|
||||
println("${node.data} -> ${node.parent}")
|
||||
}*/
|
||||
|
||||
|
||||
return root
|
||||
}
|
||||
|
||||
fun parseAsYamlInvokable(): QNDTreeNode<Pair<String, YamlInvokable?>> {
|
||||
var currentIndentLevel = -1
|
||||
val root = QNDTreeNode<Pair<String, YamlInvokable?>>()
|
||||
var currentNode = root
|
||||
val nodesStack = Stack<QNDTreeNode<Pair<String, YamlInvokable?>>>()
|
||||
val validLineStartRe = Regex(""" *\- """)
|
||||
|
||||
nodesStack.push(currentNode)
|
||||
|
||||
text.split('\n') .forEach {
|
||||
if (validLineStartRe.containsMatchIn(it)) { // take partial match; do the task if the text's line is valid
|
||||
val indentLevel = it.countSpaces()
|
||||
val it = it.trimIndent()
|
||||
if (it.startsWith("- ")) { // just double check if indent-trimmed line looks valid
|
||||
val nodeString = it.drop(2)
|
||||
val nodeNameAndInvocation = nodeString.split(SEPARATOR)
|
||||
val nodeName = nodeNameAndInvocation[0]
|
||||
val nodeInvocation = if (nodeNameAndInvocation.size == 2)
|
||||
loadClass(nodeNameAndInvocation[1])
|
||||
else
|
||||
null
|
||||
|
||||
val nameInvokePair = nodeName to nodeInvocation
|
||||
|
||||
if (indentLevel == currentIndentLevel) {
|
||||
val sibling = QNDTreeNode(nameInvokePair, currentNode.parent)
|
||||
currentNode.parent!!.children.add(sibling)
|
||||
currentNode = sibling
|
||||
}
|
||||
else if (indentLevel > currentIndentLevel) {
|
||||
val childNode = QNDTreeNode(nameInvokePair, currentNode)
|
||||
currentNode.children.add(childNode)
|
||||
nodesStack.push(currentNode)
|
||||
currentNode = childNode
|
||||
currentIndentLevel = indentLevel
|
||||
}
|
||||
else {
|
||||
repeat(currentIndentLevel - indentLevel) { currentNode = nodesStack.pop() }
|
||||
currentIndentLevel = indentLevel
|
||||
val sibling = QNDTreeNode(nameInvokePair, currentNode.parent)
|
||||
currentNode.parent!!.children.add(sibling)
|
||||
currentNode = sibling
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// test traverse resulting tree
|
||||
/*root.traversePreorder { node, depth ->
|
||||
repeat(depth + 1) { print("-") }
|
||||
println("${node.data} -> ${node.parent}")
|
||||
}*/
|
||||
|
||||
|
||||
return root
|
||||
}
|
||||
|
||||
private fun String.countSpaces(): Int {
|
||||
var c = 0
|
||||
while (c <= this.length) {
|
||||
if (this[c] == ' ')
|
||||
c++
|
||||
else
|
||||
break
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
private fun loadClass(name: String): YamlInvokable {
|
||||
val newClass = Class.forName(name)
|
||||
val newClassConstructor = newClass.getConstructor(/* no args defined */)
|
||||
val newClassInstance = newClassConstructor.newInstance(/* no args defined */)
|
||||
return newClassInstance as YamlInvokable
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple interface that meant to be attached with Yaml tree, so that the entry can be ```invoke()```d.
|
||||
*
|
||||
* Example usage in Yaml:
|
||||
* ```
|
||||
* - File
|
||||
* - Import : net.torvald.terrarum.whatever.package.ImportFile
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
interface YamlInvokable {
|
||||
operator fun invoke(args: Array<Any>)
|
||||
}
|
||||
@@ -5,149 +5,126 @@ package net.torvald.terrarum.blockproperties
|
||||
*/
|
||||
object Block {
|
||||
|
||||
val AIR = 0 // hard coded; this is the standard
|
||||
const val AIR = 0 // hard coded; this is the standard
|
||||
|
||||
val STONE = 16
|
||||
val STONE_QUARRIED = 17
|
||||
val STONE_TILE_WHITE = 18
|
||||
val STONE_BRICKS = 19
|
||||
const val STONE = 16
|
||||
const val STONE_QUARRIED = 17
|
||||
const val STONE_TILE_WHITE = 18
|
||||
const val STONE_BRICKS = 19
|
||||
|
||||
val DIRT = 32
|
||||
val GRASS = 33
|
||||
val GRASSWALL = 34
|
||||
const val DIRT = 32
|
||||
const val GRASS = 33
|
||||
const val GRASSWALL = 34
|
||||
|
||||
val PLANK_NORMAL = 48
|
||||
val PLANK_EBONY = 49
|
||||
val PLANK_BIRCH = 50
|
||||
val PLANK_BLOODROSE = 51
|
||||
const val PLANK_NORMAL = 48
|
||||
const val PLANK_EBONY = 49
|
||||
const val PLANK_BIRCH = 50
|
||||
const val PLANK_BLOODROSE = 51
|
||||
|
||||
val TRUNK_NORMAL = 64
|
||||
val TRUNK_EBONY = 65
|
||||
val TRUNK_BIRCH = 66
|
||||
val TRUNK_BLOODROSE = 67
|
||||
const val TRUNK_NORMAL = 64
|
||||
const val TRUNK_EBONY = 65
|
||||
const val TRUNK_BIRCH = 66
|
||||
const val TRUNK_BLOODROSE = 67
|
||||
|
||||
val SAND = 80
|
||||
val SAND_WHITE = 81
|
||||
val SAND_RED = 82
|
||||
val SAND_DESERT = 83
|
||||
val SAND_BLACK = 84
|
||||
val SAND_GREEN = 85
|
||||
const val SAND = 80
|
||||
const val SAND_WHITE = 81
|
||||
const val SAND_RED = 82
|
||||
const val SAND_DESERT = 83
|
||||
const val SAND_BLACK = 84
|
||||
const val SAND_GREEN = 85
|
||||
|
||||
val GRAVEL = 96
|
||||
val GRAVEL_GREY = 97
|
||||
const val GRAVEL = 96
|
||||
const val GRAVEL_GREY = 97
|
||||
|
||||
val ORE_COPPER = 112
|
||||
val ORE_IRON = 113
|
||||
val ORE_GOLD = 114
|
||||
val ORE_SILVER = 115
|
||||
val ORE_ILMENITE = 116
|
||||
val ORE_AURICHALCUM = 117
|
||||
const val ORE_COPPER = 112
|
||||
const val ORE_IRON = 113
|
||||
const val ORE_GOLD = 114
|
||||
const val ORE_SILVER = 115
|
||||
const val ORE_ILMENITE = 116
|
||||
const val ORE_AURICHALCUM = 117
|
||||
|
||||
val RAW_RUBY = 128
|
||||
val RAW_EMERALD = 129
|
||||
val RAW_SAPPHIRE = 130
|
||||
val RAW_TOPAZ = 131
|
||||
val RAW_DIAMOND = 132
|
||||
val RAW_AMETHYST = 133
|
||||
const val RAW_RUBY = 128
|
||||
const val RAW_EMERALD = 129
|
||||
const val RAW_SAPPHIRE = 130
|
||||
const val RAW_TOPAZ = 131
|
||||
const val RAW_DIAMOND = 132
|
||||
const val RAW_AMETHYST = 133
|
||||
|
||||
val SNOW = 144
|
||||
val ICE_FRAGILE = 145
|
||||
val ICE_NATURAL = 146
|
||||
val ICE_MAGICAL = 147
|
||||
const val SNOW = 144
|
||||
const val ICE_FRAGILE = 145
|
||||
const val ICE_NATURAL = 146
|
||||
const val ICE_MAGICAL = 147
|
||||
|
||||
val GLASS_CRUDE = 148
|
||||
val GLASS_CLEAN = 149
|
||||
const val GLASS_CRUDE = 148
|
||||
const val GLASS_CLEAN = 149
|
||||
|
||||
val PLATFORM_STONE = 160
|
||||
val PLATFORM_WOODEN = 161
|
||||
val PLATFORM_EBONY = 162
|
||||
val PLATFORM_BIRCH = 163
|
||||
val PLATFORM_BLOODROSE = 164
|
||||
const val PLATFORM_STONE = 160
|
||||
const val PLATFORM_WOODEN = 161
|
||||
const val PLATFORM_EBONY = 162
|
||||
const val PLATFORM_BIRCH = 163
|
||||
const val PLATFORM_BLOODROSE = 164
|
||||
|
||||
val TORCH = 176
|
||||
val TORCH_FROST = 177
|
||||
const val TORCH = 176
|
||||
const val TORCH_FROST = 177
|
||||
|
||||
val TORCH_OFF = 192
|
||||
val TORCH_FROST_OFF = 193
|
||||
const val TORCH_OFF = 192
|
||||
const val TORCH_FROST_OFF = 193
|
||||
|
||||
val ILLUMINATOR_WHITE = 208
|
||||
val ILLUMINATOR_YELLOW = 209
|
||||
val ILLUMINATOR_ORANGE = 210
|
||||
val ILLUMINATOR_RED = 211
|
||||
val ILLUMINATOR_FUCHSIA = 212
|
||||
val ILLUMINATOR_PURPLE = 213
|
||||
val ILLUMINATOR_BLUE = 214
|
||||
val ILLUMINATOR_CYAN = 215
|
||||
val ILLUMINATOR_GREEN = 216
|
||||
val ILLUMINATOR_GREEN_DARK = 217
|
||||
val ILLUMINATOR_BROWN = 218
|
||||
val ILLUMINATOR_TAN = 219
|
||||
val ILLUMINATOR_GREY_LIGHT = 220
|
||||
val ILLUMINATOR_GREY_MED = 221
|
||||
val ILLUMINATOR_GREY_DARK = 222
|
||||
val ILLUMINATOR_BLACK = 223
|
||||
const val ILLUMINATOR_WHITE = 208
|
||||
const val ILLUMINATOR_YELLOW = 209
|
||||
const val ILLUMINATOR_ORANGE = 210
|
||||
const val ILLUMINATOR_RED = 211
|
||||
const val ILLUMINATOR_FUCHSIA = 212
|
||||
const val ILLUMINATOR_PURPLE = 213
|
||||
const val ILLUMINATOR_BLUE = 214
|
||||
const val ILLUMINATOR_CYAN = 215
|
||||
const val ILLUMINATOR_GREEN = 216
|
||||
const val ILLUMINATOR_GREEN_DARK = 217
|
||||
const val ILLUMINATOR_BROWN = 218
|
||||
const val ILLUMINATOR_TAN = 219
|
||||
const val ILLUMINATOR_GREY_LIGHT = 220
|
||||
const val ILLUMINATOR_GREY_MED = 221
|
||||
const val ILLUMINATOR_GREY_DARK = 222
|
||||
const val ILLUMINATOR_BLACK = 223
|
||||
|
||||
val ILLUMINATOR_WHITE_OFF = 224
|
||||
val ILLUMINATOR_YELLOW_OFF = 225
|
||||
val ILLUMINATOR_ORANGE_OFF = 226
|
||||
val ILLUMINATOR_RED_OFF = 227
|
||||
val ILLUMINATOR_FUCHSIA_OFF = 228
|
||||
val ILLUMINATOR_PURPLE_OFF = 229
|
||||
val ILLUMINATOR_BLUE_OFF = 230
|
||||
val ILLUMINATOR_CYAN_OFF = 231
|
||||
val ILLUMINATOR_GREEN_OFF = 232
|
||||
val ILLUMINATOR_GREEN_DARK_OFF = 233
|
||||
val ILLUMINATOR_BROWN_OFF = 234
|
||||
val ILLUMINATOR_TAN_OFF = 235
|
||||
val ILLUMINATOR_GREY_LIGHT_OFF = 236
|
||||
val ILLUMINATOR_GREY_MED_OFF = 237
|
||||
val ILLUMINATOR_GREY_DARK_OFF = 238
|
||||
val ILLUMINATOR_BLACK_OFF = 239
|
||||
const val ILLUMINATOR_WHITE_OFF = 224
|
||||
const val ILLUMINATOR_YELLOW_OFF = 225
|
||||
const val ILLUMINATOR_ORANGE_OFF = 226
|
||||
const val ILLUMINATOR_RED_OFF = 227
|
||||
const val ILLUMINATOR_FUCHSIA_OFF = 228
|
||||
const val ILLUMINATOR_PURPLE_OFF = 229
|
||||
const val ILLUMINATOR_BLUE_OFF = 230
|
||||
const val ILLUMINATOR_CYAN_OFF = 231
|
||||
const val ILLUMINATOR_GREEN_OFF = 232
|
||||
const val ILLUMINATOR_GREEN_DARK_OFF = 233
|
||||
const val ILLUMINATOR_BROWN_OFF = 234
|
||||
const val ILLUMINATOR_TAN_OFF = 235
|
||||
const val ILLUMINATOR_GREY_LIGHT_OFF = 236
|
||||
const val ILLUMINATOR_GREY_MED_OFF = 237
|
||||
const val ILLUMINATOR_GREY_DARK_OFF = 238
|
||||
const val ILLUMINATOR_BLACK_OFF = 239
|
||||
|
||||
val SANDSTONE = 240
|
||||
val SANDSTONE_WHITE = 241
|
||||
val SANDSTONE_RED = 242
|
||||
val SANDSTONE_DESERT = 243
|
||||
val SANDSTONE_BLACK = 244
|
||||
val SANDSTONE_GREEN = 245
|
||||
const val SANDSTONE = 240
|
||||
const val SANDSTONE_WHITE = 241
|
||||
const val SANDSTONE_RED = 242
|
||||
const val SANDSTONE_DESERT = 243
|
||||
const val SANDSTONE_BLACK = 244
|
||||
const val SANDSTONE_GREEN = 245
|
||||
|
||||
val LANTERN = 256
|
||||
val SUNSTONE = 257
|
||||
val DAYLIGHT_CAPACITOR = 258
|
||||
const val LANTERN = 256
|
||||
const val SUNSTONE = 257
|
||||
const val DAYLIGHT_CAPACITOR = 258
|
||||
|
||||
val WATER_1 = 4080
|
||||
val WATER_2 = 4081
|
||||
val WATER_3 = 4082
|
||||
val WATER_4 = 4083
|
||||
val WATER_5 = 4084
|
||||
val WATER_6 = 4085
|
||||
val WATER_7 = 4086
|
||||
val WATER_8 = 4087
|
||||
val WATER_9 = 4088
|
||||
val WATER_10 = 4089
|
||||
val WATER_11 = 4090
|
||||
val WATER_12 = 4091
|
||||
val WATER_13 = 4092
|
||||
val WATER_14 = 4093
|
||||
val WATER_15 = 4094
|
||||
val WATER = 4095
|
||||
|
||||
val LAVA_1 = 4064
|
||||
val LAVA_2 = 4065
|
||||
val LAVA_3 = 4066
|
||||
val LAVA_4 = 4067
|
||||
val LAVA_5 = 4068
|
||||
val LAVA_6 = 4069
|
||||
val LAVA_7 = 4070
|
||||
val LAVA_8 = 4071
|
||||
val LAVA_9 = 4072
|
||||
val LAVA_10 = 4073
|
||||
val LAVA_11 = 4074
|
||||
val LAVA_12 = 4075
|
||||
val LAVA_13 = 4076
|
||||
val LAVA_14 = 4077
|
||||
val LAVA_15 = 4078
|
||||
val LAVA = 4079
|
||||
const val ACTORBLOCK_NO_COLLISION = 4191
|
||||
const val ACTORBLOCK_FULL_COLLISION = 4092
|
||||
const val ACTORBLOCK_ALLOW_MOVE_DOWN = 4093
|
||||
const val ACTORBLOCK_NO_PASS_RIGHT = 4094
|
||||
const val ACTORBLOCK_NO_PASS_LEFT = 4095
|
||||
|
||||
val NULL = -1
|
||||
|
||||
const val LAVA = 4094
|
||||
const val WATER = 4095
|
||||
|
||||
const val NULL = -1
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package net.torvald.terrarum.blockproperties
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.utils.CSVFetcher
|
||||
import net.torvald.terrarum.gameworld.FluidType
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.MapLayer
|
||||
import net.torvald.terrarum.gameworld.PairedMapLayer
|
||||
import net.torvald.terrarum.utils.CSVFetcher
|
||||
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
||||
import org.apache.commons.csv.CSVRecord
|
||||
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
@@ -73,6 +75,19 @@ object BlockCodex {
|
||||
}
|
||||
}
|
||||
|
||||
operator fun get(fluidType: FluidType?): BlockProp {
|
||||
if (fluidType == null || fluidType.value == 0) {
|
||||
return blockProps[Block.AIR]
|
||||
}
|
||||
|
||||
try {
|
||||
return blockProps[fluidType.abs() + GameWorld.TILES_SUPPORTED - 1]
|
||||
}
|
||||
catch (e: NullPointerException) {
|
||||
throw NullPointerException("Blockprop with raw id $fluidType does not exist.")
|
||||
}
|
||||
}
|
||||
|
||||
fun getOrNull(rawIndex: Int?): BlockProp? {
|
||||
if (rawIndex == null || rawIndex == Block.NULL) {
|
||||
return null
|
||||
@@ -96,21 +111,24 @@ object BlockCodex {
|
||||
prop.shadeColG = floatVal(record, "shdg") / LightmapRenderer.MUL_FLOAT
|
||||
prop.shadeColB = floatVal(record, "shdb") / LightmapRenderer.MUL_FLOAT
|
||||
prop.shadeColA = floatVal(record, "shduv") / LightmapRenderer.MUL_FLOAT
|
||||
prop.shadeColor = Color(prop.shadeColR, prop.shadeColG, prop.shadeColB, prop.shadeColA)
|
||||
|
||||
prop.strength = intVal(record, "strength")
|
||||
prop.strength = intVal(record, "str")
|
||||
prop.density = intVal(record, "dsty")
|
||||
|
||||
prop.lumColR = floatVal(record, "lumr") / LightmapRenderer.MUL_FLOAT
|
||||
prop.lumColG = floatVal(record, "lumg") / LightmapRenderer.MUL_FLOAT
|
||||
prop.lumColB = floatVal(record, "lumb") / LightmapRenderer.MUL_FLOAT
|
||||
prop.lumColA = floatVal(record, "lumuv") / LightmapRenderer.MUL_FLOAT
|
||||
prop.internalLumCol = Color(prop.lumColR, prop.lumColG, prop.lumColB, prop.lumColA)
|
||||
|
||||
prop.friction = intVal(record, "friction")
|
||||
prop.friction = intVal(record, "fr")
|
||||
prop.viscosity = intVal(record, "vscs")
|
||||
|
||||
prop.isFluid = boolVal(record, "fluid")
|
||||
//prop.isFluid = boolVal(record, "fluid")
|
||||
prop.isSolid = boolVal(record, "solid")
|
||||
prop.isClear = boolVal(record, "clear")
|
||||
//prop.isClear = boolVal(record, "clear")
|
||||
prop.isPlatform = boolVal(record, "plat")
|
||||
prop.isWallable = boolVal(record, "wall")
|
||||
prop.isFallable = boolVal(record, "fall")
|
||||
prop.isVertFriction = boolVal(record, "fv")
|
||||
|
||||
@@ -16,6 +16,7 @@ class BlockProp {
|
||||
var shadeColG = 0f
|
||||
var shadeColB = 0f
|
||||
var shadeColA = 0f
|
||||
lateinit var shadeColor: Color
|
||||
|
||||
/**
|
||||
* @param opacity Raw RGB value, without alpha
|
||||
@@ -27,9 +28,9 @@ class BlockProp {
|
||||
var density: Int = 0
|
||||
var viscosity: Int = 0
|
||||
|
||||
var isFluid: Boolean = false
|
||||
var isSolid: Boolean = false
|
||||
var isClear: Boolean = false
|
||||
//var isClear: Boolean = false
|
||||
var isPlatform: Boolean = false
|
||||
var isWallable: Boolean = false
|
||||
var isVertFriction: Boolean = false
|
||||
|
||||
@@ -39,12 +40,13 @@ class BlockProp {
|
||||
var lumColG = 0f
|
||||
var lumColB = 0f
|
||||
var lumColA = 0f
|
||||
lateinit var internalLumCol: Color
|
||||
|
||||
/**
|
||||
* @param luminosity
|
||||
*/
|
||||
inline val luminosity: Color
|
||||
get() = BlockPropUtil.getDynamicLumFunc(Color(lumColR, lumColG, lumColB, lumColA), dynamicLuminosityFunction)
|
||||
get() = BlockPropUtil.getDynamicLumFunc(internalLumCol, dynamicLuminosityFunction)
|
||||
|
||||
var drop: Int = 0
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.Second
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
|
||||
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
||||
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
|
||||
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2016-06-16.
|
||||
@@ -63,9 +63,9 @@ object BlockPropUtil {
|
||||
internal fun dynamicLumFuncTickClock() {
|
||||
// FPS-time compensation
|
||||
if (Gdx.graphics.framesPerSecond > 0) {
|
||||
flickerFuncX += Terrarum.deltaTime * 1000f
|
||||
breathFuncX += Terrarum.deltaTime * 1000f
|
||||
pulsateFuncX += Terrarum.deltaTime * 1000f
|
||||
flickerFuncX += Gdx.graphics.deltaTime * 1000f
|
||||
breathFuncX += Gdx.graphics.deltaTime * 1000f
|
||||
pulsateFuncX += Gdx.graphics.deltaTime * 1000f
|
||||
}
|
||||
|
||||
// flicker-related vars
|
||||
|
||||
20
src/net/torvald/terrarum/blockproperties/Fluid.kt
Normal file
20
src/net/torvald/terrarum/blockproperties/Fluid.kt
Normal file
@@ -0,0 +1,20 @@
|
||||
package net.torvald.terrarum.blockproperties
|
||||
|
||||
import net.torvald.terrarum.gameworld.FluidType
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2016-08-06.
|
||||
*/
|
||||
object Fluid {
|
||||
|
||||
val NULL = FluidType(0)
|
||||
|
||||
val WATER = FluidType(1)
|
||||
val STATIC_WATER = FluidType(-1)
|
||||
|
||||
val LAVA = FluidType(2)
|
||||
val STATIC_LAVA = FluidType(-2)
|
||||
|
||||
|
||||
val fluidRange = 1..2 // TODO MANUAL UPDATE
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user