mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-08 17:44:06 +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/*
|
out/*
|
||||||
bin/*
|
bin/*
|
||||||
build/*
|
build/*
|
||||||
.gradle/*
|
.gradle/*
|
||||||
|
|
||||||
|
# Java native errors
|
||||||
hs_err_pid*
|
hs_err_pid*
|
||||||
|
|
||||||
|
# OS files
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
*.jar
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
~$*
|
|
||||||
|
# Resources that should not be tracked
|
||||||
|
*.jar
|
||||||
assets/mods/basegame/demoworld
|
assets/mods/basegame/demoworld
|
||||||
assets/mods/basegame/demoworld.gz
|
#assets/mods/basegame/demoworld.gz
|
||||||
external_resource_packs.zip
|
external_resource_packs.zip
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
workspace.xml
|
workspace.xml
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
.tmp*
|
.tmp*
|
||||||
tmp_*
|
tmp_*
|
||||||
|
~$*
|
||||||
|
|
||||||
|
# Eclipse MAT heap files
|
||||||
|
*.hprof
|
||||||
|
*.bin
|
||||||
|
*.index
|
||||||
|
*.threads
|
||||||
|
*_Leak_Suspects.zip
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
*Terrarum*
|
*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
|
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
|
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*
|
*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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
|0..4095|Tiles (4096 possible)|
|
|0..4095|Tiles (4096 possible)|
|
||||||
|4096..8191|Walls (4096 possible)|
|
|4096..8191|Walls (4096 possible)|
|
||||||
|8192..8447|Wires (256 possible)|
|
|8192..8447|Wires (256 possible)|
|
||||||
|8448..32767|Items (static) (24320 possible)|
|
|8448..0x0F_FFFF|Items (static) (1M possible)|
|
||||||
|32768..0x0FFF_FFFF|Items (dynamic\*) (268M possible)|
|
|0x10_0000..0x0FFF_FFFF|Items (dynamic\*) (267M possible)|
|
||||||
|0x1000_0000..0x7FFF_FFFF|Actors|
|
|0x1000_0000..0x7FFF_FFFF|Actors (1879M possible)|
|
||||||
|-2147483648..-1 (all negative numbers)|Faction|
|
|-2147483648..-1 (all negative numbers)|Faction (2147M possible)|
|
||||||
|
|
||||||
* dynamic items have own properties that will persist through savegame.
|
* dynamic items have own properties that will persist through savegame.
|
||||||
|
|
||||||
@@ -14,7 +14,8 @@ Actors range in-depth
|
|||||||
|
|
||||||
|Range|Description|
|
|Range|Description|
|
||||||
|-----|-----------|
|
|-----|-----------|
|
||||||
|0x1000_0000..0x1FFF_FFFF|Rendered behind (e.g. tapestries)
|
|0x1000_0000..0x1FFF_FFFF|Rendered behind (e.g. tapestries)|
|
||||||
|0x2000_0000..0x5FFF_FFFF|Regular actors (e.g. almost all of them)
|
|0x2000_0000..0x4FFF_FFFF|Regular actors (e.g. almost all of them)|
|
||||||
|0x6000_0000..0x6FFF_FFFF|Special (e.g. weapon swung, bullets, dropped item, particles)
|
|0x5000_0000..0x5FFF_FFFF|Special (e.g. weapon swung, bullets, dropped item, particles)|
|
||||||
|0x7000_0000..0x7FFF_FFFF|Rendered front (e.g. fake tile)
|
|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
|
#ifdef GL_ES
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ The control is omnidirectional. In other words, \emph{not} cell-based.
|
|||||||
\subsubsection{ISO\slash ANSI\slash JIS pedalboards}
|
\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.}
|
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”.
|
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}
|
\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
|
// "steps" of R, G and B. Must be integer && equal or greater than 2
|
||||||
uniform float rcount = 32.0;
|
uniform float rcount = 64.0;
|
||||||
uniform float gcount = 32.0;
|
uniform float gcount = 64.0;
|
||||||
uniform float bcount = 32.0;
|
uniform float bcount = 64.0;
|
||||||
uniform float acount = 1.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);
|
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",
|
"n": "MENU_LABEL_MAINMENU",
|
||||||
"s": "메뉴"
|
"s": "메인 메뉴"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"n": "MENU_LABEL_MORE",
|
"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"
|
"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.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"4"
|
"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"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"-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"
|
||||||
"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"
|
|
||||||
|
|
||||||
## Notes ##
|
## 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
|
# drop: Drop ID
|
||||||
|
#
|
||||||
# shdr/g/b, lumr/g/b: Shade RGB/ Lum RGB.
|
# shdr/g/b, lumr/g/b: Shade RGB/ Lum RGB.
|
||||||
# valid range: float of 0..4; 1.0 for 255
|
# 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)
|
# 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)
|
# 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]
|
# dsty: density. As we are putting water an 1000, it is identical to specific gravity. [g/l]
|
||||||
|
#
|
||||||
# dlfn: dynamic luminosity function.
|
# dlfn: dynamic luminosity function.
|
||||||
# 0-static, 1-torch flicker, 2-current global light (sun, star, moon), 3-daylight at noon,
|
# 0-static, 1-torch flicker, 2-current global light (sun, star, moon), 3-daylight at noon,
|
||||||
# 4-slow breath, 5-pulsate
|
# 4-slow breath, 5-pulsate
|
||||||
|
#
|
||||||
# mate: material, four-letter code
|
# mate: material, four-letter code
|
||||||
|
#
|
||||||
# fv: vertical friction (boolean)
|
# fv: vertical friction (boolean)
|
||||||
|
# fr: horizontal friction. 0: frictionless, <16: slippery, 16: regular, >16: sticky
|
||||||
|
#
|
||||||
|
#
|
||||||
## Illuminators ##
|
## 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
|
# 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.
|
# 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.
|
# Sunlight capacitor: daylight at noon. Set by game's code.
|
||||||
|
#
|
||||||
# BLOCK_ILLUMINATOR_CYAN is actually a SUPER_LUMINATOR, cyan colour is used as:
|
# BLOCK_ILLUMINATOR_CYAN is actually a SUPER_LUMINATOR, cyan colour is used as:
|
||||||
# 1. It has quite a brightness on RGB colour space
|
# 1. It has quite a brightness on RGB colour space
|
||||||
# 2. Helmholz-Kohlraush effect
|
# 2. Helmholz-Kohlraush effect
|
||||||
|
#
|
||||||
|
#
|
||||||
## Tiles ##
|
## Tiles ##
|
||||||
|
#
|
||||||
# 16 colour palette : games's 16-colour palette
|
# 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.
|
# Magical ice: theoretical __metallic__ ice that might form under super-high pressure (> 5 TPa). Its density is a wild guess.
|
||||||
|
#
|
||||||
|
#
|
||||||
## References ##
|
## References ##
|
||||||
|
#
|
||||||
# * Density of various woods : http://www.engineeringtoolbox.com/wood-density-d_40.html
|
# * 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
|
# * 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,
|
"multithread": true,
|
||||||
|
|
||||||
|
|
||||||
"joypadkeyn": 4,
|
"gamepadkeyn": 4,
|
||||||
"joypadkeyw": 1,
|
"gamepadkeyw": 1,
|
||||||
"joypadkeys": 2,
|
"gamepadkeys": 2,
|
||||||
"joypadkeye": 3,
|
"gamepadkeye": 3,
|
||||||
|
|
||||||
"joypadlup": 4,
|
"gamepadlup": 4,
|
||||||
"joypadrup": 5,
|
"gamepadrup": 5,
|
||||||
"joypadldown": 6,
|
"gamepadldown": 6,
|
||||||
"joypadrdown": 7,
|
"gamepadrdown": 7,
|
||||||
|
|
||||||
"joypadlstickx": 0,
|
"gamepadlstickx": 0,
|
||||||
"joypadlsticky": 1,
|
"gamepadlsticky": 1,
|
||||||
"joypadrstickx": 2,
|
"gamepadrstickx": 2,
|
||||||
"joypadrsticky": 3,
|
"gamepadrsticky": 3,
|
||||||
|
|
||||||
"joypadlabelstyle": "msxb360",
|
"gamepadlabelstyle": "msxb360",
|
||||||
|
|
||||||
|
|
||||||
"keyup": 33,
|
"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"
|
"idst";"dsty";"forcemod";"endurance";"comments"
|
||||||
"rock";"2400"; "1"; "0.42";
|
"ROCK";"2400"; "1"; "0.42";
|
||||||
"cupr";"1000"; "2"; "1.00";"copper"
|
"CUPR";"1000"; "2"; "1.00";"copper"
|
||||||
"egls";"2500"; "4"; "0.82";"elven glass"
|
"EGLS";"2500"; "4"; "0.82";"elven glass"
|
||||||
"iron";"1000"; "5"; "1.42";
|
"IRON";"1000"; "5"; "1.42";
|
||||||
"argn";"1000"; "9"; "0.91";"argentum/silver"
|
"ARGN";"1000"; "9"; "0.91";"argentum/silver"
|
||||||
"stal";"1000"; "14"; "1.73";"steel"
|
"STAL";"1000"; "14"; "1.73";"steel"
|
||||||
"eaur";"1000"; "21"; "1.36";"elven aurichalcum"
|
"EAUR";"1000"; "21"; "1.36";"elven aurichalcum"
|
||||||
"tial";"1000"; "33"; "2.16";"titanium alloy (Ti6Al4V)"
|
"TIAL";"1000"; "33"; "2.16";"titanium alloy (Ti6Al4V)"
|
||||||
"admt";"1000"; "71"; "3.42";"adamant"
|
"ADMT";"1000"; "71"; "3.42";"adamant"
|
||||||
|
|
||||||
# idst: ID_STRING
|
# 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) {
|
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
|
#version 120
|
||||||
#ifdef GL_ES
|
#ifdef GL_ES
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
@@ -16,10 +26,11 @@ uniform vec2 screenDimension;
|
|||||||
uniform vec2 tilesInAxes; // vec2(tiles_in_horizontal, tiles_in_vertical)
|
uniform vec2 tilesInAxes; // vec2(tiles_in_horizontal, tiles_in_vertical)
|
||||||
|
|
||||||
uniform ivec2 tilemapDimension;
|
uniform ivec2 tilemapDimension;
|
||||||
uniform sampler2D tilemap; // RGB888, A is optional and will be completely ignored
|
uniform sampler2D tilemap; // RGBA8888
|
||||||
|
|
||||||
uniform sampler2D tilesAtlas;
|
uniform sampler2D tilesAtlas; // terrain, wire, fluids, etc.
|
||||||
uniform sampler2D backgroundTexture;
|
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 tilesInAtlas = ivec2(256, 256);
|
||||||
uniform ivec2 atlasTexSize = ivec2(4096, 4096);
|
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 ivec2(tileNumber % int(tilesInAtlas.x), tileNumber / int(tilesInAtlas.x));
|
||||||
}
|
}
|
||||||
|
|
||||||
// return: int=0xrrggbb
|
// return: int=0xaarrggbb
|
||||||
int _colToInt(vec4 color) {
|
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
|
// 0x0rggbb where int=0xaarrggbb
|
||||||
// return: [0..1048575]
|
// return: [0..1048575]
|
||||||
int getTileFromColor(vec4 color) {
|
int getTileFromColor(vec4 color) {
|
||||||
return _colToInt(color) & 0x0FFFFF;
|
return _colToInt(color) & 0xFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0xr00000 where int=0xaarrggbb
|
// 0x00r00000 where int=0xaarrggbb
|
||||||
// return: [0..15]
|
// return: [0..15]
|
||||||
int getBreakageFromColor(vec4 color) {
|
int getBreakageFromColor(vec4 color) {
|
||||||
return (_colToInt(color) >> 20) & 0xF;
|
return (_colToInt(color) >> 20) & 0xF;
|
||||||
@@ -56,6 +67,7 @@ void main() {
|
|||||||
// READ THE FUCKING MANUAL, YOU DONKEY !! //
|
// READ THE FUCKING MANUAL, YOU DONKEY !! //
|
||||||
// This code purposedly uses flipped fragcoord. //
|
// This code purposedly uses flipped fragcoord. //
|
||||||
// Make sure you don't use gl_FragCoord unknowingly! //
|
// 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?
|
// 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
|
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
|
// 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)
|
vec2 uvCoordOffsetTile = tileXY * singleTileSizeInUV; // where the tile starts in the atlas, using uv coord (0..1)
|
||||||
mediump vec2 uvCoordOffsetBreakage = breakageXY * singleTileSizeInUV;
|
vec2 uvCoordOffsetBreakage = breakageXY * singleTileSizeInUV;
|
||||||
|
|
||||||
mediump vec2 finalUVCoordForTile = uvCoordForTile + uvCoordOffsetTile;// where we should be actually looking for in atlas, using UV coord (0..1)
|
vec2 finalUVCoordForTile = uvCoordForTile + uvCoordOffsetTile;// where we should be actually looking for in atlas, using UV coord (0..1)
|
||||||
mediump vec2 finalUVCoordForBreakage = uvCoordForTile + uvCoordOffsetBreakage;
|
vec2 finalUVCoordForBreakage = uvCoordForTile + uvCoordOffsetBreakage;
|
||||||
|
|
||||||
|
|
||||||
// blending a breakage tex with main tex
|
// 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);
|
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
30
build.gradle
30
build.gradle
@@ -43,3 +43,33 @@ jar {
|
|||||||
baseName = 'Terrarum'
|
baseName = 'Terrarum'
|
||||||
version = '0.2'
|
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
|
package net.torvald.colourutil
|
||||||
|
|
||||||
import com.jme3.math.FastMath
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.jme3.math.FastMath
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2017-01-12.
|
* Created by minjaesong on 2017-01-12.
|
||||||
@@ -11,25 +11,27 @@ object CIEXYZUtil {
|
|||||||
/**
|
/**
|
||||||
* 0..255 -> 0.0..1.0
|
* 0..255 -> 0.0..1.0
|
||||||
*/
|
*/
|
||||||
private val rgbLineariseLUT = Array<Float>(257, {
|
private val rgbLinLUT = FloatArray(256) {
|
||||||
val step = minOf(it, 255) / 255f
|
val step = it / 255f
|
||||||
|
|
||||||
if (step > 0.04045f)
|
if (step > 0.04045f)
|
||||||
((step + 0.055f) / 1.055f).powerOf(2.4f)
|
((step + 0.055f) / 1.055f).powerOf(2.4f)
|
||||||
else step / 12.92f
|
else step / 12.92f
|
||||||
})
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0..255 -> 0.0..1.0
|
* 0..255 -> 0.0..1.0
|
||||||
*/
|
*/
|
||||||
private val rgbUnLineariseLUT = Array<Float>(257, {
|
private val rgbUnLinLUT = FloatArray(256) {
|
||||||
val step = minOf(it, 255) / 255f
|
val step = it / 255f
|
||||||
|
|
||||||
if (step > 0.0031308f)
|
if (step > 0.0031308f)
|
||||||
1.055f * step.powerOf(1f / 2.4f) - 0.055f
|
1.055f * step.powerOf(1f / 2.4f) - 0.055f
|
||||||
else
|
else
|
||||||
step * 12.92f
|
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()
|
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 {
|
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)
|
((r + 0.055f) / 1.055f).powerOf(2.4f)
|
||||||
else r / 12.92f
|
else r / 12.92f
|
||||||
val newG = if (g > 0.04045f)
|
val newG = if (g > 0.04045f)
|
||||||
@@ -77,28 +106,38 @@ object CIEXYZUtil {
|
|||||||
else b / 12.92f
|
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)
|
val out = floatArrayOf(0f, 0f, 0f)
|
||||||
for (i in 0..2) {
|
for (i in 0..2) {
|
||||||
val value = when (i) {
|
val value = when (i) {
|
||||||
0 -> this.r
|
0 -> this.r
|
||||||
1 -> this.g
|
1 -> this.g
|
||||||
2 -> this.b
|
2 -> this.b
|
||||||
else -> throw Exception("Fuck you")
|
else -> throw InternalError("Fuck you")
|
||||||
}
|
}
|
||||||
val step = value.clampOne() * 255f
|
val step = value.clampOne() * 255f // 0.0 .. 255.0
|
||||||
val intStep = step.toInt()
|
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)
|
return RGB(out[0], out[1], out[2], alpha)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun RGB.unLinearise(): RGB {
|
/** Suitable for rigorous maths but slower */
|
||||||
/*val newR = if (r > 0.0031308f)
|
fun RGB.unLineariseSuper(): RGB {
|
||||||
|
val newR = if (r > 0.0031308f)
|
||||||
1.055f * r.powerOf(1f / 2.4f) - 0.055f
|
1.055f * r.powerOf(1f / 2.4f) - 0.055f
|
||||||
else
|
else
|
||||||
r * 12.92f
|
r * 12.92f
|
||||||
@@ -112,24 +151,7 @@ object CIEXYZUtil {
|
|||||||
b * 12.92f
|
b * 12.92f
|
||||||
|
|
||||||
|
|
||||||
return RGB(newR, newG, newB, alpha)*/
|
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun RGB.toXYZ(): CIEXYZ {
|
fun RGB.toXYZ(): CIEXYZ {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
package net.torvald.colourutil
|
package net.torvald.colourutil
|
||||||
|
|
||||||
import com.jme3.math.FastMath
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.jme3.math.FastMath
|
||||||
|
import net.torvald.colourutil.CIEXYZUtil.linearise
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2016-07-26.
|
* Created by minjaesong on 2016-07-26.
|
||||||
@@ -20,4 +21,17 @@ object ColourUtil {
|
|||||||
|
|
||||||
return Color(r, g, b, a)
|
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:
|
* Notes for particle storage:
|
||||||
* Particles does not need to be removed, just let it overwrite as their operation is rather
|
* 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
|
* 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) {
|
class CircularArray<T>(val size: Int) {
|
||||||
|
|
||||||
val buffer: Array<T> = arrayOfNulls<Any>(size) as Array<T>
|
val buffer: Array<T> = arrayOfNulls<Any>(size) as Array<T>
|
||||||
var tail: Int = 0
|
var tail: Int = 0; private set
|
||||||
var head: Int = 0
|
var head: Int = -1; private set
|
||||||
|
|
||||||
|
private var unreliableAddCount = 0
|
||||||
|
|
||||||
val lastIndex = size - 1
|
val lastIndex = size - 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of elements that forEach() or fold() would iterate.
|
||||||
|
*/
|
||||||
val elemCount: Int
|
val elemCount: Int
|
||||||
get() = if (tail >= head) tail - head else size
|
get() = minOf(unreliableAddCount, size)
|
||||||
|
|
||||||
fun add(item: T) {
|
fun add(item: T) {
|
||||||
buffer[tail] = item // overwrites oldest item when eligible
|
if (unreliableAddCount <= size) unreliableAddCount += 1
|
||||||
tail = (tail + 1) % size
|
|
||||||
if (tail == head) {
|
head = (head + 1) % size
|
||||||
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
|
// has slightly better iteration performance than lambda
|
||||||
if (tail >= head) {
|
if (unreliableAddCount <= size) {
|
||||||
for (i in head..tail - 1)
|
for (i in 0..head)
|
||||||
action(buffer[i])
|
action(buffer[i])
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (i in 0..size - 1)
|
for (i in 0..size - 1)
|
||||||
action(buffer[(i + head) % size])
|
action(buffer[(i + tail) % size])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME not working as intended
|
fun <R> fold(initial: R, operation: (R, T) -> R): R {
|
||||||
inline fun <R> fold(initial: R, operation: (R, T) -> R): R {
|
|
||||||
var accumulator = initial
|
var accumulator = initial
|
||||||
//for (element in buffer) accumulator = operation(accumulator, element)
|
//for (element in buffer) accumulator = operation(accumulator, element)
|
||||||
if (tail >= head) {
|
if (unreliableAddCount <= size) {
|
||||||
for (i in head..tail - 1)
|
for (i in 0..head)
|
||||||
operation(accumulator, buffer[i])
|
accumulator = operation(accumulator, buffer[i])
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (i in 0..size - 1)
|
for (i in 0..size - 1)
|
||||||
operation(accumulator, buffer[(i + head) % size])
|
accumulator = operation(accumulator, buffer[(i + tail) % size])
|
||||||
}
|
}
|
||||||
|
|
||||||
return accumulator
|
return accumulator
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun forEachConcurrent(action: (T) -> Unit) {
|
|
||||||
TODO()
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun forEachConcurrentWaitFor(action: (T) -> Unit) {
|
|
||||||
TODO()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "CircularArray(size=" + buffer.size + ", head=" + head + ", tail=" + tail + ")"
|
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.Color
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
|
import net.torvald.terrarum.Second
|
||||||
import net.torvald.terrarum.gameactors.ActorWBMovable
|
import net.torvald.terrarum.gameactors.ActorWBMovable
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
|
|
||||||
class SpriteAnimation(val parentActor: ActorWBMovable) {
|
class SpriteAnimation(val parentActor: ActorWBMovable) {
|
||||||
|
|
||||||
private lateinit var textureRegion: TextureRegionPack
|
lateinit var textureRegion: TextureRegionPack; private set
|
||||||
|
|
||||||
var currentFrame = 0
|
var currentFrame = 0
|
||||||
var currentRow = 0
|
var currentRow = 0
|
||||||
var nFrames: Int = 1
|
|
||||||
private set
|
var nFrames: IntArray = intArrayOf(1)
|
||||||
|
internal set
|
||||||
var nRows: Int = 1
|
var nRows: Int = 1
|
||||||
private set
|
internal set
|
||||||
var delay = 200f
|
|
||||||
|
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
|
private var delta = 0f
|
||||||
|
|
||||||
val looping = true
|
val looping = true
|
||||||
private var animationRunning = true
|
private var animationRunning = true
|
||||||
var flipHorizontal = false
|
var flipHorizontal = false
|
||||||
@@ -53,7 +71,15 @@ class SpriteAnimation(val parentActor: ActorWBMovable) {
|
|||||||
*/
|
*/
|
||||||
fun setRowsAndFrames(nRows: Int, nFrames: Int) {
|
fun setRowsAndFrames(nRows: Int, nFrames: Int) {
|
||||||
this.nRows = nRows
|
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) {
|
fun update(delta: Float) {
|
||||||
@@ -61,17 +87,23 @@ class SpriteAnimation(val parentActor: ActorWBMovable) {
|
|||||||
//skip this if animation is stopped
|
//skip this if animation is stopped
|
||||||
this.delta += delta
|
this.delta += delta
|
||||||
|
|
||||||
|
//println("delta accumulation: $delta, currentDelay: $currentDelay")
|
||||||
|
|
||||||
//check if it's time to advance the frame
|
//check if it's time to advance the frame
|
||||||
if (this.delta >= this.delay) {
|
while (this.delta >= currentDelay) {
|
||||||
//if set to not loop, keep the frame at the last frame
|
// advance frame
|
||||||
if (this.currentFrame == this.nFrames && !this.looping) {
|
if (looping) { // looping, wrap around
|
||||||
this.currentFrame = this.nFrames - 1
|
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
|
// discount counter
|
||||||
this.currentFrame = this.currentFrame % this.nFrames
|
this.delta -= currentDelay
|
||||||
this.delta = 0f
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//println("row, frame: $currentRow, $currentFrame")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,13 +118,13 @@ class SpriteAnimation(val parentActor: ActorWBMovable) {
|
|||||||
* *
|
* *
|
||||||
* @param scale
|
* @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) {
|
if (cellWidth == 0 || cellHeight == 0) {
|
||||||
throw Error("Sprite width or height is set to zero! ($cellWidth, $cellHeight); master: $parentActor")
|
throw Error("Sprite width or height is set to zero! ($cellWidth, $cellHeight); master: $parentActor")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
val region = textureRegion.get(currentRow, currentFrame)
|
val region = textureRegion.get(currentFrame, currentRow)
|
||||||
batch.color = colorFilter
|
batch.color = colorFilter
|
||||||
|
|
||||||
if (flipHorizontal && flipVertical) {
|
if (flipHorizontal && flipVertical) {
|
||||||
@@ -131,20 +163,9 @@ class SpriteAnimation(val parentActor: ActorWBMovable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun switchRow(newRow: Int) {
|
fun switchRow(newRow: Int) {
|
||||||
currentRow = newRow % nRows
|
if (newRow != currentRow) {
|
||||||
|
currentRow = newRow
|
||||||
//if beyond the frame index then reset
|
currentFrame = 1
|
||||||
if (currentFrame > nFrames) {
|
|
||||||
reset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setSpriteDelay(newDelay: Float) {
|
|
||||||
if (newDelay > 0) {
|
|
||||||
delay = newDelay
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw IllegalArgumentException("Delay equal or less than zero")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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;
|
package net.torvald.terrarum;
|
||||||
|
|
||||||
import com.badlogic.gdx.ApplicationListener;
|
import com.badlogic.gdx.*;
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.assets.AssetManager;
|
||||||
import com.badlogic.gdx.Screen;
|
import com.badlogic.gdx.audio.AudioDevice;
|
||||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
|
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
|
||||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
|
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
|
||||||
import com.badlogic.gdx.graphics.*;
|
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.g2d.TextureRegion;
|
||||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
|
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
|
||||||
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
|
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.GameFontBase;
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack;
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack;
|
||||||
|
import org.lwjgl.input.Controller;
|
||||||
|
import org.lwjgl.input.Controllers;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import static net.torvald.terrarum.TerrarumKt.gdxClearAndSetBlend;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The framework's Application Loader
|
* The framework's Application Loader
|
||||||
*
|
*
|
||||||
@@ -30,19 +49,62 @@ public class AppLoader implements ApplicationListener {
|
|||||||
* AA: Major version
|
* AA: Major version
|
||||||
* BB: Minor version
|
* BB: Minor version
|
||||||
* XXXX: Revision (Repository commits, or something arbitrary)
|
* XXXX: Revision (Repository commits, or something arbitrary)
|
||||||
*
|
* <p>
|
||||||
* e.g. 0x02010034 can be translated as 2.1.52
|
* e.g. 0x02010034 will be translated as 2.1.52
|
||||||
*/
|
*/
|
||||||
public static final int VERSION_RAW = 0x00_02_027C;
|
public static final int VERSION_RAW = 0x00_02_04B1;
|
||||||
public static final boolean IS_DEVELOPMENT_BUILD = true;
|
|
||||||
|
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 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() {
|
public static AppLoader getINSTANCE() {
|
||||||
if (INSTANCE == null) {
|
if (INSTANCE == null) {
|
||||||
INSTANCE = new AppLoader();
|
INSTANCE = new AppLoader();
|
||||||
@@ -51,9 +113,29 @@ public class AppLoader implements ApplicationListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static final String GAME_NAME = "Terrarum";
|
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 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!!
|
private static final String[] localeSimple = {"de", "en", "es", "it"}; // must be sorted!!
|
||||||
|
|
||||||
public static String getSysLang() {
|
public static String getSysLang() {
|
||||||
@@ -81,13 +163,19 @@ public class AppLoader implements ApplicationListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String getVERSION_STRING() {
|
private static boolean splashDisplayed = false;
|
||||||
return String.format("%d.%d.%d", VERSION_RAW >>> 24, (VERSION_RAW & 0xff0000) >>> 16, VERSION_RAW & 0xFFFF);
|
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 LwjglApplicationConfiguration appConfig;
|
||||||
|
|
||||||
public static GameFontBase fontGame;
|
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)
|
* 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 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) {
|
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;
|
ShaderProgram.pedantic = false;
|
||||||
|
|
||||||
appConfig = new LwjglApplicationConfiguration();
|
LwjglApplicationConfiguration appConfig = new LwjglApplicationConfiguration();
|
||||||
appConfig.vSyncEnabled = false;
|
//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.resizable = false;//true;
|
||||||
//appConfig.width = 1072; // IMAX ratio
|
//appConfig.width = 1110; // photographic ratio (1.5:1)
|
||||||
//appConfig.height = 742; // IMAX ratio
|
//appConfig.height = 740; // photographic ratio (1.5:1)
|
||||||
appConfig.width = 1110; // photographic ratio (1.5:1)
|
appConfig.width = getConfigInt("screenwidth");
|
||||||
appConfig.height = 740; // photographic ratio (1.5:1)
|
appConfig.height = getConfigInt("screenheight");
|
||||||
appConfig.backgroundFPS = 9999;
|
appConfig.backgroundFPS = getConfigInt("displayfps");
|
||||||
appConfig.foregroundFPS = 9999;
|
appConfig.foregroundFPS = getConfigInt("displayfps");
|
||||||
appConfig.title = GAME_NAME;
|
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;
|
private static ShaderProgram shaderBayerSkyboxFill;
|
||||||
public static ShaderProgram shaderHicolour;
|
public static ShaderProgram shaderHicolour;
|
||||||
|
public static ShaderProgram shaderPassthru;
|
||||||
public static ShaderProgram shaderColLUT;
|
public static ShaderProgram shaderColLUT;
|
||||||
|
|
||||||
public static Mesh fullscreenQuad;
|
public static Mesh fullscreenQuad;
|
||||||
private OrthographicCamera camera;
|
private OrthographicCamera camera;
|
||||||
private SpriteBatch logoBatch;
|
private SpriteBatch logoBatch;
|
||||||
public static TextureRegion logo;
|
public static TextureRegion logo;
|
||||||
|
public static AudioDevice audioDevice;
|
||||||
|
|
||||||
private Color gradWhiteTop = new Color(0xf8f8f8ff);
|
private Color gradWhiteTop = new Color(0xf8f8f8ff);
|
||||||
private Color gradWhiteBottom = new Color(0xd8d8d8ff);
|
private Color gradWhiteBottom = new Color(0xd8d8d8ff);
|
||||||
|
|
||||||
public Screen screen;
|
public Screen screen;
|
||||||
|
public static int screenW = 0;
|
||||||
|
public static int screenH = 0;
|
||||||
|
|
||||||
|
public static Texture textureWhiteSquare;
|
||||||
|
|
||||||
private void initViewPort(int width, int height) {
|
private void initViewPort(int width, int height) {
|
||||||
// Set Y to point downwards
|
// Set Y to point downwards
|
||||||
@@ -138,26 +268,34 @@ public class AppLoader implements ApplicationListener {
|
|||||||
Gdx.gl20.glViewport(0, 0, width, height);
|
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 float loadTimer = 0f;
|
||||||
private final float showupTime = 100f / 1000f;
|
private final float showupTime = 100f / 1000f;
|
||||||
|
|
||||||
private FrameBuffer renderFBO;
|
private FrameBuffer renderFBO;
|
||||||
|
|
||||||
|
public static AssetManager assetManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void create() {
|
public void create() {
|
||||||
|
assetManager = new AssetManager();
|
||||||
|
|
||||||
|
// set basis of draw
|
||||||
logoBatch = new SpriteBatch();
|
logoBatch = new SpriteBatch();
|
||||||
camera = new OrthographicCamera(((float) appConfig.width), ((float) appConfig.height));
|
camera = new OrthographicCamera(((float) appConfig.width), ((float) appConfig.height));
|
||||||
|
|
||||||
|
|
||||||
initViewPort(appConfig.width, 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"));
|
// set GL graphics constants
|
||||||
shaderHicolour = new ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/hicolour.frag"));
|
shaderBayerSkyboxFill = loadShader("assets/4096.vert", "assets/4096_bayer_skyboxfill.frag");
|
||||||
shaderColLUT = new ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/passthru.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(
|
fullscreenQuad = new Mesh(
|
||||||
true, 4, 6,
|
true, 4, 6,
|
||||||
@@ -165,40 +303,58 @@ public class AppLoader implements ApplicationListener {
|
|||||||
VertexAttribute.ColorUnpacked(),
|
VertexAttribute.ColorUnpacked(),
|
||||||
VertexAttribute.TexCoords(0)
|
VertexAttribute.TexCoords(0)
|
||||||
);
|
);
|
||||||
|
updateFullscreenQuad(appConfig.width, appConfig.height);
|
||||||
|
|
||||||
fullscreenQuad.setVertices(new float[]{
|
// enlist suitable gamepads
|
||||||
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f,
|
try {
|
||||||
((float) appConfig.width), 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f,
|
Controllers.create();
|
||||||
((float) appConfig.width), ((float) appConfig.height), 0f, 1f, 1f, 1f, 1f, 1f, 0f,
|
|
||||||
0f, ((float) appConfig.height), 0f, 1f, 1f, 1f, 1f, 0f, 0f
|
printdbg(this, "Available gamepads: " + Controllers.getControllerCount());
|
||||||
});
|
for (int x = 0; x < Controllers.getControllerCount(); x++) {
|
||||||
fullscreenQuad.setIndices(new short[]{0, 1, 2, 2, 3, 0});
|
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")));
|
// set up renderer info variables
|
||||||
logo.flip(false, true);
|
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
|
@Override
|
||||||
public void render() {
|
public void render() {
|
||||||
|
Gdx.gl.glDisable(GL20.GL_DITHER);
|
||||||
|
|
||||||
|
if (splashDisplayed && !postInitFired) {
|
||||||
|
postInitFired = true;
|
||||||
|
postInit();
|
||||||
|
}
|
||||||
|
|
||||||
FrameBufferManager.begin(renderFBO);
|
FrameBufferManager.begin(renderFBO);
|
||||||
Gdx.gl.glClearColor(.094f, .094f, .094f, 0f);
|
gdxClearAndSetBlend(.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);
|
|
||||||
setCameraPosition(0, 0);
|
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) {
|
if (screen == null) {
|
||||||
shaderBayerSkyboxFill.begin();
|
shaderBayerSkyboxFill.begin();
|
||||||
shaderBayerSkyboxFill.setUniformMatrix("u_projTrans", camera.combined);
|
shaderBayerSkyboxFill.setUniformMatrix("u_projTrans", camera.combined);
|
||||||
@@ -224,91 +380,187 @@ public class AppLoader implements ApplicationListener {
|
|||||||
loadTimer += Gdx.graphics.getRawDeltaTime();
|
loadTimer += Gdx.graphics.getRawDeltaTime();
|
||||||
|
|
||||||
if (loadTimer >= showupTime) {
|
if (loadTimer >= showupTime) {
|
||||||
Terrarum.INSTANCE.setScreenW(appConfig.width);
|
// hand over the scene control to this single class; Terrarum must call
|
||||||
Terrarum.INSTANCE.setScreenH(appConfig.height);
|
// 'AppLoader.getINSTANCE().screen.render(delta)', this is not redundant at all!
|
||||||
setScreen(Terrarum.INSTANCE);
|
setScreen(Terrarum.INSTANCE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// draw the screen
|
||||||
else {
|
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!
|
// nested FBOs are just not a thing in GL!
|
||||||
net.torvald.terrarum.FrameBufferManager.end();
|
net.torvald.terrarum.FrameBufferManager.end();
|
||||||
|
|
||||||
PostProcessor.INSTANCE.draw(camera.combined, renderFBO);
|
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;
|
GLOBAL_RENDER_TIMER += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resize(int width, int height) {
|
public void resize(int width, int height) {
|
||||||
|
printdbg(this, "Resize called");
|
||||||
|
for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {
|
||||||
|
printdbg(this, stackTraceElement);
|
||||||
|
}
|
||||||
|
|
||||||
//initViewPort(width, height);
|
//initViewPort(width, height);
|
||||||
|
|
||||||
Terrarum.INSTANCE.resize(width, height);
|
screenW = width;
|
||||||
if (screen != null) screen.resize(Terrarum.INSTANCE.getWIDTH(), Terrarum.INSTANCE.getHEIGHT());
|
screenH = height;
|
||||||
|
|
||||||
|
if (screenW % 2 == 1) screenW -= 1;
|
||||||
|
if (screenH % 2 == 1) screenH -= 1;
|
||||||
|
|
||||||
|
if (screen != null) screen.resize(screenW, screenH);
|
||||||
|
|
||||||
|
|
||||||
if (renderFBO == null ||
|
if (renderFBO == null ||
|
||||||
(renderFBO.getWidth() != Terrarum.INSTANCE.getWIDTH() ||
|
(renderFBO.getWidth() != screenW ||
|
||||||
renderFBO.getHeight() != Terrarum.INSTANCE.getHEIGHT())
|
renderFBO.getHeight() != screenH)
|
||||||
) {
|
) {
|
||||||
renderFBO = new FrameBuffer(
|
renderFBO = new FrameBuffer(
|
||||||
Pixmap.Format.RGBA8888,
|
Pixmap.Format.RGBA8888,
|
||||||
Terrarum.INSTANCE.getWIDTH(),
|
screenW,
|
||||||
Terrarum.INSTANCE.getHEIGHT(),
|
screenH,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
appConfig.width = Terrarum.INSTANCE.getWIDTH();
|
appConfig.width = screenW;
|
||||||
appConfig.height = Terrarum.INSTANCE.getHEIGHT();
|
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
|
@Override
|
||||||
public void dispose () {
|
public void dispose() {
|
||||||
if (screen != null) screen.hide();
|
|
||||||
|
|
||||||
System.out.println("Goodbye !");
|
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
|
// delete temp files
|
||||||
new File("./tmp_wenquanyi.tga").delete();
|
new File("./tmp_wenquanyi.tga").delete(); // FIXME this is pretty much ad-hoc
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pause () {
|
public void pause() {
|
||||||
if (screen != null) screen.pause();
|
if (screen != null) screen.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resume () {
|
public void resume() {
|
||||||
if (screen != null) screen.resume();
|
if (screen != null) screen.resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setScreen(Screen screen) {
|
public void setScreen(Screen screen) {
|
||||||
printdbg(this, "Changing screen to " + screen.getClass().getCanonicalName());
|
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;
|
this.screen = screen;
|
||||||
if (this.screen != null) {
|
if (this.screen != null) {
|
||||||
this.screen.show();
|
this.screen.show();
|
||||||
this.screen.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
this.screen.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.gc();
|
||||||
|
|
||||||
printdbg(this, "Screen transisiton complete: " + this.screen.getClass().getCanonicalName());
|
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) {
|
private void setCameraPosition(float newX, float newY) {
|
||||||
camera.position.set((-newX + appConfig.width / 2), (-newY + appConfig.height / 2), 0f);
|
camera.position.set((-newX + appConfig.width / 2), (-newY + appConfig.height / 2), 0f);
|
||||||
camera.update();
|
camera.update();
|
||||||
logoBatch.setProjectionMatrix(camera.combined);
|
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[]{
|
fullscreenQuad.setVertices(new float[]{
|
||||||
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f,
|
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f,
|
||||||
WIDTH, 0f, 0f, 1f, 1f, 1f, 1f, 1f, 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});
|
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) {
|
// DEFAULT DIRECTORIES //
|
||||||
if (IS_DEVELOPMENT_BUILD) {
|
|
||||||
System.out.println("["+obj.getClass().getSimpleName()+"] "+message.toString());
|
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) {
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @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) {
|
if (IS_DEVELOPMENT_BUILD) {
|
||||||
System.err.println("["+obj.getClass().getSimpleName()+"] "+message.toString());
|
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()
|
val jsonObject = JsonObject()
|
||||||
|
|
||||||
jsonObject.addProperty("displayfps", 0) // 0: no limit, non-zero: limit
|
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("imtooyoungtodie", false) // no perma-death
|
||||||
jsonObject.addProperty("language", AppLoader.getSysLang())
|
jsonObject.addProperty("language", AppLoader.getSysLang())
|
||||||
jsonObject.addProperty("notificationshowuptime", 6500)
|
jsonObject.addProperty("notificationshowuptime", 4000)
|
||||||
jsonObject.addProperty("multithread", true) // experimental!
|
jsonObject.addProperty("multithread", true) // experimental!
|
||||||
jsonObject.addProperty("multithreadedlight", false) // experimental!
|
jsonObject.addProperty("multithreadedlight", false) // experimental!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// control-gamepad
|
// control-gamepad
|
||||||
jsonObject.addProperty("joypadkeyn", 4)
|
jsonObject.addProperty("gamepadkeyn", 4)
|
||||||
jsonObject.addProperty("joypadkeyw", 1)
|
jsonObject.addProperty("gamepadkeyw", 1)
|
||||||
jsonObject.addProperty("joypadkeys", 2)
|
jsonObject.addProperty("gamepadkeys", 2)
|
||||||
jsonObject.addProperty("joypadkeye", 3) // logitech indices
|
jsonObject.addProperty("gamepadkeye", 3) // logitech indices
|
||||||
|
|
||||||
jsonObject.addProperty("joypadlup", 4)
|
jsonObject.addProperty("gamepadlup", 4)
|
||||||
jsonObject.addProperty("joypadrup", 5)
|
jsonObject.addProperty("gamepadrup", 5)
|
||||||
jsonObject.addProperty("joypadldown", 6)
|
jsonObject.addProperty("gamepadldown", 6)
|
||||||
jsonObject.addProperty("joypadrdown", 7) // logitech indices
|
jsonObject.addProperty("gamepadrdown", 7) // logitech indices
|
||||||
|
|
||||||
jsonObject.addProperty("joypadlstickx", 0)
|
jsonObject.addProperty("gamepadlstickx", 0)
|
||||||
jsonObject.addProperty("joypadlsticky", 1)
|
jsonObject.addProperty("gamepadlsticky", 1)
|
||||||
jsonObject.addProperty("joypadrstickx", 2)
|
jsonObject.addProperty("gamepadrstickx", 2)
|
||||||
jsonObject.addProperty("joypadrsticky", 3) // 0-1-2-3 but sometimes 3-2-1-0 ?! what the actual fuck?
|
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)
|
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
|
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("keyquickbars", keyquickbars)
|
jsonObject.add("keyquickslots", keyquickslots)
|
||||||
|
|
||||||
jsonObject.addProperty("mouseprimary", Input.Buttons.LEFT) // left mouse
|
jsonObject.addProperty("mouseprimary", Input.Buttons.LEFT) // left mouse
|
||||||
jsonObject.addProperty("mousesecondary", Input.Buttons.RIGHT) // right mouse
|
jsonObject.addProperty("mousesecondary", Input.Buttons.RIGHT) // right mouse
|
||||||
@@ -75,23 +77,17 @@ object DefaultConfig {
|
|||||||
|
|
||||||
jsonObject.addProperty("pcgamepadenv", "console")
|
jsonObject.addProperty("pcgamepadenv", "console")
|
||||||
|
|
||||||
jsonObject.addProperty("safetywarning", true)
|
//jsonObject.addProperty("safetywarning", true)
|
||||||
|
|
||||||
|
|
||||||
jsonObject.addProperty("maxparticles", 768)
|
jsonObject.addProperty("maxparticles", 768)
|
||||||
|
|
||||||
|
|
||||||
jsonObject.addProperty("fullframelightupdate", false)
|
|
||||||
|
|
||||||
jsonObject.addProperty("temperatureunit", 1) // -1: american, 0: kelvin, 1: celcius
|
jsonObject.addProperty("temperatureunit", 1) // -1: american, 0: kelvin, 1: celcius
|
||||||
|
|
||||||
|
|
||||||
// "fancy" graphics settings
|
// "fancy" graphics settings
|
||||||
jsonObject.addProperty("fxdither", true)
|
jsonObject.addProperty("fxdither", true)
|
||||||
jsonObject.addProperty("fx3dlut", false)
|
//jsonObject.addProperty("fx3dlut", false)
|
||||||
|
|
||||||
|
|
||||||
jsonObject.addProperty("__debug", false)
|
|
||||||
|
|
||||||
|
|
||||||
return jsonObject
|
return jsonObject
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package net.torvald.terrarum
|
|||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.Screen
|
import com.badlogic.gdx.Screen
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.GL20
|
|
||||||
import com.badlogic.gdx.graphics.OrthographicCamera
|
import com.badlogic.gdx.graphics.OrthographicCamera
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
@@ -39,8 +38,7 @@ object ErrorDisp : Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun render(delta: Float) {
|
override fun render(delta: Float) {
|
||||||
Gdx.gl.glClearColor(.094f, .094f, .094f, 0f)
|
gdxClearAndSetBlend(.094f, .094f, .094f, 0f)
|
||||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
* list of Actors that is sorted by Actors' referenceID
|
* list of Actors that is sorted by Actors' referenceID
|
||||||
*/
|
*/
|
||||||
//val ACTORCONTAINER_INITIAL_SIZE = 64
|
//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 actorContainer = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
|
||||||
//val actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
|
//val actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
|
||||||
val particlesContainer = CircularArray<ParticleBase>(PARTICLES_MAX)
|
val particlesContainer = CircularArray<ParticleBase>(PARTICLES_MAX)
|
||||||
@@ -362,14 +362,14 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
width = 900,
|
width = 900,
|
||||||
height = Terrarum.HEIGHT - 160,
|
height = Terrarum.HEIGHT - 160,
|
||||||
categoryWidth = 210,
|
categoryWidth = 210,
|
||||||
toggleKeyLiteral = Terrarum.getConfigInt("keyinventory")
|
toggleKeyLiteral = AppLoader.getConfigInt("keyinventory")
|
||||||
)*/
|
)*/
|
||||||
/*uiInventoryPlayer.setPosition(
|
/*uiInventoryPlayer.setPosition(
|
||||||
-uiInventoryPlayer.width,
|
-uiInventoryPlayer.width,
|
||||||
70
|
70
|
||||||
)*/
|
)*/
|
||||||
uiInventoryPlayer = UIInventoryFull(player,
|
uiInventoryPlayer = UIInventoryFull(player,
|
||||||
toggleKeyLiteral = Terrarum.getConfigInt("keyinventory")
|
toggleKeyLiteral = AppLoader.getConfigInt("keyinventory")
|
||||||
)
|
)
|
||||||
uiInventoryPlayer.setPosition(0, 0)
|
uiInventoryPlayer.setPosition(0, 0)
|
||||||
|
|
||||||
@@ -464,7 +464,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
override fun run() {
|
override fun run() {
|
||||||
var updateTries = 0
|
var updateTries = 0
|
||||||
while (ingame.updateDeltaCounter >= ingame.updateRate) {
|
while (ingame.updateDeltaCounter >= ingame.updateRate) {
|
||||||
ingame.updateGame(Terrarum.deltaTime)
|
ingame.updateGame(AppLoader.UPDATE_RATE.toFloat())
|
||||||
ingame.updateDeltaCounter -= ingame.updateRate
|
ingame.updateDeltaCounter -= ingame.updateRate
|
||||||
updateTries++
|
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) {
|
if (firstTimeRun || updateThreadWrapper.state == Thread.State.TERMINATED) {
|
||||||
updateThreadWrapper = Thread(ingameUpdateThread, "Terrarum UpdateThread")
|
updateThreadWrapper = Thread(ingameUpdateThread, "Terrarum UpdateThread")
|
||||||
updateThreadWrapper.start()
|
updateThreadWrapper.start()
|
||||||
@@ -529,7 +529,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
while (updateDeltaCounter >= updateRate) {
|
while (updateDeltaCounter >= updateRate) {
|
||||||
|
|
||||||
//updateGame(delta)
|
//updateGame(delta)
|
||||||
Terrarum.debugTimers["Ingame.update"] = measureNanoTime { updateGame(delta) }
|
AppLoader.measureDebugTime("Ingame.update") { updateGame(delta) }
|
||||||
|
|
||||||
updateDeltaCounter -= updateRate
|
updateDeltaCounter -= updateRate
|
||||||
updateTries++
|
updateTries++
|
||||||
@@ -544,7 +544,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
/** RENDER CODE GOES HERE */
|
/** RENDER CODE GOES HERE */
|
||||||
//renderGame(batch)
|
//renderGame(batch)
|
||||||
Terrarum.debugTimers["Ingame.render"] = measureNanoTime { renderGame(batch) }
|
AppLoader.measureDebugTime("Ingame.render") { renderGame(batch) }
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun updateGame(delta: Float) {
|
protected fun updateGame(delta: Float) {
|
||||||
@@ -1090,7 +1090,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
playableActorDelegate = newActor
|
playableActorDelegate = newActor
|
||||||
WorldSimulator(player, Terrarum.deltaTime)
|
WorldSimulator(player, AppLoader.UPDATE_RATE.toFloat())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun changePossession(refid: Int) {
|
private fun changePossession(refid: Int) {
|
||||||
@@ -1107,7 +1107,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
// accept new delegate
|
// accept new delegate
|
||||||
playableActorDelegate = PlayableActorDelegate(getActorByID(refid) as ActorHumanoid)
|
playableActorDelegate = PlayableActorDelegate(getActorByID(refid) as ActorHumanoid)
|
||||||
playableActorDelegate!!.actor.collisionType = ActorWithPhysics.COLLISION_KINEMATIC
|
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. */
|
/** Send message to notifier UI and toggle the UI as opened. */
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ class GdxColorMap {
|
|||||||
height = pixmap.height
|
height = pixmap.height
|
||||||
is2D = pixmap.height > 1
|
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)
|
pixmap.getPixel(it % pixmap.width, it / pixmap.width)
|
||||||
})
|
}
|
||||||
|
|
||||||
|
|
||||||
AppLoader.printdbg(this, "Loading colormap from ${imageFile.name()}; PixmapFormat: ${pixmap.format}; Dimension: $width x $height")
|
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, y: Int): RGBA8888 = data[y * width + x]
|
||||||
fun getRaw(x: Int): RGBA8888 = if (is2D) throw OperationNotSupportedException("This is 2D color map") else data[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.Screen
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import com.badlogic.gdx.utils.Queue
|
||||||
import net.torvald.terrarum.gameactors.Actor
|
import net.torvald.terrarum.gameactors.Actor
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||||
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.ui.ConsoleWindow
|
import net.torvald.terrarum.ui.ConsoleWindow
|
||||||
import java.util.ArrayList
|
import java.util.*
|
||||||
import java.util.concurrent.locks.Lock
|
import java.util.concurrent.locks.Lock
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
import javax.swing.JOptionPane
|
import javax.swing.JOptionPane
|
||||||
@@ -23,7 +25,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
|||||||
|
|
||||||
open lateinit var consoleHandler: ConsoleWindow
|
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. */
|
/** how many different planets/stages/etc. are thenre. Whole stages must be manually managed by YOU. */
|
||||||
var gameworldCount = 0
|
var gameworldCount = 0
|
||||||
/** The actor the game is currently allowing you to control.
|
/** 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 actorNowPlaying: ActorHumanoid? = null
|
||||||
|
|
||||||
|
open var gameInitialised = false
|
||||||
|
internal set
|
||||||
|
open var gameFullyLoaded = false
|
||||||
|
internal set
|
||||||
|
|
||||||
val ACTORCONTAINER_INITIAL_SIZE = 64
|
val ACTORCONTAINER_INITIAL_SIZE = 64
|
||||||
val actorContainer = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
|
val actorContainer = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
|
||||||
val actorContainerInactive = 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 hide() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun show() {
|
override fun show() {
|
||||||
|
// the very basic show() implementation
|
||||||
|
gameInitialised = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun render(delta: Float) {
|
override fun render(delta: Float) {
|
||||||
@@ -89,6 +102,33 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
|||||||
open fun worldSecondaryClickEnd(delta: Float) {
|
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>) {
|
fun insertionSortLastElem(arr: ArrayList<Actor>) {
|
||||||
lock(ReentrantLock()) {
|
ReentrantLock().lock {
|
||||||
var j = arr.lastIndex - 1
|
var j = arr.lastIndex - 1
|
||||||
val x = arr.last()
|
val x = arr.last()
|
||||||
while (j >= 0 && arr[j] > x) {
|
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()
|
data class BlockChangeQueueItem(val old: Int, val new: Int, val posX: Int, val posY: Int)
|
||||||
try {
|
}
|
||||||
body()
|
|
||||||
}
|
inline fun Lock.lock(body: () -> Unit) {
|
||||||
finally {
|
this.lock()
|
||||||
lock.unlock()
|
try {
|
||||||
}
|
body()
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
this.unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,6 @@ import com.google.gson.JsonPrimitive
|
|||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
|
|
||||||
typealias ItemValue = KVHashMap
|
typealias ItemValue = KVHashMap
|
||||||
typealias GameConfig = KVHashMap
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2015-12-30.
|
* Created by minjaesong on 2015-12-30.
|
||||||
|
|||||||
@@ -2,19 +2,21 @@ package net.torvald.terrarum
|
|||||||
|
|
||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.ScreenAdapter
|
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.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.dataclass.HistoryArray
|
import net.torvald.dataclass.HistoryArray
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.modulebasegame.Ingame
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2017-07-13.
|
* Created by minjaesong on 2017-07-13.
|
||||||
*/
|
*/
|
||||||
object LoadScreen : ScreenAdapter() {
|
object LoadScreen : ScreenAdapter() {
|
||||||
|
|
||||||
var screenToLoad: Ingame? = null
|
var screenToLoad: IngameInstance? = null
|
||||||
private lateinit var screenLoadingThread: Thread
|
private lateinit var screenLoadingThread: Thread
|
||||||
|
|
||||||
|
|
||||||
@@ -123,12 +125,10 @@ object LoadScreen : ScreenAdapter() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Gdx.gl.glClearColor(.094f, .094f, .094f, 0f)
|
gdxClearAndSetBlend(.094f, .094f, .094f, 0f)
|
||||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
|
||||||
|
|
||||||
textFbo.inAction(null, null) {
|
textFbo.inAction(null, null) {
|
||||||
Gdx.gl.glClearColor(0f, 0f, 0f, 0f)
|
gdxClearAndSetBlend(0f, 0f, 0f, 0f)
|
||||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update arrow object
|
// update arrow object
|
||||||
@@ -161,7 +161,7 @@ object LoadScreen : ScreenAdapter() {
|
|||||||
Terrarum.batch.inUse {
|
Terrarum.batch.inUse {
|
||||||
|
|
||||||
|
|
||||||
blendNormal()
|
blendNormal(Terrarum.batch)
|
||||||
Terrarum.fontGame
|
Terrarum.fontGame
|
||||||
it.color = Color.WHITE
|
it.color = Color.WHITE
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ object LoadScreen : ScreenAdapter() {
|
|||||||
Terrarum.fontGame.draw(it, textToPrint, ((textFbo.width - textWidth) / 2).toInt().toFloat(), 0f)
|
Terrarum.fontGame.draw(it, textToPrint, ((textFbo.width - textWidth) / 2).toInt().toFloat(), 0f)
|
||||||
|
|
||||||
|
|
||||||
blendMul()
|
blendMul(Terrarum.batch)
|
||||||
// draw colour overlay, flipped
|
// draw colour overlay, flipped
|
||||||
it.draw(textOverlayTex,
|
it.draw(textOverlayTex,
|
||||||
(textFbo.width - textWidth) / 2f,
|
(textFbo.width - textWidth) / 2f,
|
||||||
@@ -184,7 +184,7 @@ object LoadScreen : ScreenAdapter() {
|
|||||||
Terrarum.batch.inUse {
|
Terrarum.batch.inUse {
|
||||||
initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT) // dunno, no render without this
|
initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT) // dunno, no render without this
|
||||||
it.projectionMatrix = camera.combined
|
it.projectionMatrix = camera.combined
|
||||||
blendNormal()
|
blendNormal(Terrarum.batch)
|
||||||
|
|
||||||
|
|
||||||
// almost black background
|
// almost black background
|
||||||
@@ -239,7 +239,7 @@ object LoadScreen : ScreenAdapter() {
|
|||||||
for (i in 0 until messages.elemCount) {
|
for (i in 0 until messages.elemCount) {
|
||||||
Terrarum.fontGame.draw(it,
|
Terrarum.fontGame.draw(it,
|
||||||
messages[i] ?: "",
|
messages[i] ?: "",
|
||||||
40f,
|
AppLoader.getTvSafeGraphicsWidth() + 16f,
|
||||||
80f + (messages.size - i - 1) * Terrarum.fontGame.lineHeight
|
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
|
initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT) // dunno, no render without this
|
||||||
it.projectionMatrix = camera.combined
|
it.projectionMatrix = camera.combined
|
||||||
blendNormal()
|
blendNormal(Terrarum.batch)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -264,7 +264,7 @@ object LoadScreen : ScreenAdapter() {
|
|||||||
for (i in 0 until messages.elemCount) {
|
for (i in 0 until messages.elemCount) {
|
||||||
Terrarum.fontGame.draw(it,
|
Terrarum.fontGame.draw(it,
|
||||||
messages[i] ?: "",
|
messages[i] ?: "",
|
||||||
40f,
|
AppLoader.getTvSafeGraphicsWidth() + 16f,
|
||||||
80f + (messages.size - i - 1) * Terrarum.fontGame.lineHeight
|
80f + (messages.size - i - 1) * Terrarum.fontGame.lineHeight
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -313,7 +313,6 @@ object LoadScreen : ScreenAdapter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun hide() {
|
override fun hide() {
|
||||||
dispose()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resize(width: Int, height: Int) {
|
override fun resize(width: Int, height: Int) {
|
||||||
|
|||||||
@@ -229,6 +229,8 @@ object ModMgr {
|
|||||||
val className = it["classname"].toString()
|
val className = it["classname"].toString()
|
||||||
val itemID = it["id"].toInt()
|
val itemID = it["id"].toInt()
|
||||||
|
|
||||||
|
printdbg(this, "Reading item #$itemID with className $className")
|
||||||
|
|
||||||
val loadedClass = Class.forName(className)
|
val loadedClass = Class.forName(className)
|
||||||
val loadedClassConstructor = loadedClass.getConstructor(ItemID::class.java)
|
val loadedClassConstructor = loadedClass.getConstructor(ItemID::class.java)
|
||||||
val loadedClassInstance = loadedClassConstructor.newInstance(itemID)
|
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())
|
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
|
package net.torvald.terrarum
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx
|
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.GL20
|
||||||
|
import com.badlogic.gdx.graphics.OrthographicCamera
|
||||||
import com.badlogic.gdx.graphics.Texture
|
import com.badlogic.gdx.graphics.Texture
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
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.FrameBuffer
|
||||||
import com.badlogic.gdx.graphics.glutils.ShaderProgram
|
import com.badlogic.gdx.graphics.glutils.ShaderProgram
|
||||||
|
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
|
||||||
import com.badlogic.gdx.math.Matrix4
|
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
|
* Must be called by the App Loader
|
||||||
@@ -16,57 +20,139 @@ import kotlin.system.measureNanoTime
|
|||||||
object PostProcessor {
|
object PostProcessor {
|
||||||
|
|
||||||
private lateinit var batch: SpriteBatch // not nulling to save some lines of code
|
private lateinit var batch: SpriteBatch // not nulling to save some lines of code
|
||||||
//private lateinit var camera: OrthographicCamera
|
private lateinit var shapeRenderer: ShapeRenderer
|
||||||
private var textureRegion: TextureRegion? = null
|
private lateinit var camera: OrthographicCamera
|
||||||
|
|
||||||
|
|
||||||
private lateinit var lutTex: Texture
|
private lateinit var lutTex: Texture
|
||||||
|
|
||||||
|
private var init = false
|
||||||
|
|
||||||
fun reloadLUT(filename: String) {
|
fun reloadLUT(filename: String) {
|
||||||
lutTex = Texture(Gdx.files.internal("assets/clut/$filename"))
|
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) {
|
fun draw(projMat: Matrix4, fbo: FrameBuffer) {
|
||||||
|
|
||||||
if (textureRegion == null) {
|
// init
|
||||||
textureRegion = TextureRegion(fbo.colorBufferTexture)
|
if (!init) {
|
||||||
|
init = true
|
||||||
|
|
||||||
|
debugUI.setPosition(0, 0)
|
||||||
|
|
||||||
batch = SpriteBatch()
|
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)
|
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)
|
gdxClearAndSetBlend(.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)
|
|
||||||
|
|
||||||
val shader: ShaderProgram? =
|
postShader(projMat, fbo)
|
||||||
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
|
|
||||||
|
|
||||||
|
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.
|
* 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.Gdx
|
||||||
import com.badlogic.gdx.Screen
|
import com.badlogic.gdx.Screen
|
||||||
import com.badlogic.gdx.assets.AssetManager
|
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.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||||
import com.badlogic.gdx.graphics.glutils.ShaderProgram
|
import com.badlogic.gdx.graphics.glutils.ShaderProgram
|
||||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
|
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
|
||||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||||
import com.google.gson.JsonArray
|
|
||||||
import com.google.gson.JsonPrimitive
|
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.dataclass.ArrayListMap
|
|
||||||
import net.torvald.dataclass.CircularArray
|
import net.torvald.dataclass.CircularArray
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
import net.torvald.terrarum.AppLoader.printdbg
|
import net.torvald.terrarum.AppLoader.*
|
||||||
import net.torvald.terrarum.AppLoader.printdbgerr
|
|
||||||
import net.torvald.terrarum.gameactors.Actor
|
import net.torvald.terrarum.gameactors.Actor
|
||||||
import net.torvald.terrarum.gameactors.ActorID
|
import net.torvald.terrarum.gameactors.ActorID
|
||||||
import net.torvald.terrarum.imagefont.TinyAlphNum
|
import net.torvald.terrarum.imagefont.TinyAlphNum
|
||||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
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.FeaturesDrawer
|
||||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase
|
import net.torvald.terrarumsansbitmap.gdx.GameFontBase
|
||||||
@@ -30,8 +27,7 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
|||||||
import org.lwjgl.BufferUtils
|
import org.lwjgl.BufferUtils
|
||||||
import org.lwjgl.input.Controllers
|
import org.lwjgl.input.Controllers
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import kotlin.math.absoluteValue
|
||||||
import net.torvald.getcpuname.GetCpuName
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -50,11 +46,6 @@ object Terrarum : Screen {
|
|||||||
*/
|
*/
|
||||||
const val PLAYER_REF_ID: Int = 0x91A7E2
|
const val PLAYER_REF_ID: Int = 0x91A7E2
|
||||||
|
|
||||||
val debugTimers = ArrayListMap<String, Long>()
|
|
||||||
|
|
||||||
var screenW = 0
|
|
||||||
var screenH = 0
|
|
||||||
|
|
||||||
lateinit var batch: SpriteBatch
|
lateinit var batch: SpriteBatch
|
||||||
lateinit var shapeRender: ShapeRenderer // DO NOT USE!! for very limited applications e.g. WeatherMixer
|
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) {
|
inline fun inShapeRenderer(shapeRendererType: ShapeRenderer.ShapeType = ShapeRenderer.ShapeType.Filled, action: (ShapeRenderer) -> Unit) {
|
||||||
@@ -69,9 +60,9 @@ object Terrarum : Screen {
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
val WIDTH: Int
|
val WIDTH: Int
|
||||||
get() = if (screenW % 2 == 0) screenW else screenW - 1
|
get() = AppLoader.screenW
|
||||||
val HEIGHT: Int
|
val HEIGHT: Int
|
||||||
get() = if (screenH % 2 == 0) screenH else screenH - 1
|
get() = AppLoader.screenH
|
||||||
|
|
||||||
//val WIDTH_MIN = 800
|
//val WIDTH_MIN = 800
|
||||||
//val HEIGHT_MIN = 600
|
//val HEIGHT_MIN = 600
|
||||||
@@ -82,44 +73,22 @@ object Terrarum : Screen {
|
|||||||
get() = HEIGHT.ushr(1)
|
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!!)
|
// 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
|
// 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 previousScreen: Screen? = null // to be used with temporary states like StateMonitorCheck
|
||||||
|
|
||||||
|
|
||||||
var ingame: IngameInstance? = null
|
var ingame: IngameInstance? = null
|
||||||
private val gameConfig = GameConfig()
|
|
||||||
|
|
||||||
val OSName = System.getProperty("os.name")
|
private val javaHeapCircularArray = CircularArray<Int>(64)
|
||||||
val OSVersion = System.getProperty("os.version")
|
private val nativeHeapCircularArray = CircularArray<Int>(64)
|
||||||
lateinit var OperationSystem: String // all caps "WINDOWS, "OSX", "LINUX", "SOLARIS", "UNKNOWN"
|
private val updateRateCircularArray = CircularArray<Double>(16)
|
||||||
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)
|
|
||||||
|
|
||||||
val memJavaHeap: Int
|
val memJavaHeap: Int
|
||||||
get() {
|
get() {
|
||||||
@@ -139,30 +108,35 @@ object Terrarum : Screen {
|
|||||||
}
|
}
|
||||||
val memXmx: Int
|
val memXmx: Int
|
||||||
get() = (Runtime.getRuntime().maxMemory() shr 20).toInt()
|
get() = (Runtime.getRuntime().maxMemory() shr 20).toInt()
|
||||||
|
val updateRateStr: String
|
||||||
|
get() {
|
||||||
|
updateRateCircularArray.add(updateRate)
|
||||||
|
|
||||||
var environment: RunningEnvironment
|
var acc = 0.0
|
||||||
private set
|
updateRateCircularArray.forEach { acc = maxOf(acc, it) }
|
||||||
|
return String.format("%.2f", acc)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val fontGame: GameFontBase = AppLoader.fontGame
|
val fontGame: GameFontBase = AppLoader.fontGame
|
||||||
lateinit var fontSmallNumbers: TinyAlphNum
|
val fontSmallNumbers: TinyAlphNum = AppLoader.fontSmallNumbers
|
||||||
|
|
||||||
var joypadLabelStart: Char = 0xE000.toChar() // lateinit
|
var gamepadLabelStart: Char = 0xE000.toChar() // lateinit
|
||||||
var joypadLableSelect: Char = 0xE000.toChar() // lateinit
|
var gamepadLableSelect: Char = 0xE000.toChar() // lateinit
|
||||||
var joypadLabelNinA: Char = 0xE000.toChar() // lateinit TODO
|
var gamepadLabelNinA: Char = 0xE000.toChar() // lateinit TODO
|
||||||
var joypadLabelNinB: Char = 0xE000.toChar() // lateinit TODO
|
var gamepadLabelNinB: Char = 0xE000.toChar() // lateinit TODO
|
||||||
var joypadLabelNinX: Char = 0xE000.toChar() // lateinit TODO
|
var gamepadLabelNinX: Char = 0xE000.toChar() // lateinit TODO
|
||||||
var joypadLabelNinY: Char = 0xE000.toChar() // lateinit TODO
|
var gamepadLabelNinY: Char = 0xE000.toChar() // lateinit TODO
|
||||||
var joypadLabelNinL: Char = 0xE000.toChar() // lateinit TODO
|
var gamepadLabelNinL: Char = 0xE000.toChar() // lateinit TODO
|
||||||
var joypadLabelNinR: Char = 0xE000.toChar() // lateinit TODO
|
var gamepadLabelNinR: Char = 0xE000.toChar() // lateinit TODO
|
||||||
var joypadLabelNinZL: Char = 0xE000.toChar() // lateinit TODO
|
var gamepadLabelNinZL: Char = 0xE000.toChar() // lateinit TODO
|
||||||
var joypadLabelNinZR: Char = 0xE000.toChar() // lateinit TODO
|
var gamepadLabelNinZR: Char = 0xE000.toChar() // lateinit TODO
|
||||||
val joypadLabelLEFT = 0xE068.toChar()
|
val gamepadLabelLEFT = 0xE068.toChar()
|
||||||
val joypadLabelDOWN = 0xE069.toChar()
|
val gamepadLabelDOWN = 0xE069.toChar()
|
||||||
val joypadLabelUP = 0xE06A.toChar()
|
val gamepadLabelUP = 0xE06A.toChar()
|
||||||
val joypadLabelRIGHT = 0xE06B.toChar()
|
val gamepadLabelRIGHT = 0xE06B.toChar()
|
||||||
|
|
||||||
// 0x0 - 0xF: Game-related
|
// 0x0 - 0xF: Game-related
|
||||||
// 0x10 - 0x1F: Config
|
// 0x10 - 0x1F: Config
|
||||||
@@ -185,12 +159,8 @@ object Terrarum : Screen {
|
|||||||
val STATE_ID_TOOL_NOISEGEN = 0x200
|
val STATE_ID_TOOL_NOISEGEN = 0x200
|
||||||
val STATE_ID_TOOL_RUMBLE_DIAGNOSIS = 0x201
|
val STATE_ID_TOOL_RUMBLE_DIAGNOSIS = 0x201
|
||||||
|
|
||||||
var controller: org.lwjgl.input.Controller? = null
|
|
||||||
private set
|
|
||||||
val CONTROLLER_DEADZONE = 0.1f
|
|
||||||
|
|
||||||
/** Available CPU threads */
|
/** Available CPU threads */
|
||||||
val THREADS = Runtime.getRuntime().availableProcessors()
|
val THREADS = Runtime.getRuntime().availableProcessors() + 1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the game is multithreading.
|
* If the game is multithreading.
|
||||||
@@ -199,20 +169,11 @@ object Terrarum : Screen {
|
|||||||
* THREADS >= 2 and config "multithread" is true
|
* THREADS >= 2 and config "multithread" is true
|
||||||
*/
|
*/
|
||||||
val MULTITHREAD: Boolean
|
val MULTITHREAD: Boolean
|
||||||
get() = THREADS >= 2 && getConfigBoolean("multithread")
|
get() = THREADS >= 3 && getConfigBoolean("multithread")
|
||||||
|
|
||||||
private lateinit var configDir: String
|
|
||||||
|
|
||||||
const val NAME = AppLoader.GAME_NAME
|
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 shaderBlur: ShaderProgram
|
||||||
lateinit var shaderBayer: ShaderProgram
|
lateinit var shaderBayer: ShaderProgram
|
||||||
lateinit var shaderSkyboxFill: ShaderProgram
|
lateinit var shaderSkyboxFill: ShaderProgram
|
||||||
@@ -220,10 +181,6 @@ object Terrarum : Screen {
|
|||||||
lateinit var shaderRGBOnly: ShaderProgram
|
lateinit var shaderRGBOnly: ShaderProgram
|
||||||
lateinit var shaderAtoGrey: ShaderProgram
|
lateinit var shaderAtoGrey: ShaderProgram
|
||||||
|
|
||||||
|
|
||||||
lateinit var textureWhiteSquare: Texture
|
|
||||||
|
|
||||||
|
|
||||||
lateinit var testTexture: Texture
|
lateinit var testTexture: Texture
|
||||||
|
|
||||||
|
|
||||||
@@ -231,8 +188,6 @@ object Terrarum : Screen {
|
|||||||
val fullscreenQuad = AppLoader.fullscreenQuad
|
val fullscreenQuad = AppLoader.fullscreenQuad
|
||||||
|
|
||||||
|
|
||||||
val deltaTime: Float; get() = Gdx.graphics.rawDeltaTime
|
|
||||||
|
|
||||||
|
|
||||||
lateinit var assetManager: AssetManager // TODO
|
lateinit var assetManager: AssetManager // TODO
|
||||||
|
|
||||||
@@ -243,16 +198,6 @@ object Terrarum : Screen {
|
|||||||
println("LibGDX version ${com.badlogic.gdx.Version.VERSION}")
|
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
|
println("os.arch = $systemArch") // debug info
|
||||||
|
|
||||||
if (is32BitJVM) {
|
if (is32BitJVM) {
|
||||||
@@ -264,12 +209,12 @@ object Terrarum : Screen {
|
|||||||
println("vendor = $processorVendor")
|
println("vendor = $processorVendor")
|
||||||
|
|
||||||
|
|
||||||
joypadLabelStart = when (getConfigString("joypadlabelstyle")) {
|
gamepadLabelStart = when (getConfigString("gamepadlabelstyle")) {
|
||||||
"nwii" -> 0xE04B.toChar() // + mark
|
"nwii" -> 0xE04B.toChar() // + mark
|
||||||
"logitech" -> 0xE05A.toChar() // number 10
|
"logitech" -> 0xE05A.toChar() // number 10
|
||||||
else -> 0xE042.toChar() // |> mark (sonyps, msxb360, generic)
|
else -> 0xE042.toChar() // |> mark (sonyps, msxb360, generic)
|
||||||
}
|
}
|
||||||
joypadLableSelect = when (getConfigString("joypadlabelstyle")) {
|
gamepadLableSelect = when (getConfigString("gamepadlabelstyle")) {
|
||||||
"nwii" -> 0xE04D.toChar() // - mark
|
"nwii" -> 0xE04D.toChar() // - mark
|
||||||
"logitech" -> 0xE059.toChar() // number 9
|
"logitech" -> 0xE059.toChar() // number 9
|
||||||
"sonyps" -> 0xE043.toChar() // solid rectangle
|
"sonyps" -> 0xE043.toChar() // solid rectangle
|
||||||
@@ -278,17 +223,19 @@ object Terrarum : Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// setting environment as MOBILE precedes this code
|
||||||
environment = try {
|
//if (environment != RunningEnvironment.MOBILE) {
|
||||||
Controllers.getController(0) // test if controller exists
|
environment = try {
|
||||||
if (getConfigString("pcgamepadenv") == "console")
|
Controllers.getController(0) // test if controller exists
|
||||||
RunningEnvironment.CONSOLE
|
if (getConfigString("pcgamepadenv") == "console")
|
||||||
else
|
RunningEnvironment.CONSOLE
|
||||||
|
else
|
||||||
|
RunningEnvironment.PC
|
||||||
|
}
|
||||||
|
catch (e: IndexOutOfBoundsException) {
|
||||||
RunningEnvironment.PC
|
RunningEnvironment.PC
|
||||||
}
|
}
|
||||||
catch (e: IndexOutOfBoundsException) {
|
//}
|
||||||
RunningEnvironment.PC
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,20 +261,17 @@ object Terrarum : Screen {
|
|||||||
val MINIMAL_GL_MAX_TEXTURE_SIZE = 4096
|
val MINIMAL_GL_MAX_TEXTURE_SIZE = 4096
|
||||||
|
|
||||||
override fun show() {
|
override fun show() {
|
||||||
if (environment != RunningEnvironment.MOBILE) {
|
|
||||||
Gdx.gl.glDisable(GL20.GL_DITHER)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
assetManager = AssetManager()
|
assetManager = AssetManager()
|
||||||
|
|
||||||
|
|
||||||
testTexture = Texture(Gdx.files.internal("./assets/test_texture.tga"))
|
testTexture = Texture(Gdx.files.internal("./assets/test_texture.tga"))
|
||||||
|
|
||||||
|
|
||||||
|
val glInfo = Gdx.graphics.glVersion.debugVersionString
|
||||||
|
|
||||||
println("GL_VERSION = $GL_VERSION")
|
println("GL_VERSION = $GL_VERSION")
|
||||||
println("GL_MAX_TEXTURE_SIZE = $GL_MAX_TEXTURE_SIZE")
|
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) {
|
if (GL_VERSION < MINIMAL_GL_VERSION || GL_MAX_TEXTURE_SIZE < MINIMAL_GL_MAX_TEXTURE_SIZE) {
|
||||||
@@ -345,27 +289,19 @@ object Terrarum : Screen {
|
|||||||
shapeRender = ShapeRenderer()
|
shapeRender = ShapeRenderer()
|
||||||
|
|
||||||
|
|
||||||
//fontGame = GameFontBase("assets/graphics/fonts/terrarum-sans-bitmap", flipY = true)
|
|
||||||
fontSmallNumbers = TinyAlphNum
|
|
||||||
|
|
||||||
|
shaderBlur = AppLoader.loadShader("assets/blur.vert", "assets/blur.frag")
|
||||||
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"))
|
|
||||||
|
|
||||||
|
|
||||||
if (getConfigBoolean("fxdither")) {
|
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.begin()
|
||||||
shaderBayer.setUniformf("rcount", 64f)
|
shaderBayer.setUniformf("rcount", 64f)
|
||||||
shaderBayer.setUniformf("gcount", 64f)
|
shaderBayer.setUniformf("gcount", 64f)
|
||||||
shaderBayer.setUniformf("bcount", 64f)
|
shaderBayer.setUniformf("bcount", 64f)
|
||||||
shaderBayer.end()
|
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.begin()
|
||||||
shaderSkyboxFill.setUniformf("rcount", 64f)
|
shaderSkyboxFill.setUniformf("rcount", 64f)
|
||||||
shaderSkyboxFill.setUniformf("gcount", 64f)
|
shaderSkyboxFill.setUniformf("gcount", 64f)
|
||||||
@@ -373,15 +309,15 @@ object Terrarum : Screen {
|
|||||||
shaderSkyboxFill.end()
|
shaderSkyboxFill.end()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
shaderBayer = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/passthru.frag"))
|
shaderBayer = AppLoader.loadShader("assets/4096.vert", "assets/passthru.frag")
|
||||||
shaderSkyboxFill = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/skyboxfill.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"))
|
shaderRGBOnly = AppLoader.loadShader("assets/4096.vert", "assets/rgbonly.frag")
|
||||||
shaderAtoGrey = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/aonly.frag"))
|
shaderAtoGrey = AppLoader.loadShader("assets/4096.vert", "assets/aonly.frag")
|
||||||
|
|
||||||
|
|
||||||
if (!shaderBlendGlow.isCompiled) {
|
if (!shaderBlendGlow.isCompiled) {
|
||||||
@@ -419,18 +355,18 @@ object Terrarum : Screen {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// jump right into the ingame
|
// jump straight into the ingame
|
||||||
/*ingame = Ingame(batch)
|
/*val ingame = Ingame(batch)
|
||||||
ingame!!.gameLoadInfoPayload = Ingame.NewWorldParameters(2400, 800, HQRNG().nextLong())
|
ingame.gameLoadInfoPayload = Ingame.NewWorldParameters(2400, 800, HQRNG().nextLong())
|
||||||
ingame!!.gameLoadMode = Ingame.GameLoadMode.CREATE_NEW
|
ingame.gameLoadMode = Ingame.GameLoadMode.CREATE_NEW
|
||||||
LoadScreen.screenToLoad = ingame!!
|
LoadScreen.screenToLoad = ingame
|
||||||
super.setScreen(LoadScreen)*/
|
this.ingame = ingame
|
||||||
|
setScreen(LoadScreen)*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// title screen
|
// title screen
|
||||||
AppLoader.getINSTANCE().setScreen(TitleScreen(batch))
|
AppLoader.getINSTANCE().setScreen(TitleScreen(batch))
|
||||||
//appLoader.setScreen(FuckingWorldRenderer(batch))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setScreen(screen: Screen) {
|
fun setScreen(screen: Screen) {
|
||||||
@@ -438,10 +374,9 @@ object Terrarum : Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun render(delta: Float) {
|
override fun render(delta: Float) {
|
||||||
Terrarum.debugTimers["GDX.delta"] = delta.times(1000_000_000f).toLong()
|
AppLoader.setDebugTime("GDX.rawDelta", Gdx.graphics.rawDeltaTime.times(1000_000_000f).toLong())
|
||||||
AppLoader.getINSTANCE().screen.render(deltaTime)
|
AppLoader.setDebugTime("GDX.smtDelta", Gdx.graphics.deltaTime.times(1000_000_000f).toLong())
|
||||||
//GLOBAL_RENDER_TIMER += 1
|
AppLoader.getINSTANCE().screen.render(delta)
|
||||||
// moved to AppLoader; global event must be place at the apploader to prevent ACCIDENTAL forgot-to-update type of bug.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pause() {
|
override fun pause() {
|
||||||
@@ -452,231 +387,30 @@ object Terrarum : Screen {
|
|||||||
AppLoader.getINSTANCE().screen.resume()
|
AppLoader.getINSTANCE().screen.resume()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Don't call this! Call AppLoader.dispose() */
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
AppLoader.getINSTANCE().screen.dispose()
|
|
||||||
|
|
||||||
fontGame.dispose()
|
|
||||||
fontSmallNumbers.dispose()
|
|
||||||
|
|
||||||
|
|
||||||
//dispose any other resources used in this level
|
//dispose any other resources used in this level
|
||||||
|
|
||||||
|
|
||||||
shaderBayer.dispose()
|
shaderBayer.dispose()
|
||||||
shaderSkyboxFill.dispose()
|
shaderSkyboxFill.dispose()
|
||||||
shaderBlur.dispose()
|
shaderBlur.dispose()
|
||||||
shaderBlendGlow.dispose()
|
shaderBlendGlow.dispose()
|
||||||
|
|
||||||
|
ingame?.dispose()
|
||||||
shapeRender.dispose()
|
|
||||||
batch.dispose()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hide() {
|
override fun hide() {
|
||||||
AppLoader.getINSTANCE().screen.hide()
|
AppLoader.getINSTANCE().screen.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** For the actual resize, call AppLoader.resize() */
|
||||||
override fun resize(width: Int, height: Int) {
|
override fun resize(width: Int, height: Int) {
|
||||||
//var width = maxOf(width, WIDTH_MIN)
|
ingame?.resize(width, height)
|
||||||
//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)
|
|
||||||
|
|
||||||
printdbg(this, "newsize: ${Gdx.graphics.width}x${Gdx.graphics.height} | internal: ${width}x$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
|
val currentSaveDir: File
|
||||||
get() {
|
get() {
|
||||||
val file = File(defaultSaveDir + "/test")
|
val file = File(defaultSaveDir + "/test")
|
||||||
@@ -688,30 +422,36 @@ object Terrarum : Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Position of the cursor in the world */
|
/** Position of the cursor in the world */
|
||||||
inline val mouseX: Double
|
val mouseX: Double
|
||||||
get() = WorldCamera.x + Gdx.input.x / (ingame?.screenZoom ?: 1f).toDouble()
|
get() = WorldCamera.x + Gdx.input.x / (ingame?.screenZoom ?: 1f).toDouble()
|
||||||
/** Position of the cursor in the world */
|
/** Position of the cursor in the world */
|
||||||
inline val mouseY: Double
|
val mouseY: Double
|
||||||
get() = WorldCamera.y + Gdx.input.y / (ingame?.screenZoom ?: 1f).toDouble()
|
get() = WorldCamera.y + Gdx.input.y / (ingame?.screenZoom ?: 1f).toDouble()
|
||||||
/** Position of the cursor in the world */
|
/** 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()
|
get() = (mouseX / FeaturesDrawer.TILE_SIZE).floorInt()
|
||||||
/** Position of the cursor in the world */
|
/** Position of the cursor in the world */
|
||||||
@JvmStatic inline val mouseTileY: Int
|
@JvmStatic val mouseTileY: Int
|
||||||
get() = (mouseY / FeaturesDrawer.TILE_SIZE).floorInt()
|
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
|
inline val mouseScreenX: Int
|
||||||
get() = Gdx.input.x
|
get() = Gdx.input.x
|
||||||
inline val mouseScreenY: Int
|
inline val mouseScreenY: Int
|
||||||
get() = Gdx.input.y
|
get() = Gdx.input.y
|
||||||
/** Bigger than 1.0 */
|
/** Delta converted as it it was a FPS */
|
||||||
inline val updateRate: Double
|
inline val updateRate: Double
|
||||||
get() = 1.0 / Gdx.graphics.deltaTime
|
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:
|
* Usage:
|
||||||
*
|
*
|
||||||
@@ -727,6 +467,7 @@ object Terrarum : Screen {
|
|||||||
Actor.RenderOrder.MIDDLE -> Actor.RANGE_MIDDLE
|
Actor.RenderOrder.MIDDLE -> Actor.RANGE_MIDDLE
|
||||||
Actor.RenderOrder.MIDTOP -> Actor.RANGE_MIDTOP
|
Actor.RenderOrder.MIDTOP -> Actor.RANGE_MIDTOP
|
||||||
Actor.RenderOrder.FRONT -> Actor.RANGE_FRONT
|
Actor.RenderOrder.FRONT -> Actor.RANGE_FRONT
|
||||||
|
Actor.RenderOrder.OVERLAY-> Actor.RANDE_OVERLAY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (gameNotInitialisedException: KotlinNullPointerException) {
|
catch (gameNotInitialisedException: KotlinNullPointerException) {
|
||||||
@@ -780,9 +521,9 @@ fun Float.round(): Float {
|
|||||||
|
|
||||||
// ShapeRenderer alternative for rects
|
// ShapeRenderer alternative for rects
|
||||||
fun SpriteBatch.fillRect(x: Float, y: Float, w: Float, h: Float) {
|
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)
|
if (!isVertical)
|
||||||
this.fillRect(x, y, otherEnd - x, thickness)
|
this.fillRect(x, y, otherEnd - x, thickness)
|
||||||
else
|
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.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
|
||||||
|
|
||||||
|
return this
|
||||||
|
|
||||||
/*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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun blendNormal(batch: SpriteBatch? = null) {
|
|
||||||
(batch ?: Terrarum.batch).enableBlending()
|
fun blendMul(batch: SpriteBatch) {
|
||||||
(batch ?: Terrarum.batch).setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA)
|
// will break if the colour image contains semitransparency
|
||||||
Gdx.gl.glBlendEquation(GL20.GL_FUNC_ADD) // batch.flush does not touch blend equation
|
batch.enableBlending()
|
||||||
|
batch.setBlendFunction(GL20.GL_DST_COLOR, GL20.GL_ONE_MINUS_SRC_ALPHA)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun blendScreen(batch: SpriteBatch? = null) {
|
fun blendScreen(batch: SpriteBatch) {
|
||||||
(batch ?: Terrarum.batch).enableBlending()
|
// will break if the colour image contains semitransparency
|
||||||
(batch ?: Terrarum.batch).setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_COLOR)
|
batch.enableBlending()
|
||||||
Gdx.gl.glBlendEquation(GL20.GL_FUNC_ADD) // batch.flush does not touch blend equation
|
batch.setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_COLOR)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun blendDisable(batch: SpriteBatch? = null) {
|
fun blendDisable(batch: SpriteBatch) {
|
||||||
(batch ?: Terrarum.batch).disableBlending()
|
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 {
|
object BlendMode {
|
||||||
@@ -832,11 +615,11 @@ object BlendMode {
|
|||||||
const val NORMAL = "normal"
|
const val NORMAL = "normal"
|
||||||
//const val MAX = "GL_MAX" // not supported by GLES -- use shader
|
//const val MAX = "GL_MAX" // not supported by GLES -- use shader
|
||||||
|
|
||||||
fun resolve(mode: String) {
|
fun resolve(mode: String, batch: SpriteBatch) {
|
||||||
when (mode) {
|
when (mode) {
|
||||||
SCREEN -> blendScreen()
|
SCREEN -> blendScreen(batch)
|
||||||
MULTIPLY -> blendMul()
|
MULTIPLY -> blendMul(batch)
|
||||||
NORMAL -> blendNormal()
|
NORMAL -> blendNormal(batch)
|
||||||
//MAX -> blendLightenOnly() // not supported by GLES -- use shader
|
//MAX -> blendLightenOnly() // not supported by GLES -- use shader
|
||||||
else -> throw Error("Unknown blend mode: $mode")
|
else -> throw Error("Unknown blend mode: $mode")
|
||||||
}
|
}
|
||||||
@@ -844,7 +627,7 @@ object BlendMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum class RunningEnvironment {
|
enum class RunningEnvironment {
|
||||||
PC, CONSOLE, MOBILE
|
PC, CONSOLE//, MOBILE
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun Color.screen(other: Color) = Color(
|
infix fun Color.screen(other: Color) = Color(
|
||||||
@@ -890,23 +673,24 @@ val ccK = GameFontBase.toColorCode(0x888F)
|
|||||||
|
|
||||||
typealias Second = Float
|
typealias Second = Float
|
||||||
|
|
||||||
inline fun Int.sqr(): Int = this * this
|
fun Int.sqr(): Int = this * this
|
||||||
inline fun Double.floorInt() = Math.floor(this).toInt()
|
fun Double.floorInt() = Math.floor(this).toInt()
|
||||||
inline fun Float.floorInt() = FastMath.floor(this)
|
fun Float.floorInt() = FastMath.floor(this)
|
||||||
inline fun Float.floor() = FastMath.floor(this).toFloat()
|
fun Float.floor() = FastMath.floor(this).toFloat()
|
||||||
inline fun Double.ceilInt() = Math.ceil(this).toInt()
|
fun Double.ceilInt() = Math.ceil(this).toInt()
|
||||||
inline fun Float.ceil(): Float = FastMath.ceil(this).toFloat()
|
fun Float.ceil(): Float = FastMath.ceil(this).toFloat()
|
||||||
inline fun Float.ceilInt() = FastMath.ceil(this)
|
fun Float.ceilInt() = FastMath.ceil(this)
|
||||||
inline fun Double.round() = Math.round(this).toDouble()
|
fun Double.round() = Math.round(this).toDouble()
|
||||||
inline fun Double.floor() = Math.floor(this)
|
fun Double.floor() = Math.floor(this)
|
||||||
inline fun Double.ceil() = this.floor() + 1.0
|
fun Double.ceil() = this.floor() + 1.0
|
||||||
inline fun Double.roundInt(): Int = Math.round(this).toInt()
|
fun Double.roundInt(): Int = Math.round(this).toInt()
|
||||||
inline fun Float.roundInt(): Int = Math.round(this)
|
fun Float.roundInt(): Int = Math.round(this)
|
||||||
inline fun Double.abs() = Math.abs(this)
|
fun Double.abs() = Math.abs(this)
|
||||||
inline fun Double.sqr() = this * this
|
fun Double.sqr() = this * this
|
||||||
inline fun Double.sqrt() = Math.sqrt(this)
|
fun Float.sqr() = this * this
|
||||||
inline fun Float.sqrt() = FastMath.sqrt(this)
|
fun Double.sqrt() = Math.sqrt(this)
|
||||||
inline fun Int.abs() = if (this < 0) -this else this
|
fun Float.sqrt() = FastMath.sqrt(this)
|
||||||
|
fun Int.abs() = this.absoluteValue
|
||||||
fun Double.bipolarClamp(limit: Double) =
|
fun Double.bipolarClamp(limit: Double) =
|
||||||
this.coerceIn(-limit, limit)
|
this.coerceIn(-limit, limit)
|
||||||
|
|
||||||
@@ -939,3 +723,18 @@ fun interpolateLinear(scale: Double, startValue: Double, endValue: Double): Doub
|
|||||||
}
|
}
|
||||||
return (1.0 - scale) * startValue + scale * 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.Gdx
|
||||||
import com.badlogic.gdx.InputAdapter
|
import com.badlogic.gdx.InputAdapter
|
||||||
import com.badlogic.gdx.Screen
|
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.SpriteBatch
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
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.langpack.Lang
|
||||||
import net.torvald.terrarum.modulebasegame.Ingame
|
import net.torvald.terrarum.modulebasegame.Ingame
|
||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
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.GameWorldExtension
|
||||||
|
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIRemoCon
|
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.ui.UITitleRemoConYaml
|
||||||
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
|
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
|
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 demoWorld: GameWorldExtension
|
||||||
private lateinit var cameraNodes: FloatArray // camera Y-pos
|
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")))
|
demoWorld = ReadLayerData(FileInputStream(ModMgr.getFile("basegame", "demoworld")))
|
||||||
|
// set time to summer
|
||||||
|
demoWorld.time.addTime(WorldTime.DAY_LENGTH * 32)
|
||||||
|
|
||||||
// construct camera nodes
|
// construct camera nodes
|
||||||
val nodeCount = 100
|
val nodeCount = 100
|
||||||
cameraNodes = kotlin.FloatArray(nodeCount, { it ->
|
cameraNodes = kotlin.FloatArray(nodeCount) { it ->
|
||||||
val tileXPos = (demoWorld.width.toFloat() * it / nodeCount).floorInt()
|
val tileXPos = (demoWorld.width.toFloat() * it / nodeCount).floorInt()
|
||||||
var travelDownCounter = 0
|
var travelDownCounter = 0
|
||||||
while (!BlockCodex[demoWorld.getTileFromTerrain(tileXPos, travelDownCounter)].isSolid) {
|
while (!BlockCodex[demoWorld.getTileFromTerrain(tileXPos, travelDownCounter)].isSolid) {
|
||||||
travelDownCounter += 4
|
travelDownCounter += 4
|
||||||
}
|
}
|
||||||
travelDownCounter * FeaturesDrawer.TILE_SIZE.toFloat()
|
travelDownCounter * FeaturesDrawer.TILE_SIZE.toFloat()
|
||||||
})
|
}
|
||||||
|
|
||||||
|
|
||||||
cameraPlayer = object : HumanoidNPC(cameraAI, born = 0, usePhysics = false, forceAssignRefID = Terrarum.PLAYER_REF_ID) {
|
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)
|
uiContainer.add(uiMenu)
|
||||||
|
|
||||||
loadDone = true
|
//loadDone = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -172,7 +179,7 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun show() {
|
override fun show() {
|
||||||
printdbg(this, "atrniartsientsarinoetsar")
|
printdbg(this, "show() called")
|
||||||
|
|
||||||
initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT)
|
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)
|
worldFBO = FrameBuffer(Pixmap.Format.RGBA8888, Terrarum.WIDTH, Terrarum.HEIGHT, false)
|
||||||
|
|
||||||
|
loadThingsWhileIntroIsVisible()
|
||||||
|
|
||||||
|
printdbg(this, "show() exit")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private val introUncoverTime: Second = 0.3f
|
private val introUncoverTime: Second = 0.3f
|
||||||
private var introUncoverDeltaCounter = 0f
|
private var introUncoverDeltaCounter = 0f
|
||||||
private var updateDeltaCounter = 0.0
|
private var updateAkku = 0.0
|
||||||
protected val renderRate = Terrarum.renderRate
|
|
||||||
|
|
||||||
override fun render(delta: Float) {
|
override fun render(delta: Float) {
|
||||||
if (!loadDone) {
|
// async update and render
|
||||||
loadThingsWhileIntroIsVisible()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// async update
|
|
||||||
updateDeltaCounter += delta
|
|
||||||
var updateTries = 0
|
|
||||||
while (updateDeltaCounter >= renderRate) {
|
|
||||||
updateScreen(delta)
|
|
||||||
updateDeltaCounter -= renderRate
|
|
||||||
updateTries++
|
|
||||||
|
|
||||||
if (updateTries >= Terrarum.UPDATE_CATCHUP_MAX_TRIES) {
|
val dt = Gdx.graphics.deltaTime
|
||||||
break
|
updateAkku += dt
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// render? just do it anyway
|
var i = 0L
|
||||||
renderScreen()
|
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) {
|
fun updateScreen(delta: Float) {
|
||||||
//Gdx.graphics.setTitle(Ingame.getCanonicalTitle())
|
|
||||||
|
|
||||||
demoWorld.globalLight = WeatherMixer.globalLightNow
|
demoWorld.globalLight = WeatherMixer.globalLightNow
|
||||||
demoWorld.updateWorldTime(delta)
|
demoWorld.updateWorldTime(delta)
|
||||||
WeatherMixer.update(delta, cameraPlayer, demoWorld)
|
WeatherMixer.update(delta, cameraPlayer, demoWorld)
|
||||||
@@ -236,12 +243,13 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun renderScreen() {
|
fun renderScreen() {
|
||||||
|
Gdx.graphics.setTitle(Ingame.getCanonicalTitle())
|
||||||
|
|
||||||
|
|
||||||
//camera.setToOrtho(true, Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT.toFloat())
|
//camera.setToOrtho(true, Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT.toFloat())
|
||||||
|
|
||||||
// render world
|
// render world
|
||||||
Gdx.gl.glClearColor(.64f, .754f, .84f, 1f)
|
gdxClearAndSetBlend(.64f, .754f, .84f, 1f)
|
||||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
|
||||||
|
|
||||||
|
|
||||||
IngameRenderer.invoke(world = demoWorld, uisToDraw = uiContainer)
|
IngameRenderer.invoke(world = demoWorld, uisToDraw = uiContainer)
|
||||||
@@ -257,7 +265,7 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
|
|||||||
|
|
||||||
private fun renderOverlayTexts() {
|
private fun renderOverlayTexts() {
|
||||||
setCameraPosition(0f, 0f)
|
setCameraPosition(0f, 0f)
|
||||||
blendNormal()
|
blendNormal(batch)
|
||||||
batch.shader = null
|
batch.shader = null
|
||||||
|
|
||||||
batch.color = Color.LIGHT_GRAY
|
batch.color = Color.LIGHT_GRAY
|
||||||
@@ -289,22 +297,24 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun resize(width: Int, height: Int) {
|
override fun resize(width: Int, height: Int) {
|
||||||
|
printdbg(this, "resize() called")
|
||||||
|
|
||||||
// Set up viewport when window is resized
|
// Set up viewport when window is resized
|
||||||
initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT)
|
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 (!!)
|
||||||
// resize UI by re-creating it (!!)
|
uiMenu.resize(Terrarum.WIDTH, Terrarum.HEIGHT)
|
||||||
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, UITitleRemoConRoot.menubarOffY)
|
||||||
uiMenu.setPosition(0, 0) // shitty hack. Could be:
|
uiMenu.setPosition(0, 0) // shitty hack. Could be:
|
||||||
// 1: Init code and resize code are different
|
// 1: Init code and resize code are different
|
||||||
// 2: The UI is coded shit
|
// 2: The UI is coded shit
|
||||||
}
|
|
||||||
|
|
||||||
IngameRenderer.resize(Terrarum.WIDTH, Terrarum.HEIGHT)
|
IngameRenderer.resize(Terrarum.WIDTH, Terrarum.HEIGHT)
|
||||||
|
|
||||||
|
printdbg(this, "resize() exit")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import com.badlogic.gdx.graphics.Pixmap
|
|||||||
import com.badlogic.gdx.graphics.Texture
|
import com.badlogic.gdx.graphics.Texture
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull
|
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.
|
* Created by minjaesong on 2017-10-20.
|
||||||
@@ -18,6 +20,12 @@ class UIItemInventoryCatBar(
|
|||||||
override val width: Int
|
override val width: Int
|
||||||
) : UIItem(parentUI) {
|
) : 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 catIcons = parentUI.catIcons
|
||||||
private val catArrangement = parentUI.catArrangement
|
private val catArrangement = parentUI.catArrangement
|
||||||
|
|
||||||
@@ -91,15 +99,23 @@ class UIItemInventoryCatBar(
|
|||||||
private val underlineColour = Color(0xeaeaea_40.toInt())
|
private val underlineColour = Color(0xeaeaea_40.toInt())
|
||||||
private val underlineHighlightColour = mainButtons[0].highlightCol
|
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 highlighterXStart = highlighterXPos
|
||||||
private var highlighterXEnd = highlighterXPos
|
private var highlighterXEnd = highlighterXPos
|
||||||
|
|
||||||
private val highlighterYPos = catIcons.tileH + 4f
|
private val highlighterYPos = catIcons.tileH + 4f
|
||||||
private var highlighterMoving = false
|
private var highlighterMoving = false
|
||||||
private val highlighterMoveDuration: Second = 0.1f
|
private val highlighterMoveDuration: Second = 0.15f
|
||||||
private var highlighterMoveTimer: Second = 0f
|
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
|
// set up underlined indicator
|
||||||
init {
|
init {
|
||||||
// procedurally generate texture
|
// procedurally generate texture
|
||||||
@@ -134,8 +150,8 @@ class UIItemInventoryCatBar(
|
|||||||
highlighterXPos = UIUtils.moveQuick(
|
highlighterXPos = UIUtils.moveQuick(
|
||||||
highlighterXStart,
|
highlighterXStart,
|
||||||
highlighterXEnd,
|
highlighterXEnd,
|
||||||
highlighterMoveTimer.toDouble(),
|
highlighterMoveTimer,
|
||||||
highlighterMoveDuration.toDouble()
|
highlighterMoveDuration
|
||||||
)
|
)
|
||||||
|
|
||||||
if (highlighterMoveTimer > highlighterMoveDuration) {
|
if (highlighterMoveTimer > highlighterMoveDuration) {
|
||||||
@@ -150,23 +166,61 @@ class UIItemInventoryCatBar(
|
|||||||
mainButtons.forEachIndexed { index, btn ->
|
mainButtons.forEachIndexed { index, btn ->
|
||||||
btn.update(delta)
|
btn.update(delta)
|
||||||
|
|
||||||
|
if (btn.mousePushed && selectedPanel != 1) {
|
||||||
|
transitionFired = true
|
||||||
|
selectedPanel = 1
|
||||||
|
}
|
||||||
|
|
||||||
if (btn.mousePushed && index != selectedIndex) {
|
if (btn.mousePushed && index != selectedIndex) {
|
||||||
|
// normal stuffs
|
||||||
val oldIndex = selectedIndex
|
val oldIndex = selectedIndex
|
||||||
|
|
||||||
highlighterXStart = mainButtons[selectedIndex].posX.toDouble() // using old selectedIndex
|
highlighterXStart = mainButtons[selectedIndex].posX.toFloat() // using old selectedIndex
|
||||||
selectedIndex = index
|
selectedIndex = index
|
||||||
highlighterMoving = true
|
highlighterMoving = true
|
||||||
highlighterXEnd = mainButtons[selectedIndex].posX.toDouble() // using new selectedIndex
|
highlighterXEnd = mainButtons[selectedIndex].posX.toFloat() // using new selectedIndex
|
||||||
|
|
||||||
selectionChangeListener?.invoke(oldIndex, index)
|
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[0].update(delta)
|
||||||
sideButtons[3].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) {
|
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)
|
batch.drawStraightLine(posX.toFloat(), posY + height - 1f, posX + width.toFloat(), 1f, false)
|
||||||
|
|
||||||
// indicator
|
// indicator
|
||||||
batch.color = underlineHighlightColour
|
if (selectedPanel == 1) {
|
||||||
batch.draw(underlineIndTex, (highlighterXPos - buttonGapSize / 2).toFloat().round(), posY + highlighterYPos)
|
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.Ingame
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull
|
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellBase
|
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.
|
* Note that the UI will not render if either item or itemImage is null.
|
||||||
@@ -36,6 +36,10 @@ class UIItemInventoryElem(
|
|||||||
val drawBackOnNull: Boolean = true
|
val drawBackOnNull: Boolean = true
|
||||||
) : UIItemInventoryCellBase(parentUI, posX, posY, item, amount, itemImage, quickslot, equippedSlot) {
|
) : UIItemInventoryCellBase(parentUI, posX, posY, item, amount, itemImage, quickslot, equippedSlot) {
|
||||||
|
|
||||||
|
// deal with the moving position
|
||||||
|
override var oldPosX = posX
|
||||||
|
override var oldPosY = posY
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val height = 48
|
val height = 48
|
||||||
val UNIQUE_ITEM_HAS_NO_AMOUNT = -1
|
val UNIQUE_ITEM_HAS_NO_AMOUNT = -1
|
||||||
@@ -74,12 +78,12 @@ class UIItemInventoryElem(
|
|||||||
if (item != null || drawBackOnNull) {
|
if (item != null || drawBackOnNull) {
|
||||||
// do not highlight even if drawBackOnNull is true
|
// do not highlight even if drawBackOnNull is true
|
||||||
if (mouseUp && item != null) {
|
if (mouseUp && item != null) {
|
||||||
BlendMode.resolve(mouseoverBackBlendMode)
|
BlendMode.resolve(mouseoverBackBlendMode, batch)
|
||||||
batch.color = mouseoverBackCol
|
batch.color = mouseoverBackCol
|
||||||
}
|
}
|
||||||
// if drawBackOnNull, just draw background
|
// if drawBackOnNull, just draw background
|
||||||
else {
|
else {
|
||||||
BlendMode.resolve(backBlendMode)
|
BlendMode.resolve(backBlendMode, batch)
|
||||||
batch.color = backCol
|
batch.color = backCol
|
||||||
}
|
}
|
||||||
batch.fillRect(posX.toFloat(), posY.toFloat(), width.toFloat(), height.toFloat())
|
batch.fillRect(posX.toFloat(), posY.toFloat(), width.toFloat(), height.toFloat())
|
||||||
@@ -87,7 +91,7 @@ class UIItemInventoryElem(
|
|||||||
|
|
||||||
|
|
||||||
if (item != null && itemImage != null) {
|
if (item != null && itemImage != null) {
|
||||||
blendNormal()
|
blendNormal(batch)
|
||||||
|
|
||||||
// item image
|
// item image
|
||||||
batch.color = Color.WHITE
|
batch.color = Color.WHITE
|
||||||
@@ -136,14 +140,14 @@ class UIItemInventoryElem(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun keyDown(keycode: Int): Boolean {
|
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
|
val player = (Terrarum.ingame!! as Ingame).actorNowPlaying
|
||||||
|
|
||||||
if (player == null) return false
|
if (player == null) return false
|
||||||
|
|
||||||
val inventory = player.inventory
|
val inventory = player.inventory
|
||||||
val slot = if (keycode == Input.Keys.NUM_0) 9 else keycode - Input.Keys.NUM_1
|
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(
|
inventory.setQuickBar(
|
||||||
@@ -157,13 +161,13 @@ class UIItemInventoryElem(
|
|||||||
// search for duplicates in the quickbar, except mine
|
// search for duplicates in the quickbar, except mine
|
||||||
// if there is, unregister the other
|
// if there is, unregister the other
|
||||||
(0..9).minus(slot).forEach {
|
(0..9).minus(slot).forEach {
|
||||||
if (inventory.getQuickBar(it)?.item == item) {
|
if (inventory.getQuickslot(it)?.item == item) {
|
||||||
inventory.setQuickBar(it, null)
|
inventory.setQuickBar(it, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return super.keyDown(keycode)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
||||||
@@ -171,6 +175,10 @@ class UIItemInventoryElem(
|
|||||||
|
|
||||||
// equip da shit
|
// equip da shit
|
||||||
val itemEquipSlot = item!!.equipPosition
|
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
|
val player = (Terrarum.ingame!! as Ingame).actorNowPlaying
|
||||||
|
|
||||||
if (player == null) return false
|
if (player == null) return false
|
||||||
@@ -185,12 +193,11 @@ class UIItemInventoryElem(
|
|||||||
|
|
||||||
inventoryUI.rebuildList()
|
inventoryUI.rebuildList()
|
||||||
|
|
||||||
return true
|
return super.touchDown(screenX, screenY, pointer, button)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
itemImage?.texture?.dispose()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun keyUp(keycode: Int): Boolean {
|
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.Ingame
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull
|
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellBase
|
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.
|
* Created by minjaesong on 2017-10-20.
|
||||||
@@ -33,6 +33,10 @@ class UIItemInventoryElemSimple(
|
|||||||
val drawBackOnNull: Boolean = true
|
val drawBackOnNull: Boolean = true
|
||||||
) : UIItemInventoryCellBase(parentUI, posX, posY, item, amount, itemImage, quickslot, equippedSlot) {
|
) : UIItemInventoryCellBase(parentUI, posX, posY, item, amount, itemImage, quickslot, equippedSlot) {
|
||||||
|
|
||||||
|
// deal with the moving position
|
||||||
|
override var oldPosX = posX
|
||||||
|
override var oldPosY = posY
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val height = UIItemInventoryElem.height
|
val height = UIItemInventoryElem.height
|
||||||
}
|
}
|
||||||
@@ -56,12 +60,12 @@ class UIItemInventoryElemSimple(
|
|||||||
if (item != null || drawBackOnNull) {
|
if (item != null || drawBackOnNull) {
|
||||||
// do not highlight even if drawBackOnNull is true
|
// do not highlight even if drawBackOnNull is true
|
||||||
if (mouseUp && item != null || equippedSlot != null) { // "equippedSlot != null": also highlight back if equipped
|
if (mouseUp && item != null || equippedSlot != null) { // "equippedSlot != null": also highlight back if equipped
|
||||||
BlendMode.resolve(mouseoverBackBlendMode)
|
BlendMode.resolve(mouseoverBackBlendMode, batch)
|
||||||
batch.color = mouseoverBackCol
|
batch.color = mouseoverBackCol
|
||||||
}
|
}
|
||||||
// if drawBackOnNull, just draw background
|
// if drawBackOnNull, just draw background
|
||||||
else {
|
else {
|
||||||
BlendMode.resolve(backBlendMode)
|
BlendMode.resolve(backBlendMode, batch)
|
||||||
batch.color = backCol
|
batch.color = backCol
|
||||||
}
|
}
|
||||||
batch.fillRect(posX.toFloat(), posY.toFloat(), width.toFloat(), height.toFloat())
|
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
|
// and you can clearly see the quickslot UI anyway
|
||||||
|
|
||||||
if (item != null && itemImage != null) {
|
if (item != null && itemImage != null) {
|
||||||
blendNormal()
|
blendNormal(batch)
|
||||||
|
|
||||||
// item image
|
// item image
|
||||||
batch.color = Color.WHITE
|
batch.color = Color.WHITE
|
||||||
@@ -96,8 +100,8 @@ class UIItemInventoryElemSimple(
|
|||||||
batch.drawStraightLine(barOffset, posY + height - thickness, barOffset + barFullLen * (item!!.durability / item!!.maxDurability), thickness, false)
|
batch.drawStraightLine(barOffset, posY + height - thickness, barOffset + barFullLen * (item!!.durability / item!!.maxDurability), thickness, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
// draw item count when applicable
|
||||||
// draw item count
|
else if (item!!.stackable) {
|
||||||
val amountString = amount.toString()
|
val amountString = amount.toString()
|
||||||
|
|
||||||
// highlight item count (blocks/walls) if the item is equipped
|
// highlight item count (blocks/walls) if the item is equipped
|
||||||
@@ -121,15 +125,14 @@ class UIItemInventoryElemSimple(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun keyDown(keycode: Int): Boolean {
|
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) {
|
||||||
println("keydown elemgrid")
|
|
||||||
|
|
||||||
val player = (Terrarum.ingame!! as Ingame).actorNowPlaying
|
val player = (Terrarum.ingame!! as Ingame).actorNowPlaying
|
||||||
if (player == null) return false
|
if (player == null) return false
|
||||||
|
|
||||||
val inventory = player.inventory
|
val inventory = player.inventory
|
||||||
val slot = if (keycode == Input.Keys.NUM_0) 9 else keycode - Input.Keys.NUM_1
|
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(
|
inventory.setQuickBar(
|
||||||
@@ -143,13 +146,13 @@ class UIItemInventoryElemSimple(
|
|||||||
// search for duplicates in the quickbar, except mine
|
// search for duplicates in the quickbar, except mine
|
||||||
// if there is, unregister the other
|
// if there is, unregister the other
|
||||||
(0..9).minus(slot).forEach {
|
(0..9).minus(slot).forEach {
|
||||||
if (inventory.getQuickBar(it)?.item == item) {
|
if (inventory.getQuickslot(it)?.item == item) {
|
||||||
inventory.setQuickBar(it, null)
|
inventory.setQuickBar(it, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return super.keyDown(keycode)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
||||||
@@ -172,12 +175,11 @@ class UIItemInventoryElemSimple(
|
|||||||
|
|
||||||
inventoryUI.rebuildList()
|
inventoryUI.rebuildList()
|
||||||
|
|
||||||
return true
|
return super.touchDown(screenX, screenY, pointer, button)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
itemImage?.texture?.dispose()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun keyUp(keycode: Int): Boolean {
|
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 {
|
object Block {
|
||||||
|
|
||||||
val AIR = 0 // hard coded; this is the standard
|
const val AIR = 0 // hard coded; this is the standard
|
||||||
|
|
||||||
val STONE = 16
|
const val STONE = 16
|
||||||
val STONE_QUARRIED = 17
|
const val STONE_QUARRIED = 17
|
||||||
val STONE_TILE_WHITE = 18
|
const val STONE_TILE_WHITE = 18
|
||||||
val STONE_BRICKS = 19
|
const val STONE_BRICKS = 19
|
||||||
|
|
||||||
val DIRT = 32
|
const val DIRT = 32
|
||||||
val GRASS = 33
|
const val GRASS = 33
|
||||||
val GRASSWALL = 34
|
const val GRASSWALL = 34
|
||||||
|
|
||||||
val PLANK_NORMAL = 48
|
const val PLANK_NORMAL = 48
|
||||||
val PLANK_EBONY = 49
|
const val PLANK_EBONY = 49
|
||||||
val PLANK_BIRCH = 50
|
const val PLANK_BIRCH = 50
|
||||||
val PLANK_BLOODROSE = 51
|
const val PLANK_BLOODROSE = 51
|
||||||
|
|
||||||
val TRUNK_NORMAL = 64
|
const val TRUNK_NORMAL = 64
|
||||||
val TRUNK_EBONY = 65
|
const val TRUNK_EBONY = 65
|
||||||
val TRUNK_BIRCH = 66
|
const val TRUNK_BIRCH = 66
|
||||||
val TRUNK_BLOODROSE = 67
|
const val TRUNK_BLOODROSE = 67
|
||||||
|
|
||||||
val SAND = 80
|
const val SAND = 80
|
||||||
val SAND_WHITE = 81
|
const val SAND_WHITE = 81
|
||||||
val SAND_RED = 82
|
const val SAND_RED = 82
|
||||||
val SAND_DESERT = 83
|
const val SAND_DESERT = 83
|
||||||
val SAND_BLACK = 84
|
const val SAND_BLACK = 84
|
||||||
val SAND_GREEN = 85
|
const val SAND_GREEN = 85
|
||||||
|
|
||||||
val GRAVEL = 96
|
const val GRAVEL = 96
|
||||||
val GRAVEL_GREY = 97
|
const val GRAVEL_GREY = 97
|
||||||
|
|
||||||
val ORE_COPPER = 112
|
const val ORE_COPPER = 112
|
||||||
val ORE_IRON = 113
|
const val ORE_IRON = 113
|
||||||
val ORE_GOLD = 114
|
const val ORE_GOLD = 114
|
||||||
val ORE_SILVER = 115
|
const val ORE_SILVER = 115
|
||||||
val ORE_ILMENITE = 116
|
const val ORE_ILMENITE = 116
|
||||||
val ORE_AURICHALCUM = 117
|
const val ORE_AURICHALCUM = 117
|
||||||
|
|
||||||
val RAW_RUBY = 128
|
const val RAW_RUBY = 128
|
||||||
val RAW_EMERALD = 129
|
const val RAW_EMERALD = 129
|
||||||
val RAW_SAPPHIRE = 130
|
const val RAW_SAPPHIRE = 130
|
||||||
val RAW_TOPAZ = 131
|
const val RAW_TOPAZ = 131
|
||||||
val RAW_DIAMOND = 132
|
const val RAW_DIAMOND = 132
|
||||||
val RAW_AMETHYST = 133
|
const val RAW_AMETHYST = 133
|
||||||
|
|
||||||
val SNOW = 144
|
const val SNOW = 144
|
||||||
val ICE_FRAGILE = 145
|
const val ICE_FRAGILE = 145
|
||||||
val ICE_NATURAL = 146
|
const val ICE_NATURAL = 146
|
||||||
val ICE_MAGICAL = 147
|
const val ICE_MAGICAL = 147
|
||||||
|
|
||||||
val GLASS_CRUDE = 148
|
const val GLASS_CRUDE = 148
|
||||||
val GLASS_CLEAN = 149
|
const val GLASS_CLEAN = 149
|
||||||
|
|
||||||
val PLATFORM_STONE = 160
|
const val PLATFORM_STONE = 160
|
||||||
val PLATFORM_WOODEN = 161
|
const val PLATFORM_WOODEN = 161
|
||||||
val PLATFORM_EBONY = 162
|
const val PLATFORM_EBONY = 162
|
||||||
val PLATFORM_BIRCH = 163
|
const val PLATFORM_BIRCH = 163
|
||||||
val PLATFORM_BLOODROSE = 164
|
const val PLATFORM_BLOODROSE = 164
|
||||||
|
|
||||||
val TORCH = 176
|
const val TORCH = 176
|
||||||
val TORCH_FROST = 177
|
const val TORCH_FROST = 177
|
||||||
|
|
||||||
val TORCH_OFF = 192
|
const val TORCH_OFF = 192
|
||||||
val TORCH_FROST_OFF = 193
|
const val TORCH_FROST_OFF = 193
|
||||||
|
|
||||||
val ILLUMINATOR_WHITE = 208
|
const val ILLUMINATOR_WHITE = 208
|
||||||
val ILLUMINATOR_YELLOW = 209
|
const val ILLUMINATOR_YELLOW = 209
|
||||||
val ILLUMINATOR_ORANGE = 210
|
const val ILLUMINATOR_ORANGE = 210
|
||||||
val ILLUMINATOR_RED = 211
|
const val ILLUMINATOR_RED = 211
|
||||||
val ILLUMINATOR_FUCHSIA = 212
|
const val ILLUMINATOR_FUCHSIA = 212
|
||||||
val ILLUMINATOR_PURPLE = 213
|
const val ILLUMINATOR_PURPLE = 213
|
||||||
val ILLUMINATOR_BLUE = 214
|
const val ILLUMINATOR_BLUE = 214
|
||||||
val ILLUMINATOR_CYAN = 215
|
const val ILLUMINATOR_CYAN = 215
|
||||||
val ILLUMINATOR_GREEN = 216
|
const val ILLUMINATOR_GREEN = 216
|
||||||
val ILLUMINATOR_GREEN_DARK = 217
|
const val ILLUMINATOR_GREEN_DARK = 217
|
||||||
val ILLUMINATOR_BROWN = 218
|
const val ILLUMINATOR_BROWN = 218
|
||||||
val ILLUMINATOR_TAN = 219
|
const val ILLUMINATOR_TAN = 219
|
||||||
val ILLUMINATOR_GREY_LIGHT = 220
|
const val ILLUMINATOR_GREY_LIGHT = 220
|
||||||
val ILLUMINATOR_GREY_MED = 221
|
const val ILLUMINATOR_GREY_MED = 221
|
||||||
val ILLUMINATOR_GREY_DARK = 222
|
const val ILLUMINATOR_GREY_DARK = 222
|
||||||
val ILLUMINATOR_BLACK = 223
|
const val ILLUMINATOR_BLACK = 223
|
||||||
|
|
||||||
val ILLUMINATOR_WHITE_OFF = 224
|
const val ILLUMINATOR_WHITE_OFF = 224
|
||||||
val ILLUMINATOR_YELLOW_OFF = 225
|
const val ILLUMINATOR_YELLOW_OFF = 225
|
||||||
val ILLUMINATOR_ORANGE_OFF = 226
|
const val ILLUMINATOR_ORANGE_OFF = 226
|
||||||
val ILLUMINATOR_RED_OFF = 227
|
const val ILLUMINATOR_RED_OFF = 227
|
||||||
val ILLUMINATOR_FUCHSIA_OFF = 228
|
const val ILLUMINATOR_FUCHSIA_OFF = 228
|
||||||
val ILLUMINATOR_PURPLE_OFF = 229
|
const val ILLUMINATOR_PURPLE_OFF = 229
|
||||||
val ILLUMINATOR_BLUE_OFF = 230
|
const val ILLUMINATOR_BLUE_OFF = 230
|
||||||
val ILLUMINATOR_CYAN_OFF = 231
|
const val ILLUMINATOR_CYAN_OFF = 231
|
||||||
val ILLUMINATOR_GREEN_OFF = 232
|
const val ILLUMINATOR_GREEN_OFF = 232
|
||||||
val ILLUMINATOR_GREEN_DARK_OFF = 233
|
const val ILLUMINATOR_GREEN_DARK_OFF = 233
|
||||||
val ILLUMINATOR_BROWN_OFF = 234
|
const val ILLUMINATOR_BROWN_OFF = 234
|
||||||
val ILLUMINATOR_TAN_OFF = 235
|
const val ILLUMINATOR_TAN_OFF = 235
|
||||||
val ILLUMINATOR_GREY_LIGHT_OFF = 236
|
const val ILLUMINATOR_GREY_LIGHT_OFF = 236
|
||||||
val ILLUMINATOR_GREY_MED_OFF = 237
|
const val ILLUMINATOR_GREY_MED_OFF = 237
|
||||||
val ILLUMINATOR_GREY_DARK_OFF = 238
|
const val ILLUMINATOR_GREY_DARK_OFF = 238
|
||||||
val ILLUMINATOR_BLACK_OFF = 239
|
const val ILLUMINATOR_BLACK_OFF = 239
|
||||||
|
|
||||||
val SANDSTONE = 240
|
const val SANDSTONE = 240
|
||||||
val SANDSTONE_WHITE = 241
|
const val SANDSTONE_WHITE = 241
|
||||||
val SANDSTONE_RED = 242
|
const val SANDSTONE_RED = 242
|
||||||
val SANDSTONE_DESERT = 243
|
const val SANDSTONE_DESERT = 243
|
||||||
val SANDSTONE_BLACK = 244
|
const val SANDSTONE_BLACK = 244
|
||||||
val SANDSTONE_GREEN = 245
|
const val SANDSTONE_GREEN = 245
|
||||||
|
|
||||||
val LANTERN = 256
|
const val LANTERN = 256
|
||||||
val SUNSTONE = 257
|
const val SUNSTONE = 257
|
||||||
val DAYLIGHT_CAPACITOR = 258
|
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
|
const val ACTORBLOCK_NO_COLLISION = 4191
|
||||||
val LAVA_2 = 4065
|
const val ACTORBLOCK_FULL_COLLISION = 4092
|
||||||
val LAVA_3 = 4066
|
const val ACTORBLOCK_ALLOW_MOVE_DOWN = 4093
|
||||||
val LAVA_4 = 4067
|
const val ACTORBLOCK_NO_PASS_RIGHT = 4094
|
||||||
val LAVA_5 = 4068
|
const val ACTORBLOCK_NO_PASS_LEFT = 4095
|
||||||
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
|
|
||||||
|
|
||||||
val NULL = -1
|
|
||||||
|
const val LAVA = 4094
|
||||||
|
const val WATER = 4095
|
||||||
|
|
||||||
|
const val NULL = -1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
package net.torvald.terrarum.blockproperties
|
package net.torvald.terrarum.blockproperties
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Color
|
||||||
import net.torvald.terrarum.AppLoader
|
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.MapLayer
|
||||||
import net.torvald.terrarum.gameworld.PairedMapLayer
|
import net.torvald.terrarum.gameworld.PairedMapLayer
|
||||||
|
import net.torvald.terrarum.utils.CSVFetcher
|
||||||
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
||||||
import org.apache.commons.csv.CSVRecord
|
import org.apache.commons.csv.CSVRecord
|
||||||
|
|
||||||
import java.io.IOException
|
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? {
|
fun getOrNull(rawIndex: Int?): BlockProp? {
|
||||||
if (rawIndex == null || rawIndex == Block.NULL) {
|
if (rawIndex == null || rawIndex == Block.NULL) {
|
||||||
return null
|
return null
|
||||||
@@ -96,21 +111,24 @@ object BlockCodex {
|
|||||||
prop.shadeColG = floatVal(record, "shdg") / LightmapRenderer.MUL_FLOAT
|
prop.shadeColG = floatVal(record, "shdg") / LightmapRenderer.MUL_FLOAT
|
||||||
prop.shadeColB = floatVal(record, "shdb") / LightmapRenderer.MUL_FLOAT
|
prop.shadeColB = floatVal(record, "shdb") / LightmapRenderer.MUL_FLOAT
|
||||||
prop.shadeColA = floatVal(record, "shduv") / 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.density = intVal(record, "dsty")
|
||||||
|
|
||||||
prop.lumColR = floatVal(record, "lumr") / LightmapRenderer.MUL_FLOAT
|
prop.lumColR = floatVal(record, "lumr") / LightmapRenderer.MUL_FLOAT
|
||||||
prop.lumColG = floatVal(record, "lumg") / LightmapRenderer.MUL_FLOAT
|
prop.lumColG = floatVal(record, "lumg") / LightmapRenderer.MUL_FLOAT
|
||||||
prop.lumColB = floatVal(record, "lumb") / LightmapRenderer.MUL_FLOAT
|
prop.lumColB = floatVal(record, "lumb") / LightmapRenderer.MUL_FLOAT
|
||||||
prop.lumColA = floatVal(record, "lumuv") / 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.viscosity = intVal(record, "vscs")
|
||||||
|
|
||||||
prop.isFluid = boolVal(record, "fluid")
|
//prop.isFluid = boolVal(record, "fluid")
|
||||||
prop.isSolid = boolVal(record, "solid")
|
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.isWallable = boolVal(record, "wall")
|
||||||
prop.isFallable = boolVal(record, "fall")
|
prop.isFallable = boolVal(record, "fall")
|
||||||
prop.isVertFriction = boolVal(record, "fv")
|
prop.isVertFriction = boolVal(record, "fv")
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class BlockProp {
|
|||||||
var shadeColG = 0f
|
var shadeColG = 0f
|
||||||
var shadeColB = 0f
|
var shadeColB = 0f
|
||||||
var shadeColA = 0f
|
var shadeColA = 0f
|
||||||
|
lateinit var shadeColor: Color
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param opacity Raw RGB value, without alpha
|
* @param opacity Raw RGB value, without alpha
|
||||||
@@ -27,9 +28,9 @@ class BlockProp {
|
|||||||
var density: Int = 0
|
var density: Int = 0
|
||||||
var viscosity: Int = 0
|
var viscosity: Int = 0
|
||||||
|
|
||||||
var isFluid: Boolean = false
|
|
||||||
var isSolid: Boolean = false
|
var isSolid: Boolean = false
|
||||||
var isClear: Boolean = false
|
//var isClear: Boolean = false
|
||||||
|
var isPlatform: Boolean = false
|
||||||
var isWallable: Boolean = false
|
var isWallable: Boolean = false
|
||||||
var isVertFriction: Boolean = false
|
var isVertFriction: Boolean = false
|
||||||
|
|
||||||
@@ -39,12 +40,13 @@ class BlockProp {
|
|||||||
var lumColG = 0f
|
var lumColG = 0f
|
||||||
var lumColB = 0f
|
var lumColB = 0f
|
||||||
var lumColA = 0f
|
var lumColA = 0f
|
||||||
|
lateinit var internalLumCol: Color
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param luminosity
|
* @param luminosity
|
||||||
*/
|
*/
|
||||||
inline val luminosity: Color
|
inline val luminosity: Color
|
||||||
get() = BlockPropUtil.getDynamicLumFunc(Color(lumColR, lumColG, lumColB, lumColA), dynamicLuminosityFunction)
|
get() = BlockPropUtil.getDynamicLumFunc(internalLumCol, dynamicLuminosityFunction)
|
||||||
|
|
||||||
var drop: Int = 0
|
var drop: Int = 0
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import com.badlogic.gdx.Gdx
|
|||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
import net.torvald.terrarum.Terrarum
|
|
||||||
import net.torvald.terrarum.Second
|
import net.torvald.terrarum.Second
|
||||||
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
|
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
|
||||||
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
|
||||||
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
|
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
|
||||||
|
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2016-06-16.
|
* Created by minjaesong on 2016-06-16.
|
||||||
@@ -63,9 +63,9 @@ object BlockPropUtil {
|
|||||||
internal fun dynamicLumFuncTickClock() {
|
internal fun dynamicLumFuncTickClock() {
|
||||||
// FPS-time compensation
|
// FPS-time compensation
|
||||||
if (Gdx.graphics.framesPerSecond > 0) {
|
if (Gdx.graphics.framesPerSecond > 0) {
|
||||||
flickerFuncX += Terrarum.deltaTime * 1000f
|
flickerFuncX += Gdx.graphics.deltaTime * 1000f
|
||||||
breathFuncX += Terrarum.deltaTime * 1000f
|
breathFuncX += Gdx.graphics.deltaTime * 1000f
|
||||||
pulsateFuncX += Terrarum.deltaTime * 1000f
|
pulsateFuncX += Gdx.graphics.deltaTime * 1000f
|
||||||
}
|
}
|
||||||
|
|
||||||
// flicker-related vars
|
// 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