Compare commits
1742 Commits
sapier-201
...
0.4.9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ad81c1ce3 | ||
|
|
25b1cca415 | ||
|
|
767b2e7b17 | ||
|
|
2902a29c2d | ||
|
|
829426c714 | ||
|
|
8e1d78e9de | ||
|
|
4b31a38ae9 | ||
|
|
bf9f50bc0e | ||
|
|
3aa28bc7a2 | ||
|
|
a5377251e2 | ||
|
|
a58b47d0f6 | ||
|
|
7ae0b90ff7 | ||
|
|
a50db0e824 | ||
|
|
e1f9ba435f | ||
|
|
ba8fa0bd42 | ||
|
|
1ed90c90c3 | ||
|
|
49cec3f782 | ||
|
|
38d112033b | ||
|
|
54dbd78f90 | ||
|
|
c9ac9992c7 | ||
|
|
3946d2a504 | ||
|
|
5fd92d67d5 | ||
|
|
c120ea57c9 | ||
|
|
848f80b2e5 | ||
|
|
e9e9fd7c3f | ||
|
|
9772322613 | ||
|
|
7a4c1e7327 | ||
|
|
15c316765d | ||
|
|
c3708b456e | ||
|
|
83853ccd41 | ||
|
|
e275b7099a | ||
|
|
0d990bd189 | ||
|
|
b03135548b | ||
|
|
0a903e69fb | ||
|
|
0404bbf671 | ||
|
|
0ea3e6dbe2 | ||
|
|
67bf7130ce | ||
|
|
d9ef072305 | ||
|
|
33de69a173 | ||
|
|
76036abdb0 | ||
|
|
4ccaa6d0af | ||
|
|
dfd1f87762 | ||
|
|
6c4a8766ab | ||
|
|
dae03382bf | ||
|
|
50b0e9f7a4 | ||
|
|
206565d965 | ||
|
|
3cc45fd8ad | ||
|
|
83cc882335 | ||
|
|
bbae8eb751 | ||
|
|
a0dce51af6 | ||
|
|
96f753a108 | ||
|
|
e15681080e | ||
|
|
35f88ac67c | ||
|
|
22dbbf0a6f | ||
|
|
000da6b25d | ||
|
|
e51ad5337f | ||
|
|
15be2659ea | ||
|
|
d9de9f23d9 | ||
|
|
2330267d22 | ||
|
|
60113bde74 | ||
|
|
1309e52198 | ||
|
|
5004f31575 | ||
|
|
6cbd1b8bf7 | ||
|
|
6fa3892a71 | ||
|
|
04e9a9d541 | ||
|
|
f3439c40d8 | ||
|
|
20e3d550fa | ||
|
|
de0cdbc01c | ||
|
|
e605d70256 | ||
|
|
4696c59a5f | ||
|
|
4594ba6522 | ||
|
|
06baf05c64 | ||
|
|
d879a539cd | ||
|
|
752e11e114 | ||
|
|
9a927476ca | ||
|
|
ff7d7080e3 | ||
|
|
769b2d7c05 | ||
|
|
5be786c804 | ||
|
|
747bc40840 | ||
|
|
d19a69cd0d | ||
|
|
d02ce1cf4d | ||
|
|
2e66aca357 | ||
|
|
b08d7558de | ||
|
|
ff25218374 | ||
|
|
7433d65d3e | ||
|
|
1fd9a11e30 | ||
|
|
4f246f0e22 | ||
|
|
f87c1c2410 | ||
|
|
122875c30c | ||
|
|
068dd796f5 | ||
|
|
16bd368374 | ||
|
|
83f1d9ae6b | ||
|
|
374e68d205 | ||
|
|
fb150e0504 | ||
|
|
c439bdd4e5 | ||
|
|
d661cb320d | ||
|
|
78f1fcf450 | ||
|
|
28c21ed566 | ||
|
|
d7b0fcb2f0 | ||
|
|
e5b1447d72 | ||
|
|
dfc268d88b | ||
|
|
8c3cf606a6 | ||
|
|
c28810f6df | ||
|
|
012551f16f | ||
|
|
4d165f5ea5 | ||
|
|
71cc575ea0 | ||
|
|
e023e7228e | ||
|
|
80981f80f3 | ||
|
|
ab601e8710 | ||
|
|
ee0b8da844 | ||
|
|
6f851c9692 | ||
|
|
e52d811110 | ||
|
|
5323d800cc | ||
|
|
98e4e2b373 | ||
|
|
b38afc9311 | ||
|
|
0c8bf7cf94 | ||
|
|
0930911efa | ||
|
|
86ef7147b6 | ||
|
|
a55c073ce9 | ||
|
|
21789ccc5f | ||
|
|
b2d9205796 | ||
|
|
eadc943159 | ||
|
|
dc407e219f | ||
|
|
d419e4cbb6 | ||
|
|
aa172bdda4 | ||
|
|
a439aea9ba | ||
|
|
367b5382a3 | ||
|
|
a92fc3563c | ||
|
|
533785ec9a | ||
|
|
3985c01ad7 | ||
|
|
cca4f09ba1 | ||
|
|
e396fb2984 | ||
|
|
90e7832408 | ||
|
|
35606cfb67 | ||
|
|
371b39a09a | ||
|
|
3f519eb729 | ||
|
|
9a750450ed | ||
|
|
5094a39f05 | ||
|
|
a935d81053 | ||
|
|
bb54e2cf1d | ||
|
|
22a59b3912 | ||
|
|
0f9440fa61 | ||
|
|
d75b1718f8 | ||
|
|
a92e90f684 | ||
|
|
b401e58c0d | ||
|
|
0aeecf3f7f | ||
|
|
b6bb3ffec4 | ||
|
|
7bd30b59ee | ||
|
|
1afd359550 | ||
|
|
1d856b734b | ||
|
|
3d63492f50 | ||
|
|
8ad052881c | ||
|
|
d886f34003 | ||
|
|
8903c68460 | ||
|
|
6f44492238 | ||
|
|
2e89209cf1 | ||
|
|
e46c527733 | ||
|
|
1a96987d0f | ||
|
|
7be18657b1 | ||
|
|
cf0786dc9d | ||
|
|
4a8a50a2a2 | ||
|
|
0fd29b7e09 | ||
|
|
4c2687775f | ||
|
|
50ea8601d5 | ||
|
|
68bbdf1b2c | ||
|
|
5fbc39a76c | ||
|
|
25edae00ea | ||
|
|
0b78889289 | ||
|
|
06a5eceb81 | ||
|
|
2636c92075 | ||
|
|
d11c76b9f2 | ||
|
|
0d35350b69 | ||
|
|
2bf9abade2 | ||
|
|
69a59f1e41 | ||
|
|
b1c82f332c | ||
|
|
fba2650e39 | ||
|
|
1cbba877ff | ||
|
|
53ab2f8def | ||
|
|
bd6d4666ab | ||
|
|
2f10cfb226 | ||
|
|
8bc68645cb | ||
|
|
6e17503208 | ||
|
|
382357d61c | ||
|
|
a924409bd1 | ||
|
|
e232f7311f | ||
|
|
12504a18ec | ||
|
|
b3591019ad | ||
|
|
34e0a0ca0f | ||
|
|
4e5760a541 | ||
|
|
19742d8d98 | ||
|
|
f86cdf0960 | ||
|
|
ee9f4f11a3 | ||
|
|
919ffd9d36 | ||
|
|
406bed1164 | ||
|
|
d0ddcecbe5 | ||
|
|
25304b53a1 | ||
|
|
14e562e92b | ||
|
|
b3ad0f1ed4 | ||
|
|
5f3806c93c | ||
|
|
5598f3c81b | ||
|
|
afb27329fc | ||
|
|
2170c9958a | ||
|
|
2134316c80 | ||
|
|
a9c0961e0c | ||
|
|
731392866f | ||
|
|
5dce44ec5e | ||
|
|
f0edd88dff | ||
|
|
8bc7ea61b9 | ||
|
|
372d638ec1 | ||
|
|
4ea0e4f606 | ||
|
|
fb6a789991 | ||
|
|
9e6bdc377f | ||
|
|
27947d85f7 | ||
|
|
f7ee5da4c1 | ||
|
|
c0398224ef | ||
|
|
9bccd75e34 | ||
|
|
c9eb17aba3 | ||
|
|
cfe6eaa66b | ||
|
|
62bc5331aa | ||
|
|
4c704fe306 | ||
|
|
d308352dbd | ||
|
|
3c4734d69a | ||
|
|
da9fe64851 | ||
|
|
4feea0ac68 | ||
|
|
681e136d5f | ||
|
|
e0f9f15d1d | ||
|
|
214da7bef9 | ||
|
|
dd5c451e03 | ||
|
|
d820a6bfd8 | ||
|
|
10a38a3005 | ||
|
|
c6e3797c1a | ||
|
|
168fa2ffe0 | ||
|
|
6fb4a78d71 | ||
|
|
217b66e5d2 | ||
|
|
95e4a93b1b | ||
|
|
3725179736 | ||
|
|
1f3402e7a1 | ||
|
|
49a75b1894 | ||
|
|
321ac66558 | ||
|
|
d423a8fc20 | ||
|
|
f1e4a671dc | ||
|
|
1cc1c56234 | ||
|
|
7e44c2ace1 | ||
|
|
58841ef12f | ||
|
|
71a8769bb5 | ||
|
|
6de16bb438 | ||
|
|
6291fd1cbb | ||
|
|
4a2203413f | ||
|
|
0be633a61d | ||
|
|
2963f631e3 | ||
|
|
df3a5a2abf | ||
|
|
211b372e26 | ||
|
|
8489980039 | ||
|
|
7935044820 | ||
|
|
e8b9467905 | ||
|
|
7860097eda | ||
|
|
5b518ed2fe | ||
|
|
af490330e7 | ||
|
|
1ad9365d34 | ||
|
|
e61b1773c9 | ||
|
|
1ecf51a13f | ||
|
|
71a6ffa762 | ||
|
|
5d0f19fd7d | ||
|
|
a0ef75d32d | ||
|
|
fd6e7cef92 | ||
|
|
d01d9217dd | ||
|
|
1751fdf937 | ||
|
|
7766420cf4 | ||
|
|
e69764a6f3 | ||
|
|
525483c500 | ||
|
|
18bf767014 | ||
|
|
cfaa9b3be5 | ||
|
|
902d5927f0 | ||
|
|
82e1ab7b2b | ||
|
|
d470842e8e | ||
|
|
439079cad8 | ||
|
|
fead7a27ca | ||
|
|
4679455c3f | ||
|
|
d05b15df77 | ||
|
|
151617c552 | ||
|
|
5a0cadab0c | ||
|
|
c9449c6fb7 | ||
|
|
833183ddb4 | ||
|
|
f4ef91debf | ||
|
|
e74dfaf868 | ||
|
|
4260b99df2 | ||
|
|
9ebed5e497 | ||
|
|
342629a3bf | ||
|
|
ca58c2464a | ||
|
|
9f2b08ddf0 | ||
|
|
ba335958d6 | ||
|
|
78ea818aaf | ||
|
|
deaa8dc287 | ||
|
|
ade70fe4b9 | ||
|
|
4242782dc2 | ||
|
|
8548bb75b6 | ||
|
|
72b9b0fe3a | ||
|
|
392689e7ba | ||
|
|
09a50d0458 | ||
|
|
787b43b218 | ||
|
|
3ee8098708 | ||
|
|
4095e8f383 | ||
|
|
a2380bf76f | ||
|
|
75a139e62c | ||
|
|
1e4e64f831 | ||
|
|
b94f18298d | ||
|
|
d52185c43e | ||
|
|
5e312dc40d | ||
|
|
d8337034b5 | ||
|
|
7921fe2cd1 | ||
|
|
a97c085e9e | ||
|
|
58beca005c | ||
|
|
4e1f50035e | ||
|
|
6228d634fb | ||
|
|
fc72d7fbb6 | ||
|
|
fc571ad46d | ||
|
|
d718b0b34e | ||
|
|
c8930850e3 | ||
|
|
c06caa14c3 | ||
|
|
56b9377c1c | ||
|
|
0d60bc55e4 | ||
|
|
35c5ccfad3 | ||
|
|
2ed3067bbe | ||
|
|
218f82f798 | ||
|
|
8b9bf47166 | ||
|
|
7294f28c3a | ||
|
|
779165144e | ||
|
|
7fbc8152bf | ||
|
|
7b13d119ed | ||
|
|
ba65e2ae6c | ||
|
|
53bf62bb83 | ||
|
|
61f240946a | ||
|
|
14eab22d81 | ||
|
|
96c34d369e | ||
|
|
2336d21efd | ||
|
|
314e4dd4a6 | ||
|
|
44eb01695a | ||
|
|
0b0919e81c | ||
|
|
714a8cef38 | ||
|
|
be4670fecf | ||
|
|
2af5864534 | ||
|
|
3fd84edb61 | ||
|
|
383153419b | ||
|
|
fe1fe1b1e4 | ||
|
|
e6687be493 | ||
|
|
8831669505 | ||
|
|
742614180c | ||
|
|
bc5db9b027 | ||
|
|
c50c9a10f1 | ||
|
|
45589fae58 | ||
|
|
5e433fa913 | ||
|
|
0b77588e87 | ||
|
|
06cdce1e12 | ||
|
|
0e89bca173 | ||
|
|
c6cb97e693 | ||
|
|
251e3e01c7 | ||
|
|
ff7c380d0e | ||
|
|
4fb4efd8ed | ||
|
|
174285f298 | ||
|
|
037e84d377 | ||
|
|
3aedfac968 | ||
|
|
e65d8ad655 | ||
|
|
215e37aac3 | ||
|
|
a59f85c1a0 | ||
|
|
8e2467c393 | ||
|
|
3629a90c2e | ||
|
|
a0f5b70568 | ||
|
|
0b4b9e7f3a | ||
|
|
a38f8d9900 | ||
|
|
4f3bc05a5b | ||
|
|
b3db44f801 | ||
|
|
4e2b394ae8 | ||
|
|
e7ba4777fe | ||
|
|
60225be7fa | ||
|
|
07fb257c04 | ||
|
|
8beb0f19d1 | ||
|
|
32001d1e2b | ||
|
|
e3827fbc23 | ||
|
|
5160be91ae | ||
|
|
d6c052038f | ||
|
|
8a1658ec3e | ||
|
|
baf5614880 | ||
|
|
868f35e27a | ||
|
|
5c7ecdb7c5 | ||
|
|
80a2acaa86 | ||
|
|
47a0a5c746 | ||
|
|
7a9f365ba4 | ||
|
|
0850d3fcf8 | ||
|
|
46d1d70e4c | ||
|
|
8cae659786 | ||
|
|
413f0d0353 | ||
|
|
cba90d4441 | ||
|
|
d19c8b815d | ||
|
|
ab145c8827 | ||
|
|
ecb024af64 | ||
|
|
4e5a45952a | ||
|
|
112dbba7c4 | ||
|
|
9733dd5b5e | ||
|
|
a70993d6d2 | ||
|
|
0a2de78da4 | ||
|
|
288948edf7 | ||
|
|
a0771d0940 | ||
|
|
38bc38cd88 | ||
|
|
494fa0c81a | ||
|
|
7dbbbfc665 | ||
|
|
ac7a44792c | ||
|
|
fc6725f14e | ||
|
|
320a00e7c6 | ||
|
|
6027c8d259 | ||
|
|
52beafff53 | ||
|
|
e8f201cefa | ||
|
|
1c7c5d571d | ||
|
|
e3b7c8e0cc | ||
|
|
c8bd2ae11c | ||
|
|
e1a13608d8 | ||
|
|
eedb29346e | ||
|
|
39d03148e5 | ||
|
|
f419f66546 | ||
|
|
fca4610f11 | ||
|
|
ce955f37ba | ||
|
|
c813a3cc53 | ||
|
|
0b5f18754c | ||
|
|
a75afb85ca | ||
|
|
9dcd21911a | ||
|
|
9bd5f612f7 | ||
|
|
6bc3a43d52 | ||
|
|
88d43af276 | ||
|
|
7e73b7cae9 | ||
|
|
b3001bcd6e | ||
|
|
07715b1b6a | ||
|
|
39ab22070e | ||
|
|
ae8ff4b8e2 | ||
|
|
d22baa88ed | ||
|
|
65874c25db | ||
|
|
06266abd6e | ||
|
|
55ecde665d | ||
|
|
307c57dcc4 | ||
|
|
18d7bc7fa1 | ||
|
|
3607fae75a | ||
|
|
922a30ee47 | ||
|
|
92833a07d1 | ||
|
|
a013f762c4 | ||
|
|
3f6f327cb9 | ||
|
|
b850f0f038 | ||
|
|
a225efaec5 | ||
|
|
ad4c065344 | ||
|
|
89533f0811 | ||
|
|
8f1d5d34a6 | ||
|
|
b1ef850877 | ||
|
|
967121a34b | ||
|
|
fe4ce03d52 | ||
|
|
8161ab573f | ||
|
|
caf0b67e47 | ||
|
|
90b095aa54 | ||
|
|
4bbb78a99b | ||
|
|
dd6d1afd8e | ||
|
|
131eb56f52 | ||
|
|
37ca8854f7 | ||
|
|
067888d549 | ||
|
|
848c3fe51a | ||
|
|
21a4adcd27 | ||
|
|
0003fc8215 | ||
|
|
9126823c7e | ||
|
|
3f13dc790c | ||
|
|
280946ba83 | ||
|
|
9e100bc42b | ||
|
|
6b3169e4d0 | ||
|
|
2e292b67a0 | ||
|
|
18882a4d26 | ||
|
|
8aa930f28e | ||
|
|
2c0b51795e | ||
|
|
d6ac3d8d9a | ||
|
|
e47f6fdfe9 | ||
|
|
30d6d4c733 | ||
|
|
f764297be2 | ||
|
|
75b8c13b00 | ||
|
|
f960c3be31 | ||
|
|
309c5f3641 | ||
|
|
130464c268 | ||
|
|
4d77781ce7 | ||
|
|
c1b829077a | ||
|
|
b1a74df26d | ||
|
|
3af90db5b5 | ||
|
|
58f3cd3eb5 | ||
|
|
b1ebd9f79c | ||
|
|
c2cdaceed0 | ||
|
|
469d0b120e | ||
|
|
81c8b404e7 | ||
|
|
9b6f1d647c | ||
|
|
53066024f6 | ||
|
|
e65ac4d626 | ||
|
|
26165453d2 | ||
|
|
f18b4872ea | ||
|
|
261f559339 | ||
|
|
d74c377337 | ||
|
|
c8ed61b281 | ||
|
|
816ffa99ba | ||
|
|
0b20768a24 | ||
|
|
56093b6614 | ||
|
|
0a8519a26f | ||
|
|
eccd1fdbed | ||
|
|
b5918760fb | ||
|
|
4405310184 | ||
|
|
0413f8ad9d | ||
|
|
93dfc3ec70 | ||
|
|
3e4f1462bc | ||
|
|
40b2f36eb8 | ||
|
|
7a58c1d4ca | ||
|
|
21d6b39fd7 | ||
|
|
2cdf0ff4ab | ||
|
|
773471750d | ||
|
|
6b3e553dd5 | ||
|
|
bfa608b85e | ||
|
|
7cb5217255 | ||
|
|
4f6bec19bc | ||
|
|
649dca4d16 | ||
|
|
601ab85226 | ||
|
|
e988df0fbd | ||
|
|
b89c79e905 | ||
|
|
9fe74a34ea | ||
|
|
64befefcfc | ||
|
|
6f9d384311 | ||
|
|
29e9d09c68 | ||
|
|
c25102a4f7 | ||
|
|
c893958bb1 | ||
|
|
db9c86d6c1 | ||
|
|
1dfc2e02b3 | ||
|
|
ec039a3d12 | ||
|
|
77acdfed43 | ||
|
|
926a47f35b | ||
|
|
df2f4168e5 | ||
|
|
fe560d81e7 | ||
|
|
64627817fc | ||
|
|
a61aa6690b | ||
|
|
7721948a2f | ||
|
|
6b2c46c431 | ||
|
|
83f1d7cd9e | ||
|
|
13f7049d84 | ||
|
|
503e61cf2b | ||
|
|
efc75db764 | ||
|
|
f62ddf9022 | ||
|
|
96fe1de832 | ||
|
|
730d316efe | ||
|
|
e464f19356 | ||
|
|
ab43377577 | ||
|
|
865f380c91 | ||
|
|
3abbe7efd1 | ||
|
|
7f6e9e9540 | ||
|
|
4a9fe1a1d5 | ||
|
|
e57dc4ef18 | ||
|
|
c67f72890c | ||
|
|
5e80df46b8 | ||
|
|
c135e9c7d4 | ||
|
|
1ba1fb42a4 | ||
|
|
127c488355 | ||
|
|
981c6c9bf2 | ||
|
|
d00e8bd31a | ||
|
|
55a97f4605 | ||
|
|
3e2efdf18a | ||
|
|
bc66f46323 | ||
|
|
cc92e45b78 | ||
|
|
b2253e5b42 | ||
|
|
dcd0b63f64 | ||
|
|
b2577b1f27 | ||
|
|
93474c4218 | ||
|
|
f577facf79 | ||
|
|
45fcc9de29 | ||
|
|
b24f7a4d13 | ||
|
|
6074163bf3 | ||
|
|
b76ec317c9 | ||
|
|
714ecc5e27 | ||
|
|
9397b5de08 | ||
|
|
1369503aba | ||
|
|
fedf644635 | ||
|
|
f9b5771274 | ||
|
|
8512cd967d | ||
|
|
94eb370710 | ||
|
|
587e7b299b | ||
|
|
d5ca3b721e | ||
|
|
27f5ff950e | ||
|
|
4a95c37e14 | ||
|
|
5d9ab86adf | ||
|
|
e0564d5de0 | ||
|
|
be96fa2fb8 | ||
|
|
726dcaacb6 | ||
|
|
70190624c6 | ||
|
|
71e5a466a6 | ||
|
|
822723c246 | ||
|
|
bda62bd3bf | ||
|
|
efc9329033 | ||
|
|
2c09e8a84c | ||
|
|
9575b0a2a8 | ||
|
|
6911a7d279 | ||
|
|
5068cb40ce | ||
|
|
e5781b5e34 | ||
|
|
782d06be46 | ||
|
|
81c863ac4d | ||
|
|
d859ad7ed7 | ||
|
|
ee1155fe6d | ||
|
|
3b1c3ac678 | ||
|
|
3332f606ed | ||
|
|
f00cee75c1 | ||
|
|
0913287578 | ||
|
|
7b41f54411 | ||
|
|
03ab6aa24c | ||
|
|
9a559eb8cf | ||
|
|
58f036ad1d | ||
|
|
098692ef26 | ||
|
|
a888b232fe | ||
|
|
b88aa81da7 | ||
|
|
8d5b400d09 | ||
|
|
969d2b3eb1 | ||
|
|
a031a15487 | ||
|
|
777ac58f85 | ||
|
|
be4cc306a5 | ||
|
|
0deb68d81c | ||
|
|
b75505e6b2 | ||
|
|
ee8067f7cf | ||
|
|
2cf76f6f1b | ||
|
|
80874391b8 | ||
|
|
2708482f1b | ||
|
|
084be3599a | ||
|
|
b28734c82c | ||
|
|
d07000ed1d | ||
|
|
647f1cbfe5 | ||
|
|
2b0d1710a5 | ||
|
|
97cddd1b96 | ||
|
|
f1f2004cb9 | ||
|
|
289c4a7776 | ||
|
|
97790c7711 | ||
|
|
149b51967d | ||
|
|
898a4e441f | ||
|
|
a4183994a4 | ||
|
|
c824abd7b2 | ||
|
|
d7395cd2ab | ||
|
|
8767c78169 | ||
|
|
0fb9567f13 | ||
|
|
43a388ec53 | ||
|
|
d3f0ce6224 | ||
|
|
d83602d98e | ||
|
|
c33b993397 | ||
|
|
88ffb3f73b | ||
|
|
386108f982 | ||
|
|
ddd2b18321 | ||
|
|
bc3072b35e | ||
|
|
e9a4e98cb9 | ||
|
|
53da8bd1c8 | ||
|
|
625a4c2e66 | ||
|
|
e703c5b81f | ||
|
|
33dd267fd9 | ||
|
|
a699bdb7a1 | ||
|
|
770305e28d | ||
|
|
36747794ab | ||
|
|
c03c296dc7 | ||
|
|
4a9b8aae5e | ||
|
|
3d4d0cb574 | ||
|
|
9894167bbf | ||
|
|
7c37b1891a | ||
|
|
418c2e7a44 | ||
|
|
4117ab473b | ||
|
|
93d36e88f9 | ||
|
|
b11834605b | ||
|
|
58ded5cd27 | ||
|
|
bc6f3e4e00 | ||
|
|
37e6d1356b | ||
|
|
daddd37706 | ||
|
|
14ba94ad6a | ||
|
|
03868ff8e1 | ||
|
|
527deb947c | ||
|
|
c45c530f74 | ||
|
|
47f60aebcd | ||
|
|
852f768a75 | ||
|
|
9e6376bd95 | ||
|
|
e385af7cc0 | ||
|
|
220c4f1142 | ||
|
|
0a376c1d50 | ||
|
|
b83e9225b7 | ||
|
|
ca8c1b6134 | ||
|
|
a71bfb4b60 | ||
|
|
e60eb32050 | ||
|
|
666aae3593 | ||
|
|
49f6e347f0 | ||
|
|
1f42479e0c | ||
|
|
9e0bb94460 | ||
|
|
ce901f4c4c | ||
|
|
7cd5eb4c77 | ||
|
|
17cfb1850d | ||
|
|
e7f5cdf9d4 | ||
|
|
dda2071cc0 | ||
|
|
6e4fdf37ba | ||
|
|
7d002b60ff | ||
|
|
04c3b17c78 | ||
|
|
58fd39de35 | ||
|
|
9449026839 | ||
|
|
e7247c1a66 | ||
|
|
0d26bb36af | ||
|
|
10502b59bc | ||
|
|
abe74ea5ea | ||
|
|
98182f6097 | ||
|
|
cd27c8ef5d | ||
|
|
2bdff11d54 | ||
|
|
7a32698312 | ||
|
|
5743ef4e64 | ||
|
|
3b684d306c | ||
|
|
e1146396bc | ||
|
|
7c0e707cf1 | ||
|
|
feb7de91ec | ||
|
|
4468ea84e6 | ||
|
|
96e2931c5c | ||
|
|
5961106f9f | ||
|
|
fbf76184f0 | ||
|
|
8ec3fc35c6 | ||
|
|
d50b2ede92 | ||
|
|
453d79e3a2 | ||
|
|
046534e14b | ||
|
|
120f02e20b | ||
|
|
becd8c03fd | ||
|
|
69367aa799 | ||
|
|
97f0bb0342 | ||
|
|
1586cdac53 | ||
|
|
1bae82e6c4 | ||
|
|
2fb0e547a0 | ||
|
|
1a5dcfd0c8 | ||
|
|
e38d65f8d1 | ||
|
|
33052abf42 | ||
|
|
b0e6806077 | ||
|
|
76b86c0368 | ||
|
|
c5a8448c41 | ||
|
|
2a0badf2d5 | ||
|
|
6b8435cf8c | ||
|
|
c1bf6f9f7a | ||
|
|
f85c1165c2 | ||
|
|
37acadc2af | ||
|
|
82709549ff | ||
|
|
6e96bc98de | ||
|
|
60aaf65b10 | ||
|
|
7d83fefd7f | ||
|
|
2bb559be82 | ||
|
|
d27f57e48f | ||
|
|
e59d971e7b | ||
|
|
025f4d28c1 | ||
|
|
0ed34e6780 | ||
|
|
9ff8012655 | ||
|
|
7d036e3ab2 | ||
|
|
8f57246620 | ||
|
|
2985dc4fc8 | ||
|
|
dd0b8c3de5 | ||
|
|
7dd07cc7c5 | ||
|
|
8d4b768297 | ||
|
|
35ed5198fe | ||
|
|
624461c6c6 | ||
|
|
319662c0ed | ||
|
|
5b597a6bfa | ||
|
|
68fb68a83b | ||
|
|
a2e5706661 | ||
|
|
7d3b3890b5 | ||
|
|
96387ee88a | ||
|
|
23590a8383 | ||
|
|
923a97b108 | ||
|
|
c517215bcf | ||
|
|
414f0275cf | ||
|
|
04414a963c | ||
|
|
02d8df94a8 | ||
|
|
a0566270d9 | ||
|
|
0d83bdc3aa | ||
|
|
062a140b9c | ||
|
|
3e9ed6c1c7 | ||
|
|
3983019fd8 | ||
|
|
3ec3aca78d | ||
|
|
1aa50b1362 | ||
|
|
e17ae475cf | ||
|
|
6cf581e360 | ||
|
|
177ca4f4d5 | ||
|
|
16c11eb4a3 | ||
|
|
df49b93877 | ||
|
|
5e7e0347cd | ||
|
|
7d9329ecfe | ||
|
|
3640c8c051 | ||
|
|
02cbb58107 | ||
|
|
5b854f95d2 | ||
|
|
b0f39da131 | ||
|
|
dc54af7a89 | ||
|
|
d01b74d00a | ||
|
|
a782a88913 | ||
|
|
8800896824 | ||
|
|
880d9e53c3 | ||
|
|
26cad481d0 | ||
|
|
8d13967aa3 | ||
|
|
650d706d35 | ||
|
|
0e07a7157f | ||
|
|
423d69bd40 | ||
|
|
6767ed74f8 | ||
|
|
57cbb8bfd8 | ||
|
|
f70378f7f5 | ||
|
|
e1ff5b1361 | ||
|
|
ab57fdac44 | ||
|
|
dacc8cdb3a | ||
|
|
ca7043e52d | ||
|
|
6f8d40ef5d | ||
|
|
2318d19bb4 | ||
|
|
f98d0433f9 | ||
|
|
34b185e955 | ||
|
|
b6dcadeb79 | ||
|
|
c2250d95c4 | ||
|
|
adc52f3f3c | ||
|
|
0a568a6037 | ||
|
|
0747c285cd | ||
|
|
306d1ab866 | ||
|
|
9b5bb5c755 | ||
|
|
450e7ef0c5 | ||
|
|
8f0d29f931 | ||
|
|
d6026a5fee | ||
|
|
939397dd6e | ||
|
|
d207d359d1 | ||
|
|
5f88cd98ad | ||
|
|
7f51b2da28 | ||
|
|
c00c8832c6 | ||
|
|
5a9fd8f433 | ||
|
|
fc5d2074b9 | ||
|
|
10c03e1a9d | ||
|
|
67228160ae | ||
|
|
165498cecf | ||
|
|
e3badd7062 | ||
|
|
6823ce99a7 | ||
|
|
1f1ad9fd23 | ||
|
|
f5ab056b38 | ||
|
|
16c031be77 | ||
|
|
350596b94f | ||
|
|
66750dc88e | ||
|
|
d10223254a | ||
|
|
eb90c3d92d | ||
|
|
6a1670dbc3 | ||
|
|
e204bedf1d | ||
|
|
650e932ddf | ||
|
|
b7def0fcf4 | ||
|
|
e6bf6950eb | ||
|
|
17bbf4d3f6 | ||
|
|
57f5dc5dcf | ||
|
|
aa77ee66c5 | ||
|
|
b9512cab1b | ||
|
|
dd8593f2d6 | ||
|
|
5af8acfa6e | ||
|
|
ba78194636 | ||
|
|
bdbdeab005 | ||
|
|
038529c763 | ||
|
|
55097e1985 | ||
|
|
c61a2ef44f | ||
|
|
5917e86297 | ||
|
|
75a8312f4e | ||
|
|
48b999a8dd | ||
|
|
3823878305 | ||
|
|
fceb465fc9 | ||
|
|
72abd5a88e | ||
|
|
066b0314b1 | ||
|
|
22e186b4aa | ||
|
|
372acf7b8e | ||
|
|
5b16271bd6 | ||
|
|
8de315738b | ||
|
|
13504b6adc | ||
|
|
f43b90da38 | ||
|
|
1f11cd09d5 | ||
|
|
82e9faf2a9 | ||
|
|
7caa28a6aa | ||
|
|
0183bdad04 | ||
|
|
d31f07bd4b | ||
|
|
979ca23f1e | ||
|
|
9b5f182642 | ||
|
|
f00d136ab1 | ||
|
|
28c50c16cd | ||
|
|
5bd50a2d90 | ||
|
|
60e6284f30 | ||
|
|
67c59645ec | ||
|
|
5ec5b1cbd6 | ||
|
|
76217939e0 | ||
|
|
206ec36c8e | ||
|
|
3b7a445cd7 | ||
|
|
b9d8e59bbf | ||
|
|
6d0ea26c2d | ||
|
|
92c7bd02fb | ||
|
|
497ff1ecd6 | ||
|
|
22b0039ad4 | ||
|
|
b90e431fc7 | ||
|
|
9bd76f2972 | ||
|
|
f0d70d4e86 | ||
|
|
6b9906687b | ||
|
|
bc2e9dbaf2 | ||
|
|
4d73d99ebc | ||
|
|
a3ad84feef | ||
|
|
f9a8efb992 | ||
|
|
42eb8c8e3b | ||
|
|
7f240aea1e | ||
|
|
c19fc00b04 | ||
|
|
ee07c3f7cf | ||
|
|
724b0a0162 | ||
|
|
ef6b8bee07 | ||
|
|
b29834ab02 | ||
|
|
89b88917a8 | ||
|
|
93fc957036 | ||
|
|
164318bd97 | ||
|
|
fc61c8809b | ||
|
|
365c169b43 | ||
|
|
214a8b4597 | ||
|
|
d2ff536a3b | ||
|
|
8d920dd09b | ||
|
|
c88d89d26e | ||
|
|
4035bf3259 | ||
|
|
65cb318cd9 | ||
|
|
30b9a4d6b4 | ||
|
|
df3c925b3c | ||
|
|
86b906d015 | ||
|
|
b1019a88ba | ||
|
|
8e69b9cb26 | ||
|
|
9f1ae4084d | ||
|
|
2c362badd4 | ||
|
|
6b1420a58a | ||
|
|
1cda39d5bb | ||
|
|
32552fede5 | ||
|
|
6c3829c2b5 | ||
|
|
ea044adf1a | ||
|
|
47f38d2316 | ||
|
|
f944ff233d | ||
|
|
a27857e938 | ||
|
|
0cda2d5193 | ||
|
|
65fa26e93e | ||
|
|
5d4f2f1528 | ||
|
|
f8d0b7d651 | ||
|
|
7895376821 | ||
|
|
aca501df8c | ||
|
|
06ec9e2e1a | ||
|
|
f9e28285ac | ||
|
|
90a8aa1444 | ||
|
|
9a39548367 | ||
|
|
db5df028b3 | ||
|
|
7a8094a9c0 | ||
|
|
10b12cc86e | ||
|
|
9b2044351f | ||
|
|
86b33c4922 | ||
|
|
97260d09a8 | ||
|
|
c4e1a01349 | ||
|
|
f148ae58c3 | ||
|
|
bd55b9cc0f | ||
|
|
77dbad72f7 | ||
|
|
75fe948bf7 | ||
|
|
a73905401a | ||
|
|
8e5b33d359 | ||
|
|
4ba6387980 | ||
|
|
b19726db6c | ||
|
|
c48c6d188c | ||
|
|
f6e0e1f5d7 | ||
|
|
20031a1008 | ||
|
|
a933cb31d4 | ||
|
|
2868676693 | ||
|
|
366724f6bf | ||
|
|
c59a9720fd | ||
|
|
2dde1d70ec | ||
|
|
1d248cce30 | ||
|
|
c33654c21a | ||
|
|
5721ff3837 | ||
|
|
e215c9a84f | ||
|
|
e5cdf486aa | ||
|
|
820d8a920b | ||
|
|
0f6af98d09 | ||
|
|
6424c5b698 | ||
|
|
eed6e04ed1 | ||
|
|
9ebf1fd3b7 | ||
|
|
fb12a82d65 | ||
|
|
c8cdc80fd6 | ||
|
|
33cb3d713c | ||
|
|
0addefad05 | ||
|
|
3bb89bb155 | ||
|
|
9d6caa4e5f | ||
|
|
12472a44d4 | ||
|
|
cbbb6447bf | ||
|
|
154a8bb466 | ||
|
|
d1be82d97c | ||
|
|
8e2a3c7279 | ||
|
|
ebe2f704d1 | ||
|
|
63c27766ef | ||
|
|
6912f65cd7 | ||
|
|
28f5b55643 | ||
|
|
c1fee78e85 | ||
|
|
d6f0bf9eef | ||
|
|
bcc0ca93d4 | ||
|
|
eb2a8fe8b8 | ||
|
|
13358c29b8 | ||
|
|
aaee2786a7 | ||
|
|
9d69b38583 | ||
|
|
69ba485415 | ||
|
|
91e88196c7 | ||
|
|
035933f806 | ||
|
|
1163fdfa11 | ||
|
|
0a27e81704 | ||
|
|
c4af909ac8 | ||
|
|
f099861245 | ||
|
|
f214940c96 | ||
|
|
26a0efae23 | ||
|
|
e237c1d07d | ||
|
|
33be32f278 | ||
|
|
297186b834 | ||
|
|
5696ee8421 | ||
|
|
d8a0efa6af | ||
|
|
b52dfbe510 | ||
|
|
b87cd8c58b | ||
|
|
318669327e | ||
|
|
278d93a3ee | ||
|
|
b55fb4f2f6 | ||
|
|
1cd8351054 | ||
|
|
631a835e07 | ||
|
|
45cf32afc5 | ||
|
|
cde3d38766 | ||
|
|
d5029958b9 | ||
|
|
bddd5f2b98 | ||
|
|
96898c1794 | ||
|
|
11afcbff69 | ||
|
|
736b386554 | ||
|
|
a785522194 | ||
|
|
8e50e256e6 | ||
|
|
9b3287b865 | ||
|
|
14657bd29a | ||
|
|
6af8a34d91 | ||
|
|
6f93c01af9 | ||
|
|
12e9f3d010 | ||
|
|
c691d619c2 | ||
|
|
61f5ca6b16 | ||
|
|
443bbe6a78 | ||
|
|
183c81b5ec | ||
|
|
076f13cc01 | ||
|
|
8eb717d4d0 | ||
|
|
8aa190606e | ||
|
|
0437abbffb | ||
|
|
0b1d09ff4f | ||
|
|
8b75736c6f | ||
|
|
099d7ff2ad | ||
|
|
46d431e7c3 | ||
|
|
615fd498bc | ||
|
|
bc879a1453 | ||
|
|
82fd83fd12 | ||
|
|
b50da63852 | ||
|
|
5bc14e2fe4 | ||
|
|
d2b1210376 | ||
|
|
a27cdf16f4 | ||
|
|
5a13c49492 | ||
|
|
8493979d86 | ||
|
|
2c472a66d1 | ||
|
|
69bd803a32 | ||
|
|
b7de864f2e | ||
|
|
da9707950e | ||
|
|
36f03a7f4a | ||
|
|
5d18dc358b | ||
|
|
b40e599866 | ||
|
|
45029117f5 | ||
|
|
578ece8dd0 | ||
|
|
896e1a30b0 | ||
|
|
0f1d2c127c | ||
|
|
d880a5ec0c | ||
|
|
145e301269 | ||
|
|
c4172934e5 | ||
|
|
40dac4cde4 | ||
|
|
05b58501f2 | ||
|
|
29c17c14f1 | ||
|
|
f4ed37ec6f | ||
|
|
e9006f904c | ||
|
|
e301bc2d77 | ||
|
|
3578e1d4a7 | ||
|
|
aa46e5c5e7 | ||
|
|
9786202b08 | ||
|
|
52ba413185 | ||
|
|
1d13d106dd | ||
|
|
ab06fca4be | ||
|
|
fd9e226b79 | ||
|
|
7d2f0d7b1b | ||
|
|
870f7bcc93 | ||
|
|
543fc6702f | ||
|
|
5080b63435 | ||
|
|
8bb36f4650 | ||
|
|
a47b829040 | ||
|
|
07632b7d69 | ||
|
|
ec54e35757 | ||
|
|
68e36226b3 | ||
|
|
15b86a6b9b | ||
|
|
eeb0900291 | ||
|
|
804a7875a2 | ||
|
|
041585a78e | ||
|
|
cd1f604ffe | ||
|
|
566f7f638a | ||
|
|
3e07c5bf82 | ||
|
|
ca16119adb | ||
|
|
d0b9b10ee0 | ||
|
|
98fd364672 | ||
|
|
151fad1f2b | ||
|
|
27373919f4 | ||
|
|
22e6fb7056 | ||
|
|
e3258b78e2 | ||
|
|
bee170570d | ||
|
|
ba73e75ef9 | ||
|
|
f4b7e1a570 | ||
|
|
fa50341a71 | ||
|
|
fa76057e7f | ||
|
|
bb454b1846 | ||
|
|
778d9b0cd6 | ||
|
|
84ace27872 | ||
|
|
c1d8eeb70a | ||
|
|
6cf87e1d23 | ||
|
|
8a93581c8a | ||
|
|
6c8fa83ecd | ||
|
|
ab45133ab4 | ||
|
|
7b6d642300 | ||
|
|
96a286dcf5 | ||
|
|
420de7ad5e | ||
|
|
8ccdd3bdb4 | ||
|
|
23913f26cd | ||
|
|
9714612999 | ||
|
|
69cdcea9fc | ||
|
|
30ec69c7d3 | ||
|
|
f720c67f3e | ||
|
|
655bb526f4 | ||
|
|
5c26972cdd | ||
|
|
117f208826 | ||
|
|
5f798d944e | ||
|
|
6b927229f5 | ||
|
|
ffad18e424 | ||
|
|
e0eaed5fdb | ||
|
|
5bd638d4a5 | ||
|
|
eca1c96412 | ||
|
|
2f5686ca48 | ||
|
|
4fa4340b95 | ||
|
|
197542c7ec | ||
|
|
ab507f83e2 | ||
|
|
d67004a3be | ||
|
|
c8acc373c1 | ||
|
|
3d1c481f0b | ||
|
|
756db8174a | ||
|
|
fa67b46c04 | ||
|
|
4d656963e4 | ||
|
|
9259d028ac | ||
|
|
52fcb0b4b9 | ||
|
|
d7d759b43f | ||
|
|
ba3fd63e29 | ||
|
|
948b5a8be7 | ||
|
|
e42eeec8f6 | ||
|
|
118285e6ba | ||
|
|
ba4d93027f | ||
|
|
fb0c431864 | ||
|
|
9c8ba42750 | ||
|
|
f9675bd2b4 | ||
|
|
cb40b3517a | ||
|
|
0a020dbcc8 | ||
|
|
ac97a7f70e | ||
|
|
e02b95741b | ||
|
|
bbd990f2cc | ||
|
|
a0b5605db8 | ||
|
|
3ba9b26310 | ||
|
|
6c43ec2d2b | ||
|
|
9b9eb23b6d | ||
|
|
8b16e5f27d | ||
|
|
5292476841 | ||
|
|
1db0334787 | ||
|
|
6e2ba111af | ||
|
|
5f1d3ad754 | ||
|
|
46f471c89f | ||
|
|
0dd9c14ff8 | ||
|
|
0709918bd8 | ||
|
|
8e5167d726 | ||
|
|
8c3ffa3907 | ||
|
|
8540871ebc | ||
|
|
23837e4352 | ||
|
|
3cab24fbcf | ||
|
|
755df5f659 | ||
|
|
936411e4d1 | ||
|
|
21317be493 | ||
|
|
41c00e87d4 | ||
|
|
2863a3291a | ||
|
|
8adad36a66 | ||
|
|
b701f8a878 | ||
|
|
63e73f29cc | ||
|
|
7fcf153ada | ||
|
|
0443d36abf | ||
|
|
df2ad89518 | ||
|
|
10dc2b30fb | ||
|
|
f9087d14a3 | ||
|
|
25cf3757b2 | ||
|
|
72ef6f637e | ||
|
|
9cadaf824b | ||
|
|
1cc1b93e65 | ||
|
|
c4f400acd0 | ||
|
|
ac628c9b0a | ||
|
|
926830e0df | ||
|
|
9696ed31a4 | ||
|
|
c8895dd43b | ||
|
|
5dd1d354f8 | ||
|
|
a0da6bcf43 | ||
|
|
1b63f8d6b9 | ||
|
|
60932d2bd7 | ||
|
|
ee2d9d973a | ||
|
|
0e6f7a21c6 | ||
|
|
cc47ff7c4c | ||
|
|
e1a495ee30 | ||
|
|
6495007924 | ||
|
|
d53a6cd851 | ||
|
|
b6c12d2aa3 | ||
|
|
7a14171be4 | ||
|
|
5194505407 | ||
|
|
3e7957512b | ||
|
|
c0bd96d9b3 | ||
|
|
0f7728f84d | ||
|
|
c129b3852b | ||
|
|
3b43c69df4 | ||
|
|
b17d3e7ad7 | ||
|
|
6a16075912 | ||
|
|
43ebec2be1 | ||
|
|
f60227f112 | ||
|
|
f3630e95d6 | ||
|
|
8887105ffd | ||
|
|
1d7408a7b8 | ||
|
|
0b1ab41a95 | ||
|
|
b717b6505b | ||
|
|
b29d609b0b | ||
|
|
8a3c777c40 | ||
|
|
548da26ddc | ||
|
|
8e0ac70c4d | ||
|
|
1ed559bd24 | ||
|
|
e3b831e975 | ||
|
|
d05e3adbc7 | ||
|
|
a9a475ad50 | ||
|
|
d38b465b7c | ||
|
|
fd7ec2da91 | ||
|
|
c9ed379e39 | ||
|
|
e64feefc61 | ||
|
|
3e754382af | ||
|
|
7ef0a13250 | ||
|
|
0de3fb786d | ||
|
|
1d44a98f2f | ||
|
|
98ff4eb4ee | ||
|
|
a9d8df83d2 | ||
|
|
508b7b5e51 | ||
|
|
f7dc72f8aa | ||
|
|
0190f9b077 | ||
|
|
0c91a0d59d | ||
|
|
a26a66a8c4 | ||
|
|
100345f1e4 | ||
|
|
4535166a3b | ||
|
|
0346e68deb | ||
|
|
db62c227c8 | ||
|
|
983e45ae92 | ||
|
|
0a18dda158 | ||
|
|
9eaf93d41d | ||
|
|
2ac20982e0 | ||
|
|
96eac87d47 | ||
|
|
0cf1ed544c | ||
|
|
558e284e25 | ||
|
|
5c31445117 | ||
|
|
717ae67995 | ||
|
|
e8331f0c1d | ||
|
|
c009aa3a22 | ||
|
|
9af9d8f5d0 | ||
|
|
2c027b03db | ||
|
|
aef1332e42 | ||
|
|
16fc8b5fc2 | ||
|
|
fd845f27f5 | ||
|
|
ea62ee4b61 | ||
|
|
cd6becd442 | ||
|
|
829f262c79 | ||
|
|
246520b5cb | ||
|
|
38bb649582 | ||
|
|
82855a04ec | ||
|
|
6dfefaf229 | ||
|
|
d44f8a854b | ||
|
|
acf3a43095 | ||
|
|
4cc98d7add | ||
|
|
506203345b | ||
|
|
c259f7c8bd | ||
|
|
c62a121cca | ||
|
|
136eb32389 | ||
|
|
e3ddbe8c6b | ||
|
|
d085139057 | ||
|
|
28e7443f9b | ||
|
|
e79ad21aeb | ||
|
|
0b61253931 | ||
|
|
a2738dec59 | ||
|
|
1788709e2d | ||
|
|
47d30d12cb | ||
|
|
43df78102c | ||
|
|
cc10eec6c6 | ||
|
|
15bf9a7026 | ||
|
|
2795f44f03 | ||
|
|
b0ba05c9ac | ||
|
|
71c6845a94 | ||
|
|
4b97023251 | ||
|
|
369046bbb4 | ||
|
|
38580fbee7 | ||
|
|
08e1d40d6e | ||
|
|
80f35467d8 | ||
|
|
1b19020bf4 | ||
|
|
61e58ee9b7 | ||
|
|
f21af8da9c | ||
|
|
dece3a3600 | ||
|
|
16ad10e62f | ||
|
|
02fb912a95 | ||
|
|
48790c0751 | ||
|
|
c57e5083e8 | ||
|
|
c9a2058361 | ||
|
|
7039dfafd6 | ||
|
|
22ae83a589 | ||
|
|
1575448b1a | ||
|
|
9f031a6759 | ||
|
|
d0ea6f9920 | ||
|
|
1bc37d576c | ||
|
|
d159591b9a | ||
|
|
57550b2b3d | ||
|
|
d15d6c4e6b | ||
|
|
6b598f61a6 | ||
|
|
9e21204f8b | ||
|
|
e6b86fa304 | ||
|
|
268e50dfbd | ||
|
|
07ccc15fc2 | ||
|
|
2b500d72e5 | ||
|
|
cd0014b24f | ||
|
|
b3786d84c5 | ||
|
|
fd1135c7af | ||
|
|
f0678979b1 | ||
|
|
f4a7e11bce | ||
|
|
6a0388bb4b | ||
|
|
7ba72f2763 | ||
|
|
f7147d9c0a | ||
|
|
523a5fd2e5 | ||
|
|
ff85e2343c | ||
|
|
e74668ef7f | ||
|
|
22502f80db | ||
|
|
4b2cc38aba | ||
|
|
a8eb68142e | ||
|
|
81554fbf72 | ||
|
|
a435cfcd82 | ||
|
|
7631918a12 | ||
|
|
e070f1e525 | ||
|
|
430d6e1cca | ||
|
|
3a0562bebc | ||
|
|
c3658e7c79 | ||
|
|
b0f81c3253 | ||
|
|
31c171fc1e | ||
|
|
e9c123b1b9 | ||
|
|
037b259197 | ||
|
|
a569961e0f | ||
|
|
7eabde6aee | ||
|
|
ed772da0cc | ||
|
|
f48882213e | ||
|
|
1cd2076d42 | ||
|
|
816b9c8d71 | ||
|
|
3bea1a944e | ||
|
|
3e419ffb38 | ||
|
|
a149c6ecde | ||
|
|
3f18e9a2da | ||
|
|
4b0494062e | ||
|
|
a09d86dd3c | ||
|
|
3ccb0f691b | ||
|
|
1709fd854a | ||
|
|
7bf446f671 | ||
|
|
e4bc76f55c | ||
|
|
81c5e5200b | ||
|
|
9c3830dd35 | ||
|
|
bf8cfce50e | ||
|
|
b235e4d290 | ||
|
|
b8cf6dee3e | ||
|
|
35df1ee253 | ||
|
|
353f9fd43c | ||
|
|
3899f83da8 | ||
|
|
5f3c70061d | ||
|
|
aba7134301 | ||
|
|
d7447cdf9e | ||
|
|
ff8d2bbc36 | ||
|
|
70c98c9972 | ||
|
|
45f32838b9 | ||
|
|
7d6e80a423 | ||
|
|
f3ec1452cd | ||
|
|
29f03756bd | ||
|
|
fe8c5546f0 | ||
|
|
c4315a7afa | ||
|
|
704782c95b | ||
|
|
67059e1932 | ||
|
|
e2ea711136 | ||
|
|
74aa598769 | ||
|
|
747ff7daf8 | ||
|
|
1f670fc688 | ||
|
|
388906ac70 | ||
|
|
49d9745dc4 | ||
|
|
7c15d793ac | ||
|
|
d90cb3511c | ||
|
|
5100272dc3 | ||
|
|
afda9810f1 | ||
|
|
22df8b81b3 | ||
|
|
7a427c9070 | ||
|
|
a35e4bdbda | ||
|
|
0aeb5adb8f | ||
|
|
9c5cc217bf | ||
|
|
24603d7ad3 | ||
|
|
1eac6ff8ff | ||
|
|
8742b3dab2 | ||
|
|
93cdc9b9dc | ||
|
|
8ed74a3429 | ||
|
|
07a5e59ae7 | ||
|
|
f8c2f1cf54 | ||
|
|
b1f043d010 | ||
|
|
251c0c8508 | ||
|
|
3214daca4c | ||
|
|
e4485f5412 | ||
|
|
4eaaa0ec53 | ||
|
|
42323014ea | ||
|
|
c59d139eeb | ||
|
|
2b4d21160f | ||
|
|
e29a5b11e4 | ||
|
|
b58ee690a3 | ||
|
|
d8edd3d0c8 | ||
|
|
1b078efd5f | ||
|
|
e8e73d37fb | ||
|
|
2eec788544 | ||
|
|
dca28b9e12 | ||
|
|
e879c92596 | ||
|
|
7281c68b27 | ||
|
|
d228f1b658 | ||
|
|
2e60593c5b | ||
|
|
531fe10f51 | ||
|
|
454b07455a | ||
|
|
a4dc6f2c76 | ||
|
|
5608f12f9b | ||
|
|
18d8e3acec | ||
|
|
578fc5bb44 | ||
|
|
e8660cfd8e | ||
|
|
6a57eabb14 | ||
|
|
a67540807a | ||
|
|
20c377ca65 | ||
|
|
5436f1c7d5 | ||
|
|
4107390337 | ||
|
|
e74da72b82 | ||
|
|
24953ba974 | ||
|
|
22a5a1fa43 | ||
|
|
7bac62ee7f | ||
|
|
fcda11c6b0 | ||
|
|
66e1cb324c | ||
|
|
a869d23451 | ||
|
|
41f4941b74 | ||
|
|
b22168d3da | ||
|
|
b9b56bac6b | ||
|
|
fa670fa4b5 | ||
|
|
b131a0cf0c | ||
|
|
d7cef8d762 | ||
|
|
4483fc7df3 | ||
|
|
2cd5addc0c | ||
|
|
5bf06efb2a | ||
|
|
5196e309b8 | ||
|
|
bee1adc651 | ||
|
|
f0e7da8a63 | ||
|
|
5bd32eca0f | ||
|
|
491287c0af | ||
|
|
8ecfd88d92 | ||
|
|
b54178bbbd | ||
|
|
67547f74fc | ||
|
|
56ba193c77 | ||
|
|
d5594e431c | ||
|
|
7bfa2d4da6 | ||
|
|
4cf00f5698 | ||
|
|
a18326e97a | ||
|
|
36c9463467 | ||
|
|
13159c1a48 | ||
|
|
0fbef74f31 | ||
|
|
52122c342d | ||
|
|
96ee73f790 | ||
|
|
dc70f50b59 | ||
|
|
e297c73913 | ||
|
|
280e1a2512 | ||
|
|
1518b8f753 | ||
|
|
5403b1cf6d | ||
|
|
29110d5428 | ||
|
|
462003363f | ||
|
|
b494324ec3 | ||
|
|
4cee9a86ac | ||
|
|
7cad0a2dcd | ||
|
|
ed1ff06867 | ||
|
|
80a64341f0 | ||
|
|
bbf3eebb1a | ||
|
|
6b20ea0752 | ||
|
|
3241ad3ae8 | ||
|
|
9e7ccedba4 | ||
|
|
b9ffb5f30d | ||
|
|
9d456ca87a | ||
|
|
18350ad37f | ||
|
|
0983f65da7 | ||
|
|
42bbd5c9ae | ||
|
|
92ae11bd3b | ||
|
|
443f45eca1 | ||
|
|
a9ddbb4beb | ||
|
|
f8c3743991 | ||
|
|
072c265c30 | ||
|
|
440e9cdbef | ||
|
|
ace005bf7c | ||
|
|
75821c6889 | ||
|
|
d376148ca1 | ||
|
|
582ca33507 | ||
|
|
a6ca7eb29d | ||
|
|
02c035c548 | ||
|
|
418041d906 | ||
|
|
a3a400992e | ||
|
|
68625b047f | ||
|
|
9a1df7bf38 | ||
|
|
81b9cfdfa4 | ||
|
|
ae7aa65069 | ||
|
|
9e0f969b8b | ||
|
|
14a8fa4d68 | ||
|
|
07e5c9bd5f | ||
|
|
49c2ca0216 | ||
|
|
04172e3dd0 | ||
|
|
2c56a9f588 | ||
|
|
20e025b3d8 | ||
|
|
10591d2080 | ||
|
|
af29c0ade5 | ||
|
|
4c876ac62e | ||
|
|
66bf7b0b01 | ||
|
|
17d51a1609 | ||
|
|
0a59605e05 | ||
|
|
202658678d | ||
|
|
4f01db256f | ||
|
|
c04f4a7d73 | ||
|
|
f5e46ba7fc | ||
|
|
8609af54fc | ||
|
|
9a4ef87859 | ||
|
|
a57f4c23d8 | ||
|
|
d629f4d2fb | ||
|
|
6f20a73782 | ||
|
|
8cb7badd63 | ||
|
|
0f3c2f6541 | ||
|
|
56496ad5d8 | ||
|
|
e15dca2a9f | ||
|
|
a32706bc26 | ||
|
|
bdcca4767c | ||
|
|
38f4dbfb51 | ||
|
|
a374b1a6a3 | ||
|
|
0ff94978f5 | ||
|
|
fa24e6b995 | ||
|
|
37b64ff616 | ||
|
|
a2fd8d1db1 | ||
|
|
684b004751 | ||
|
|
cbe11fc7aa | ||
|
|
d01387a82f | ||
|
|
862d76b617 | ||
|
|
bd9912213f | ||
|
|
814ada538a | ||
|
|
53f7eef052 | ||
|
|
405347769a | ||
|
|
5b31d32da8 | ||
|
|
dcef5183f7 | ||
|
|
728d01ef4b | ||
|
|
0557df8d06 | ||
|
|
3a9753b85f | ||
|
|
8e6ac5c263 | ||
|
|
188b303991 | ||
|
|
836595313c | ||
|
|
6779036d25 | ||
|
|
4fb6c07535 | ||
|
|
f01c988094 | ||
|
|
677456d319 | ||
|
|
f022af66da | ||
|
|
98c40f5ee6 | ||
|
|
db0928add3 | ||
|
|
a9a923e4da | ||
|
|
1cac1de3b2 | ||
|
|
524c78a8d6 | ||
|
|
e71262463f | ||
|
|
26666bb36f | ||
|
|
f801e16b78 | ||
|
|
4bf5065a9c | ||
|
|
04085cad3c | ||
|
|
c8997e48c0 | ||
|
|
77621568fd | ||
|
|
601d1936c9 | ||
|
|
06e93f8d95 | ||
|
|
74780134f2 | ||
|
|
93219e3b9d | ||
|
|
77120a021d | ||
|
|
6c14025b2d | ||
|
|
e53794868e | ||
|
|
8c2f3bb378 | ||
|
|
0ac2ce7dea | ||
|
|
c301e3c82a | ||
|
|
9dd78a8a45 | ||
|
|
ede1674d6a | ||
|
|
c3f2b24a9a | ||
|
|
b91bba1ab2 | ||
|
|
fbc22f91d5 | ||
|
|
424b36d469 | ||
|
|
8070f9485b | ||
|
|
c353709f7e | ||
|
|
c13691a8e6 | ||
|
|
2671b9af1b | ||
|
|
7d0ad0f521 | ||
|
|
9bd75d5668 | ||
|
|
fde676a43a | ||
|
|
2469ce6067 | ||
|
|
ef0ec31554 | ||
|
|
da4f51332f | ||
|
|
194258b479 | ||
|
|
fa416e7116 | ||
|
|
71b2e0e002 | ||
|
|
7d1ac4d1f6 | ||
|
|
2f2ef80ec2 | ||
|
|
c0530921ff | ||
|
|
94f1ab4da3 | ||
|
|
3f75b748cf | ||
|
|
8181b68531 | ||
|
|
2de91f11fb | ||
|
|
50621ffe85 | ||
|
|
db4911f956 | ||
|
|
2a325de7aa | ||
|
|
b9cc0a7976 | ||
|
|
97b693052c | ||
|
|
19ed3bb193 | ||
|
|
895b970a10 | ||
|
|
1f56d71f19 | ||
|
|
1ff20da5b6 | ||
|
|
5ef78cd815 | ||
|
|
9101b680c0 | ||
|
|
d24c56fd4b | ||
|
|
77d09552ae | ||
|
|
dbaccff476 | ||
|
|
dc6cf5cdee | ||
|
|
fb3ac49335 | ||
|
|
c54a40df06 | ||
|
|
9c4f68e174 | ||
|
|
4ee4dfdc13 | ||
|
|
2e0c0e9d89 | ||
|
|
db5db587be | ||
|
|
569fca5308 | ||
|
|
b409803527 | ||
|
|
99d257ae8b | ||
|
|
2f2b7915ea | ||
|
|
c1cfcb1577 | ||
|
|
2e90ed07ac | ||
|
|
58bed83d03 | ||
|
|
54917e3062 | ||
|
|
81385682c8 | ||
|
|
807a0d313b | ||
|
|
f9a66c5d46 | ||
|
|
60add387e3 | ||
|
|
ca0fd4173c | ||
|
|
4aa0f040fb | ||
|
|
5957fed9a7 | ||
|
|
6298878bfa | ||
|
|
899004207d | ||
|
|
2b200d481f | ||
|
|
8551ddc839 | ||
|
|
eea3277b81 | ||
|
|
11b86f8d8a | ||
|
|
71a3c2fcd1 | ||
|
|
4ff36696ea | ||
|
|
800d3b4ee7 | ||
|
|
a0b2c7ba25 | ||
|
|
64232f0aec | ||
|
|
591527d878 | ||
|
|
82073025cc | ||
|
|
2c9bb06516 | ||
|
|
18c4a90101 | ||
|
|
5a8ee4889d | ||
|
|
ea1fdf3201 | ||
|
|
2e61008fd9 | ||
|
|
eafde7186f | ||
|
|
a72dc388c3 | ||
|
|
618314985d | ||
|
|
d1d83d7e7f | ||
|
|
bcaab74f1f | ||
|
|
1b670a293b | ||
|
|
45f78bdf40 | ||
|
|
54eca4e736 | ||
|
|
3da05a09b5 | ||
|
|
f79082a46d | ||
|
|
e71d75ed9a | ||
|
|
a4a35f659b | ||
|
|
9eba6a349f | ||
|
|
6a1b6d0344 | ||
|
|
7f7fb9750d | ||
|
|
df190b8f87 | ||
|
|
af33b3b338 | ||
|
|
a87d19cd7e | ||
|
|
611fe41588 | ||
|
|
8b6cce18cb | ||
|
|
d330430336 | ||
|
|
37b2bc3c0c | ||
|
|
f49914dd17 | ||
|
|
f1d9880006 | ||
|
|
6ec447a1aa | ||
|
|
b485fac33e | ||
|
|
98404ad8ea | ||
|
|
e1f5227304 | ||
|
|
2de8f915f8 | ||
|
|
967f25461b | ||
|
|
0053651814 | ||
|
|
7d36833bd4 | ||
|
|
1bbfd0b6d2 | ||
|
|
4547ace59a | ||
|
|
d74659254b | ||
|
|
55d310b05a | ||
|
|
15da308c2a | ||
|
|
e80bc6ef58 | ||
|
|
d81e783665 | ||
|
|
030b63c3d2 | ||
|
|
f3dba05143 | ||
|
|
1020707918 | ||
|
|
c89d1cf072 | ||
|
|
9c5e422d3a | ||
|
|
5e00141005 | ||
|
|
fa70413c82 | ||
|
|
06d2bc7fbd | ||
|
|
1ae9e0afa1 | ||
|
|
f9da2c9507 | ||
|
|
989aba1966 | ||
|
|
6b7d6c27ee | ||
|
|
8db89b8136 | ||
|
|
8c01ad8a9d | ||
|
|
f60a5ec08f | ||
|
|
501b8fe743 | ||
|
|
e9cdb938fe | ||
|
|
f1cb91cd93 | ||
|
|
910186905f | ||
|
|
07ed57476f | ||
|
|
0b21618a05 | ||
|
|
b49a7c140e | ||
|
|
562ac3bce9 | ||
|
|
f21291211c | ||
|
|
d834d6e074 | ||
|
|
11716825fc | ||
|
|
0309021359 | ||
|
|
14a71590c3 | ||
|
|
a5f6d65c37 | ||
|
|
79326e6287 | ||
|
|
c8ec711503 | ||
|
|
0f8b91bfba | ||
|
|
b7fd3c8669 | ||
|
|
b3f4cbe157 | ||
|
|
d0491ce8b6 | ||
|
|
806f10524f | ||
|
|
50110e00e8 | ||
|
|
3a89c40e26 | ||
|
|
ff678d1607 | ||
|
|
abab3db23d | ||
|
|
496451c164 | ||
|
|
ac69a3561a |
63
.gitignore
vendored
@@ -1,27 +1,66 @@
|
|||||||
map/*
|
## Generic ignorable patterns and files
|
||||||
world/*
|
*~
|
||||||
|
.*.swp
|
||||||
|
*bak*
|
||||||
|
tags
|
||||||
|
*.vim
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
|
|
||||||
|
## Non-static Minetest directories
|
||||||
|
/bin/
|
||||||
|
/games/*
|
||||||
|
!/games/minimal/
|
||||||
|
/cache/
|
||||||
|
/textures/*
|
||||||
|
!/textures/base/
|
||||||
|
/sounds/
|
||||||
|
/mods/*
|
||||||
|
!/mods/minetest/
|
||||||
|
/mods/minetest/*
|
||||||
|
!/mods/minetest/mods_here.txt
|
||||||
|
/worlds/
|
||||||
|
/world/
|
||||||
|
|
||||||
|
## Configuration/log files
|
||||||
|
minetest.conf
|
||||||
|
debug.txt
|
||||||
|
|
||||||
|
## Build files
|
||||||
CMakeFiles/*
|
CMakeFiles/*
|
||||||
src/CMakeFiles/*
|
src/CMakeFiles/*
|
||||||
src/Makefile
|
src/Makefile
|
||||||
src/cmake_config.h
|
src/cmake_config.h
|
||||||
|
src/cmake_config_githash.h
|
||||||
src/cmake_install.cmake
|
src/cmake_install.cmake
|
||||||
|
src/script/CMakeFiles/*
|
||||||
|
src/script/common/CMakeFiles/*
|
||||||
|
src/script/cpp_api/CMakeFiles/*
|
||||||
|
src/script/lua_api/CMakeFiles/*
|
||||||
|
src/util/CMakeFiles/*
|
||||||
src/jthread/CMakeFiles/*
|
src/jthread/CMakeFiles/*
|
||||||
src/jthread/Makefile
|
src/jthread/Makefile
|
||||||
src/jthread/cmake_config.h
|
src/jthread/cmake_config.h
|
||||||
src/jthread/cmake_install.cmake
|
src/jthread/cmake_install.cmake
|
||||||
.*.swp
|
src/jthread/libjthread.a
|
||||||
minetest.conf
|
src/json/libjson.a
|
||||||
bin/
|
src/lua/build/
|
||||||
|
src/lua/CMakeFiles/
|
||||||
|
src/cguittfont/CMakeFiles/
|
||||||
|
src/cguittfont/libcguittfont.a
|
||||||
|
src/cguittfont/cmake_install.cmake
|
||||||
|
src/cguittfont/Makefile
|
||||||
|
src/json/CMakeFiles/
|
||||||
|
src/json/libjsoncpp.a
|
||||||
|
src/sqlite/CMakeFiles/*
|
||||||
|
src/sqlite/libsqlite3.a
|
||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
CPackConfig.cmake
|
CPackConfig.cmake
|
||||||
CPackSourceConfig.cmake
|
CPackSourceConfig.cmake
|
||||||
Makefile
|
Makefile
|
||||||
cmake_install.cmake
|
cmake_install.cmake
|
||||||
src/jthread/libjthread.a
|
|
||||||
debug.txt
|
|
||||||
bin/debug.txt
|
|
||||||
minetestmapper/map.png
|
|
||||||
locale/
|
locale/
|
||||||
src/lua/build/
|
*.cbp
|
||||||
src/lua/CMakeFiles/
|
*.layout
|
||||||
*bak*
|
*.o
|
||||||
|
|
||||||
|
|||||||
25
.hgignore
@@ -1,25 +0,0 @@
|
|||||||
map/*
|
|
||||||
world/*
|
|
||||||
CMakeFiles/*
|
|
||||||
src/CMakeFiles/*
|
|
||||||
src/Makefile
|
|
||||||
src/cmake_config.h
|
|
||||||
src/cmake_install.cmake
|
|
||||||
src/jthread/CMakeFiles/*
|
|
||||||
src/jthread/Makefile
|
|
||||||
src/jthread/cmake_config.h
|
|
||||||
src/jthread/cmake_install.cmake
|
|
||||||
src/.*.swp
|
|
||||||
src/sqlite/libsqlite3.a
|
|
||||||
src/session.vim
|
|
||||||
util/uloste.png
|
|
||||||
minetest.conf
|
|
||||||
debug.txt
|
|
||||||
bin/
|
|
||||||
CMakeCache.txt
|
|
||||||
CPackConfig.cmake
|
|
||||||
CPackSourceConfig.cmake
|
|
||||||
Makefile
|
|
||||||
cmake_install.cmake
|
|
||||||
src/jthread/libjthread.a
|
|
||||||
data_temp/*
|
|
||||||
10
.travis.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
language: cpp
|
||||||
|
compiler:
|
||||||
|
- gcc
|
||||||
|
- clang
|
||||||
|
before_install:
|
||||||
|
- if [ $CC = "clang" ]; then export PATH="/usr/bin/:$PATH"; sudo sh -c 'echo "deb http://ppa.launchpad.net/eudoxos/llvm-3.1/ubuntu precise main" >> /etc/apt/sources.list'; sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 92DE8183; sudo apt-get update; sudo apt-get install llvm-3.1; sudo apt-get install clang; fi
|
||||||
|
- sudo apt-get install libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev
|
||||||
|
script: cmake . && make
|
||||||
|
notifications:
|
||||||
|
email: false
|
||||||
124
CMakeLists.txt
@@ -7,10 +7,18 @@ endif(${CMAKE_VERSION} STREQUAL "2.8.2")
|
|||||||
# This can be read from ${PROJECT_NAME} after project() is called
|
# This can be read from ${PROJECT_NAME} after project() is called
|
||||||
project(minetest)
|
project(minetest)
|
||||||
|
|
||||||
|
set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
|
||||||
|
|
||||||
# Also remember to set PROTOCOL_VERSION in clientserver.h when releasing
|
# Also remember to set PROTOCOL_VERSION in clientserver.h when releasing
|
||||||
set(VERSION_MAJOR 0)
|
set(VERSION_MAJOR 0)
|
||||||
set(VERSION_MINOR 4)
|
set(VERSION_MINOR 4)
|
||||||
set(VERSION_PATCH dev-20120122-1)
|
set(VERSION_PATCH 9)
|
||||||
|
if(VERSION_EXTRA)
|
||||||
|
set(VERSION_PATCH ${VERSION_PATCH}-${VERSION_EXTRA})
|
||||||
|
else()
|
||||||
|
# Comment the following line during release
|
||||||
|
#set(VERSION_PATCH ${VERSION_PATCH}-dev)
|
||||||
|
endif()
|
||||||
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
||||||
|
|
||||||
MESSAGE(STATUS "*** Will build version ${VERSION_STRING} ***")
|
MESSAGE(STATUS "*** Will build version ${VERSION_STRING} ***")
|
||||||
@@ -23,6 +31,13 @@ else()
|
|||||||
set(RUN_IN_PLACE 0 CACHE BOOL "Run directly in source directory structure")
|
set(RUN_IN_PLACE 0 CACHE BOOL "Run directly in source directory structure")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# RUN_IN_PLACE is exported as a #define value, ensure it's 1/0 instead of ON/OFF
|
||||||
|
if(RUN_IN_PLACE)
|
||||||
|
set(RUN_IN_PLACE 1)
|
||||||
|
else()
|
||||||
|
set(RUN_IN_PLACE 0)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(BUILD_CLIENT 1 CACHE BOOL "Build client")
|
set(BUILD_CLIENT 1 CACHE BOOL "Build client")
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(BUILD_SERVER 0 CACHE BOOL "Build server")
|
set(BUILD_SERVER 0 CACHE BOOL "Build server")
|
||||||
@@ -49,26 +64,113 @@ find_package(Irrlicht)
|
|||||||
#
|
#
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(DATADIR "data")
|
set(SHAREDIR ".")
|
||||||
set(BINDIR "bin")
|
set(BINDIR "bin")
|
||||||
set(DOCDIR "doc")
|
set(DOCDIR "doc")
|
||||||
set(EXAMPLE_CONF_DIR ".")
|
set(EXAMPLE_CONF_DIR ".")
|
||||||
|
set(LOCALEDIR "locale")
|
||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
# random placeholders
|
# Random placeholders; this isn't usually used and may not work
|
||||||
set(DATADIR "share/${PROJECT_NAME}")
|
# See https://github.com/toabi/minetest-mac/
|
||||||
|
set(SHAREDIR "${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}")
|
||||||
set(BINDIR "bin")
|
set(BINDIR "bin")
|
||||||
set(DOCDIR "share/doc/${PROJECT_NAME}")
|
set(DOCDIR "share/doc/${PROJECT_NAME}")
|
||||||
set(EXAMPLE_CONF_DIR ".")
|
set(EXAMPLE_CONF_DIR ${DOCDIR})
|
||||||
|
set(LOCALEDIR "locale")
|
||||||
elseif(UNIX) # Linux, BSD etc
|
elseif(UNIX) # Linux, BSD etc
|
||||||
set(DATADIR "share/${PROJECT_NAME}")
|
if(RUN_IN_PLACE)
|
||||||
set(BINDIR "bin")
|
set(SHAREDIR ".")
|
||||||
set(DOCDIR "share/doc/${PROJECT_NAME}")
|
set(BINDIR "bin")
|
||||||
set(EXAMPLE_CONF_DIR "share/doc/${PROJECT_NAME}")
|
set(DOCDIR "doc")
|
||||||
|
set(EXAMPLE_CONF_DIR ".")
|
||||||
|
set(MANDIR "unix/man")
|
||||||
|
set(XDG_APPS_DIR "unix/applications")
|
||||||
|
set(ICONDIR "unix/icons")
|
||||||
|
set(LOCALEDIR "locale")
|
||||||
|
else()
|
||||||
|
set(SHAREDIR "${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}")
|
||||||
|
set(BINDIR "${CMAKE_INSTALL_PREFIX}/bin")
|
||||||
|
set(DOCDIR "${CMAKE_INSTALL_PREFIX}/share/doc/${PROJECT_NAME}")
|
||||||
|
set(MANDIR "${CMAKE_INSTALL_PREFIX}/share/man")
|
||||||
|
set(EXAMPLE_CONF_DIR ${DOCDIR})
|
||||||
|
set(XDG_APPS_DIR "${CMAKE_INSTALL_PREFIX}/share/applications")
|
||||||
|
set(ICONDIR "${CMAKE_INSTALL_PREFIX}/share/icons")
|
||||||
|
set(LOCALEDIR "${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}/locale")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(CUSTOM_SHAREDIR "" CACHE STRING "Directory to install data files into")
|
||||||
|
if(NOT CUSTOM_SHAREDIR STREQUAL "")
|
||||||
|
set(SHAREDIR "${CUSTOM_SHAREDIR}")
|
||||||
|
message(STATUS "Using SHAREDIR=${SHAREDIR}")
|
||||||
|
endif()
|
||||||
|
set(CUSTOM_BINDIR "" CACHE STRING "Directory to install binaries into")
|
||||||
|
if(NOT CUSTOM_BINDIR STREQUAL "")
|
||||||
|
set(BINDIR "${CUSTOM_BINDIR}")
|
||||||
|
message(STATUS "Using BINDIR=${BINDIR}")
|
||||||
|
endif()
|
||||||
|
set(CUSTOM_DOCDIR "" CACHE STRING "Directory to install documentation into")
|
||||||
|
if(NOT CUSTOM_DOCDIR STREQUAL "")
|
||||||
|
set(DOCDIR "${CUSTOM_DOCDIR}")
|
||||||
|
message(STATUS "Using DOCDIR=${DOCDIR}")
|
||||||
|
endif()
|
||||||
|
set(CUSTOM_MANDIR "" CACHE STRING "Directory to install manpages into")
|
||||||
|
if(NOT CUSTOM_MANDIR STREQUAL "")
|
||||||
|
set(MANDIR "${CUSTOM_MANDIR}")
|
||||||
|
message(STATUS "Using MANDIR=${MANDIR}")
|
||||||
|
endif()
|
||||||
|
set(CUSTOM_EXAMPLE_CONF_DIR "" CACHE STRING "Directory to install example config file into")
|
||||||
|
if(NOT CUSTOM_EXAMPLE_CONF_DIR STREQUAL "")
|
||||||
|
set(EXAMPLE_CONF_DIR "${CUSTOM_EXAMPLE_CONF_DIR}")
|
||||||
|
message(STATUS "Using EXAMPLE_CONF_DIR=${EXAMPLE_CONF_DIR}")
|
||||||
|
endif()
|
||||||
|
set(CUSTOM_XDG_APPS_DIR "" CACHE STRING "Directory to install .desktop files into")
|
||||||
|
if(NOT CUSTOM_XDG_APPS_DIR STREQUAL "")
|
||||||
|
set(XDG_APPS_DIR "${CUSTOM_XDG_APPS_DIR}")
|
||||||
|
message(STATUS "Using XDG_APPS_DIR=${XDG_APPS_DIR}")
|
||||||
|
endif()
|
||||||
|
set(CUSTOM_ICONDIR "" CACHE STRING "Directory to install icons into")
|
||||||
|
if(NOT CUSTOM_ICONDIR STREQUAL "")
|
||||||
|
set(ICONDIR "${CUSTOM_ICONDIR}")
|
||||||
|
message(STATUS "Using ICONDIR=${ICONDIR}")
|
||||||
|
endif()
|
||||||
|
set(CUSTOM_LOCALEDIR "" CACHE STRING "Directory to install l10n files into")
|
||||||
|
if(NOT CUSTOM_LOCALEDIR STREQUAL "")
|
||||||
|
set(LOCALEDIR "${CUSTOM_LOCALEDIR}")
|
||||||
|
message(STATUS "Using LOCALEDIR=${LOCALEDIR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/builtin" DESTINATION "${SHAREDIR}")
|
||||||
|
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/client" DESTINATION "${SHAREDIR}")
|
||||||
|
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/minimal" DESTINATION "${SHAREDIR}/games")
|
||||||
|
set(MINETEST_GAME_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/games/minetest_game")
|
||||||
|
if(EXISTS ${MINETEST_GAME_SOURCE} AND IS_DIRECTORY ${MINETEST_GAME_SOURCE})
|
||||||
|
install(FILES ${MINETEST_GAME_SOURCE}/game.conf DESTINATION "${SHAREDIR}/games/minetest_game/")
|
||||||
|
install(FILES ${MINETEST_GAME_SOURCE}/README.txt DESTINATION "${SHAREDIR}/games/minetest_game/")
|
||||||
|
install(DIRECTORY ${MINETEST_GAME_SOURCE}/mods DESTINATION "${SHAREDIR}/games/minetest_game")
|
||||||
|
install(DIRECTORY ${MINETEST_GAME_SOURCE}/menu DESTINATION "${SHAREDIR}/games/minetest_game")
|
||||||
|
endif()
|
||||||
|
if(BUILD_CLIENT)
|
||||||
|
#install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/sounds/base/pack" DESTINATION "${SHAREDIR}/sounds/base")
|
||||||
|
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/textures/base/pack" DESTINATION "${SHAREDIR}/textures/base")
|
||||||
|
endif()
|
||||||
|
if(RUN_IN_PLACE)
|
||||||
|
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/mods/mods_here.txt" DESTINATION "${SHAREDIR}/mods")
|
||||||
|
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/textures/texture_packs_here.txt" DESTINATION "${SHAREDIR}/textures")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/fonts" DESTINATION "${SHAREDIR}")
|
||||||
|
|
||||||
install(FILES "README.txt" DESTINATION "${DOCDIR}")
|
install(FILES "README.txt" DESTINATION "${DOCDIR}")
|
||||||
install(FILES "doc/changelog.txt" DESTINATION "${DOCDIR}")
|
install(FILES "doc/lua_api.txt" DESTINATION "${DOCDIR}")
|
||||||
install(FILES "minetest.conf.example" DESTINATION "${DOCDIR}")
|
install(FILES "doc/mapformat.txt" DESTINATION "${DOCDIR}")
|
||||||
|
install(FILES "minetest.conf.example" DESTINATION "${EXAMPLE_CONF_DIR}")
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
install(FILES "doc/minetest.6" "doc/minetestserver.6" DESTINATION "${MANDIR}/man6")
|
||||||
|
install(FILES "misc/minetest.desktop" DESTINATION "${XDG_APPS_DIR}")
|
||||||
|
install(FILES "misc/minetest-icon.svg" DESTINATION "${ICONDIR}/hicolor/scalable/apps")
|
||||||
|
endif()
|
||||||
|
|
||||||
#
|
#
|
||||||
# Subdirectories
|
# Subdirectories
|
||||||
|
|||||||
237
README.txt
@@ -1,50 +1,80 @@
|
|||||||
Minetest-c55
|
Minetest
|
||||||
---------------
|
============
|
||||||
An InfiniMiner/Minecraft inspired game.
|
|
||||||
Copyright (c) 2010-2011 Perttu Ahola <celeron55@gmail.com>
|
|
||||||
(see source files for other contributors)
|
|
||||||
|
|
||||||
Further documentation:
|
An InfiniMiner/Minecraft inspired game.
|
||||||
|
|
||||||
|
Copyright (c) 2010-2013 Perttu Ahola <celeron55@gmail.com>
|
||||||
|
and contributors (see source file comments and the version control log)
|
||||||
|
|
||||||
|
In case you downloaded the source code:
|
||||||
|
---------------------------------------
|
||||||
|
If you downloaded the Minetest Engine source code in which this file is
|
||||||
|
contained, you probably want to download the minetest_game project too:
|
||||||
|
https://github.com/minetest/minetest_game/
|
||||||
|
See the README.txt in it.
|
||||||
|
|
||||||
|
Further documentation
|
||||||
----------------------
|
----------------------
|
||||||
- Website: http://celeron.55.lt/~celeron55/minetest/
|
- Website: http://minetest.net/
|
||||||
- Wiki: http://celeron.55.lt/~celeron55/minetest/wiki/
|
- Wiki: http://wiki.minetest.net/
|
||||||
- Forum: http://celeron.55.lt/~celeron55/minetest/forum/
|
- Developer wiki: http://dev.minetest.net/
|
||||||
|
- Forum: http://forum.minetest.net/
|
||||||
|
- Github: https://github.com/minetest/minetest/
|
||||||
- doc/ directory of source distribution
|
- doc/ directory of source distribution
|
||||||
|
|
||||||
This game is not finished:
|
This game is not finished
|
||||||
--------------------------
|
--------------------------
|
||||||
- Don't expect it to work as well as a finished game will.
|
- Don't expect it to work as well as a finished game will.
|
||||||
- Please report any bugs to me. debug.txt is useful.
|
- Please report any bugs. When doing that, debug.txt is useful.
|
||||||
|
|
||||||
Controls:
|
Default Controls
|
||||||
---------
|
-----------------
|
||||||
- See the in-game pause menu
|
- WASD: move
|
||||||
|
- Space: jump/climb
|
||||||
|
- Shift: sneak/go down
|
||||||
|
- Q: drop item
|
||||||
|
- I: inventory
|
||||||
|
- Mouse: turn/look
|
||||||
|
- Mouse left: dig/punch
|
||||||
|
- Mouse right: place/use
|
||||||
|
- Mouse wheel: select item
|
||||||
|
- Esc: pause menu
|
||||||
|
- T: chat
|
||||||
- Settable in the configuration file, see the section below.
|
- Settable in the configuration file, see the section below.
|
||||||
|
|
||||||
Map directory:
|
Paths
|
||||||
--------------
|
------
|
||||||
- Map is stored in a directory, which can be removed to generate a new map.
|
$bin - Compiled binaries
|
||||||
- There is a command-line option for it: --map-dir
|
$share - Distributed read-only data
|
||||||
- For a RUN_IN_PLACE build, it is located in:
|
$user - User-created modifiable data
|
||||||
../world
|
|
||||||
- Otherwise something like this:
|
Windows .zip / RUN_IN_PLACE source:
|
||||||
Windows: C:\Documents and Settings\user\Application Data\minetest\world
|
$bin = bin
|
||||||
Linux: ~/.minetest/world
|
$share = .
|
||||||
OS X: ~/Library/Application Support/minetest/world
|
$user = .
|
||||||
|
|
||||||
|
Linux installed:
|
||||||
|
$bin = /usr/bin
|
||||||
|
$share = /usr/share/minetest
|
||||||
|
$user = ~/.minetest
|
||||||
|
|
||||||
|
OS X:
|
||||||
|
$bin = ?
|
||||||
|
$share = ?
|
||||||
|
$user = ~/Library/Application Support/minetest
|
||||||
|
|
||||||
|
World directory
|
||||||
|
----------------
|
||||||
|
- Worlds can be found as separate folders in:
|
||||||
|
$user/worlds/
|
||||||
|
|
||||||
Configuration file:
|
Configuration file:
|
||||||
-------------------
|
-------------------
|
||||||
- An optional configuration file can be used. See minetest.conf.example.
|
- Default location:
|
||||||
- Path to file can be passed as a parameter to the executable:
|
$user/minetest.conf
|
||||||
|
- It is created by Minetest when it is ran the first time.
|
||||||
|
- A specific file can be specified on the command line:
|
||||||
--config <path-to-file>
|
--config <path-to-file>
|
||||||
- Defaults:
|
|
||||||
- If built with -DRUN_IN_PLACE=1:
|
|
||||||
../minetest.conf
|
|
||||||
../../minetest.conf
|
|
||||||
- Otherwise something like this:
|
|
||||||
Windows: C:\Documents and Settings\user\Application Data\minetest\minetest.conf
|
|
||||||
Linux: ~/.minetest/minetest.conf
|
|
||||||
OS X: ~/Library/Application Support/minetest.conf
|
|
||||||
|
|
||||||
Command-line options:
|
Command-line options:
|
||||||
---------------------
|
---------------------
|
||||||
@@ -54,12 +84,19 @@ Compiling on GNU/Linux:
|
|||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
Install dependencies. Here's an example for Debian/Ubuntu:
|
Install dependencies. Here's an example for Debian/Ubuntu:
|
||||||
$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev
|
$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev
|
||||||
|
|
||||||
Download source, extract (this is the URL to the latest of source repository, which might not work at all times):
|
Download source, extract (this is the URL to the latest of source repository, which might not work at all times):
|
||||||
$ wget https://github.com/celeron55/minetest/tarball/master -O master.tar.gz
|
$ wget https://github.com/minetest/minetest/tarball/master -O master.tar.gz
|
||||||
$ tar xf master.tar.gz
|
$ tar xf master.tar.gz
|
||||||
$ cd celeron55-minetest-286edd4 (or similar)
|
$ cd minetest-minetest-286edd4 (or similar)
|
||||||
|
|
||||||
|
Download minetest_game (otherwise only the "Minimal development test" game is available)
|
||||||
|
$ cd games/
|
||||||
|
$ wget https://github.com/minetest/minetest_game/tarball/master -O minetest_game.tar.gz
|
||||||
|
$ tar xf minetest_game.tar.gz
|
||||||
|
$ mv minetest-minetest_game-* minetest_game
|
||||||
|
$ cd ..
|
||||||
|
|
||||||
Build a version that runs directly from the source directory:
|
Build a version that runs directly from the source directory:
|
||||||
$ cmake . -DRUN_IN_PLACE=1
|
$ cmake . -DRUN_IN_PLACE=1
|
||||||
@@ -74,9 +111,13 @@ $ ./minetest
|
|||||||
- You can build a bare server or a bare client by specifying -DBUILD_CLIENT=0 or -DBUILD_SERVER=0
|
- You can build a bare server or a bare client by specifying -DBUILD_CLIENT=0 or -DBUILD_SERVER=0
|
||||||
- You can select between Release and Debug build by -DCMAKE_BUILD_TYPE=<Debug or Release>
|
- You can select between Release and Debug build by -DCMAKE_BUILD_TYPE=<Debug or Release>
|
||||||
- Debug build is slower, but gives much more useful output in a debugger
|
- Debug build is slower, but gives much more useful output in a debugger
|
||||||
|
- If you build a bare server, you don't need to have Irrlicht installed. In that case use -DIRRLICHT_SOURCE_DIR=/the/irrlicht/source
|
||||||
|
|
||||||
Compiling on Windows:
|
Compiling on Windows:
|
||||||
---------------------
|
---------------------
|
||||||
|
- This section is outdated. In addition to what is described here:
|
||||||
|
- In addition to minetest, you need to download minetest_game.
|
||||||
|
- If you wish to have sound support, you need libogg, libvorbis and libopenal
|
||||||
|
|
||||||
- You need:
|
- You need:
|
||||||
* CMake:
|
* CMake:
|
||||||
@@ -90,16 +131,17 @@ Compiling on Windows:
|
|||||||
http://www.winimage.com/zLibDll/index.html
|
http://www.winimage.com/zLibDll/index.html
|
||||||
* Zlib library (zlibwapi.lib and zlibwapi.dll from zlib125dll.zip):
|
* Zlib library (zlibwapi.lib and zlibwapi.dll from zlib125dll.zip):
|
||||||
http://www.winimage.com/zLibDll/index.html
|
http://www.winimage.com/zLibDll/index.html
|
||||||
* Optional: gettext bibrary and tools:
|
* Optional: gettext library and tools:
|
||||||
http://gnuwin32.sourceforge.net/downlinks/gettext.php
|
http://gnuwin32.sourceforge.net/downlinks/gettext.php
|
||||||
- This is used for other UI languages. Feel free to leave it out.
|
- This is used for other UI languages. Feel free to leave it out.
|
||||||
* And, of course, Minetest-c55:
|
* And, of course, Minetest:
|
||||||
http://celeron.55.lt/~celeron55/minetest/download
|
http://minetest.net/download.php
|
||||||
- Steps:
|
- Steps:
|
||||||
- Select a directory called DIR hereafter in which you will operate.
|
- Select a directory called DIR hereafter in which you will operate.
|
||||||
- Make sure you have CMake and a compiler installed.
|
- Make sure you have CMake and a compiler installed.
|
||||||
- Download all the other stuff to DIR and extract them into there.
|
- Download all the other stuff to DIR and extract them into there.
|
||||||
("extract here", not "extract to packagename/")
|
("extract here", not "extract to packagename/")
|
||||||
|
NOTE: zlib125dll.zip needs to be extracted into zlib125dll
|
||||||
- All those packages contain a nice base directory in them, which
|
- All those packages contain a nice base directory in them, which
|
||||||
should end up being the direct subdirectories of DIR.
|
should end up being the direct subdirectories of DIR.
|
||||||
- You will end up with a directory structure like this (+=dir, -=file):
|
- You will end up with a directory structure like this (+=dir, -=file):
|
||||||
@@ -176,51 +218,78 @@ Compiling on Windows:
|
|||||||
If using MinGW:
|
If using MinGW:
|
||||||
- Using the command line, browse to the build directory and run 'make'
|
- Using the command line, browse to the build directory and run 'make'
|
||||||
(or mingw32-make or whatever it happens to be)
|
(or mingw32-make or whatever it happens to be)
|
||||||
|
- You may need to copy some of the downloaded DLLs into bin/, see what
|
||||||
|
running the produced executable tells you it doesn't have.
|
||||||
- You should now have a working game with the executable in
|
- You should now have a working game with the executable in
|
||||||
DIR/minetest/bin/minetest.exe
|
DIR/minetest/bin/minetest.exe
|
||||||
|
|
||||||
Windows releases of minetest are built using a bat script like this:
|
Windows releases of minetest are built using a bat script like this:
|
||||||
--------------------------------------------------------------------
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
set sourcedir=%CD%
|
||||||
set installpath="C:\tmp\minetest_install"
|
set installpath="C:\tmp\minetest_install"
|
||||||
set irrlichtpath="C:\tmp\irrlicht-1.7.2"
|
set irrlichtpath="C:\tmp\irrlicht-1.7.2"
|
||||||
|
|
||||||
set sourcedir=%CD%
|
|
||||||
set builddir=%sourcedir%\bvc10
|
set builddir=%sourcedir%\bvc10
|
||||||
mkdir %builddir%
|
mkdir %builddir%
|
||||||
pushd %builddir%
|
pushd %builddir%
|
||||||
cmake %sourcedir% -G "Visual Studio 10" -DIRRLICHT_SOURCE_DIR=%irrlichtpath% -DRUN_IN_PLACE=1 -DCMAKE_INSTALL_PREFIX=%installpath%
|
cmake %sourcedir% -G "Visual Studio 10" -DIRRLICHT_SOURCE_DIR=%irrlichtpath% -DRUN_IN_PLACE=1 -DCMAKE_INSTALL_PREFIX=%installpath%
|
||||||
|
if %errorlevel% neq 0 goto fail
|
||||||
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" ALL_BUILD.vcxproj /p:Configuration=Release
|
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" ALL_BUILD.vcxproj /p:Configuration=Release
|
||||||
|
if %errorlevel% neq 0 goto fail
|
||||||
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" INSTALL.vcxproj /p:Configuration=Release
|
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" INSTALL.vcxproj /p:Configuration=Release
|
||||||
|
if %errorlevel% neq 0 goto fail
|
||||||
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" PACKAGE.vcxproj /p:Configuration=Release
|
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" PACKAGE.vcxproj /p:Configuration=Release
|
||||||
|
if %errorlevel% neq 0 goto fail
|
||||||
popd
|
popd
|
||||||
|
echo Finished.
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
License of Minetest-c55 textures and sounds
|
:fail
|
||||||
-------------------------------------------
|
popd
|
||||||
|
echo Failed.
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
License of Minetest textures and sounds
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
This applies to textures and sounds contained in the main Minetest
|
This applies to textures and sounds contained in the main Minetest
|
||||||
distribution.
|
distribution.
|
||||||
|
|
||||||
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||||
http://creativecommons.org/licenses/by-sa/3.0/
|
http://creativecommons.org/licenses/by-sa/3.0/
|
||||||
|
|
||||||
License of Minetest-c55 source code
|
Authors of media files
|
||||||
-----------------------------------
|
-----------------------
|
||||||
|
Everything not listed in here:
|
||||||
|
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
Minetest-c55
|
BlockMen:
|
||||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
textures/base/pack/menuheader.png
|
||||||
|
|
||||||
|
erlehmann:
|
||||||
|
misc/minetest-icon-24x24.png
|
||||||
|
misc/minetest-icon.ico
|
||||||
|
misc/minetest-icon.svg
|
||||||
|
textures/base/pack/logo.png
|
||||||
|
|
||||||
|
License of Minetest source code
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
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 Lesser General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
@@ -276,4 +345,68 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|||||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
IN THE SOFTWARE.
|
IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Lua
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Lua is licensed under the terms of the MIT license reproduced below.
|
||||||
|
This means that Lua is free software and can be used for both academic
|
||||||
|
and commercial purposes at absolutely no cost.
|
||||||
|
|
||||||
|
For details and rationale, see http://www.lua.org/license.html .
|
||||||
|
|
||||||
|
Copyright (C) 1994-2008 Lua.org, PUC-Rio.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
Fonts
|
||||||
|
---------------
|
||||||
|
|
||||||
|
DejaVu Sans Mono:
|
||||||
|
|
||||||
|
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
|
||||||
|
Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
|
||||||
|
|
||||||
|
Bitstream Vera Fonts Copyright:
|
||||||
|
|
||||||
|
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
|
||||||
|
a trademark of Bitstream, Inc.
|
||||||
|
|
||||||
|
Arev Fonts Copyright:
|
||||||
|
|
||||||
|
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
|
||||||
|
|
||||||
|
Liberation Fonts Copyright:
|
||||||
|
|
||||||
|
Copyright (c) 2007 Red Hat, Inc. All rights reserved. LIBERATION is a trademark of Red Hat, Inc.
|
||||||
|
|
||||||
|
DroidSansFallback:
|
||||||
|
|
||||||
|
Copyright (C) 2008 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
|||||||
19
builtin/async_env.lua
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
engine.log("info","Initializing Asynchronous environment")
|
||||||
|
|
||||||
|
dofile(SCRIPTDIR .. DIR_DELIM .. "misc_helpers.lua")
|
||||||
|
|
||||||
|
function engine.job_processor(serialized_function, serialized_data)
|
||||||
|
|
||||||
|
local fct = marshal.decode(serialized_function)
|
||||||
|
local params = marshal.decode(serialized_data)
|
||||||
|
local retval = marshal.encode(nil)
|
||||||
|
|
||||||
|
if fct ~= nil and type(fct) == "function" then
|
||||||
|
local result = fct(params)
|
||||||
|
retval = marshal.encode(result)
|
||||||
|
else
|
||||||
|
engine.log("error","ASYNC WORKER: unable to deserialize function")
|
||||||
|
end
|
||||||
|
|
||||||
|
return retval,retval:len()
|
||||||
|
end
|
||||||
59
builtin/async_event.lua
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
local tbl = engine or minetest
|
||||||
|
|
||||||
|
tbl.async_jobs = {}
|
||||||
|
|
||||||
|
if engine ~= nil then
|
||||||
|
function tbl.async_event_handler(jobid, serialized_retval)
|
||||||
|
local retval = nil
|
||||||
|
if serialized_retval ~= "ERROR" then
|
||||||
|
retval= marshal.decode(serialized_retval)
|
||||||
|
else
|
||||||
|
tbl.log("error","Error fetching async result")
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(type(tbl.async_jobs[jobid]) == "function")
|
||||||
|
tbl.async_jobs[jobid](retval)
|
||||||
|
tbl.async_jobs[jobid] = nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
|
||||||
|
minetest.register_globalstep(
|
||||||
|
function(dtime)
|
||||||
|
local list = tbl.get_finished_jobs()
|
||||||
|
|
||||||
|
for i=1,#list,1 do
|
||||||
|
local retval = marshal.decode(list[i].retval)
|
||||||
|
|
||||||
|
assert(type(tbl.async_jobs[jobid]) == "function")
|
||||||
|
tbl.async_jobs[list[i].jobid](retval)
|
||||||
|
tbl.async_jobs[list[i].jobid] = nil
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function tbl.handle_async(fct, parameters, callback)
|
||||||
|
|
||||||
|
--serialize fct
|
||||||
|
local serialized_fct = marshal.encode(fct)
|
||||||
|
|
||||||
|
assert(marshal.decode(serialized_fct) ~= nil)
|
||||||
|
|
||||||
|
--serialize parameters
|
||||||
|
local serialized_params = marshal.encode(parameters)
|
||||||
|
|
||||||
|
if serialized_fct == nil or
|
||||||
|
serialized_params == nil or
|
||||||
|
serialized_fct:len() == 0 or
|
||||||
|
serialized_params:len() == 0 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local jobid = tbl.do_async_callback( serialized_fct,
|
||||||
|
serialized_fct:len(),
|
||||||
|
serialized_params,
|
||||||
|
serialized_params:len())
|
||||||
|
|
||||||
|
tbl.async_jobs[jobid] = callback
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
188
builtin/auth.lua
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
-- Minetest: builtin/auth.lua
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Authentication handler
|
||||||
|
--
|
||||||
|
|
||||||
|
function minetest.string_to_privs(str, delim)
|
||||||
|
assert(type(str) == "string")
|
||||||
|
delim = delim or ','
|
||||||
|
privs = {}
|
||||||
|
for _, priv in pairs(string.split(str, delim)) do
|
||||||
|
privs[priv:trim()] = true
|
||||||
|
end
|
||||||
|
return privs
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.privs_to_string(privs, delim)
|
||||||
|
assert(type(privs) == "table")
|
||||||
|
delim = delim or ','
|
||||||
|
list = {}
|
||||||
|
for priv, bool in pairs(privs) do
|
||||||
|
if bool then
|
||||||
|
table.insert(list, priv)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return table.concat(list, delim)
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(minetest.string_to_privs("a,b").b == true)
|
||||||
|
assert(minetest.privs_to_string({a=true,b=true}) == "a,b")
|
||||||
|
|
||||||
|
minetest.auth_file_path = minetest.get_worldpath().."/auth.txt"
|
||||||
|
minetest.auth_table = {}
|
||||||
|
|
||||||
|
local function read_auth_file()
|
||||||
|
local newtable = {}
|
||||||
|
local file, errmsg = io.open(minetest.auth_file_path, 'rb')
|
||||||
|
if not file then
|
||||||
|
minetest.log("info", minetest.auth_file_path.." could not be opened for reading ("..errmsg.."); assuming new world")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
for line in file:lines() do
|
||||||
|
if line ~= "" then
|
||||||
|
local name, password, privilegestring = string.match(line, "([^:]*):([^:]*):([^:]*)")
|
||||||
|
if not name or not password or not privilegestring then
|
||||||
|
error("Invalid line in auth.txt: "..dump(line))
|
||||||
|
end
|
||||||
|
local privileges = minetest.string_to_privs(privilegestring)
|
||||||
|
newtable[name] = {password=password, privileges=privileges}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
io.close(file)
|
||||||
|
minetest.auth_table = newtable
|
||||||
|
minetest.notify_authentication_modified()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function save_auth_file()
|
||||||
|
local newtable = {}
|
||||||
|
-- Check table for validness before attempting to save
|
||||||
|
for name, stuff in pairs(minetest.auth_table) do
|
||||||
|
assert(type(name) == "string")
|
||||||
|
assert(name ~= "")
|
||||||
|
assert(type(stuff) == "table")
|
||||||
|
assert(type(stuff.password) == "string")
|
||||||
|
assert(type(stuff.privileges) == "table")
|
||||||
|
end
|
||||||
|
local file, errmsg = io.open(minetest.auth_file_path, 'w+b')
|
||||||
|
if not file then
|
||||||
|
error(minetest.auth_file_path.." could not be opened for writing: "..errmsg)
|
||||||
|
end
|
||||||
|
for name, stuff in pairs(minetest.auth_table) do
|
||||||
|
local privstring = minetest.privs_to_string(stuff.privileges)
|
||||||
|
file:write(name..":"..stuff.password..":"..privstring..'\n')
|
||||||
|
end
|
||||||
|
io.close(file)
|
||||||
|
end
|
||||||
|
|
||||||
|
read_auth_file()
|
||||||
|
|
||||||
|
minetest.builtin_auth_handler = {
|
||||||
|
get_auth = function(name)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
-- Figure out what password to use for a new player (singleplayer
|
||||||
|
-- always has an empty password, otherwise use default, which is
|
||||||
|
-- usually empty too)
|
||||||
|
local new_password_hash = ""
|
||||||
|
-- If not in authentication table, return nil
|
||||||
|
if not minetest.auth_table[name] then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
-- Figure out what privileges the player should have.
|
||||||
|
-- Take a copy of the privilege table
|
||||||
|
local privileges = {}
|
||||||
|
for priv, _ in pairs(minetest.auth_table[name].privileges) do
|
||||||
|
privileges[priv] = true
|
||||||
|
end
|
||||||
|
-- If singleplayer, give all privileges except those marked as give_to_singleplayer = false
|
||||||
|
if minetest.is_singleplayer() then
|
||||||
|
for priv, def in pairs(minetest.registered_privileges) do
|
||||||
|
if def.give_to_singleplayer then
|
||||||
|
privileges[priv] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- For the admin, give everything
|
||||||
|
elseif name == minetest.setting_get("name") then
|
||||||
|
for priv, def in pairs(minetest.registered_privileges) do
|
||||||
|
privileges[priv] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- All done
|
||||||
|
return {
|
||||||
|
password = minetest.auth_table[name].password,
|
||||||
|
privileges = privileges,
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
create_auth = function(name, password)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
assert(type(password) == "string")
|
||||||
|
minetest.log('info', "Built-in authentication handler adding player '"..name.."'")
|
||||||
|
minetest.auth_table[name] = {
|
||||||
|
password = password,
|
||||||
|
privileges = minetest.string_to_privs(minetest.setting_get("default_privs")),
|
||||||
|
}
|
||||||
|
save_auth_file()
|
||||||
|
end,
|
||||||
|
set_password = function(name, password)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
assert(type(password) == "string")
|
||||||
|
if not minetest.auth_table[name] then
|
||||||
|
minetest.builtin_auth_handler.create_auth(name, password)
|
||||||
|
else
|
||||||
|
minetest.log('info', "Built-in authentication handler setting password of player '"..name.."'")
|
||||||
|
minetest.auth_table[name].password = password
|
||||||
|
save_auth_file()
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
set_privileges = function(name, privileges)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
assert(type(privileges) == "table")
|
||||||
|
if not minetest.auth_table[name] then
|
||||||
|
minetest.builtin_auth_handler.create_auth(name, minetest.get_password_hash(name, minetest.setting_get("default_password")))
|
||||||
|
end
|
||||||
|
minetest.auth_table[name].privileges = privileges
|
||||||
|
minetest.notify_authentication_modified(name)
|
||||||
|
save_auth_file()
|
||||||
|
end,
|
||||||
|
reload = function()
|
||||||
|
read_auth_file()
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
function minetest.register_authentication_handler(handler)
|
||||||
|
if minetest.registered_auth_handler then
|
||||||
|
error("Add-on authentication handler already registered by "..minetest.registered_auth_handler_modname)
|
||||||
|
end
|
||||||
|
minetest.registered_auth_handler = handler
|
||||||
|
minetest.registered_auth_handler_modname = minetest.get_current_modname()
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.get_auth_handler()
|
||||||
|
if minetest.registered_auth_handler then
|
||||||
|
return minetest.registered_auth_handler
|
||||||
|
end
|
||||||
|
return minetest.builtin_auth_handler
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.set_player_password(name, password)
|
||||||
|
if minetest.get_auth_handler().set_password then
|
||||||
|
minetest.get_auth_handler().set_password(name, password)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.set_player_privs(name, privs)
|
||||||
|
if minetest.get_auth_handler().set_privileges then
|
||||||
|
minetest.get_auth_handler().set_privileges(name, privs)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.auth_reload()
|
||||||
|
if minetest.get_auth_handler().reload then
|
||||||
|
return minetest.get_auth_handler().reload()
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
36
builtin/builtin.lua
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
--
|
||||||
|
-- This file contains built-in stuff in Minetest implemented in Lua.
|
||||||
|
--
|
||||||
|
-- It is always loaded and executed after registration of the C API,
|
||||||
|
-- before loading and running any mods.
|
||||||
|
--
|
||||||
|
|
||||||
|
-- Initialize some very basic things
|
||||||
|
print = minetest.debug
|
||||||
|
math.randomseed(os.time())
|
||||||
|
os.setlocale("C", "numeric")
|
||||||
|
|
||||||
|
local errorfct = error
|
||||||
|
error = function(text)
|
||||||
|
print(debug.traceback(""))
|
||||||
|
errorfct(text)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Load other files
|
||||||
|
local modpath = minetest.get_modpath("__builtin")
|
||||||
|
dofile(modpath.."/serialize.lua")
|
||||||
|
dofile(modpath.."/misc_helpers.lua")
|
||||||
|
dofile(modpath.."/item.lua")
|
||||||
|
dofile(modpath.."/misc_register.lua")
|
||||||
|
dofile(modpath.."/item_entity.lua")
|
||||||
|
dofile(modpath.."/deprecated.lua")
|
||||||
|
dofile(modpath.."/misc.lua")
|
||||||
|
dofile(modpath.."/privileges.lua")
|
||||||
|
dofile(modpath.."/auth.lua")
|
||||||
|
dofile(modpath.."/chatcommands.lua")
|
||||||
|
dofile(modpath.."/static_spawn.lua")
|
||||||
|
dofile(modpath.."/detached_inventory.lua")
|
||||||
|
dofile(modpath.."/falling.lua")
|
||||||
|
dofile(modpath.."/features.lua")
|
||||||
|
dofile(modpath.."/voxelarea.lua")
|
||||||
|
dofile(modpath.."/vector.lua")
|
||||||
704
builtin/chatcommands.lua
Normal file
@@ -0,0 +1,704 @@
|
|||||||
|
-- Minetest: builtin/chatcommands.lua
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Chat command handler
|
||||||
|
--
|
||||||
|
|
||||||
|
minetest.chatcommands = {}
|
||||||
|
function minetest.register_chatcommand(cmd, def)
|
||||||
|
def = def or {}
|
||||||
|
def.params = def.params or ""
|
||||||
|
def.description = def.description or ""
|
||||||
|
def.privs = def.privs or {}
|
||||||
|
minetest.chatcommands[cmd] = def
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_on_chat_message(function(name, message)
|
||||||
|
local cmd, param = string.match(message, "^/([^ ]+) *(.*)")
|
||||||
|
if not param then
|
||||||
|
param = ""
|
||||||
|
end
|
||||||
|
local cmd_def = minetest.chatcommands[cmd]
|
||||||
|
if cmd_def then
|
||||||
|
local has_privs, missing_privs = minetest.check_player_privs(name, cmd_def.privs)
|
||||||
|
if has_privs then
|
||||||
|
cmd_def.func(name, param)
|
||||||
|
else
|
||||||
|
minetest.chat_send_player(name, "You don't have permission to run this command (missing privileges: "..table.concat(missing_privs, ", ")..")")
|
||||||
|
end
|
||||||
|
return true -- handled chat message
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end)
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Chat commands
|
||||||
|
--
|
||||||
|
minetest.register_chatcommand("me", {
|
||||||
|
params = "<action>",
|
||||||
|
description = "chat action (eg. /me orders a pizza)",
|
||||||
|
privs = {shout=true},
|
||||||
|
func = function(name, param)
|
||||||
|
minetest.chat_send_all("* " .. name .. " " .. param)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("help", {
|
||||||
|
privs = {},
|
||||||
|
params = "(nothing)/all/privs/<cmd>",
|
||||||
|
description = "Get help for commands or list privileges",
|
||||||
|
func = function(name, param)
|
||||||
|
local format_help_line = function(cmd, def)
|
||||||
|
local msg = "/"..cmd
|
||||||
|
if def.params and def.params ~= "" then msg = msg .. " " .. def.params end
|
||||||
|
if def.description and def.description ~= "" then msg = msg .. ": " .. def.description end
|
||||||
|
return msg
|
||||||
|
end
|
||||||
|
if param == "" then
|
||||||
|
local msg = ""
|
||||||
|
cmds = {}
|
||||||
|
for cmd, def in pairs(minetest.chatcommands) do
|
||||||
|
if minetest.check_player_privs(name, def.privs) then
|
||||||
|
table.insert(cmds, cmd)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
minetest.chat_send_player(name, "Available commands: "..table.concat(cmds, " "))
|
||||||
|
minetest.chat_send_player(name, "Use '/help <cmd>' to get more information, or '/help all' to list everything.")
|
||||||
|
elseif param == "all" then
|
||||||
|
minetest.chat_send_player(name, "Available commands:")
|
||||||
|
for cmd, def in pairs(minetest.chatcommands) do
|
||||||
|
if minetest.check_player_privs(name, def.privs) then
|
||||||
|
minetest.chat_send_player(name, format_help_line(cmd, def))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif param == "privs" then
|
||||||
|
minetest.chat_send_player(name, "Available privileges:")
|
||||||
|
for priv, def in pairs(minetest.registered_privileges) do
|
||||||
|
minetest.chat_send_player(name, priv..": "..def.description)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local cmd = param
|
||||||
|
def = minetest.chatcommands[cmd]
|
||||||
|
if not def then
|
||||||
|
minetest.chat_send_player(name, "Command not available: "..cmd)
|
||||||
|
else
|
||||||
|
minetest.chat_send_player(name, format_help_line(cmd, def))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
minetest.register_chatcommand("privs", {
|
||||||
|
params = "<name>",
|
||||||
|
description = "print out privileges of player",
|
||||||
|
func = function(name, param)
|
||||||
|
if param == "" then
|
||||||
|
param = name
|
||||||
|
else
|
||||||
|
--[[if not minetest.check_player_privs(name, {privs=true}) then
|
||||||
|
minetest.chat_send_player(name, "Privileges of "..param.." are hidden from you.")
|
||||||
|
return
|
||||||
|
end]]
|
||||||
|
end
|
||||||
|
minetest.chat_send_player(name, "Privileges of "..param..": "..minetest.privs_to_string(minetest.get_player_privs(param), ' '))
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
minetest.register_chatcommand("grant", {
|
||||||
|
params = "<name> <privilege>|all",
|
||||||
|
description = "Give privilege to player",
|
||||||
|
privs = {},
|
||||||
|
func = function(name, param)
|
||||||
|
if not minetest.check_player_privs(name, {privs=true}) and
|
||||||
|
not minetest.check_player_privs(name, {basic_privs=true}) then
|
||||||
|
minetest.chat_send_player(name, "Your privileges are insufficient.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local grantname, grantprivstr = string.match(param, "([^ ]+) (.+)")
|
||||||
|
if not grantname or not grantprivstr then
|
||||||
|
minetest.chat_send_player(name, "Invalid parameters (see /help grant)")
|
||||||
|
return
|
||||||
|
elseif not minetest.auth_table[grantname] then
|
||||||
|
minetest.chat_send_player(name, "Player "..grantname.." does not exist.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local grantprivs = minetest.string_to_privs(grantprivstr)
|
||||||
|
if grantprivstr == "all" then
|
||||||
|
grantprivs = minetest.registered_privileges
|
||||||
|
end
|
||||||
|
local privs = minetest.get_player_privs(grantname)
|
||||||
|
local privs_known = true
|
||||||
|
for priv, _ in pairs(grantprivs) do
|
||||||
|
if priv ~= "interact" and priv ~= "shout" and priv ~= "interact_extra" and not minetest.check_player_privs(name, {privs=true}) then
|
||||||
|
minetest.chat_send_player(name, "Your privileges are insufficient.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not minetest.registered_privileges[priv] then
|
||||||
|
minetest.chat_send_player(name, "Unknown privilege: "..priv)
|
||||||
|
privs_known = false
|
||||||
|
end
|
||||||
|
privs[priv] = true
|
||||||
|
end
|
||||||
|
if not privs_known then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
minetest.set_player_privs(grantname, privs)
|
||||||
|
minetest.log(name..' granted ('..minetest.privs_to_string(grantprivs, ', ')..') privileges to '..grantname)
|
||||||
|
minetest.chat_send_player(name, "Privileges of "..grantname..": "..minetest.privs_to_string(minetest.get_player_privs(grantname), ' '))
|
||||||
|
if grantname ~= name then
|
||||||
|
minetest.chat_send_player(grantname, name.." granted you privileges: "..minetest.privs_to_string(grantprivs, ' '))
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
minetest.register_chatcommand("revoke", {
|
||||||
|
params = "<name> <privilege>|all",
|
||||||
|
description = "Remove privilege from player",
|
||||||
|
privs = {},
|
||||||
|
func = function(name, param)
|
||||||
|
if not minetest.check_player_privs(name, {privs=true}) and
|
||||||
|
not minetest.check_player_privs(name, {basic_privs=true}) then
|
||||||
|
minetest.chat_send_player(name, "Your privileges are insufficient.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local revokename, revokeprivstr = string.match(param, "([^ ]+) (.+)")
|
||||||
|
if not revokename or not revokeprivstr then
|
||||||
|
minetest.chat_send_player(name, "Invalid parameters (see /help revoke)")
|
||||||
|
return
|
||||||
|
elseif not minetest.auth_table[revokename] then
|
||||||
|
minetest.chat_send_player(name, "Player "..revokename.." does not exist.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local revokeprivs = minetest.string_to_privs(revokeprivstr)
|
||||||
|
local privs = minetest.get_player_privs(revokename)
|
||||||
|
for priv, _ in pairs(revokeprivs) do
|
||||||
|
if priv ~= "interact" and priv ~= "shout" and priv ~= "interact_extra" and not minetest.check_player_privs(name, {privs=true}) then
|
||||||
|
minetest.chat_send_player(name, "Your privileges are insufficient.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if revokeprivstr == "all" then
|
||||||
|
privs = {}
|
||||||
|
else
|
||||||
|
for priv, _ in pairs(revokeprivs) do
|
||||||
|
privs[priv] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
minetest.set_player_privs(revokename, privs)
|
||||||
|
minetest.log(name..' revoked ('..minetest.privs_to_string(revokeprivs, ', ')..') privileges from '..revokename)
|
||||||
|
minetest.chat_send_player(name, "Privileges of "..revokename..": "..minetest.privs_to_string(minetest.get_player_privs(revokename), ' '))
|
||||||
|
if revokename ~= name then
|
||||||
|
minetest.chat_send_player(revokename, name.." revoked privileges from you: "..minetest.privs_to_string(revokeprivs, ' '))
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
minetest.register_chatcommand("setpassword", {
|
||||||
|
params = "<name> <password>",
|
||||||
|
description = "set given password",
|
||||||
|
privs = {password=true},
|
||||||
|
func = function(name, param)
|
||||||
|
local toname, raw_password = string.match(param, "^([^ ]+) +(.+)$")
|
||||||
|
if not toname then
|
||||||
|
toname = string.match(param, "^([^ ]+) *$")
|
||||||
|
raw_password = nil
|
||||||
|
end
|
||||||
|
if not toname then
|
||||||
|
minetest.chat_send_player(name, "Name field required")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local actstr = "?"
|
||||||
|
if not raw_password then
|
||||||
|
minetest.set_player_password(toname, "")
|
||||||
|
actstr = "cleared"
|
||||||
|
else
|
||||||
|
minetest.set_player_password(toname, minetest.get_password_hash(toname, raw_password))
|
||||||
|
actstr = "set"
|
||||||
|
end
|
||||||
|
minetest.chat_send_player(name, "Password of player \""..toname.."\" "..actstr)
|
||||||
|
if toname ~= name then
|
||||||
|
minetest.chat_send_player(toname, "Your password was "..actstr.." by "..name)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
minetest.register_chatcommand("clearpassword", {
|
||||||
|
params = "<name>",
|
||||||
|
description = "set empty password",
|
||||||
|
privs = {password=true},
|
||||||
|
func = function(name, param)
|
||||||
|
toname = param
|
||||||
|
if toname == "" then
|
||||||
|
minetest.chat_send_player(name, "Name field required")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
minetest.set_player_password(toname, '')
|
||||||
|
minetest.chat_send_player(name, "Password of player \""..toname.."\" cleared")
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("auth_reload", {
|
||||||
|
params = "",
|
||||||
|
description = "reload authentication data",
|
||||||
|
privs = {server=true},
|
||||||
|
func = function(name, param)
|
||||||
|
local done = minetest.auth_reload()
|
||||||
|
if done then
|
||||||
|
minetest.chat_send_player(name, "Done.")
|
||||||
|
else
|
||||||
|
minetest.chat_send_player(name, "Failed.")
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("teleport", {
|
||||||
|
params = "<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>",
|
||||||
|
description = "teleport to given position",
|
||||||
|
privs = {teleport=true},
|
||||||
|
func = function(name, param)
|
||||||
|
-- Returns (pos, true) if found, otherwise (pos, false)
|
||||||
|
local function find_free_position_near(pos)
|
||||||
|
local tries = {
|
||||||
|
{x=1,y=0,z=0},
|
||||||
|
{x=-1,y=0,z=0},
|
||||||
|
{x=0,y=0,z=1},
|
||||||
|
{x=0,y=0,z=-1},
|
||||||
|
}
|
||||||
|
for _, d in ipairs(tries) do
|
||||||
|
local p = {x = pos.x+d.x, y = pos.y+d.y, z = pos.z+d.z}
|
||||||
|
local n = minetest.get_node(p)
|
||||||
|
if not minetest.registered_nodes[n.name].walkable then
|
||||||
|
return p, true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return pos, false
|
||||||
|
end
|
||||||
|
|
||||||
|
local teleportee = nil
|
||||||
|
local p = {}
|
||||||
|
p.x, p.y, p.z = string.match(param, "^([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
|
||||||
|
p.x = tonumber(p.x)
|
||||||
|
p.y = tonumber(p.y)
|
||||||
|
p.z = tonumber(p.z)
|
||||||
|
teleportee = minetest.get_player_by_name(name)
|
||||||
|
if teleportee and p.x and p.y and p.z then
|
||||||
|
minetest.chat_send_player(name, "Teleporting to ("..p.x..", "..p.y..", "..p.z..")")
|
||||||
|
teleportee:setpos(p)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local teleportee = nil
|
||||||
|
local p = nil
|
||||||
|
local target_name = nil
|
||||||
|
target_name = string.match(param, "^([^ ]+)$")
|
||||||
|
teleportee = minetest.get_player_by_name(name)
|
||||||
|
if target_name then
|
||||||
|
local target = minetest.get_player_by_name(target_name)
|
||||||
|
if target then
|
||||||
|
p = target:getpos()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if teleportee and p then
|
||||||
|
p = find_free_position_near(p)
|
||||||
|
minetest.chat_send_player(name, "Teleporting to "..target_name.." at ("..p.x..", "..p.y..", "..p.z..")")
|
||||||
|
teleportee:setpos(p)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if minetest.check_player_privs(name, {bring=true}) then
|
||||||
|
local teleportee = nil
|
||||||
|
local p = {}
|
||||||
|
local teleportee_name = nil
|
||||||
|
teleportee_name, p.x, p.y, p.z = string.match(param, "^([^ ]+) +([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
|
||||||
|
p.x = tonumber(p.x)
|
||||||
|
p.y = tonumber(p.y)
|
||||||
|
p.z = tonumber(p.z)
|
||||||
|
if teleportee_name then
|
||||||
|
teleportee = minetest.get_player_by_name(teleportee_name)
|
||||||
|
end
|
||||||
|
if teleportee and p.x and p.y and p.z then
|
||||||
|
minetest.chat_send_player(name, "Teleporting "..teleportee_name.." to ("..p.x..", "..p.y..", "..p.z..")")
|
||||||
|
teleportee:setpos(p)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local teleportee = nil
|
||||||
|
local p = nil
|
||||||
|
local teleportee_name = nil
|
||||||
|
local target_name = nil
|
||||||
|
teleportee_name, target_name = string.match(param, "^([^ ]+) +([^ ]+)$")
|
||||||
|
if teleportee_name then
|
||||||
|
teleportee = minetest.get_player_by_name(teleportee_name)
|
||||||
|
end
|
||||||
|
if target_name then
|
||||||
|
local target = minetest.get_player_by_name(target_name)
|
||||||
|
if target then
|
||||||
|
p = target:getpos()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if teleportee and p then
|
||||||
|
p = find_free_position_near(p)
|
||||||
|
minetest.chat_send_player(name, "Teleporting "..teleportee_name.." to "..target_name.." at ("..p.x..", "..p.y..", "..p.z..")")
|
||||||
|
teleportee:setpos(p)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.chat_send_player(name, "Invalid parameters (\""..param.."\") or player not found (see /help teleport)")
|
||||||
|
return
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("set", {
|
||||||
|
params = "[-n] <name> <value> | <name>",
|
||||||
|
description = "set or read server configuration setting",
|
||||||
|
privs = {server=true},
|
||||||
|
func = function(name, param)
|
||||||
|
local arg, setname, setvalue = string.match(param, "(-[n]) ([^ ]+) (.+)")
|
||||||
|
if arg and arg == "-n" and setname and setvalue then
|
||||||
|
minetest.setting_set(setname, setvalue)
|
||||||
|
minetest.chat_send_player(name, setname.." = "..setvalue)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local setname, setvalue = string.match(param, "([^ ]+) (.+)")
|
||||||
|
if setname and setvalue then
|
||||||
|
if not minetest.setting_get(setname) then
|
||||||
|
minetest.chat_send_player(name, "Failed. Use '/set -n <name> <value>' to create a new setting.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
minetest.setting_set(setname, setvalue)
|
||||||
|
minetest.chat_send_player(name, setname.." = "..setvalue)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local setname = string.match(param, "([^ ]+)")
|
||||||
|
if setname then
|
||||||
|
local setvalue = minetest.setting_get(setname)
|
||||||
|
if not setvalue then
|
||||||
|
setvalue = "<not set>"
|
||||||
|
end
|
||||||
|
minetest.chat_send_player(name, setname.." = "..setvalue)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
minetest.chat_send_player(name, "Invalid parameters (see /help set)")
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("mods", {
|
||||||
|
params = "",
|
||||||
|
description = "lists mods installed on the server",
|
||||||
|
privs = {},
|
||||||
|
func = function(name, param)
|
||||||
|
local response = ""
|
||||||
|
local modnames = minetest.get_modnames()
|
||||||
|
for i, mod in ipairs(modnames) do
|
||||||
|
response = response .. mod
|
||||||
|
-- Add space if not at the end
|
||||||
|
if i ~= #modnames then
|
||||||
|
response = response .. " "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
minetest.chat_send_player(name, response)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
local function handle_give_command(cmd, giver, receiver, stackstring)
|
||||||
|
minetest.log("action", giver.." invoked "..cmd..', stackstring="'
|
||||||
|
..stackstring..'"')
|
||||||
|
minetest.log(cmd..' invoked, stackstring="'..stackstring..'"')
|
||||||
|
local itemstack = ItemStack(stackstring)
|
||||||
|
if itemstack:is_empty() then
|
||||||
|
minetest.chat_send_player(giver, 'error: cannot give an empty item')
|
||||||
|
return
|
||||||
|
elseif not itemstack:is_known() then
|
||||||
|
minetest.chat_send_player(giver, 'error: cannot give an unknown item')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local receiverref = minetest.get_player_by_name(receiver)
|
||||||
|
if receiverref == nil then
|
||||||
|
minetest.chat_send_player(giver, receiver..' is not a known player')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local leftover = receiverref:get_inventory():add_item("main", itemstack)
|
||||||
|
if leftover:is_empty() then
|
||||||
|
partiality = ""
|
||||||
|
elseif leftover:get_count() == itemstack:get_count() then
|
||||||
|
partiality = "could not be "
|
||||||
|
else
|
||||||
|
partiality = "partially "
|
||||||
|
end
|
||||||
|
-- The actual item stack string may be different from what the "giver"
|
||||||
|
-- entered (e.g. big numbers are always interpreted as 2^16-1).
|
||||||
|
stackstring = itemstack:to_string()
|
||||||
|
if giver == receiver then
|
||||||
|
minetest.chat_send_player(giver, '"'..stackstring
|
||||||
|
..'" '..partiality..'added to inventory.');
|
||||||
|
else
|
||||||
|
minetest.chat_send_player(giver, '"'..stackstring
|
||||||
|
..'" '..partiality..'added to '..receiver..'\'s inventory.');
|
||||||
|
minetest.chat_send_player(receiver, '"'..stackstring
|
||||||
|
..'" '..partiality..'added to inventory.');
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_chatcommand("give", {
|
||||||
|
params = "<name> <itemstring>",
|
||||||
|
description = "give item to player",
|
||||||
|
privs = {give=true},
|
||||||
|
func = function(name, param)
|
||||||
|
local toname, itemstring = string.match(param, "^([^ ]+) +(.+)$")
|
||||||
|
if not toname or not itemstring then
|
||||||
|
minetest.chat_send_player(name, "name and itemstring required")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
handle_give_command("/give", name, toname, itemstring)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
minetest.register_chatcommand("giveme", {
|
||||||
|
params = "<itemstring>",
|
||||||
|
description = "give item to yourself",
|
||||||
|
privs = {give=true},
|
||||||
|
func = function(name, param)
|
||||||
|
local itemstring = string.match(param, "(.+)$")
|
||||||
|
if not itemstring then
|
||||||
|
minetest.chat_send_player(name, "itemstring required")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
handle_give_command("/giveme", name, name, itemstring)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
minetest.register_chatcommand("spawnentity", {
|
||||||
|
params = "<entityname>",
|
||||||
|
description = "spawn entity at your position",
|
||||||
|
privs = {give=true, interact=true},
|
||||||
|
func = function(name, param)
|
||||||
|
local entityname = string.match(param, "(.+)$")
|
||||||
|
if not entityname then
|
||||||
|
minetest.chat_send_player(name, "entityname required")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
minetest.log("action", '/spawnentity invoked, entityname="'..entityname..'"')
|
||||||
|
local player = minetest.get_player_by_name(name)
|
||||||
|
if player == nil then
|
||||||
|
minetest.log("error", "Unable to spawn entity, player is nil")
|
||||||
|
return true -- Handled chat message
|
||||||
|
end
|
||||||
|
local p = player:getpos()
|
||||||
|
p.y = p.y + 1
|
||||||
|
minetest.add_entity(p, entityname)
|
||||||
|
minetest.chat_send_player(name, '"'..entityname
|
||||||
|
..'" spawned.');
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
minetest.register_chatcommand("pulverize", {
|
||||||
|
params = "",
|
||||||
|
description = "delete item in hand",
|
||||||
|
privs = {},
|
||||||
|
func = function(name, param)
|
||||||
|
local player = minetest.get_player_by_name(name)
|
||||||
|
if player == nil then
|
||||||
|
minetest.log("error", "Unable to pulverize, player is nil")
|
||||||
|
return true -- Handled chat message
|
||||||
|
end
|
||||||
|
if player:get_wielded_item():is_empty() then
|
||||||
|
minetest.chat_send_player(name, 'Unable to pulverize, no item in hand.')
|
||||||
|
else
|
||||||
|
player:set_wielded_item(nil)
|
||||||
|
minetest.chat_send_player(name, 'An item was pulverized.')
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Key = player name
|
||||||
|
minetest.rollback_punch_callbacks = {}
|
||||||
|
|
||||||
|
minetest.register_on_punchnode(function(pos, node, puncher)
|
||||||
|
local name = puncher:get_player_name()
|
||||||
|
if minetest.rollback_punch_callbacks[name] then
|
||||||
|
minetest.rollback_punch_callbacks[name](pos, node, puncher)
|
||||||
|
minetest.rollback_punch_callbacks[name] = nil
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
minetest.register_chatcommand("rollback_check", {
|
||||||
|
params = "[<range>] [<seconds>] [limit]",
|
||||||
|
description = "check who has last touched a node or near it, "..
|
||||||
|
"max. <seconds> ago (default range=0, seconds=86400=24h, limit=5)",
|
||||||
|
privs = {rollback=true},
|
||||||
|
func = function(name, param)
|
||||||
|
local range, seconds, limit =
|
||||||
|
param:match("(%d+) *(%d*) *(%d*)")
|
||||||
|
range = tonumber(range) or 0
|
||||||
|
seconds = tonumber(seconds) or 86400
|
||||||
|
limit = tonumber(limit) or 5
|
||||||
|
if limit > 100 then
|
||||||
|
minetest.chat_send_player(name, "That limit is too high!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
minetest.chat_send_player(name, "Punch a node (range="..
|
||||||
|
range..", seconds="..seconds.."s, limit="..limit..")")
|
||||||
|
|
||||||
|
minetest.rollback_punch_callbacks[name] = function(pos, node, puncher)
|
||||||
|
local name = puncher:get_player_name()
|
||||||
|
minetest.chat_send_player(name, "Checking "..minetest.pos_to_string(pos).."...")
|
||||||
|
local actions = minetest.rollback_get_node_actions(pos, range, seconds, limit)
|
||||||
|
local num_actions = #actions
|
||||||
|
if num_actions == 0 then
|
||||||
|
minetest.chat_send_player(name, "Nobody has touched the "..
|
||||||
|
"specified location in "..seconds.." seconds")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local time = os.time()
|
||||||
|
for i = num_actions, 1, -1 do
|
||||||
|
local action = actions[i]
|
||||||
|
minetest.chat_send_player(name,
|
||||||
|
("%s %s %s -> %s %d seconds ago.")
|
||||||
|
:format(
|
||||||
|
minetest.pos_to_string(action.pos),
|
||||||
|
action.actor,
|
||||||
|
action.oldnode.name,
|
||||||
|
action.newnode.name,
|
||||||
|
time - action.time))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("rollback", {
|
||||||
|
params = "<player name> [<seconds>] | :<actor> [<seconds>]",
|
||||||
|
description = "revert actions of a player; default for <seconds> is 60",
|
||||||
|
privs = {rollback=true},
|
||||||
|
func = function(name, param)
|
||||||
|
local target_name, seconds = string.match(param, ":([^ ]+) *(%d*)")
|
||||||
|
if not target_name then
|
||||||
|
local player_name = nil
|
||||||
|
player_name, seconds = string.match(param, "([^ ]+) *(%d*)")
|
||||||
|
if not player_name then
|
||||||
|
minetest.chat_send_player(name, "Invalid parameters. See /help rollback and /help rollback_check")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
target_name = "player:"..player_name
|
||||||
|
end
|
||||||
|
seconds = tonumber(seconds) or 60
|
||||||
|
minetest.chat_send_player(name, "Reverting actions of "..
|
||||||
|
target_name.." since "..seconds.." seconds.")
|
||||||
|
local success, log = minetest.rollback_revert_actions_by(
|
||||||
|
target_name, seconds)
|
||||||
|
if #log > 100 then
|
||||||
|
minetest.chat_send_player(name, "(log is too long to show)")
|
||||||
|
else
|
||||||
|
for _, line in pairs(log) do
|
||||||
|
minetest.chat_send_player(name, line)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if success then
|
||||||
|
minetest.chat_send_player(name, "Reverting actions succeeded.")
|
||||||
|
else
|
||||||
|
minetest.chat_send_player(name, "Reverting actions FAILED.")
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("status", {
|
||||||
|
params = "",
|
||||||
|
description = "print server status line",
|
||||||
|
privs = {},
|
||||||
|
func = function(name, param)
|
||||||
|
minetest.chat_send_player(name, minetest.get_server_status())
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("time", {
|
||||||
|
params = "<0...24000>",
|
||||||
|
description = "set time of day",
|
||||||
|
privs = {settime=true},
|
||||||
|
func = function(name, param)
|
||||||
|
if param == "" then
|
||||||
|
minetest.chat_send_player(name, "Missing parameter")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local newtime = tonumber(param)
|
||||||
|
if newtime == nil then
|
||||||
|
minetest.chat_send_player(name, "Invalid time")
|
||||||
|
else
|
||||||
|
minetest.set_timeofday((newtime % 24000) / 24000)
|
||||||
|
minetest.chat_send_player(name, "Time of day changed.")
|
||||||
|
minetest.log("action", name .. " sets time " .. newtime)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("shutdown", {
|
||||||
|
params = "",
|
||||||
|
description = "shutdown server",
|
||||||
|
privs = {server=true},
|
||||||
|
func = function(name, param)
|
||||||
|
minetest.log("action", name .. " shuts down server")
|
||||||
|
minetest.request_shutdown()
|
||||||
|
minetest.chat_send_all("*** Server shutting down (operator request).")
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("ban", {
|
||||||
|
params = "<name>",
|
||||||
|
description = "ban IP of player",
|
||||||
|
privs = {ban=true},
|
||||||
|
func = function(name, param)
|
||||||
|
if param == "" then
|
||||||
|
minetest.chat_send_player(name, "Ban list: " .. minetest.get_ban_list())
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not minetest.get_player_by_name(param) then
|
||||||
|
minetest.chat_send_player(name, "No such player")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not minetest.ban_player(param) then
|
||||||
|
minetest.chat_send_player(name, "Failed to ban player")
|
||||||
|
else
|
||||||
|
local desc = minetest.get_ban_description(param)
|
||||||
|
minetest.chat_send_player(name, "Banned " .. desc .. ".")
|
||||||
|
minetest.log("action", name .. " bans " .. desc .. ".")
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("unban", {
|
||||||
|
params = "<name/ip>",
|
||||||
|
description = "remove IP ban",
|
||||||
|
privs = {ban=true},
|
||||||
|
func = function(name, param)
|
||||||
|
if not minetest.unban_player_or_ip(param) then
|
||||||
|
minetest.chat_send_player(name, "Failed to unban player/IP")
|
||||||
|
else
|
||||||
|
minetest.chat_send_player(name, "Unbanned " .. param)
|
||||||
|
minetest.log("action", name .. " unbans " .. param)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("clearobjects", {
|
||||||
|
params = "",
|
||||||
|
description = "clear all objects in world",
|
||||||
|
privs = {server=true},
|
||||||
|
func = function(name, param)
|
||||||
|
minetest.log("action", name .. " clears all objects")
|
||||||
|
minetest.chat_send_all("Clearing all objects. This may take long. You may experience a timeout. (by " .. name .. ")")
|
||||||
|
minetest.clear_objects()
|
||||||
|
minetest.log("action", "object clearing done")
|
||||||
|
minetest.chat_send_all("*** Cleared all objects.")
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("msg", {
|
||||||
|
params = "<name> <message>",
|
||||||
|
description = "Send a private message",
|
||||||
|
privs = {shout=true},
|
||||||
|
func = function(name, param)
|
||||||
|
local found, _, sendto, message = param:find("^([^%s]+)%s(.+)$")
|
||||||
|
if found then
|
||||||
|
if minetest.get_player_by_name(sendto) then
|
||||||
|
minetest.log("action", "PM from "..name.." to "..sendto..": "..message)
|
||||||
|
minetest.chat_send_player(sendto, "PM from "..name..": "..message, false)
|
||||||
|
minetest.chat_send_player(name, "Message sent")
|
||||||
|
else
|
||||||
|
minetest.chat_send_player(name, "The player "..sendto.." is not online")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
minetest.chat_send_player(name, "Invalid usage, see /help msg")
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
53
builtin/deprecated.lua
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
-- Minetest: builtin/deprecated.lua
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Default material types
|
||||||
|
--
|
||||||
|
function digprop_err()
|
||||||
|
minetest.log("info", debug.traceback())
|
||||||
|
minetest.log("info", "WARNING: The minetest.digprop_* functions are obsolete and need to be replaced by item groups.")
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.digprop_constanttime = digprop_err
|
||||||
|
minetest.digprop_stonelike = digprop_err
|
||||||
|
minetest.digprop_dirtlike = digprop_err
|
||||||
|
minetest.digprop_gravellike = digprop_err
|
||||||
|
minetest.digprop_woodlike = digprop_err
|
||||||
|
minetest.digprop_leaveslike = digprop_err
|
||||||
|
minetest.digprop_glasslike = digprop_err
|
||||||
|
|
||||||
|
minetest.node_metadata_inventory_move_allow_all = function()
|
||||||
|
minetest.log("info", "WARNING: minetest.node_metadata_inventory_move_allow_all is obsolete and does nothing.")
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.add_to_creative_inventory = function(itemstring)
|
||||||
|
minetest.log('info', "WARNING: minetest.add_to_creative_inventory: This function is deprecated and does nothing.")
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- EnvRef
|
||||||
|
--
|
||||||
|
minetest.env = {}
|
||||||
|
local envref_deprecation_message_printed = false
|
||||||
|
setmetatable(minetest.env, {
|
||||||
|
__index = function(table, key)
|
||||||
|
if not envref_deprecation_message_printed then
|
||||||
|
minetest.log("info", "WARNING: minetest.env:[...] is deprecated and should be replaced with minetest.[...]")
|
||||||
|
envref_deprecation_message_printed = true
|
||||||
|
end
|
||||||
|
local func = minetest[key]
|
||||||
|
if type(func) == "function" then
|
||||||
|
rawset(table, key, function(self, ...)
|
||||||
|
return func(...)
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
rawset(table, key, nil)
|
||||||
|
end
|
||||||
|
return rawget(table, key)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
function minetest.rollback_get_last_node_actor(pos, range, seconds)
|
||||||
|
return minetest.rollback_get_node_actions(pos, range, seconds, 1)[1]
|
||||||
|
end
|
||||||
|
|
||||||
19
builtin/detached_inventory.lua
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
-- Minetest: builtin/detached_inventory.lua
|
||||||
|
|
||||||
|
minetest.detached_inventories = {}
|
||||||
|
|
||||||
|
function minetest.create_detached_inventory(name, callbacks)
|
||||||
|
local stuff = {}
|
||||||
|
stuff.name = name
|
||||||
|
if callbacks then
|
||||||
|
stuff.allow_move = callbacks.allow_move
|
||||||
|
stuff.allow_put = callbacks.allow_put
|
||||||
|
stuff.allow_take = callbacks.allow_take
|
||||||
|
stuff.on_move = callbacks.on_move
|
||||||
|
stuff.on_put = callbacks.on_put
|
||||||
|
stuff.on_take = callbacks.on_take
|
||||||
|
end
|
||||||
|
minetest.detached_inventories[name] = stuff
|
||||||
|
return minetest.create_detached_inventory_raw(name)
|
||||||
|
end
|
||||||
|
|
||||||
217
builtin/falling.lua
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
-- Minetest: builtin/item.lua
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Falling stuff
|
||||||
|
--
|
||||||
|
|
||||||
|
minetest.register_entity("__builtin:falling_node", {
|
||||||
|
initial_properties = {
|
||||||
|
physical = true,
|
||||||
|
collide_with_objects = false,
|
||||||
|
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
|
||||||
|
visual = "wielditem",
|
||||||
|
textures = {},
|
||||||
|
visual_size = {x=0.667, y=0.667},
|
||||||
|
},
|
||||||
|
|
||||||
|
node = {},
|
||||||
|
|
||||||
|
set_node = function(self, node)
|
||||||
|
self.node = node
|
||||||
|
local stack = ItemStack(node.name)
|
||||||
|
local itemtable = stack:to_table()
|
||||||
|
local itemname = nil
|
||||||
|
if itemtable then
|
||||||
|
itemname = stack:to_table().name
|
||||||
|
end
|
||||||
|
local item_texture = nil
|
||||||
|
local item_type = ""
|
||||||
|
if minetest.registered_items[itemname] then
|
||||||
|
item_texture = minetest.registered_items[itemname].inventory_image
|
||||||
|
item_type = minetest.registered_items[itemname].type
|
||||||
|
end
|
||||||
|
prop = {
|
||||||
|
is_visible = true,
|
||||||
|
textures = {node.name},
|
||||||
|
}
|
||||||
|
self.object:set_properties(prop)
|
||||||
|
end,
|
||||||
|
|
||||||
|
get_staticdata = function(self)
|
||||||
|
return self.node.name
|
||||||
|
end,
|
||||||
|
|
||||||
|
on_activate = function(self, staticdata)
|
||||||
|
self.object:set_armor_groups({immortal=1})
|
||||||
|
--self.object:setacceleration({x=0, y=-10, z=0})
|
||||||
|
self:set_node({name=staticdata})
|
||||||
|
end,
|
||||||
|
|
||||||
|
on_step = function(self, dtime)
|
||||||
|
-- Set gravity
|
||||||
|
self.object:setacceleration({x=0, y=-10, z=0})
|
||||||
|
-- Turn to actual sand when collides to ground or just move
|
||||||
|
local pos = self.object:getpos()
|
||||||
|
local bcp = {x=pos.x, y=pos.y-0.7, z=pos.z} -- Position of bottom center point
|
||||||
|
local bcn = minetest.get_node(bcp)
|
||||||
|
local bcd = minetest.registered_nodes[bcn.name]
|
||||||
|
-- Note: walkable is in the node definition, not in item groups
|
||||||
|
if not bcd or
|
||||||
|
(bcd.walkable or
|
||||||
|
(minetest.get_node_group(self.node.name, "float") ~= 0 and
|
||||||
|
bcd.liquidtype ~= "none")) then
|
||||||
|
if bcd and bcd.leveled and
|
||||||
|
bcn.name == self.node.name then
|
||||||
|
local addlevel = self.node.level
|
||||||
|
if addlevel == nil or addlevel <= 0 then
|
||||||
|
addlevel = bcd.leveled
|
||||||
|
end
|
||||||
|
if minetest.add_node_level(bcp, addlevel) == 0 then
|
||||||
|
self.object:remove()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
elseif bcd and bcd.buildable_to and
|
||||||
|
(minetest.get_node_group(self.node.name, "float") == 0 or
|
||||||
|
bcd.liquidtype == "none") then
|
||||||
|
minetest.remove_node(bcp)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local np = {x=bcp.x, y=bcp.y+1, z=bcp.z}
|
||||||
|
-- Check what's here
|
||||||
|
local n2 = minetest.get_node(np)
|
||||||
|
-- If it's not air or liquid, remove node and replace it with
|
||||||
|
-- it's drops
|
||||||
|
if n2.name ~= "air" and (not minetest.registered_nodes[n2.name] or
|
||||||
|
minetest.registered_nodes[n2.name].liquidtype == "none") then
|
||||||
|
local drops = minetest.get_node_drops(n2.name, "")
|
||||||
|
minetest.remove_node(np)
|
||||||
|
-- Add dropped items
|
||||||
|
local _, dropped_item
|
||||||
|
for _, dropped_item in ipairs(drops) do
|
||||||
|
minetest.add_item(np, dropped_item)
|
||||||
|
end
|
||||||
|
-- Run script hook
|
||||||
|
local _, callback
|
||||||
|
for _, callback in ipairs(minetest.registered_on_dignodes) do
|
||||||
|
callback(np, n2, nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Create node and remove entity
|
||||||
|
minetest.add_node(np, self.node)
|
||||||
|
self.object:remove()
|
||||||
|
nodeupdate(np)
|
||||||
|
else
|
||||||
|
-- Do nothing
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
function spawn_falling_node(p, node)
|
||||||
|
obj = minetest.add_entity(p, "__builtin:falling_node")
|
||||||
|
obj:get_luaentity():set_node(node)
|
||||||
|
end
|
||||||
|
|
||||||
|
function drop_attached_node(p)
|
||||||
|
local nn = minetest.get_node(p).name
|
||||||
|
minetest.remove_node(p)
|
||||||
|
for _,item in ipairs(minetest.get_node_drops(nn, "")) do
|
||||||
|
local pos = {
|
||||||
|
x = p.x + math.random()/2 - 0.25,
|
||||||
|
y = p.y + math.random()/2 - 0.25,
|
||||||
|
z = p.z + math.random()/2 - 0.25,
|
||||||
|
}
|
||||||
|
minetest.add_item(pos, item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function check_attached_node(p, n)
|
||||||
|
local def = minetest.registered_nodes[n.name]
|
||||||
|
local d = {x=0, y=0, z=0}
|
||||||
|
if def.paramtype2 == "wallmounted" then
|
||||||
|
if n.param2 == 0 then
|
||||||
|
d.y = 1
|
||||||
|
elseif n.param2 == 1 then
|
||||||
|
d.y = -1
|
||||||
|
elseif n.param2 == 2 then
|
||||||
|
d.x = 1
|
||||||
|
elseif n.param2 == 3 then
|
||||||
|
d.x = -1
|
||||||
|
elseif n.param2 == 4 then
|
||||||
|
d.z = 1
|
||||||
|
elseif n.param2 == 5 then
|
||||||
|
d.z = -1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
d.y = -1
|
||||||
|
end
|
||||||
|
local p2 = {x=p.x+d.x, y=p.y+d.y, z=p.z+d.z}
|
||||||
|
local nn = minetest.get_node(p2).name
|
||||||
|
local def2 = minetest.registered_nodes[nn]
|
||||||
|
if def2 and not def2.walkable then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Some common functions
|
||||||
|
--
|
||||||
|
|
||||||
|
function nodeupdate_single(p, delay)
|
||||||
|
n = minetest.get_node(p)
|
||||||
|
if minetest.get_node_group(n.name, "falling_node") ~= 0 then
|
||||||
|
p_bottom = {x=p.x, y=p.y-1, z=p.z}
|
||||||
|
n_bottom = minetest.get_node(p_bottom)
|
||||||
|
-- Note: walkable is in the node definition, not in item groups
|
||||||
|
if minetest.registered_nodes[n_bottom.name] and
|
||||||
|
(minetest.get_node_group(n.name, "float") == 0 or minetest.registered_nodes[n_bottom.name].liquidtype == "none") and
|
||||||
|
(n.name ~= n_bottom.name or (minetest.registered_nodes[n_bottom.name].leveled and minetest.env:get_node_level(p_bottom) < minetest.env:get_node_max_level(p_bottom))) and
|
||||||
|
(not minetest.registered_nodes[n_bottom.name].walkable or
|
||||||
|
minetest.registered_nodes[n_bottom.name].buildable_to) then
|
||||||
|
if delay then
|
||||||
|
minetest.after(0.1, nodeupdate_single, {x=p.x, y=p.y, z=p.z}, false)
|
||||||
|
else
|
||||||
|
n.level = minetest.env:get_node_level(p)
|
||||||
|
minetest.remove_node(p)
|
||||||
|
spawn_falling_node(p, n)
|
||||||
|
nodeupdate(p)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if minetest.get_node_group(n.name, "attached_node") ~= 0 then
|
||||||
|
if not check_attached_node(p, n) then
|
||||||
|
drop_attached_node(p)
|
||||||
|
nodeupdate(p)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function nodeupdate(p, delay)
|
||||||
|
-- Round p to prevent falling entities to get stuck
|
||||||
|
p.x = math.floor(p.x+0.5)
|
||||||
|
p.y = math.floor(p.y+0.5)
|
||||||
|
p.z = math.floor(p.z+0.5)
|
||||||
|
|
||||||
|
for x = -1,1 do
|
||||||
|
for y = -1,1 do
|
||||||
|
for z = -1,1 do
|
||||||
|
nodeupdate_single({x=p.x+x, y=p.y+y, z=p.z+z}, delay or not (x==0 and y==0 and z==0))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Global callbacks
|
||||||
|
--
|
||||||
|
|
||||||
|
function on_placenode(p, node)
|
||||||
|
nodeupdate(p)
|
||||||
|
end
|
||||||
|
minetest.register_on_placenode(on_placenode)
|
||||||
|
|
||||||
|
function on_dignode(p, node)
|
||||||
|
nodeupdate(p)
|
||||||
|
end
|
||||||
|
minetest.register_on_dignode(on_dignode)
|
||||||
29
builtin/features.lua
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
-- Minetest: builtin/features.lua
|
||||||
|
|
||||||
|
minetest.features = {
|
||||||
|
glasslike_framed = true,
|
||||||
|
nodebox_as_selectionbox = true,
|
||||||
|
chat_send_player_param3 = true,
|
||||||
|
get_all_craft_recipes_works = true,
|
||||||
|
use_texture_alpha = true,
|
||||||
|
no_legacy_abms = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
function minetest.has_feature(arg)
|
||||||
|
if type(arg) == "table" then
|
||||||
|
missing_features = {}
|
||||||
|
result = true
|
||||||
|
for ft, _ in pairs(arg) do
|
||||||
|
if not minetest.features[ftr] then
|
||||||
|
missing_features[ftr] = true
|
||||||
|
result = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result, missing_features
|
||||||
|
elseif type(arg) == "string" then
|
||||||
|
if not minetest.features[arg] then
|
||||||
|
return false, {[arg]=true}
|
||||||
|
end
|
||||||
|
return true, {}
|
||||||
|
end
|
||||||
|
end
|
||||||
301
builtin/filterlist.lua
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
--Minetest
|
||||||
|
--Copyright (C) 2013 sapier
|
||||||
|
--
|
||||||
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
--it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
--the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
--(at your option) any later version.
|
||||||
|
--
|
||||||
|
--This program is distributed in the hope that it will be useful,
|
||||||
|
--but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
--GNU Lesser General Public License for more details.
|
||||||
|
--
|
||||||
|
--You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
--with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Generic implementation of a filter/sortable list --
|
||||||
|
-- Usage: --
|
||||||
|
-- Filterlist needs to be initialized on creation. To achieve this you need to --
|
||||||
|
-- pass following functions: --
|
||||||
|
-- raw_fct() (mandatory): --
|
||||||
|
-- function returning a table containing the elements to be filtered --
|
||||||
|
-- compare_fct(element1,element2) (mandatory): --
|
||||||
|
-- function returning true/false if element1 is same element as element2 --
|
||||||
|
-- uid_match_fct(element1,uid) (optional) --
|
||||||
|
-- function telling if uid is attached to element1 --
|
||||||
|
-- filter_fct(element,filtercriteria) (optional) --
|
||||||
|
-- function returning true/false if filtercriteria met to element --
|
||||||
|
-- fetch_param (optional) --
|
||||||
|
-- parameter passed to raw_fct to aquire correct raw data --
|
||||||
|
-- --
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
filterlist = {}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function filterlist.refresh(this)
|
||||||
|
this.m_raw_list = this.m_raw_list_fct(this.m_fetch_param)
|
||||||
|
filterlist.process(this)
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function filterlist.create(raw_fct,compare_fct,uid_match_fct,filter_fct,fetch_param)
|
||||||
|
|
||||||
|
assert((raw_fct ~= nil) and (type(raw_fct) == "function"))
|
||||||
|
assert((compare_fct ~= nil) and (type(compare_fct) == "function"))
|
||||||
|
|
||||||
|
local this = {}
|
||||||
|
|
||||||
|
this.m_raw_list_fct = raw_fct
|
||||||
|
this.m_compare_fct = compare_fct
|
||||||
|
this.m_filter_fct = filter_fct
|
||||||
|
this.m_uid_match_fct = uid_match_fct
|
||||||
|
|
||||||
|
this.m_filtercriteria = nil
|
||||||
|
this.m_fetch_param = fetch_param
|
||||||
|
|
||||||
|
this.m_sortmode = "none"
|
||||||
|
this.m_sort_list = {}
|
||||||
|
|
||||||
|
this.m_processed_list = nil
|
||||||
|
this.m_raw_list = this.m_raw_list_fct(this.m_fetch_param)
|
||||||
|
|
||||||
|
filterlist.process(this)
|
||||||
|
|
||||||
|
return this
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function filterlist.add_sort_mechanism(this,name,fct)
|
||||||
|
this.m_sort_list[name] = fct
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function filterlist.set_filtercriteria(this,criteria)
|
||||||
|
if criteria == this.m_filtercriteria and
|
||||||
|
type(criteria) ~= "table" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
this.m_filtercriteria = criteria
|
||||||
|
filterlist.process(this)
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function filterlist.get_filtercriteria(this)
|
||||||
|
return this.m_filtercriteria
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
--supported sort mode "alphabetic|none"
|
||||||
|
function filterlist.set_sortmode(this,mode)
|
||||||
|
if (mode == this.m_sortmode) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
this.m_sortmode = mode
|
||||||
|
filterlist.process(this)
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function filterlist.get_list(this)
|
||||||
|
return this.m_processed_list
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function filterlist.get_raw_list(this)
|
||||||
|
return this.m_raw_list
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function filterlist.get_raw_element(this,idx)
|
||||||
|
if type(idx) ~= "number" then
|
||||||
|
idx = tonumber(idx)
|
||||||
|
end
|
||||||
|
|
||||||
|
if idx ~= nil and idx > 0 and idx < #this.m_raw_list then
|
||||||
|
return this.m_raw_list[idx]
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function filterlist.get_raw_index(this,listindex)
|
||||||
|
assert(this.m_processed_list ~= nil)
|
||||||
|
|
||||||
|
if listindex ~= nil and listindex > 0 and
|
||||||
|
listindex <= #this.m_processed_list then
|
||||||
|
local entry = this.m_processed_list[listindex]
|
||||||
|
|
||||||
|
for i,v in ipairs(this.m_raw_list) do
|
||||||
|
|
||||||
|
if this.m_compare_fct(v,entry) then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function filterlist.get_current_index(this,listindex)
|
||||||
|
assert(this.m_processed_list ~= nil)
|
||||||
|
|
||||||
|
if listindex ~= nil and listindex > 0 and
|
||||||
|
listindex <= #this.m_raw_list then
|
||||||
|
local entry = this.m_raw_list[listindex]
|
||||||
|
|
||||||
|
for i,v in ipairs(this.m_processed_list) do
|
||||||
|
|
||||||
|
if this.m_compare_fct(v,entry) then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function filterlist.process(this)
|
||||||
|
assert(this.m_raw_list ~= nil)
|
||||||
|
|
||||||
|
if this.m_sortmode == "none" and
|
||||||
|
this.m_filtercriteria == nil then
|
||||||
|
this.m_processed_list = this.m_raw_list
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
this.m_processed_list = {}
|
||||||
|
|
||||||
|
for k,v in pairs(this.m_raw_list) do
|
||||||
|
if this.m_filtercriteria == nil or
|
||||||
|
this.m_filter_fct(v,this.m_filtercriteria) then
|
||||||
|
table.insert(this.m_processed_list,v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if this.m_sortmode == "none" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if this.m_sort_list[this.m_sortmode] ~= nil and
|
||||||
|
type(this.m_sort_list[this.m_sortmode]) == "function" then
|
||||||
|
|
||||||
|
this.m_sort_list[this.m_sortmode](this)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function filterlist.size(this)
|
||||||
|
if this.m_processed_list == nil then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
return #this.m_processed_list
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function filterlist.uid_exists_raw(this,uid)
|
||||||
|
for i,v in ipairs(this.m_raw_list) do
|
||||||
|
if this.m_uid_match_fct(v,uid) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function filterlist.raw_index_by_uid(this, uid)
|
||||||
|
local elementcount = 0
|
||||||
|
local elementidx = 0
|
||||||
|
for i,v in ipairs(this.m_raw_list) do
|
||||||
|
if this.m_uid_match_fct(v,uid) then
|
||||||
|
elementcount = elementcount +1
|
||||||
|
elementidx = i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- If there are more elements than one with same name uid can't decide which
|
||||||
|
-- one is meant. This shouldn't be possible but just for sure.
|
||||||
|
if elementcount > 1 then
|
||||||
|
elementidx=0
|
||||||
|
end
|
||||||
|
|
||||||
|
return elementidx
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- COMMON helper functions --
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function compare_worlds(world1,world2)
|
||||||
|
|
||||||
|
if world1.path ~= world2.path then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if world1.name ~= world2.name then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if world1.gameid ~= world2.gameid then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function sort_worlds_alphabetic(this)
|
||||||
|
|
||||||
|
table.sort(this.m_processed_list, function(a, b)
|
||||||
|
--fixes issue #857 (crash due to sorting nil in worldlist)
|
||||||
|
if a == nil or b == nil then
|
||||||
|
if a == nil and b ~= nil then return false end
|
||||||
|
if b == nil and a ~= nil then return true end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if a.name:lower() == b.name:lower() then
|
||||||
|
return a.name < b.name
|
||||||
|
end
|
||||||
|
return a.name:lower() < b.name:lower()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function sort_mod_list(this)
|
||||||
|
|
||||||
|
table.sort(this.m_processed_list, function(a, b)
|
||||||
|
-- Show game mods at bottom
|
||||||
|
if a.typ ~= b.typ then
|
||||||
|
return b.typ == "game_mod"
|
||||||
|
end
|
||||||
|
-- If in same or no modpack, sort by name
|
||||||
|
if a.modpack == b.modpack then
|
||||||
|
if a.name:lower() == b.name:lower() then
|
||||||
|
return a.name < b.name
|
||||||
|
end
|
||||||
|
return a.name:lower() < b.name:lower()
|
||||||
|
-- Else compare name to modpack name
|
||||||
|
else
|
||||||
|
-- Always show modpack pseudo-mod on top of modpack mod list
|
||||||
|
if a.name == b.modpack then
|
||||||
|
return true
|
||||||
|
elseif b.name == a.modpack then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local name_a = a.modpack or a.name
|
||||||
|
local name_b = b.modpack or b.name
|
||||||
|
if name_a:lower() == name_b:lower() then
|
||||||
|
return name_a < name_b
|
||||||
|
end
|
||||||
|
return name_a:lower() < name_b:lower()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
322
builtin/gamemgr.lua
Normal file
@@ -0,0 +1,322 @@
|
|||||||
|
--Minetest
|
||||||
|
--Copyright (C) 2013 sapier
|
||||||
|
--
|
||||||
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
--it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
--the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
--(at your option) any later version.
|
||||||
|
--
|
||||||
|
--This program is distributed in the hope that it will be useful,
|
||||||
|
--but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
--GNU Lesser General Public License for more details.
|
||||||
|
--
|
||||||
|
--You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
--with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
gamemgr = {}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function gamemgr.dialog_new_game()
|
||||||
|
local retval =
|
||||||
|
"label[2,2;" .. fgettext("Game Name") .. "]"..
|
||||||
|
"field[4.5,2.4;6,0.5;te_game_name;;]" ..
|
||||||
|
"button[5,4.2;2.6,0.5;new_game_confirm;" .. fgettext("Create") .. "]" ..
|
||||||
|
"button[7.5,4.2;2.8,0.5;new_game_cancel;" .. fgettext("Cancel") .. "]"
|
||||||
|
|
||||||
|
return retval
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function gamemgr.handle_games_buttons(fields)
|
||||||
|
if fields["gamelist"] ~= nil then
|
||||||
|
local event = explode_textlist_event(fields["gamelist"])
|
||||||
|
gamemgr.selected_game = event.index
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields["btn_game_mgr_edit_game"] ~= nil then
|
||||||
|
return {
|
||||||
|
is_dialog = true,
|
||||||
|
show_buttons = false,
|
||||||
|
current_tab = "dialog_edit_game"
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields["btn_game_mgr_new_game"] ~= nil then
|
||||||
|
return {
|
||||||
|
is_dialog = true,
|
||||||
|
show_buttons = false,
|
||||||
|
current_tab = "dialog_new_game"
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function gamemgr.handle_new_game_buttons(fields)
|
||||||
|
|
||||||
|
if fields["new_game_confirm"] and
|
||||||
|
fields["te_game_name"] ~= nil and
|
||||||
|
fields["te_game_name"] ~= "" then
|
||||||
|
local gamepath = engine.get_gamepath()
|
||||||
|
|
||||||
|
if gamepath ~= nil and
|
||||||
|
gamepath ~= "" then
|
||||||
|
local gamefolder = cleanup_path(fields["te_game_name"])
|
||||||
|
|
||||||
|
--TODO check for already existing first
|
||||||
|
engine.create_dir(gamepath .. DIR_DELIM .. gamefolder)
|
||||||
|
engine.create_dir(gamepath .. DIR_DELIM .. gamefolder .. DIR_DELIM .. "mods")
|
||||||
|
engine.create_dir(gamepath .. DIR_DELIM .. gamefolder .. DIR_DELIM .. "menu")
|
||||||
|
|
||||||
|
local gameconf =
|
||||||
|
io.open(gamepath .. DIR_DELIM .. gamefolder .. DIR_DELIM .. "game.conf","w")
|
||||||
|
|
||||||
|
if gameconf then
|
||||||
|
gameconf:write("name = " .. fields["te_game_name"])
|
||||||
|
gameconf:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
is_dialog = false,
|
||||||
|
show_buttons = true,
|
||||||
|
current_tab = engine.setting_get("main_menu_tab")
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function gamemgr.handle_edit_game_buttons(fields)
|
||||||
|
local current_game = gamemgr.get_game(gamemgr.selected_game)
|
||||||
|
|
||||||
|
if fields["btn_close_edit_game"] ~= nil or
|
||||||
|
current_game == nil then
|
||||||
|
return {
|
||||||
|
is_dialog = false,
|
||||||
|
show_buttons = true,
|
||||||
|
current_tab = engine.setting_get("main_menu_tab")
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields["btn_remove_mod_from_game"] ~= nil then
|
||||||
|
gamemgr.delete_mod(current_game,engine.get_textlist_index("mods_current"))
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields["btn_add_mod_to_game"] ~= nil then
|
||||||
|
local modindex = engine.get_textlist_index("mods_available")
|
||||||
|
|
||||||
|
local mod = modmgr.get_global_mod(modindex)
|
||||||
|
if mod ~= nil then
|
||||||
|
|
||||||
|
local sourcepath = mod.path
|
||||||
|
|
||||||
|
if not gamemgr.add_mod(current_game,sourcepath) then
|
||||||
|
gamedata.errormessage =
|
||||||
|
fgettext("Gamemgr: Unable to copy mod \"$1\" to game \"$2\"", mod.name, current_game.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function gamemgr.add_mod(gamespec,sourcepath)
|
||||||
|
if gamespec.gamemods_path ~= nil and
|
||||||
|
gamespec.gamemods_path ~= "" then
|
||||||
|
|
||||||
|
local modname = get_last_folder(sourcepath)
|
||||||
|
|
||||||
|
return engine.copy_dir(sourcepath,gamespec.gamemods_path .. DIR_DELIM .. modname);
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function gamemgr.delete_mod(gamespec,modindex)
|
||||||
|
if gamespec.gamemods_path ~= nil and
|
||||||
|
gamespec.gamemods_path ~= "" then
|
||||||
|
local game_mods = {}
|
||||||
|
get_mods(gamespec.gamemods_path,game_mods)
|
||||||
|
|
||||||
|
if modindex > 0 and
|
||||||
|
#game_mods >= modindex then
|
||||||
|
|
||||||
|
if game_mods[modindex].path:sub(0,gamespec.gamemods_path:len())
|
||||||
|
== gamespec.gamemods_path then
|
||||||
|
engine.delete_dir(game_mods[modindex].path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function gamemgr.find_by_gameid(gameid)
|
||||||
|
for i=1,#gamemgr.games,1 do
|
||||||
|
if gamemgr.games[i].id == gameid then
|
||||||
|
return gamemgr.games[i], i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function gamemgr.get_game_mods(gamespec, retval)
|
||||||
|
if gamespec ~= nil and
|
||||||
|
gamespec.gamemods_path ~= nil and
|
||||||
|
gamespec.gamemods_path ~= "" then
|
||||||
|
get_mods(gamespec.gamemods_path, retval)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function gamemgr.get_game_modlist(gamespec)
|
||||||
|
local retval = ""
|
||||||
|
local game_mods = {}
|
||||||
|
gamemgr.get_game_mods(gamespec, game_mods)
|
||||||
|
for i=1,#game_mods,1 do
|
||||||
|
if retval ~= "" then
|
||||||
|
retval = retval..","
|
||||||
|
end
|
||||||
|
retval = retval .. game_mods[i].name
|
||||||
|
end
|
||||||
|
return retval
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function gamemgr.gettab(name)
|
||||||
|
local retval = ""
|
||||||
|
|
||||||
|
if name == "dialog_edit_game" then
|
||||||
|
retval = retval .. gamemgr.dialog_edit_game()
|
||||||
|
end
|
||||||
|
|
||||||
|
if name == "dialog_new_game" then
|
||||||
|
retval = retval .. gamemgr.dialog_new_game()
|
||||||
|
end
|
||||||
|
|
||||||
|
if name == "game_mgr" then
|
||||||
|
retval = retval .. gamemgr.tab()
|
||||||
|
end
|
||||||
|
|
||||||
|
return retval
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function gamemgr.tab()
|
||||||
|
if gamemgr.selected_game == nil then
|
||||||
|
gamemgr.selected_game = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local retval =
|
||||||
|
"vertlabel[0,-0.25;" .. fgettext("GAMES") .. "]" ..
|
||||||
|
"label[1,-0.25;" .. fgettext("Games") .. ":]" ..
|
||||||
|
"textlist[1,0.25;4.5,4.4;gamelist;" ..
|
||||||
|
gamemgr.gamelist() ..
|
||||||
|
";" .. gamemgr.selected_game .. "]"
|
||||||
|
|
||||||
|
local current_game = gamemgr.get_game(gamemgr.selected_game)
|
||||||
|
|
||||||
|
if current_game ~= nil then
|
||||||
|
if current_game.menuicon_path ~= nil and
|
||||||
|
current_game.menuicon_path ~= "" then
|
||||||
|
retval = retval ..
|
||||||
|
"image[5.8,-0.25;2,2;" ..
|
||||||
|
engine.formspec_escape(current_game.menuicon_path) .. "]"
|
||||||
|
end
|
||||||
|
|
||||||
|
retval = retval ..
|
||||||
|
"field[8,-0.25;6,2;;" .. current_game.name .. ";]"..
|
||||||
|
"label[6,1.4;" .. fgettext("Mods:") .."]" ..
|
||||||
|
"button[9.7,1.5;2,0.2;btn_game_mgr_edit_game;" .. fgettext("edit game") .. "]" ..
|
||||||
|
"textlist[6,2;5.5,3.3;game_mgr_modlist;"
|
||||||
|
.. gamemgr.get_game_modlist(current_game) ..";0]" ..
|
||||||
|
"button[1,4.75;3.2,0.5;btn_game_mgr_new_game;" .. fgettext("new game") .. "]"
|
||||||
|
end
|
||||||
|
return retval
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function gamemgr.dialog_edit_game()
|
||||||
|
local current_game = gamemgr.get_game(gamemgr.selected_game)
|
||||||
|
if current_game ~= nil then
|
||||||
|
local retval =
|
||||||
|
"vertlabel[0,-0.25;" .. fgettext("EDIT GAME") .."]" ..
|
||||||
|
"label[0,-0.25;" .. current_game.name .. "]" ..
|
||||||
|
"button[11.55,-0.2;0.75,0.5;btn_close_edit_game;x]"
|
||||||
|
|
||||||
|
if current_game.menuicon_path ~= nil and
|
||||||
|
current_game.menuicon_path ~= "" then
|
||||||
|
retval = retval ..
|
||||||
|
"image[5.25,0;2,2;" ..
|
||||||
|
engine.formspec_escape(current_game.menuicon_path) .. "]"
|
||||||
|
end
|
||||||
|
|
||||||
|
retval = retval ..
|
||||||
|
"textlist[0.5,0.5;4.5,4.3;mods_current;"
|
||||||
|
.. gamemgr.get_game_modlist(current_game) ..";0]"
|
||||||
|
|
||||||
|
|
||||||
|
retval = retval ..
|
||||||
|
"textlist[7,0.5;4.5,4.3;mods_available;"
|
||||||
|
.. modmgr.render_modlist() .. ";0]"
|
||||||
|
|
||||||
|
retval = retval ..
|
||||||
|
"button[0.55,4.95;4.7,0.5;btn_remove_mod_from_game;" .. fgettext("Remove selected mod") .."]"
|
||||||
|
|
||||||
|
retval = retval ..
|
||||||
|
"button[7.05,4.95;4.7,0.5;btn_add_mod_to_game;" .. fgettext("<<-- Add mod") .."]"
|
||||||
|
|
||||||
|
return retval
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function gamemgr.handle_buttons(tab,fields)
|
||||||
|
local retval = nil
|
||||||
|
|
||||||
|
if tab == "dialog_edit_game" then
|
||||||
|
retval = gamemgr.handle_edit_game_buttons(fields)
|
||||||
|
end
|
||||||
|
|
||||||
|
if tab == "dialog_new_game" then
|
||||||
|
retval = gamemgr.handle_new_game_buttons(fields)
|
||||||
|
end
|
||||||
|
|
||||||
|
if tab == "game_mgr" then
|
||||||
|
retval = gamemgr.handle_games_buttons(fields)
|
||||||
|
end
|
||||||
|
|
||||||
|
return retval
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function gamemgr.get_game(index)
|
||||||
|
if index > 0 and index <= #gamemgr.games then
|
||||||
|
return gamemgr.games[index]
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function gamemgr.update_gamelist()
|
||||||
|
gamemgr.games = engine.get_games()
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function gamemgr.gamelist()
|
||||||
|
local retval = ""
|
||||||
|
if #gamemgr.games > 0 then
|
||||||
|
retval = retval .. gamemgr.games[1].id
|
||||||
|
|
||||||
|
for i=2,#gamemgr.games,1 do
|
||||||
|
retval = retval .. "," .. gamemgr.games[i].name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return retval
|
||||||
|
end
|
||||||
576
builtin/item.lua
Normal file
@@ -0,0 +1,576 @@
|
|||||||
|
-- Minetest: builtin/item.lua
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Item definition helpers
|
||||||
|
--
|
||||||
|
|
||||||
|
function minetest.inventorycube(img1, img2, img3)
|
||||||
|
img2 = img2 or img1
|
||||||
|
img3 = img3 or img1
|
||||||
|
return "[inventorycube"
|
||||||
|
.. "{" .. img1:gsub("%^", "&")
|
||||||
|
.. "{" .. img2:gsub("%^", "&")
|
||||||
|
.. "{" .. img3:gsub("%^", "&")
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.get_pointed_thing_position(pointed_thing, above)
|
||||||
|
if pointed_thing.type == "node" then
|
||||||
|
if above then
|
||||||
|
-- The position where a node would be placed
|
||||||
|
return pointed_thing.above
|
||||||
|
else
|
||||||
|
-- The position where a node would be dug
|
||||||
|
return pointed_thing.under
|
||||||
|
end
|
||||||
|
elseif pointed_thing.type == "object" then
|
||||||
|
obj = pointed_thing.ref
|
||||||
|
if obj ~= nil then
|
||||||
|
return obj:getpos()
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.dir_to_facedir(dir, is6d)
|
||||||
|
--account for y if requested
|
||||||
|
if is6d and math.abs(dir.y) > math.abs(dir.x) and math.abs(dir.y) > math.abs(dir.z) then
|
||||||
|
|
||||||
|
--from above
|
||||||
|
if dir.y < 0 then
|
||||||
|
if math.abs(dir.x) > math.abs(dir.z) then
|
||||||
|
if dir.x < 0 then
|
||||||
|
return 19
|
||||||
|
else
|
||||||
|
return 13
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if dir.z < 0 then
|
||||||
|
return 10
|
||||||
|
else
|
||||||
|
return 4
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--from below
|
||||||
|
else
|
||||||
|
if math.abs(dir.x) > math.abs(dir.z) then
|
||||||
|
if dir.x < 0 then
|
||||||
|
return 15
|
||||||
|
else
|
||||||
|
return 17
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if dir.z < 0 then
|
||||||
|
return 6
|
||||||
|
else
|
||||||
|
return 8
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--otherwise, place horizontally
|
||||||
|
elseif math.abs(dir.x) > math.abs(dir.z) then
|
||||||
|
if dir.x < 0 then
|
||||||
|
return 3
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if dir.z < 0 then
|
||||||
|
return 2
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.facedir_to_dir(facedir)
|
||||||
|
--a table of possible dirs
|
||||||
|
return ({{x=0, y=0, z=1},
|
||||||
|
{x=1, y=0, z=0},
|
||||||
|
{x=0, y=0, z=-1},
|
||||||
|
{x=-1, y=0, z=0},
|
||||||
|
{x=0, y=-1, z=0},
|
||||||
|
{x=0, y=1, z=0}})
|
||||||
|
|
||||||
|
--indexed into by a table of correlating facedirs
|
||||||
|
[({[0]=1, 2, 3, 4,
|
||||||
|
5, 2, 6, 4,
|
||||||
|
6, 2, 5, 4,
|
||||||
|
1, 5, 3, 6,
|
||||||
|
1, 6, 3, 5,
|
||||||
|
1, 4, 3, 2})
|
||||||
|
|
||||||
|
--indexed into by the facedir in question
|
||||||
|
[facedir]]
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.dir_to_wallmounted(dir)
|
||||||
|
if math.abs(dir.y) > math.max(math.abs(dir.x), math.abs(dir.z)) then
|
||||||
|
if dir.y < 0 then
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
elseif math.abs(dir.x) > math.abs(dir.z) then
|
||||||
|
if dir.x < 0 then
|
||||||
|
return 3
|
||||||
|
else
|
||||||
|
return 2
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if dir.z < 0 then
|
||||||
|
return 5
|
||||||
|
else
|
||||||
|
return 4
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.get_node_drops(nodename, toolname)
|
||||||
|
local drop = ItemStack({name=nodename}):get_definition().drop
|
||||||
|
if drop == nil then
|
||||||
|
-- default drop
|
||||||
|
return {nodename}
|
||||||
|
elseif type(drop) == "string" then
|
||||||
|
-- itemstring drop
|
||||||
|
return {drop}
|
||||||
|
elseif drop.items == nil then
|
||||||
|
-- drop = {} to disable default drop
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Extended drop table
|
||||||
|
local got_items = {}
|
||||||
|
local got_count = 0
|
||||||
|
local _, item, tool
|
||||||
|
for _, item in ipairs(drop.items) do
|
||||||
|
local good_rarity = true
|
||||||
|
local good_tool = true
|
||||||
|
if item.rarity ~= nil then
|
||||||
|
good_rarity = item.rarity < 1 or math.random(item.rarity) == 1
|
||||||
|
end
|
||||||
|
if item.tools ~= nil then
|
||||||
|
good_tool = false
|
||||||
|
for _, tool in ipairs(item.tools) do
|
||||||
|
if tool:sub(1, 1) == '~' then
|
||||||
|
good_tool = toolname:find(tool:sub(2)) ~= nil
|
||||||
|
else
|
||||||
|
good_tool = toolname == tool
|
||||||
|
end
|
||||||
|
if good_tool then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if good_rarity and good_tool then
|
||||||
|
got_count = got_count + 1
|
||||||
|
for _, add_item in ipairs(item.items) do
|
||||||
|
got_items[#got_items+1] = add_item
|
||||||
|
end
|
||||||
|
if drop.max_items ~= nil and got_count == drop.max_items then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return got_items
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.item_place_node(itemstack, placer, pointed_thing, param2)
|
||||||
|
local item = itemstack:peek_item()
|
||||||
|
local def = itemstack:get_definition()
|
||||||
|
if def.type ~= "node" or pointed_thing.type ~= "node" then
|
||||||
|
return itemstack, false
|
||||||
|
end
|
||||||
|
|
||||||
|
local under = pointed_thing.under
|
||||||
|
local oldnode_under = minetest.get_node_or_nil(under)
|
||||||
|
local above = pointed_thing.above
|
||||||
|
local oldnode_above = minetest.get_node_or_nil(above)
|
||||||
|
|
||||||
|
if not oldnode_under or not oldnode_above then
|
||||||
|
minetest.log("info", placer:get_player_name() .. " tried to place"
|
||||||
|
.. " node in unloaded position " .. minetest.pos_to_string(above))
|
||||||
|
return itemstack, false
|
||||||
|
end
|
||||||
|
|
||||||
|
local olddef_under = ItemStack({name=oldnode_under.name}):get_definition()
|
||||||
|
olddef_under = olddef_under or minetest.nodedef_default
|
||||||
|
local olddef_above = ItemStack({name=oldnode_above.name}):get_definition()
|
||||||
|
olddef_above = olddef_above or minetest.nodedef_default
|
||||||
|
|
||||||
|
if not olddef_above.buildable_to and not olddef_under.buildable_to then
|
||||||
|
minetest.log("info", placer:get_player_name() .. " tried to place"
|
||||||
|
.. " node in invalid position " .. minetest.pos_to_string(above)
|
||||||
|
.. ", replacing " .. oldnode_above.name)
|
||||||
|
return itemstack, false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Place above pointed node
|
||||||
|
local place_to = {x = above.x, y = above.y, z = above.z}
|
||||||
|
|
||||||
|
-- If node under is buildable_to, place into it instead (eg. snow)
|
||||||
|
if olddef_under.buildable_to then
|
||||||
|
minetest.log("info", "node under is buildable to")
|
||||||
|
place_to = {x = under.x, y = under.y, z = under.z}
|
||||||
|
end
|
||||||
|
|
||||||
|
if minetest.is_protected(place_to, placer:get_player_name()) then
|
||||||
|
minetest.log("action", placer:get_player_name()
|
||||||
|
.. " tried to place " .. def.name
|
||||||
|
.. " at protected position "
|
||||||
|
.. minetest.pos_to_string(place_to))
|
||||||
|
minetest.record_protection_violation(place_to, placer:get_player_name())
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.log("action", placer:get_player_name() .. " places node "
|
||||||
|
.. def.name .. " at " .. minetest.pos_to_string(place_to))
|
||||||
|
|
||||||
|
local oldnode = minetest.get_node(place_to)
|
||||||
|
local newnode = {name = def.name, param1 = 0, param2 = param2}
|
||||||
|
|
||||||
|
-- Calculate direction for wall mounted stuff like torches and signs
|
||||||
|
if def.paramtype2 == 'wallmounted' and not param2 then
|
||||||
|
local dir = {
|
||||||
|
x = under.x - above.x,
|
||||||
|
y = under.y - above.y,
|
||||||
|
z = under.z - above.z
|
||||||
|
}
|
||||||
|
newnode.param2 = minetest.dir_to_wallmounted(dir)
|
||||||
|
-- Calculate the direction for furnaces and chests and stuff
|
||||||
|
elseif def.paramtype2 == 'facedir' and not param2 then
|
||||||
|
local placer_pos = placer:getpos()
|
||||||
|
if placer_pos then
|
||||||
|
local dir = {
|
||||||
|
x = above.x - placer_pos.x,
|
||||||
|
y = above.y - placer_pos.y,
|
||||||
|
z = above.z - placer_pos.z
|
||||||
|
}
|
||||||
|
newnode.param2 = minetest.dir_to_facedir(dir)
|
||||||
|
minetest.log("action", "facedir: " .. newnode.param2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if the node is attached and if it can be placed there
|
||||||
|
if minetest.get_item_group(def.name, "attached_node") ~= 0 and
|
||||||
|
not check_attached_node(place_to, newnode) then
|
||||||
|
minetest.log("action", "attached node " .. def.name ..
|
||||||
|
" can not be placed at " .. minetest.pos_to_string(place_to))
|
||||||
|
return itemstack, false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add node and update
|
||||||
|
minetest.add_node(place_to, newnode)
|
||||||
|
|
||||||
|
local take_item = true
|
||||||
|
|
||||||
|
-- Run callback
|
||||||
|
if def.after_place_node then
|
||||||
|
-- Copy place_to because callback can modify it
|
||||||
|
local place_to_copy = {x=place_to.x, y=place_to.y, z=place_to.z}
|
||||||
|
if def.after_place_node(place_to_copy, placer, itemstack) then
|
||||||
|
take_item = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Run script hook
|
||||||
|
local _, callback
|
||||||
|
for _, callback in ipairs(minetest.registered_on_placenodes) do
|
||||||
|
-- Copy pos and node because callback can modify them
|
||||||
|
local place_to_copy = {x=place_to.x, y=place_to.y, z=place_to.z}
|
||||||
|
local newnode_copy = {name=newnode.name, param1=newnode.param1, param2=newnode.param2}
|
||||||
|
local oldnode_copy = {name=oldnode.name, param1=oldnode.param1, param2=oldnode.param2}
|
||||||
|
if callback(place_to_copy, newnode_copy, placer, oldnode_copy, itemstack) then
|
||||||
|
take_item = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if take_item then
|
||||||
|
itemstack:take_item()
|
||||||
|
end
|
||||||
|
return itemstack, true
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.item_place_object(itemstack, placer, pointed_thing)
|
||||||
|
local pos = minetest.get_pointed_thing_position(pointed_thing, true)
|
||||||
|
if pos ~= nil then
|
||||||
|
local item = itemstack:take_item()
|
||||||
|
minetest.add_item(pos, item)
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.item_place(itemstack, placer, pointed_thing, param2)
|
||||||
|
-- Call on_rightclick if the pointed node defines it
|
||||||
|
if pointed_thing.type == "node" and placer and
|
||||||
|
not placer:get_player_control().sneak then
|
||||||
|
local n = minetest.get_node(pointed_thing.under)
|
||||||
|
local nn = n.name
|
||||||
|
if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].on_rightclick then
|
||||||
|
return minetest.registered_nodes[nn].on_rightclick(pointed_thing.under, n, placer, itemstack) or itemstack, false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if itemstack:get_definition().type == "node" then
|
||||||
|
return minetest.item_place_node(itemstack, placer, pointed_thing, param2)
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.item_drop(itemstack, dropper, pos)
|
||||||
|
if dropper.get_player_name then
|
||||||
|
local v = dropper:get_look_dir()
|
||||||
|
local p = {x=pos.x+v.x, y=pos.y+1.5+v.y, z=pos.z+v.z}
|
||||||
|
local obj = minetest.add_item(p, itemstack)
|
||||||
|
if obj then
|
||||||
|
v.x = v.x*2
|
||||||
|
v.y = v.y*2 + 1
|
||||||
|
v.z = v.z*2
|
||||||
|
obj:setvelocity(v)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
minetest.add_item(pos, itemstack)
|
||||||
|
end
|
||||||
|
return ItemStack("")
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.item_eat(hp_change, replace_with_item)
|
||||||
|
return function(itemstack, user, pointed_thing) -- closure
|
||||||
|
if itemstack:take_item() ~= nil then
|
||||||
|
user:set_hp(user:get_hp() + hp_change)
|
||||||
|
itemstack:add_item(replace_with_item) -- note: replace_with_item is optional
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.node_punch(pos, node, puncher)
|
||||||
|
-- Run script hook
|
||||||
|
local _, callback
|
||||||
|
for _, callback in ipairs(minetest.registered_on_punchnodes) do
|
||||||
|
-- Copy pos and node because callback can modify them
|
||||||
|
local pos_copy = {x=pos.x, y=pos.y, z=pos.z}
|
||||||
|
local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
|
||||||
|
callback(pos_copy, node_copy, puncher)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.handle_node_drops(pos, drops, digger)
|
||||||
|
-- Add dropped items to object's inventory
|
||||||
|
if digger:get_inventory() then
|
||||||
|
local _, dropped_item
|
||||||
|
for _, dropped_item in ipairs(drops) do
|
||||||
|
local left = digger:get_inventory():add_item("main", dropped_item)
|
||||||
|
if not left:is_empty() then
|
||||||
|
local p = {
|
||||||
|
x = pos.x + math.random()/2-0.25,
|
||||||
|
y = pos.y + math.random()/2-0.25,
|
||||||
|
z = pos.z + math.random()/2-0.25,
|
||||||
|
}
|
||||||
|
minetest.add_item(p, left)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.node_dig(pos, node, digger)
|
||||||
|
local def = ItemStack({name=node.name}):get_definition()
|
||||||
|
if not def.diggable or (def.can_dig and not def.can_dig(pos,digger)) then
|
||||||
|
minetest.log("info", digger:get_player_name() .. " tried to dig "
|
||||||
|
.. node.name .. " which is not diggable "
|
||||||
|
.. minetest.pos_to_string(pos))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if minetest.is_protected(pos, digger:get_player_name()) then
|
||||||
|
minetest.log("action", digger:get_player_name()
|
||||||
|
.. " tried to dig " .. node.name
|
||||||
|
.. " at protected position "
|
||||||
|
.. minetest.pos_to_string(pos))
|
||||||
|
minetest.record_protection_violation(pos, digger:get_player_name())
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.log('action', digger:get_player_name() .. " digs "
|
||||||
|
.. node.name .. " at " .. minetest.pos_to_string(pos))
|
||||||
|
|
||||||
|
local wielded = digger:get_wielded_item()
|
||||||
|
local drops = minetest.get_node_drops(node.name, wielded:get_name())
|
||||||
|
|
||||||
|
local wdef = wielded:get_definition()
|
||||||
|
local tp = wielded:get_tool_capabilities()
|
||||||
|
local dp = minetest.get_dig_params(def.groups, tp)
|
||||||
|
if wdef and wdef.after_use then
|
||||||
|
wielded = wdef.after_use(wielded, digger, node, dp) or wielded
|
||||||
|
else
|
||||||
|
-- Wear out tool
|
||||||
|
if not minetest.setting_getbool("creative_mode") then
|
||||||
|
wielded:add_wear(dp.wear)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
digger:set_wielded_item(wielded)
|
||||||
|
|
||||||
|
-- Handle drops
|
||||||
|
minetest.handle_node_drops(pos, drops, digger)
|
||||||
|
|
||||||
|
local oldmetadata = nil
|
||||||
|
if def.after_dig_node then
|
||||||
|
oldmetadata = minetest.get_meta(pos):to_table()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Remove node and update
|
||||||
|
minetest.remove_node(pos)
|
||||||
|
|
||||||
|
-- Run callback
|
||||||
|
if def.after_dig_node then
|
||||||
|
-- Copy pos and node because callback can modify them
|
||||||
|
local pos_copy = {x=pos.x, y=pos.y, z=pos.z}
|
||||||
|
local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
|
||||||
|
def.after_dig_node(pos_copy, node_copy, oldmetadata, digger)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Run script hook
|
||||||
|
local _, callback
|
||||||
|
for _, callback in ipairs(minetest.registered_on_dignodes) do
|
||||||
|
-- Copy pos and node because callback can modify them
|
||||||
|
local pos_copy = {x=pos.x, y=pos.y, z=pos.z}
|
||||||
|
local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
|
||||||
|
callback(pos_copy, node_copy, digger)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- This is used to allow mods to redefine minetest.item_place and so on
|
||||||
|
-- NOTE: This is not the preferred way. Preferred way is to provide enough
|
||||||
|
-- callbacks to not require redefining global functions. -celeron55
|
||||||
|
local function redef_wrapper(table, name)
|
||||||
|
return function(...)
|
||||||
|
return table[name](...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Item definition defaults
|
||||||
|
--
|
||||||
|
|
||||||
|
minetest.nodedef_default = {
|
||||||
|
-- Item properties
|
||||||
|
type="node",
|
||||||
|
-- name intentionally not defined here
|
||||||
|
description = "",
|
||||||
|
groups = {},
|
||||||
|
inventory_image = "",
|
||||||
|
wield_image = "",
|
||||||
|
wield_scale = {x=1,y=1,z=1},
|
||||||
|
stack_max = 99,
|
||||||
|
usable = false,
|
||||||
|
liquids_pointable = false,
|
||||||
|
tool_capabilities = nil,
|
||||||
|
node_placement_prediction = nil,
|
||||||
|
|
||||||
|
-- Interaction callbacks
|
||||||
|
on_place = redef_wrapper(minetest, 'item_place'), -- minetest.item_place
|
||||||
|
on_drop = redef_wrapper(minetest, 'item_drop'), -- minetest.item_drop
|
||||||
|
on_use = nil,
|
||||||
|
can_dig = nil,
|
||||||
|
|
||||||
|
on_punch = redef_wrapper(minetest, 'node_punch'), -- minetest.node_punch
|
||||||
|
on_rightclick = nil,
|
||||||
|
on_dig = redef_wrapper(minetest, 'node_dig'), -- minetest.node_dig
|
||||||
|
|
||||||
|
on_receive_fields = nil,
|
||||||
|
|
||||||
|
on_metadata_inventory_move = minetest.node_metadata_inventory_move_allow_all,
|
||||||
|
on_metadata_inventory_offer = minetest.node_metadata_inventory_offer_allow_all,
|
||||||
|
on_metadata_inventory_take = minetest.node_metadata_inventory_take_allow_all,
|
||||||
|
|
||||||
|
-- Node properties
|
||||||
|
drawtype = "normal",
|
||||||
|
visual_scale = 1.0,
|
||||||
|
-- Don't define these because otherwise the old tile_images and
|
||||||
|
-- special_materials wouldn't be read
|
||||||
|
--tiles ={""},
|
||||||
|
--special_tiles = {
|
||||||
|
-- {name="", backface_culling=true},
|
||||||
|
-- {name="", backface_culling=true},
|
||||||
|
--},
|
||||||
|
alpha = 255,
|
||||||
|
post_effect_color = {a=0, r=0, g=0, b=0},
|
||||||
|
paramtype = "none",
|
||||||
|
paramtype2 = "none",
|
||||||
|
is_ground_content = true,
|
||||||
|
sunlight_propagates = false,
|
||||||
|
walkable = true,
|
||||||
|
pointable = true,
|
||||||
|
diggable = true,
|
||||||
|
climbable = false,
|
||||||
|
buildable_to = false,
|
||||||
|
liquidtype = "none",
|
||||||
|
liquid_alternative_flowing = "",
|
||||||
|
liquid_alternative_source = "",
|
||||||
|
liquid_viscosity = 0,
|
||||||
|
drowning = 0,
|
||||||
|
light_source = 0,
|
||||||
|
damage_per_second = 0,
|
||||||
|
selection_box = {type="regular"},
|
||||||
|
legacy_facedir_simple = false,
|
||||||
|
legacy_wallmounted = false,
|
||||||
|
}
|
||||||
|
|
||||||
|
minetest.craftitemdef_default = {
|
||||||
|
type="craft",
|
||||||
|
-- name intentionally not defined here
|
||||||
|
description = "",
|
||||||
|
groups = {},
|
||||||
|
inventory_image = "",
|
||||||
|
wield_image = "",
|
||||||
|
wield_scale = {x=1,y=1,z=1},
|
||||||
|
stack_max = 99,
|
||||||
|
liquids_pointable = false,
|
||||||
|
tool_capabilities = nil,
|
||||||
|
|
||||||
|
-- Interaction callbacks
|
||||||
|
on_place = redef_wrapper(minetest, 'item_place'), -- minetest.item_place
|
||||||
|
on_drop = redef_wrapper(minetest, 'item_drop'), -- minetest.item_drop
|
||||||
|
on_use = nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
minetest.tooldef_default = {
|
||||||
|
type="tool",
|
||||||
|
-- name intentionally not defined here
|
||||||
|
description = "",
|
||||||
|
groups = {},
|
||||||
|
inventory_image = "",
|
||||||
|
wield_image = "",
|
||||||
|
wield_scale = {x=1,y=1,z=1},
|
||||||
|
stack_max = 1,
|
||||||
|
liquids_pointable = false,
|
||||||
|
tool_capabilities = nil,
|
||||||
|
|
||||||
|
-- Interaction callbacks
|
||||||
|
on_place = redef_wrapper(minetest, 'item_place'), -- minetest.item_place
|
||||||
|
on_drop = redef_wrapper(minetest, 'item_drop'), -- minetest.item_drop
|
||||||
|
on_use = nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
minetest.noneitemdef_default = { -- This is used for the hand and unknown items
|
||||||
|
type="none",
|
||||||
|
-- name intentionally not defined here
|
||||||
|
description = "",
|
||||||
|
groups = {},
|
||||||
|
inventory_image = "",
|
||||||
|
wield_image = "",
|
||||||
|
wield_scale = {x=1,y=1,z=1},
|
||||||
|
stack_max = 99,
|
||||||
|
liquids_pointable = false,
|
||||||
|
tool_capabilities = nil,
|
||||||
|
|
||||||
|
-- Interaction callbacks
|
||||||
|
on_place = redef_wrapper(minetest, 'item_place'),
|
||||||
|
on_drop = nil,
|
||||||
|
on_use = nil,
|
||||||
|
}
|
||||||
|
|
||||||
122
builtin/item_entity.lua
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
-- Minetest: builtin/item_entity.lua
|
||||||
|
|
||||||
|
function minetest.spawn_item(pos, item)
|
||||||
|
-- Take item in any format
|
||||||
|
local stack = ItemStack(item)
|
||||||
|
local obj = minetest.add_entity(pos, "__builtin:item")
|
||||||
|
obj:get_luaentity():set_item(stack:to_string())
|
||||||
|
return obj
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_entity("__builtin:item", {
|
||||||
|
initial_properties = {
|
||||||
|
hp_max = 1,
|
||||||
|
physical = true,
|
||||||
|
collide_with_objects = false,
|
||||||
|
collisionbox = {-0.17,-0.17,-0.17, 0.17,0.17,0.17},
|
||||||
|
visual = "sprite",
|
||||||
|
visual_size = {x=0.5, y=0.5},
|
||||||
|
textures = {""},
|
||||||
|
spritediv = {x=1, y=1},
|
||||||
|
initial_sprite_basepos = {x=0, y=0},
|
||||||
|
is_visible = false,
|
||||||
|
},
|
||||||
|
|
||||||
|
itemstring = '',
|
||||||
|
physical_state = true,
|
||||||
|
|
||||||
|
set_item = function(self, itemstring)
|
||||||
|
self.itemstring = itemstring
|
||||||
|
local stack = ItemStack(itemstring)
|
||||||
|
local itemtable = stack:to_table()
|
||||||
|
local itemname = nil
|
||||||
|
if itemtable then
|
||||||
|
itemname = stack:to_table().name
|
||||||
|
end
|
||||||
|
local item_texture = nil
|
||||||
|
local item_type = ""
|
||||||
|
if minetest.registered_items[itemname] then
|
||||||
|
item_texture = minetest.registered_items[itemname].inventory_image
|
||||||
|
item_type = minetest.registered_items[itemname].type
|
||||||
|
end
|
||||||
|
prop = {
|
||||||
|
is_visible = true,
|
||||||
|
visual = "sprite",
|
||||||
|
textures = {"unknown_item.png"}
|
||||||
|
}
|
||||||
|
if item_texture and item_texture ~= "" then
|
||||||
|
prop.visual = "sprite"
|
||||||
|
prop.textures = {item_texture}
|
||||||
|
prop.visual_size = {x=0.50, y=0.50}
|
||||||
|
else
|
||||||
|
prop.visual = "wielditem"
|
||||||
|
prop.textures = {itemname}
|
||||||
|
prop.visual_size = {x=0.20, y=0.20}
|
||||||
|
prop.automatic_rotate = math.pi * 0.25
|
||||||
|
end
|
||||||
|
self.object:set_properties(prop)
|
||||||
|
end,
|
||||||
|
|
||||||
|
get_staticdata = function(self)
|
||||||
|
--return self.itemstring
|
||||||
|
return minetest.serialize({
|
||||||
|
itemstring = self.itemstring,
|
||||||
|
always_collect = self.always_collect,
|
||||||
|
})
|
||||||
|
end,
|
||||||
|
|
||||||
|
on_activate = function(self, staticdata)
|
||||||
|
if string.sub(staticdata, 1, string.len("return")) == "return" then
|
||||||
|
local data = minetest.deserialize(staticdata)
|
||||||
|
if data and type(data) == "table" then
|
||||||
|
self.itemstring = data.itemstring
|
||||||
|
self.always_collect = data.always_collect
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.itemstring = staticdata
|
||||||
|
end
|
||||||
|
self.object:set_armor_groups({immortal=1})
|
||||||
|
self.object:setvelocity({x=0, y=2, z=0})
|
||||||
|
self.object:setacceleration({x=0, y=-10, z=0})
|
||||||
|
self:set_item(self.itemstring)
|
||||||
|
end,
|
||||||
|
|
||||||
|
on_step = function(self, dtime)
|
||||||
|
local p = self.object:getpos()
|
||||||
|
p.y = p.y - 0.3
|
||||||
|
local nn = minetest.get_node(p).name
|
||||||
|
-- If node is not registered or node is walkably solid and resting on nodebox
|
||||||
|
local v = self.object:getvelocity()
|
||||||
|
if not minetest.registered_nodes[nn] or minetest.registered_nodes[nn].walkable and v.y == 0 then
|
||||||
|
if self.physical_state then
|
||||||
|
self.object:setvelocity({x=0,y=0,z=0})
|
||||||
|
self.object:setacceleration({x=0, y=0, z=0})
|
||||||
|
self.physical_state = false
|
||||||
|
self.object:set_properties({
|
||||||
|
physical = false
|
||||||
|
})
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if not self.physical_state then
|
||||||
|
self.object:setvelocity({x=0,y=0,z=0})
|
||||||
|
self.object:setacceleration({x=0, y=-10, z=0})
|
||||||
|
self.physical_state = true
|
||||||
|
self.object:set_properties({
|
||||||
|
physical = true
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
on_punch = function(self, hitter)
|
||||||
|
if self.itemstring ~= '' then
|
||||||
|
local left = hitter:get_inventory():add_item("main", self.itemstring)
|
||||||
|
if not left:is_empty() then
|
||||||
|
self.itemstring = left:to_string()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.object:remove()
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
1328
builtin/mainmenu.lua
Normal file
121
builtin/misc.lua
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
-- Minetest: builtin/misc.lua
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Misc. API functions
|
||||||
|
--
|
||||||
|
|
||||||
|
minetest.timers_to_add = {}
|
||||||
|
minetest.timers = {}
|
||||||
|
minetest.register_globalstep(function(dtime)
|
||||||
|
for _, timer in ipairs(minetest.timers_to_add) do
|
||||||
|
table.insert(minetest.timers, timer)
|
||||||
|
end
|
||||||
|
minetest.timers_to_add = {}
|
||||||
|
for index, timer in ipairs(minetest.timers) do
|
||||||
|
timer.time = timer.time - dtime
|
||||||
|
if timer.time <= 0 then
|
||||||
|
timer.func(unpack(timer.args or {}))
|
||||||
|
table.remove(minetest.timers,index)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
function minetest.after(time, func, ...)
|
||||||
|
table.insert(minetest.timers_to_add, {time=time, func=func, args={...}})
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.check_player_privs(name, privs)
|
||||||
|
local player_privs = minetest.get_player_privs(name)
|
||||||
|
local missing_privileges = {}
|
||||||
|
for priv, val in pairs(privs) do
|
||||||
|
if val then
|
||||||
|
if not player_privs[priv] then
|
||||||
|
table.insert(missing_privileges, priv)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #missing_privileges > 0 then
|
||||||
|
return false, missing_privileges
|
||||||
|
end
|
||||||
|
return true, ""
|
||||||
|
end
|
||||||
|
|
||||||
|
local player_list = {}
|
||||||
|
|
||||||
|
minetest.register_on_joinplayer(function(player)
|
||||||
|
player_list[player:get_player_name()] = player
|
||||||
|
end)
|
||||||
|
|
||||||
|
minetest.register_on_leaveplayer(function(player)
|
||||||
|
player_list[player:get_player_name()] = nil
|
||||||
|
end)
|
||||||
|
|
||||||
|
function minetest.get_connected_players()
|
||||||
|
local temp_table = {}
|
||||||
|
for index, value in pairs(player_list) do
|
||||||
|
if value:is_player_connected() then
|
||||||
|
table.insert(temp_table, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return temp_table
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.hash_node_position(pos)
|
||||||
|
return (pos.z+32768)*65536*65536 + (pos.y+32768)*65536 + pos.x+32768
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.get_item_group(name, group)
|
||||||
|
if not minetest.registered_items[name] or not
|
||||||
|
minetest.registered_items[name].groups[group] then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
return minetest.registered_items[name].groups[group]
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.get_node_group(name, group)
|
||||||
|
return minetest.get_item_group(name, group)
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.string_to_pos(value)
|
||||||
|
local p = {}
|
||||||
|
p.x, p.y, p.z = string.match(value, "^([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
|
||||||
|
if p.x and p.y and p.z then
|
||||||
|
p.x = tonumber(p.x)
|
||||||
|
p.y = tonumber(p.y)
|
||||||
|
p.z = tonumber(p.z)
|
||||||
|
return p
|
||||||
|
end
|
||||||
|
local p = {}
|
||||||
|
p.x, p.y, p.z = string.match(value, "^%( *([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+) *%)$")
|
||||||
|
if p.x and p.y and p.z then
|
||||||
|
p.x = tonumber(p.x)
|
||||||
|
p.y = tonumber(p.y)
|
||||||
|
p.z = tonumber(p.z)
|
||||||
|
return p
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(minetest.string_to_pos("10.0, 5, -2").x == 10)
|
||||||
|
assert(minetest.string_to_pos("( 10.0, 5, -2)").z == -2)
|
||||||
|
assert(minetest.string_to_pos("asd, 5, -2)") == nil)
|
||||||
|
|
||||||
|
function minetest.setting_get_pos(name)
|
||||||
|
local value = minetest.setting_get(name)
|
||||||
|
if not value then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return minetest.string_to_pos(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- To be overriden by protection mods
|
||||||
|
function minetest.is_protected(pos, name)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.record_protection_violation(pos, name)
|
||||||
|
for _, func in pairs(minetest.registered_on_protection_violation) do
|
||||||
|
func(pos, name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
403
builtin/misc_helpers.lua
Normal file
@@ -0,0 +1,403 @@
|
|||||||
|
-- Minetest: builtin/misc_helpers.lua
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function basic_dump2(o)
|
||||||
|
if type(o) == "number" then
|
||||||
|
return tostring(o)
|
||||||
|
elseif type(o) == "string" then
|
||||||
|
return string.format("%q", o)
|
||||||
|
elseif type(o) == "boolean" then
|
||||||
|
return tostring(o)
|
||||||
|
elseif type(o) == "function" then
|
||||||
|
return "<function>"
|
||||||
|
elseif type(o) == "userdata" then
|
||||||
|
return "<userdata>"
|
||||||
|
elseif type(o) == "nil" then
|
||||||
|
return "nil"
|
||||||
|
else
|
||||||
|
error("cannot dump a " .. type(o))
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function dump2(o, name, dumped)
|
||||||
|
name = name or "_"
|
||||||
|
dumped = dumped or {}
|
||||||
|
io.write(name, " = ")
|
||||||
|
if type(o) == "number" or type(o) == "string" or type(o) == "boolean"
|
||||||
|
or type(o) == "function" or type(o) == "nil"
|
||||||
|
or type(o) == "userdata" then
|
||||||
|
io.write(basic_dump2(o), "\n")
|
||||||
|
elseif type(o) == "table" then
|
||||||
|
if dumped[o] then
|
||||||
|
io.write(dumped[o], "\n")
|
||||||
|
else
|
||||||
|
dumped[o] = name
|
||||||
|
io.write("{}\n") -- new table
|
||||||
|
for k,v in pairs(o) do
|
||||||
|
local fieldname = string.format("%s[%s]", name, basic_dump2(k))
|
||||||
|
dump2(v, fieldname, dumped)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
error("cannot dump a " .. type(o))
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function dump(o, dumped)
|
||||||
|
dumped = dumped or {}
|
||||||
|
if type(o) == "number" then
|
||||||
|
return tostring(o)
|
||||||
|
elseif type(o) == "string" then
|
||||||
|
return string.format("%q", o)
|
||||||
|
elseif type(o) == "table" then
|
||||||
|
if dumped[o] then
|
||||||
|
return "<circular reference>"
|
||||||
|
end
|
||||||
|
dumped[o] = true
|
||||||
|
local t = {}
|
||||||
|
for k,v in pairs(o) do
|
||||||
|
t[#t+1] = "[" .. dump(k, dumped) .. "] = " .. dump(v, dumped)
|
||||||
|
end
|
||||||
|
return "{" .. table.concat(t, ", ") .. "}"
|
||||||
|
elseif type(o) == "boolean" then
|
||||||
|
return tostring(o)
|
||||||
|
elseif type(o) == "function" then
|
||||||
|
return "<function>"
|
||||||
|
elseif type(o) == "userdata" then
|
||||||
|
return "<userdata>"
|
||||||
|
elseif type(o) == "nil" then
|
||||||
|
return "nil"
|
||||||
|
else
|
||||||
|
error("cannot dump a " .. type(o))
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function string:split(sep)
|
||||||
|
local sep, fields = sep or ",", {}
|
||||||
|
local pattern = string.format("([^%s]+)", sep)
|
||||||
|
self:gsub(pattern, function(c) fields[#fields+1] = c end)
|
||||||
|
return fields
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function file_exists(filename)
|
||||||
|
local f = io.open(filename, "r")
|
||||||
|
if f==nil then
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
f:close()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function string:trim()
|
||||||
|
return (self:gsub("^%s*(.-)%s*$", "%1"))
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(string.trim("\n \t\tfoo bar\t ") == "foo bar")
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function math.hypot(x, y)
|
||||||
|
local t
|
||||||
|
x = math.abs(x)
|
||||||
|
y = math.abs(y)
|
||||||
|
t = math.min(x, y)
|
||||||
|
x = math.max(x, y)
|
||||||
|
if x == 0 then return 0 end
|
||||||
|
t = t / x
|
||||||
|
return x * math.sqrt(1 + t * t)
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function explode_textlist_event(text)
|
||||||
|
|
||||||
|
local retval = {}
|
||||||
|
retval.typ = "INV"
|
||||||
|
|
||||||
|
local parts = text:split(":")
|
||||||
|
|
||||||
|
if #parts == 2 then
|
||||||
|
retval.typ = parts[1]:trim()
|
||||||
|
retval.index= tonumber(parts[2]:trim())
|
||||||
|
|
||||||
|
if type(retval.index) ~= "number" then
|
||||||
|
retval.typ = "INV"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return retval
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function get_last_folder(text,count)
|
||||||
|
local parts = text:split(DIR_DELIM)
|
||||||
|
|
||||||
|
if count == nil then
|
||||||
|
return parts[#parts]
|
||||||
|
end
|
||||||
|
|
||||||
|
local retval = ""
|
||||||
|
for i=1,count,1 do
|
||||||
|
retval = retval .. parts[#parts - (count-i)] .. DIR_DELIM
|
||||||
|
end
|
||||||
|
|
||||||
|
return retval
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function cleanup_path(temppath)
|
||||||
|
|
||||||
|
local parts = temppath:split("-")
|
||||||
|
temppath = ""
|
||||||
|
for i=1,#parts,1 do
|
||||||
|
if temppath ~= "" then
|
||||||
|
temppath = temppath .. "_"
|
||||||
|
end
|
||||||
|
temppath = temppath .. parts[i]
|
||||||
|
end
|
||||||
|
|
||||||
|
parts = temppath:split(".")
|
||||||
|
temppath = ""
|
||||||
|
for i=1,#parts,1 do
|
||||||
|
if temppath ~= "" then
|
||||||
|
temppath = temppath .. "_"
|
||||||
|
end
|
||||||
|
temppath = temppath .. parts[i]
|
||||||
|
end
|
||||||
|
|
||||||
|
parts = temppath:split("'")
|
||||||
|
temppath = ""
|
||||||
|
for i=1,#parts,1 do
|
||||||
|
if temppath ~= "" then
|
||||||
|
temppath = temppath .. ""
|
||||||
|
end
|
||||||
|
temppath = temppath .. parts[i]
|
||||||
|
end
|
||||||
|
|
||||||
|
parts = temppath:split(" ")
|
||||||
|
temppath = ""
|
||||||
|
for i=1,#parts,1 do
|
||||||
|
if temppath ~= "" then
|
||||||
|
temppath = temppath
|
||||||
|
end
|
||||||
|
temppath = temppath .. parts[i]
|
||||||
|
end
|
||||||
|
|
||||||
|
return temppath
|
||||||
|
end
|
||||||
|
|
||||||
|
local tbl = engine or minetest
|
||||||
|
function tbl.formspec_escape(text)
|
||||||
|
if text ~= nil then
|
||||||
|
text = string.gsub(text,"\\","\\\\")
|
||||||
|
text = string.gsub(text,"%]","\\]")
|
||||||
|
text = string.gsub(text,"%[","\\[")
|
||||||
|
text = string.gsub(text,";","\\;")
|
||||||
|
text = string.gsub(text,",","\\,")
|
||||||
|
end
|
||||||
|
return text
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function tbl.splittext(text,charlimit)
|
||||||
|
local retval = {}
|
||||||
|
|
||||||
|
local current_idx = 1
|
||||||
|
|
||||||
|
local start,stop = string.find(text," ",current_idx)
|
||||||
|
local nl_start,nl_stop = string.find(text,"\n",current_idx)
|
||||||
|
local gotnewline = false
|
||||||
|
if nl_start ~= nil and (start == nil or nl_start < start) then
|
||||||
|
start = nl_start
|
||||||
|
stop = nl_stop
|
||||||
|
gotnewline = true
|
||||||
|
end
|
||||||
|
local last_line = ""
|
||||||
|
while start ~= nil do
|
||||||
|
if string.len(last_line) + (stop-start) > charlimit then
|
||||||
|
table.insert(retval,last_line)
|
||||||
|
last_line = ""
|
||||||
|
end
|
||||||
|
|
||||||
|
if last_line ~= "" then
|
||||||
|
last_line = last_line .. " "
|
||||||
|
end
|
||||||
|
|
||||||
|
last_line = last_line .. string.sub(text,current_idx,stop -1)
|
||||||
|
|
||||||
|
if gotnewline then
|
||||||
|
table.insert(retval,last_line)
|
||||||
|
last_line = ""
|
||||||
|
gotnewline = false
|
||||||
|
end
|
||||||
|
current_idx = stop+1
|
||||||
|
|
||||||
|
start,stop = string.find(text," ",current_idx)
|
||||||
|
nl_start,nl_stop = string.find(text,"\n",current_idx)
|
||||||
|
|
||||||
|
if nl_start ~= nil and (start == nil or nl_start < start) then
|
||||||
|
start = nl_start
|
||||||
|
stop = nl_stop
|
||||||
|
gotnewline = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--add last part of text
|
||||||
|
if string.len(last_line) + (string.len(text) - current_idx) > charlimit then
|
||||||
|
table.insert(retval,last_line)
|
||||||
|
table.insert(retval,string.sub(text,current_idx))
|
||||||
|
else
|
||||||
|
last_line = last_line .. " " .. string.sub(text,current_idx)
|
||||||
|
table.insert(retval,last_line)
|
||||||
|
end
|
||||||
|
|
||||||
|
return retval
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if minetest then
|
||||||
|
local dirs1 = { 9, 18, 7, 12 }
|
||||||
|
local dirs2 = { 20, 23, 22, 21 }
|
||||||
|
|
||||||
|
function minetest.rotate_and_place(itemstack, placer, pointed_thing, infinitestacks, orient_flags)
|
||||||
|
orient_flags = orient_flags or {}
|
||||||
|
|
||||||
|
local node = minetest.get_node(pointed_thing.under)
|
||||||
|
if not minetest.registered_nodes[node.name]
|
||||||
|
or not minetest.registered_nodes[node.name].on_rightclick then
|
||||||
|
|
||||||
|
local above = pointed_thing.above
|
||||||
|
local under = pointed_thing.under
|
||||||
|
local pitch = placer:get_look_pitch()
|
||||||
|
local pname = minetest.get_node(under).name
|
||||||
|
local node = minetest.get_node(above)
|
||||||
|
local fdir = minetest.dir_to_facedir(placer:get_look_dir())
|
||||||
|
local wield_name = itemstack:get_name()
|
||||||
|
local reg_node = minetest.registered_nodes[pname]
|
||||||
|
|
||||||
|
if not reg_node or not reg_node.on_rightclick then
|
||||||
|
|
||||||
|
local iswall = (above.x ~= under.x) or (above.z ~= under.z)
|
||||||
|
local isceiling = (above.x == under.x) and (above.z == under.z)
|
||||||
|
and (pitch > 0)
|
||||||
|
local pos1 = above
|
||||||
|
|
||||||
|
if reg_node and reg_node.buildable_to then
|
||||||
|
pos1 = under
|
||||||
|
iswall = false
|
||||||
|
end
|
||||||
|
|
||||||
|
reg_node = minetest.registered_nodes[minetest.get_node(pos1).name]
|
||||||
|
if not reg_node or not reg_node.buildable_to then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if orient_flags.force_floor then
|
||||||
|
iswall = false
|
||||||
|
isceiling = false
|
||||||
|
elseif orient_flags.force_ceiling then
|
||||||
|
iswall = false
|
||||||
|
isceiling = true
|
||||||
|
elseif orient_flags.force_wall then
|
||||||
|
iswall = true
|
||||||
|
isceiling = false
|
||||||
|
elseif orient_flags.invert_wall then
|
||||||
|
iswall = not iswall
|
||||||
|
end
|
||||||
|
|
||||||
|
if iswall then
|
||||||
|
minetest.add_node(pos1, {name = wield_name, param2 = dirs1[fdir+1] })
|
||||||
|
elseif isceiling then
|
||||||
|
if orient_flags.force_facedir then
|
||||||
|
minetest.add_node(pos1, {name = wield_name, param2 = 20 })
|
||||||
|
else
|
||||||
|
minetest.add_node(pos1, {name = wield_name, param2 = dirs2[fdir+1] })
|
||||||
|
end
|
||||||
|
else -- place right side up
|
||||||
|
if orient_flags.force_facedir then
|
||||||
|
minetest.add_node(pos1, {name = wield_name, param2 = 0 })
|
||||||
|
else
|
||||||
|
minetest.add_node(pos1, {name = wield_name, param2 = fdir })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not infinitestacks then
|
||||||
|
itemstack:take_item()
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
--Wrapper for rotate_and_place() to check for sneak and assume Creative mode
|
||||||
|
--implies infinite stacks when performing a 6d rotation.
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
minetest.rotate_node = function(itemstack, placer, pointed_thing)
|
||||||
|
minetest.rotate_and_place(itemstack, placer, pointed_thing,
|
||||||
|
minetest.setting_getbool("creative_mode"),
|
||||||
|
{invert_wall = placer:get_player_control().sneak})
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- mainmenu only functions
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
if engine ~= nil then
|
||||||
|
engine.get_game = function(index)
|
||||||
|
local games = game.get_games()
|
||||||
|
|
||||||
|
if index > 0 and index <= #games then
|
||||||
|
return games[index]
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function fgettext(text, ...)
|
||||||
|
text = engine.gettext(text)
|
||||||
|
local arg = {n=select('#', ...), ...}
|
||||||
|
if arg.n >= 1 then
|
||||||
|
-- Insert positional parameters ($1, $2, ...)
|
||||||
|
result = ''
|
||||||
|
pos = 1
|
||||||
|
while pos <= text:len() do
|
||||||
|
newpos = text:find('[$]', pos)
|
||||||
|
if newpos == nil then
|
||||||
|
result = result .. text:sub(pos)
|
||||||
|
pos = text:len() + 1
|
||||||
|
else
|
||||||
|
paramindex = tonumber(text:sub(newpos+1, newpos+1))
|
||||||
|
result = result .. text:sub(pos, newpos-1) .. tostring(arg[paramindex])
|
||||||
|
pos = newpos + 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
text = result
|
||||||
|
end
|
||||||
|
return engine.formspec_escape(text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- core only fct
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
if minetest ~= nil then
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function minetest.pos_to_string(pos)
|
||||||
|
return "(" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ")"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
391
builtin/misc_register.lua
Normal file
@@ -0,0 +1,391 @@
|
|||||||
|
-- Minetest: builtin/misc_register.lua
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Make raw registration functions inaccessible to anyone except this file
|
||||||
|
--
|
||||||
|
|
||||||
|
local register_item_raw = minetest.register_item_raw
|
||||||
|
minetest.register_item_raw = nil
|
||||||
|
|
||||||
|
local register_alias_raw = minetest.register_alias_raw
|
||||||
|
minetest.register_item_raw = nil
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Item / entity / ABM registration functions
|
||||||
|
--
|
||||||
|
|
||||||
|
minetest.registered_abms = {}
|
||||||
|
minetest.registered_entities = {}
|
||||||
|
minetest.registered_items = {}
|
||||||
|
minetest.registered_nodes = {}
|
||||||
|
minetest.registered_craftitems = {}
|
||||||
|
minetest.registered_tools = {}
|
||||||
|
minetest.registered_aliases = {}
|
||||||
|
|
||||||
|
-- For tables that are indexed by item name:
|
||||||
|
-- If table[X] does not exist, default to table[minetest.registered_aliases[X]]
|
||||||
|
local alias_metatable = {
|
||||||
|
__index = function(t, name)
|
||||||
|
return rawget(t, minetest.registered_aliases[name])
|
||||||
|
end
|
||||||
|
}
|
||||||
|
setmetatable(minetest.registered_items, alias_metatable)
|
||||||
|
setmetatable(minetest.registered_nodes, alias_metatable)
|
||||||
|
setmetatable(minetest.registered_craftitems, alias_metatable)
|
||||||
|
setmetatable(minetest.registered_tools, alias_metatable)
|
||||||
|
|
||||||
|
-- These item names may not be used because they would interfere
|
||||||
|
-- with legacy itemstrings
|
||||||
|
local forbidden_item_names = {
|
||||||
|
MaterialItem = true,
|
||||||
|
MaterialItem2 = true,
|
||||||
|
MaterialItem3 = true,
|
||||||
|
NodeItem = true,
|
||||||
|
node = true,
|
||||||
|
CraftItem = true,
|
||||||
|
craft = true,
|
||||||
|
MBOItem = true,
|
||||||
|
ToolItem = true,
|
||||||
|
tool = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
local function check_modname_prefix(name)
|
||||||
|
if name:sub(1,1) == ":" then
|
||||||
|
-- Escape the modname prefix enforcement mechanism
|
||||||
|
return name:sub(2)
|
||||||
|
else
|
||||||
|
-- Modname prefix enforcement
|
||||||
|
local expected_prefix = minetest.get_current_modname() .. ":"
|
||||||
|
if name:sub(1, #expected_prefix) ~= expected_prefix then
|
||||||
|
error("Name " .. name .. " does not follow naming conventions: " ..
|
||||||
|
"\"modname:\" or \":\" prefix required")
|
||||||
|
end
|
||||||
|
local subname = name:sub(#expected_prefix+1)
|
||||||
|
if subname:find("[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]") then
|
||||||
|
error("Name " .. name .. " does not follow naming conventions: " ..
|
||||||
|
"contains unallowed characters")
|
||||||
|
end
|
||||||
|
return name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.register_abm(spec)
|
||||||
|
-- Add to minetest.registered_abms
|
||||||
|
minetest.registered_abms[#minetest.registered_abms+1] = spec
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.register_entity(name, prototype)
|
||||||
|
-- Check name
|
||||||
|
if name == nil then
|
||||||
|
error("Unable to register entity: Name is nil")
|
||||||
|
end
|
||||||
|
name = check_modname_prefix(tostring(name))
|
||||||
|
|
||||||
|
prototype.name = name
|
||||||
|
prototype.__index = prototype -- so that it can be used as a metatable
|
||||||
|
|
||||||
|
-- Add to minetest.registered_entities
|
||||||
|
minetest.registered_entities[name] = prototype
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.register_item(name, itemdef)
|
||||||
|
-- Check name
|
||||||
|
if name == nil then
|
||||||
|
error("Unable to register item: Name is nil")
|
||||||
|
end
|
||||||
|
name = check_modname_prefix(tostring(name))
|
||||||
|
if forbidden_item_names[name] then
|
||||||
|
error("Unable to register item: Name is forbidden: " .. name)
|
||||||
|
end
|
||||||
|
itemdef.name = name
|
||||||
|
|
||||||
|
-- Apply defaults and add to registered_* table
|
||||||
|
if itemdef.type == "node" then
|
||||||
|
-- Use the nodebox as selection box if it's not set manually
|
||||||
|
if itemdef.drawtype == "nodebox" and not itemdef.selection_box then
|
||||||
|
itemdef.selection_box = itemdef.node_box
|
||||||
|
elseif itemdef.drawtype == "fencelike" and not itemdef.selection_box then
|
||||||
|
itemdef.selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {-1/8, -1/2, -1/8, 1/8, 1/2, 1/8},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
setmetatable(itemdef, {__index = minetest.nodedef_default})
|
||||||
|
minetest.registered_nodes[itemdef.name] = itemdef
|
||||||
|
elseif itemdef.type == "craft" then
|
||||||
|
setmetatable(itemdef, {__index = minetest.craftitemdef_default})
|
||||||
|
minetest.registered_craftitems[itemdef.name] = itemdef
|
||||||
|
elseif itemdef.type == "tool" then
|
||||||
|
setmetatable(itemdef, {__index = minetest.tooldef_default})
|
||||||
|
minetest.registered_tools[itemdef.name] = itemdef
|
||||||
|
elseif itemdef.type == "none" then
|
||||||
|
setmetatable(itemdef, {__index = minetest.noneitemdef_default})
|
||||||
|
else
|
||||||
|
error("Unable to register item: Type is invalid: " .. dump(itemdef))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Flowing liquid uses param2
|
||||||
|
if itemdef.type == "node" and itemdef.liquidtype == "flowing" then
|
||||||
|
itemdef.paramtype2 = "flowingliquid"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- BEGIN Legacy stuff
|
||||||
|
if itemdef.cookresult_itemstring ~= nil and itemdef.cookresult_itemstring ~= "" then
|
||||||
|
minetest.register_craft({
|
||||||
|
type="cooking",
|
||||||
|
output=itemdef.cookresult_itemstring,
|
||||||
|
recipe=itemdef.name,
|
||||||
|
cooktime=itemdef.furnace_cooktime
|
||||||
|
})
|
||||||
|
end
|
||||||
|
if itemdef.furnace_burntime ~= nil and itemdef.furnace_burntime >= 0 then
|
||||||
|
minetest.register_craft({
|
||||||
|
type="fuel",
|
||||||
|
recipe=itemdef.name,
|
||||||
|
burntime=itemdef.furnace_burntime
|
||||||
|
})
|
||||||
|
end
|
||||||
|
-- END Legacy stuff
|
||||||
|
|
||||||
|
-- Disable all further modifications
|
||||||
|
getmetatable(itemdef).__newindex = {}
|
||||||
|
|
||||||
|
--minetest.log("Registering item: " .. itemdef.name)
|
||||||
|
minetest.registered_items[itemdef.name] = itemdef
|
||||||
|
minetest.registered_aliases[itemdef.name] = nil
|
||||||
|
register_item_raw(itemdef)
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.register_node(name, nodedef)
|
||||||
|
nodedef.type = "node"
|
||||||
|
minetest.register_item(name, nodedef)
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.register_craftitem(name, craftitemdef)
|
||||||
|
craftitemdef.type = "craft"
|
||||||
|
|
||||||
|
-- BEGIN Legacy stuff
|
||||||
|
if craftitemdef.inventory_image == nil and craftitemdef.image ~= nil then
|
||||||
|
craftitemdef.inventory_image = craftitemdef.image
|
||||||
|
end
|
||||||
|
-- END Legacy stuff
|
||||||
|
|
||||||
|
minetest.register_item(name, craftitemdef)
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.register_tool(name, tooldef)
|
||||||
|
tooldef.type = "tool"
|
||||||
|
tooldef.stack_max = 1
|
||||||
|
|
||||||
|
-- BEGIN Legacy stuff
|
||||||
|
if tooldef.inventory_image == nil and tooldef.image ~= nil then
|
||||||
|
tooldef.inventory_image = tooldef.image
|
||||||
|
end
|
||||||
|
if tooldef.tool_capabilities == nil and
|
||||||
|
(tooldef.full_punch_interval ~= nil or
|
||||||
|
tooldef.basetime ~= nil or
|
||||||
|
tooldef.dt_weight ~= nil or
|
||||||
|
tooldef.dt_crackiness ~= nil or
|
||||||
|
tooldef.dt_crumbliness ~= nil or
|
||||||
|
tooldef.dt_cuttability ~= nil or
|
||||||
|
tooldef.basedurability ~= nil or
|
||||||
|
tooldef.dd_weight ~= nil or
|
||||||
|
tooldef.dd_crackiness ~= nil or
|
||||||
|
tooldef.dd_crumbliness ~= nil or
|
||||||
|
tooldef.dd_cuttability ~= nil) then
|
||||||
|
tooldef.tool_capabilities = {
|
||||||
|
full_punch_interval = tooldef.full_punch_interval,
|
||||||
|
basetime = tooldef.basetime,
|
||||||
|
dt_weight = tooldef.dt_weight,
|
||||||
|
dt_crackiness = tooldef.dt_crackiness,
|
||||||
|
dt_crumbliness = tooldef.dt_crumbliness,
|
||||||
|
dt_cuttability = tooldef.dt_cuttability,
|
||||||
|
basedurability = tooldef.basedurability,
|
||||||
|
dd_weight = tooldef.dd_weight,
|
||||||
|
dd_crackiness = tooldef.dd_crackiness,
|
||||||
|
dd_crumbliness = tooldef.dd_crumbliness,
|
||||||
|
dd_cuttability = tooldef.dd_cuttability,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
-- END Legacy stuff
|
||||||
|
|
||||||
|
minetest.register_item(name, tooldef)
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.register_alias(name, convert_to)
|
||||||
|
if forbidden_item_names[name] then
|
||||||
|
error("Unable to register alias: Name is forbidden: " .. name)
|
||||||
|
end
|
||||||
|
if minetest.registered_items[name] ~= nil then
|
||||||
|
minetest.log("WARNING: Not registering alias, item with same name" ..
|
||||||
|
" is already defined: " .. name .. " -> " .. convert_to)
|
||||||
|
else
|
||||||
|
--minetest.log("Registering alias: " .. name .. " -> " .. convert_to)
|
||||||
|
minetest.registered_aliases[name] = convert_to
|
||||||
|
register_alias_raw(name, convert_to)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local register_biome_raw = minetest.register_biome
|
||||||
|
minetest.registered_biomes = {}
|
||||||
|
function minetest.register_biome(biome)
|
||||||
|
minetest.registered_biomes[biome.name] = biome
|
||||||
|
register_biome_raw(biome)
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.on_craft(itemstack, player, old_craft_list, craft_inv)
|
||||||
|
for _, func in ipairs(minetest.registered_on_crafts) do
|
||||||
|
itemstack = func(itemstack, player, old_craft_list, craft_inv) or itemstack
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.craft_predict(itemstack, player, old_craft_list, craft_inv)
|
||||||
|
for _, func in ipairs(minetest.registered_craft_predicts) do
|
||||||
|
itemstack = func(itemstack, player, old_craft_list, craft_inv) or itemstack
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Alias the forbidden item names to "" so they can't be
|
||||||
|
-- created via itemstrings (e.g. /give)
|
||||||
|
local name
|
||||||
|
for name in pairs(forbidden_item_names) do
|
||||||
|
minetest.registered_aliases[name] = ""
|
||||||
|
register_alias_raw(name, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Deprecated:
|
||||||
|
-- Aliases for minetest.register_alias (how ironic...)
|
||||||
|
--minetest.alias_node = minetest.register_alias
|
||||||
|
--minetest.alias_tool = minetest.register_alias
|
||||||
|
--minetest.alias_craftitem = minetest.register_alias
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Built-in node definitions. Also defined in C.
|
||||||
|
--
|
||||||
|
|
||||||
|
minetest.register_item(":unknown", {
|
||||||
|
type = "none",
|
||||||
|
description = "Unknown Item",
|
||||||
|
inventory_image = "unknown_item.png",
|
||||||
|
on_place = minetest.item_place,
|
||||||
|
on_drop = minetest.item_drop,
|
||||||
|
groups = {not_in_creative_inventory=1},
|
||||||
|
diggable = true,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node(":air", {
|
||||||
|
description = "Air (you hacker you!)",
|
||||||
|
inventory_image = "unknown_node.png",
|
||||||
|
wield_image = "unknown_node.png",
|
||||||
|
drawtype = "airlike",
|
||||||
|
paramtype = "light",
|
||||||
|
sunlight_propagates = true,
|
||||||
|
walkable = false,
|
||||||
|
pointable = false,
|
||||||
|
diggable = false,
|
||||||
|
buildable_to = true,
|
||||||
|
air_equivalent = true,
|
||||||
|
drop = "",
|
||||||
|
groups = {not_in_creative_inventory=1},
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node(":ignore", {
|
||||||
|
description = "Ignore (you hacker you!)",
|
||||||
|
inventory_image = "unknown_node.png",
|
||||||
|
wield_image = "unknown_node.png",
|
||||||
|
drawtype = "airlike",
|
||||||
|
paramtype = "none",
|
||||||
|
sunlight_propagates = false,
|
||||||
|
walkable = false,
|
||||||
|
pointable = false,
|
||||||
|
diggable = false,
|
||||||
|
buildable_to = true, -- A way to remove accidentally placed ignores
|
||||||
|
air_equivalent = true,
|
||||||
|
drop = "",
|
||||||
|
groups = {not_in_creative_inventory=1},
|
||||||
|
})
|
||||||
|
|
||||||
|
-- The hand (bare definition)
|
||||||
|
minetest.register_item(":", {
|
||||||
|
type = "none",
|
||||||
|
groups = {not_in_creative_inventory=1},
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
function minetest.run_callbacks(callbacks, mode, ...)
|
||||||
|
assert(type(callbacks) == "table")
|
||||||
|
local cb_len = #callbacks
|
||||||
|
if cb_len == 0 then
|
||||||
|
if mode == 2 or mode == 3 then
|
||||||
|
return true
|
||||||
|
elseif mode == 4 or mode == 5 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local ret = nil
|
||||||
|
for i = 1, cb_len do
|
||||||
|
local cb_ret = callbacks[i](...)
|
||||||
|
|
||||||
|
if mode == 0 and i == 1 then
|
||||||
|
ret = cb_ret
|
||||||
|
elseif mode == 1 and i == cb_len then
|
||||||
|
ret = cb_ret
|
||||||
|
elseif mode == 2 then
|
||||||
|
if not cb_ret or i == 1 then
|
||||||
|
ret = cb_ret
|
||||||
|
end
|
||||||
|
elseif mode == 3 then
|
||||||
|
if cb_ret then
|
||||||
|
return cb_ret
|
||||||
|
end
|
||||||
|
ret = cb_ret
|
||||||
|
elseif mode == 4 then
|
||||||
|
if (cb_ret and not ret) or i == 1 then
|
||||||
|
ret = cb_ret
|
||||||
|
end
|
||||||
|
elseif mode == 5 and cb_ret then
|
||||||
|
return cb_ret
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Callback registration
|
||||||
|
--
|
||||||
|
|
||||||
|
local function make_registration()
|
||||||
|
local t = {}
|
||||||
|
local registerfunc = function(func) table.insert(t, func) end
|
||||||
|
return t, registerfunc
|
||||||
|
end
|
||||||
|
|
||||||
|
local function make_registration_reverse()
|
||||||
|
local t = {}
|
||||||
|
local registerfunc = function(func) table.insert(t, 1, func) end
|
||||||
|
return t, registerfunc
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.registered_on_chat_messages, minetest.register_on_chat_message = make_registration()
|
||||||
|
minetest.registered_globalsteps, minetest.register_globalstep = make_registration()
|
||||||
|
minetest.registered_on_mapgen_inits, minetest.register_on_mapgen_init = make_registration()
|
||||||
|
minetest.registered_on_shutdown, minetest.register_on_shutdown = make_registration()
|
||||||
|
minetest.registered_on_punchnodes, minetest.register_on_punchnode = make_registration()
|
||||||
|
minetest.registered_on_placenodes, minetest.register_on_placenode = make_registration()
|
||||||
|
minetest.registered_on_dignodes, minetest.register_on_dignode = make_registration()
|
||||||
|
minetest.registered_on_generateds, minetest.register_on_generated = make_registration()
|
||||||
|
minetest.registered_on_newplayers, minetest.register_on_newplayer = make_registration()
|
||||||
|
minetest.registered_on_dieplayers, minetest.register_on_dieplayer = make_registration()
|
||||||
|
minetest.registered_on_respawnplayers, minetest.register_on_respawnplayer = make_registration()
|
||||||
|
minetest.registered_on_prejoinplayers, minetest.register_on_prejoinplayer = make_registration()
|
||||||
|
minetest.registered_on_joinplayers, minetest.register_on_joinplayer = make_registration()
|
||||||
|
minetest.registered_on_leaveplayers, minetest.register_on_leaveplayer = make_registration()
|
||||||
|
minetest.registered_on_player_receive_fields, minetest.register_on_player_receive_fields = make_registration_reverse()
|
||||||
|
minetest.registered_on_cheats, minetest.register_on_cheat = make_registration()
|
||||||
|
minetest.registered_on_crafts, minetest.register_on_craft = make_registration()
|
||||||
|
minetest.registered_craft_predicts, minetest.register_craft_predict = make_registration()
|
||||||
|
minetest.registered_on_protection_violation, minetest.register_on_protection_violation = make_registration()
|
||||||
|
|
||||||
80
builtin/mm_menubar.lua
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
--Minetest
|
||||||
|
--Copyright (C) 2013 sapier
|
||||||
|
--
|
||||||
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
--it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
--the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
--(at your option) any later version.
|
||||||
|
--
|
||||||
|
--This program is distributed in the hope that it will be useful,
|
||||||
|
--but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
--GNU Lesser General Public License for more details.
|
||||||
|
--
|
||||||
|
--You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
--with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
menubar = {}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function menubar.handle_buttons(fields)
|
||||||
|
for i=1,#menubar.buttons,1 do
|
||||||
|
if fields[menubar.buttons[i].btn_name] ~= nil then
|
||||||
|
menu.last_game = menubar.buttons[i].index
|
||||||
|
engine.setting_set("main_menu_last_game_idx",menu.last_game)
|
||||||
|
menu.update_gametype()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function menubar.refresh()
|
||||||
|
|
||||||
|
menubar.formspec = "box[-0.3,5.625;12.4,1.2;#000000]" ..
|
||||||
|
"box[-0.3,5.6;12.4,0.05;#FFFFFF]"
|
||||||
|
menubar.buttons = {}
|
||||||
|
|
||||||
|
local button_base = -0.08
|
||||||
|
|
||||||
|
local maxbuttons = #gamemgr.games
|
||||||
|
|
||||||
|
if maxbuttons > 11 then
|
||||||
|
maxbuttons = 11
|
||||||
|
end
|
||||||
|
|
||||||
|
for i=1,maxbuttons,1 do
|
||||||
|
|
||||||
|
local btn_name = "menubar_btn_" .. gamemgr.games[i].id
|
||||||
|
local buttonpos = button_base + (i-1) * 1.1
|
||||||
|
if gamemgr.games[i].menuicon_path ~= nil and
|
||||||
|
gamemgr.games[i].menuicon_path ~= "" then
|
||||||
|
|
||||||
|
menubar.formspec = menubar.formspec ..
|
||||||
|
"image_button[" .. buttonpos .. ",5.72;1.165,1.175;" ..
|
||||||
|
engine.formspec_escape(gamemgr.games[i].menuicon_path) .. ";" ..
|
||||||
|
btn_name .. ";;true;false]"
|
||||||
|
else
|
||||||
|
|
||||||
|
local part1 = gamemgr.games[i].id:sub(1,5)
|
||||||
|
local part2 = gamemgr.games[i].id:sub(6,10)
|
||||||
|
local part3 = gamemgr.games[i].id:sub(11)
|
||||||
|
|
||||||
|
local text = part1 .. "\n" .. part2
|
||||||
|
if part3 ~= nil and
|
||||||
|
part3 ~= "" then
|
||||||
|
text = text .. "\n" .. part3
|
||||||
|
end
|
||||||
|
menubar.formspec = menubar.formspec ..
|
||||||
|
"image_button[" .. buttonpos .. ",5.72;1.165,1.175;;" ..btn_name ..
|
||||||
|
";" .. text .. ";true;true]"
|
||||||
|
end
|
||||||
|
|
||||||
|
local toadd = {
|
||||||
|
btn_name = btn_name,
|
||||||
|
index = i,
|
||||||
|
}
|
||||||
|
|
||||||
|
table.insert(menubar.buttons,toadd)
|
||||||
|
end
|
||||||
|
end
|
||||||
146
builtin/mm_textures.lua
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
--Minetest
|
||||||
|
--Copyright (C) 2013 sapier
|
||||||
|
--
|
||||||
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
--it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
--the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
--(at your option) any later version.
|
||||||
|
--
|
||||||
|
--This program is distributed in the hope that it will be useful,
|
||||||
|
--but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
--GNU Lesser General Public License for more details.
|
||||||
|
--
|
||||||
|
--You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
--with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
|
||||||
|
mm_texture = {}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function mm_texture.init()
|
||||||
|
mm_texture.defaulttexturedir = engine.get_texturepath() .. DIR_DELIM .. "base" ..
|
||||||
|
DIR_DELIM .. "pack" .. DIR_DELIM
|
||||||
|
mm_texture.basetexturedir = mm_texture.defaulttexturedir
|
||||||
|
|
||||||
|
mm_texture.texturepack = engine.setting_get("texture_path")
|
||||||
|
|
||||||
|
mm_texture.gameid = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function mm_texture.update(tab,gamedetails)
|
||||||
|
if tab ~= "singleplayer" then
|
||||||
|
mm_texture.reset()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if gamedetails == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
mm_texture.update_game(gamedetails)
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function mm_texture.reset()
|
||||||
|
mm_texture.gameid = nil
|
||||||
|
local have_bg = false
|
||||||
|
local have_overlay = mm_texture.set_generic("overlay")
|
||||||
|
|
||||||
|
if not have_overlay then
|
||||||
|
have_bg = mm_texture.set_generic("background")
|
||||||
|
end
|
||||||
|
|
||||||
|
mm_texture.clear("header")
|
||||||
|
mm_texture.clear("footer")
|
||||||
|
engine.set_clouds(false)
|
||||||
|
|
||||||
|
mm_texture.set_generic("footer")
|
||||||
|
mm_texture.set_generic("header")
|
||||||
|
|
||||||
|
if not have_bg and
|
||||||
|
engine.setting_getbool("enable_clouds") then
|
||||||
|
engine.set_clouds(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function mm_texture.update_game(gamedetails)
|
||||||
|
if mm_texture.gameid == gamedetails.id then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local have_bg = false
|
||||||
|
local have_overlay = mm_texture.set_game("overlay",gamedetails)
|
||||||
|
|
||||||
|
if not have_overlay then
|
||||||
|
have_bg = mm_texture.set_game("background",gamedetails)
|
||||||
|
end
|
||||||
|
|
||||||
|
mm_texture.clear("header")
|
||||||
|
mm_texture.clear("footer")
|
||||||
|
engine.set_clouds(false)
|
||||||
|
|
||||||
|
if not have_bg and
|
||||||
|
engine.setting_getbool("enable_clouds") then
|
||||||
|
engine.set_clouds(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
mm_texture.set_game("footer",gamedetails)
|
||||||
|
mm_texture.set_game("header",gamedetails)
|
||||||
|
|
||||||
|
mm_texture.gameid = gamedetails.id
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function mm_texture.clear(identifier)
|
||||||
|
engine.set_background(identifier,"")
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function mm_texture.set_generic(identifier)
|
||||||
|
--try texture pack first
|
||||||
|
if mm_texture.texturepack ~= nil then
|
||||||
|
local path = mm_texture.texturepack .. DIR_DELIM .."menu_" ..
|
||||||
|
identifier .. ".png"
|
||||||
|
if engine.set_background(identifier,path) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if mm_texture.defaulttexturedir ~= nil then
|
||||||
|
local path = mm_texture.defaulttexturedir .. DIR_DELIM .."menu_" ..
|
||||||
|
identifier .. ".png"
|
||||||
|
if engine.set_background(identifier,path) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function mm_texture.set_game(identifier,gamedetails)
|
||||||
|
|
||||||
|
if gamedetails == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if mm_texture.texturepack ~= nil then
|
||||||
|
local path = mm_texture.texturepack .. DIR_DELIM ..
|
||||||
|
gamedetails.id .. "_menu_" .. identifier .. ".png"
|
||||||
|
if engine.set_background(identifier,path) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local path = gamedetails.path .. DIR_DELIM .."menu" ..
|
||||||
|
DIR_DELIM .. identifier .. ".png"
|
||||||
|
if engine.set_background(identifier,path) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
1130
builtin/modmgr.lua
Normal file
615
builtin/modstore.lua
Normal file
@@ -0,0 +1,615 @@
|
|||||||
|
--Minetest
|
||||||
|
--Copyright (C) 2013 sapier
|
||||||
|
--
|
||||||
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
--it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
--the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
--(at your option) any later version.
|
||||||
|
--
|
||||||
|
--This program is distributed in the hope that it will be useful,
|
||||||
|
--but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
--GNU Lesser General Public License for more details.
|
||||||
|
--
|
||||||
|
--You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
--with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--modstore implementation
|
||||||
|
modstore = {}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- @function [parent=#modstore] init
|
||||||
|
function modstore.init()
|
||||||
|
modstore.tabnames = {}
|
||||||
|
|
||||||
|
table.insert(modstore.tabnames,"dialog_modstore_unsorted")
|
||||||
|
table.insert(modstore.tabnames,"dialog_modstore_search")
|
||||||
|
|
||||||
|
modstore.modsperpage = 5
|
||||||
|
|
||||||
|
modstore.basetexturedir = engine.get_texturepath() .. DIR_DELIM .. "base" ..
|
||||||
|
DIR_DELIM .. "pack" .. DIR_DELIM
|
||||||
|
|
||||||
|
modstore.lastmodtitle = ""
|
||||||
|
modstore.last_search = ""
|
||||||
|
|
||||||
|
modstore.searchlist = filterlist.create(
|
||||||
|
function()
|
||||||
|
if modstore.modlist_unsorted ~= nil and
|
||||||
|
modstore.modlist_unsorted.data ~= nil then
|
||||||
|
return modstore.modlist_unsorted.data
|
||||||
|
end
|
||||||
|
return {}
|
||||||
|
end,
|
||||||
|
function(element,modid)
|
||||||
|
if element.id == modid then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end, --compare fct
|
||||||
|
nil, --uid match fct
|
||||||
|
function(element,substring)
|
||||||
|
if substring == nil or
|
||||||
|
substring == "" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
substring = substring:upper()
|
||||||
|
|
||||||
|
if element.title ~= nil and
|
||||||
|
element.title:upper():find(substring) ~= nil then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if element.details ~= nil and
|
||||||
|
element.details.author ~= nil and
|
||||||
|
element.details.author:upper():find(substring) ~= nil then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if element.details ~= nil and
|
||||||
|
element.details.description ~= nil and
|
||||||
|
element.details.description:upper():find(substring) ~= nil then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end --filter fct
|
||||||
|
)
|
||||||
|
|
||||||
|
modstore.current_list = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- @function [parent=#modstore] nametoindex
|
||||||
|
function modstore.nametoindex(name)
|
||||||
|
|
||||||
|
for i=1,#modstore.tabnames,1 do
|
||||||
|
if modstore.tabnames[i] == name then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- @function [parent=#modstore] getsuccessfuldialog
|
||||||
|
function modstore.getsuccessfuldialog()
|
||||||
|
local retval = ""
|
||||||
|
retval = retval .. "size[6,2]"
|
||||||
|
if modstore.lastmodentry ~= nil then
|
||||||
|
retval = retval .. "label[0,0.25;" .. fgettext("Successfully installed:") .. "]"
|
||||||
|
retval = retval .. "label[3,0.25;" .. modstore.lastmodentry.moddetails.title .. "]"
|
||||||
|
|
||||||
|
|
||||||
|
retval = retval .. "label[0,0.75;" .. fgettext("Shortname:") .. "]"
|
||||||
|
retval = retval .. "label[3,0.75;" .. engine.formspec_escape(modstore.lastmodentry.moddetails.basename) .. "]"
|
||||||
|
|
||||||
|
end
|
||||||
|
retval = retval .. "button[2.5,1.5;1,0.5;btn_confirm_mod_successfull;" .. fgettext("ok") .. "]"
|
||||||
|
|
||||||
|
|
||||||
|
return retval
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- @function [parent=#modstore] gettab
|
||||||
|
function modstore.gettab(tabname)
|
||||||
|
local retval = ""
|
||||||
|
|
||||||
|
local is_modstore_tab = false
|
||||||
|
|
||||||
|
if tabname == "dialog_modstore_unsorted" then
|
||||||
|
modstore.modsperpage = 5
|
||||||
|
retval = modstore.getmodlist(modstore.modlist_unsorted)
|
||||||
|
is_modstore_tab = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if tabname == "dialog_modstore_search" then
|
||||||
|
retval = modstore.getsearchpage()
|
||||||
|
is_modstore_tab = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if is_modstore_tab then
|
||||||
|
return modstore.tabheader(tabname) .. retval
|
||||||
|
end
|
||||||
|
|
||||||
|
if tabname == "modstore_mod_installed" then
|
||||||
|
return modstore.getsuccessfuldialog()
|
||||||
|
end
|
||||||
|
|
||||||
|
if tabname == "modstore_downloading" then
|
||||||
|
return "size[6,2]label[0.25,0.75;" .. fgettext("Downloading") ..
|
||||||
|
" " .. modstore.lastmodtitle .. " " ..
|
||||||
|
fgettext("please wait...") .. "]"
|
||||||
|
end
|
||||||
|
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- @function [parent=#modstore] tabheader
|
||||||
|
function modstore.tabheader(tabname)
|
||||||
|
local retval = "size[12,10.25]"
|
||||||
|
retval = retval .. "tabheader[-0.3,-0.99;modstore_tab;" ..
|
||||||
|
"Unsorted,Search;" ..
|
||||||
|
modstore.nametoindex(tabname) .. ";true;false]" ..
|
||||||
|
"button[4,9.9;4,0.5;btn_modstore_close;" ..
|
||||||
|
fgettext("Close modstore") .. "]"
|
||||||
|
|
||||||
|
return retval
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- @function [parent=#modstore] handle_buttons
|
||||||
|
function modstore.handle_buttons(current_tab,fields)
|
||||||
|
|
||||||
|
if fields["modstore_tab"] then
|
||||||
|
local index = tonumber(fields["modstore_tab"])
|
||||||
|
|
||||||
|
if index > 0 and
|
||||||
|
index <= #modstore.tabnames then
|
||||||
|
if modstore.tabnames[index] == "dialog_modstore_search" then
|
||||||
|
filterlist.set_filtercriteria(modstore.searchlist,modstore.last_search)
|
||||||
|
filterlist.refresh(modstore.searchlist)
|
||||||
|
modstore.modsperpage = 4
|
||||||
|
modstore.currentlist = {
|
||||||
|
page = 0,
|
||||||
|
pagecount =
|
||||||
|
math.ceil(filterlist.size(modstore.searchlist) / modstore.modsperpage),
|
||||||
|
data = filterlist.get_list(modstore.searchlist),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
current_tab = modstore.tabnames[index],
|
||||||
|
is_dialog = true,
|
||||||
|
show_buttons = false
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields["btn_modstore_page_up"] then
|
||||||
|
if modstore.current_list ~= nil and modstore.current_list.page > 0 then
|
||||||
|
modstore.current_list.page = modstore.current_list.page - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields["btn_modstore_page_down"] then
|
||||||
|
if modstore.current_list ~= nil and
|
||||||
|
modstore.current_list.page <modstore.current_list.pagecount-1 then
|
||||||
|
modstore.current_list.page = modstore.current_list.page +1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields["btn_hidden_close_download"] ~= nil then
|
||||||
|
if fields["btn_hidden_close_download"].successfull then
|
||||||
|
modstore.lastmodentry = fields["btn_hidden_close_download"]
|
||||||
|
return {
|
||||||
|
current_tab = "modstore_mod_installed",
|
||||||
|
is_dialog = true,
|
||||||
|
show_buttons = false
|
||||||
|
}
|
||||||
|
else
|
||||||
|
modstore.lastmodtitle = ""
|
||||||
|
return {
|
||||||
|
current_tab = modstore.tabnames[1],
|
||||||
|
is_dialog = true,
|
||||||
|
show_buttons = false
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields["btn_confirm_mod_successfull"] then
|
||||||
|
modstore.lastmodentry = nil
|
||||||
|
modstore.lastmodtitle = ""
|
||||||
|
return {
|
||||||
|
current_tab = modstore.tabnames[1],
|
||||||
|
is_dialog = true,
|
||||||
|
show_buttons = false
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields["btn_modstore_search"] or
|
||||||
|
(fields["key_enter"] and fields["te_modstore_search"] ~= nil) then
|
||||||
|
modstore.last_search = fields["te_modstore_search"]
|
||||||
|
filterlist.set_filtercriteria(modstore.searchlist,fields["te_modstore_search"])
|
||||||
|
filterlist.refresh(modstore.searchlist)
|
||||||
|
modstore.currentlist = {
|
||||||
|
page = 0,
|
||||||
|
pagecount = math.ceil(filterlist.size(modstore.searchlist) / modstore.modsperpage),
|
||||||
|
data = filterlist.get_list(modstore.searchlist),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if fields["btn_modstore_close"] then
|
||||||
|
return {
|
||||||
|
is_dialog = false,
|
||||||
|
show_buttons = true,
|
||||||
|
current_tab = engine.setting_get("main_menu_tab")
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
for key,value in pairs(fields) do
|
||||||
|
local foundat = key:find("btn_install_mod_")
|
||||||
|
if ( foundat == 1) then
|
||||||
|
local modid = tonumber(key:sub(17))
|
||||||
|
for i=1,#modstore.modlist_unsorted.data,1 do
|
||||||
|
if modstore.modlist_unsorted.data[i].id == modid then
|
||||||
|
local moddetails = modstore.modlist_unsorted.data[i].details
|
||||||
|
|
||||||
|
if modstore.lastmodtitle ~= "" then
|
||||||
|
modstore.lastmodtitle = modstore.lastmodtitle .. ", "
|
||||||
|
end
|
||||||
|
|
||||||
|
modstore.lastmodtitle = modstore.lastmodtitle .. moddetails.title
|
||||||
|
|
||||||
|
engine.handle_async(
|
||||||
|
function(param)
|
||||||
|
|
||||||
|
local fullurl = engine.setting_get("modstore_download_url") ..
|
||||||
|
param.moddetails.download_url
|
||||||
|
|
||||||
|
if param.version ~= nil then
|
||||||
|
local found = false
|
||||||
|
for i=1,#param.moddetails.versions, 1 do
|
||||||
|
if param.moddetails.versions[i].date:sub(1,10) == param.version then
|
||||||
|
fullurl = engine.setting_get("modstore_download_url") ..
|
||||||
|
param.moddetails.versions[i].download_url
|
||||||
|
found = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not found then
|
||||||
|
return {
|
||||||
|
moddetails = param.moddetails,
|
||||||
|
successfull = false
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if engine.download_file(fullurl,param.filename) then
|
||||||
|
return {
|
||||||
|
texturename = param.texturename,
|
||||||
|
moddetails = param.moddetails,
|
||||||
|
filename = param.filename,
|
||||||
|
successfull = true
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return {
|
||||||
|
modtitle = param.title,
|
||||||
|
successfull = false
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
{
|
||||||
|
moddetails = moddetails,
|
||||||
|
version = fields["dd_version" .. modid],
|
||||||
|
filename = os.tempfolder() .. "_MODNAME_" .. moddetails.basename .. ".zip",
|
||||||
|
texturename = modstore.modlist_unsorted.data[i].texturename
|
||||||
|
},
|
||||||
|
function(result)
|
||||||
|
if result.successfull then
|
||||||
|
modmgr.installmod(result.filename,result.moddetails.basename)
|
||||||
|
os.remove(result.filename)
|
||||||
|
else
|
||||||
|
gamedata.errormessage = "Failed to download " .. result.moddetails.title
|
||||||
|
end
|
||||||
|
|
||||||
|
if gamedata.errormessage == nil then
|
||||||
|
engine.button_handler({btn_hidden_close_download=result})
|
||||||
|
else
|
||||||
|
engine.button_handler({btn_hidden_close_download={successfull=false}})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
current_tab = "modstore_downloading",
|
||||||
|
is_dialog = true,
|
||||||
|
show_buttons = false,
|
||||||
|
ignore_menu_quit = true
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- @function [parent=#modstore] update_modlist
|
||||||
|
function modstore.update_modlist()
|
||||||
|
modstore.modlist_unsorted = {}
|
||||||
|
modstore.modlist_unsorted.data = {}
|
||||||
|
modstore.modlist_unsorted.pagecount = 1
|
||||||
|
modstore.modlist_unsorted.page = 0
|
||||||
|
|
||||||
|
engine.handle_async(
|
||||||
|
function(param)
|
||||||
|
return engine.get_modstore_list()
|
||||||
|
end,
|
||||||
|
nil,
|
||||||
|
function(result)
|
||||||
|
if result ~= nil then
|
||||||
|
modstore.modlist_unsorted = {}
|
||||||
|
modstore.modlist_unsorted.data = result
|
||||||
|
|
||||||
|
if modstore.modlist_unsorted.data ~= nil then
|
||||||
|
modstore.modlist_unsorted.pagecount =
|
||||||
|
math.ceil((#modstore.modlist_unsorted.data / modstore.modsperpage))
|
||||||
|
else
|
||||||
|
modstore.modlist_unsorted.data = {}
|
||||||
|
modstore.modlist_unsorted.pagecount = 1
|
||||||
|
end
|
||||||
|
modstore.modlist_unsorted.page = 0
|
||||||
|
modstore.fetchdetails()
|
||||||
|
engine.event_handler("Refresh")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- @function [parent=#modstore] fetchdetails
|
||||||
|
function modstore.fetchdetails()
|
||||||
|
|
||||||
|
for i=1,#modstore.modlist_unsorted.data,1 do
|
||||||
|
engine.handle_async(
|
||||||
|
function(param)
|
||||||
|
param.details = engine.get_modstore_details(tostring(param.modid))
|
||||||
|
return param
|
||||||
|
end,
|
||||||
|
{
|
||||||
|
modid=modstore.modlist_unsorted.data[i].id,
|
||||||
|
listindex=i
|
||||||
|
},
|
||||||
|
function(result)
|
||||||
|
if result ~= nil and
|
||||||
|
modstore.modlist_unsorted ~= nil
|
||||||
|
and modstore.modlist_unsorted.data ~= nil and
|
||||||
|
modstore.modlist_unsorted.data[result.listindex] ~= nil and
|
||||||
|
modstore.modlist_unsorted.data[result.listindex].id ~= nil then
|
||||||
|
|
||||||
|
modstore.modlist_unsorted.data[result.listindex].details = result.details
|
||||||
|
engine.event_handler("Refresh")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- @function [parent=#modstore] getscreenshot
|
||||||
|
function modstore.getscreenshot(ypos,listentry)
|
||||||
|
|
||||||
|
if listentry.details ~= nil and
|
||||||
|
(listentry.details.screenshot_url == nil or
|
||||||
|
listentry.details.screenshot_url == "") then
|
||||||
|
|
||||||
|
if listentry.texturename == nil then
|
||||||
|
listentry.texturename = modstore.basetexturedir .. "no_screenshot.png"
|
||||||
|
end
|
||||||
|
|
||||||
|
return "image[0,".. ypos .. ";3,2;" ..
|
||||||
|
engine.formspec_escape(listentry.texturename) .. "]"
|
||||||
|
end
|
||||||
|
|
||||||
|
if listentry.details ~= nil and
|
||||||
|
listentry.texturename == nil then
|
||||||
|
--make sure we don't download multiple times
|
||||||
|
listentry.texturename = "in progress"
|
||||||
|
|
||||||
|
--prepare url and filename
|
||||||
|
local fullurl = engine.setting_get("modstore_download_url") ..
|
||||||
|
listentry.details.screenshot_url
|
||||||
|
local filename = os.tempfolder() .. "_MID_" .. listentry.id
|
||||||
|
|
||||||
|
--trigger download
|
||||||
|
engine.handle_async(
|
||||||
|
--first param is downloadfct
|
||||||
|
function(param)
|
||||||
|
param.successfull = engine.download_file(param.fullurl,param.filename)
|
||||||
|
return param
|
||||||
|
end,
|
||||||
|
--second parameter is data passed to async job
|
||||||
|
{
|
||||||
|
fullurl = fullurl,
|
||||||
|
filename = filename,
|
||||||
|
modid = listentry.id
|
||||||
|
},
|
||||||
|
--integrate result to raw list
|
||||||
|
function(result)
|
||||||
|
if result.successfull then
|
||||||
|
local found = false
|
||||||
|
for i=1,#modstore.modlist_unsorted.data,1 do
|
||||||
|
if modstore.modlist_unsorted.data[i].id == result.modid then
|
||||||
|
found = true
|
||||||
|
modstore.modlist_unsorted.data[i].texturename = result.filename
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if found then
|
||||||
|
engine.event_handler("Refresh")
|
||||||
|
else
|
||||||
|
engine.log("error","got screenshot but didn't find matching mod: " .. result.modid)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
if listentry.texturename ~= nil and
|
||||||
|
listentry.texturename ~= "in progress" then
|
||||||
|
return "image[0,".. ypos .. ";3,2;" ..
|
||||||
|
engine.formspec_escape(listentry.texturename) .. "]"
|
||||||
|
end
|
||||||
|
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
--@function [parent=#modstore] getshortmodinfo
|
||||||
|
function modstore.getshortmodinfo(ypos,listentry,details)
|
||||||
|
local retval = ""
|
||||||
|
|
||||||
|
retval = retval .. "box[0," .. ypos .. ";11.4,1.75;#FFFFFF]"
|
||||||
|
|
||||||
|
--screenshot
|
||||||
|
retval = retval .. modstore.getscreenshot(ypos,listentry)
|
||||||
|
|
||||||
|
--title + author
|
||||||
|
retval = retval .."label[2.75," .. ypos .. ";" ..
|
||||||
|
engine.formspec_escape(details.title) .. " (" .. details.author .. ")]"
|
||||||
|
|
||||||
|
--description
|
||||||
|
local descriptiony = ypos + 0.5
|
||||||
|
retval = retval .. "textarea[3," .. descriptiony .. ";6.5,1.55;;" ..
|
||||||
|
engine.formspec_escape(details.description) .. ";]"
|
||||||
|
|
||||||
|
--rating
|
||||||
|
local ratingy = ypos
|
||||||
|
retval = retval .."label[7," .. ratingy .. ";" ..
|
||||||
|
fgettext("Rating") .. ":]"
|
||||||
|
retval = retval .. "label[8.7," .. ratingy .. ";" .. details.rating .."]"
|
||||||
|
|
||||||
|
--versions (IMPORTANT has to be defined AFTER rating)
|
||||||
|
if details.versions ~= nil and
|
||||||
|
#details.versions > 1 then
|
||||||
|
local versiony = ypos + 0.05
|
||||||
|
retval = retval .. "dropdown[9.1," .. versiony .. ";2.48,0.25;dd_version" .. details.id .. ";"
|
||||||
|
local versions = ""
|
||||||
|
for i=1,#details.versions , 1 do
|
||||||
|
if versions ~= "" then
|
||||||
|
versions = versions .. ","
|
||||||
|
end
|
||||||
|
|
||||||
|
versions = versions .. details.versions[i].date:sub(1,10)
|
||||||
|
end
|
||||||
|
retval = retval .. versions .. ";1]"
|
||||||
|
end
|
||||||
|
|
||||||
|
if details.basename then
|
||||||
|
--install button
|
||||||
|
local buttony = ypos + 1.2
|
||||||
|
retval = retval .."button[9.1," .. buttony .. ";2.5,0.5;btn_install_mod_" .. details.id .. ";"
|
||||||
|
|
||||||
|
if modmgr.mod_exists(details.basename) then
|
||||||
|
retval = retval .. fgettext("re-Install") .."]"
|
||||||
|
else
|
||||||
|
retval = retval .. fgettext("Install") .."]"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return retval
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
--@function [parent=#modstore] getmodlist
|
||||||
|
function modstore.getmodlist(list,yoffset)
|
||||||
|
|
||||||
|
modstore.current_list = list
|
||||||
|
|
||||||
|
if #list.data == 0 then
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
|
||||||
|
if yoffset == nil then
|
||||||
|
yoffset = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local scrollbar = ""
|
||||||
|
scrollbar = scrollbar .. "label[0.1,9.5;"
|
||||||
|
.. fgettext("Page $1 of $2", list.page+1, list.pagecount) .. "]"
|
||||||
|
scrollbar = scrollbar .. "box[11.6," .. (yoffset + 0.35) .. ";0.28,"
|
||||||
|
.. (8.6 - yoffset) .. ";#000000]"
|
||||||
|
local scrollbarpos = (yoffset + 0.75) +
|
||||||
|
((7.7 -yoffset)/(list.pagecount-1)) * list.page
|
||||||
|
scrollbar = scrollbar .. "box[11.6," ..scrollbarpos .. ";0.28,0.5;#32CD32]"
|
||||||
|
scrollbar = scrollbar .. "button[11.6," .. (yoffset + (0.3))
|
||||||
|
.. ";0.5,0.5;btn_modstore_page_up;^]"
|
||||||
|
scrollbar = scrollbar .. "button[11.6," .. 9.0
|
||||||
|
.. ";0.5,0.5;btn_modstore_page_down;v]"
|
||||||
|
|
||||||
|
local retval = ""
|
||||||
|
|
||||||
|
local endmod = (list.page * modstore.modsperpage) + modstore.modsperpage
|
||||||
|
|
||||||
|
if (endmod > #list.data) then
|
||||||
|
endmod = #list.data
|
||||||
|
end
|
||||||
|
|
||||||
|
for i=(list.page * modstore.modsperpage) +1, endmod, 1 do
|
||||||
|
--getmoddetails
|
||||||
|
local details = list.data[i].details
|
||||||
|
|
||||||
|
if details == nil then
|
||||||
|
details = {}
|
||||||
|
details.title = list.data[i].title
|
||||||
|
details.author = ""
|
||||||
|
details.rating = -1
|
||||||
|
details.description = ""
|
||||||
|
end
|
||||||
|
|
||||||
|
if details ~= nil then
|
||||||
|
local screenshot_ypos =
|
||||||
|
yoffset +(i-1 - (list.page * modstore.modsperpage))*1.9 +0.2
|
||||||
|
|
||||||
|
retval = retval .. modstore.getshortmodinfo(screenshot_ypos,
|
||||||
|
list.data[i],
|
||||||
|
details)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return retval .. scrollbar
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
--@function [parent=#modstore] getsearchpage
|
||||||
|
function modstore.getsearchpage()
|
||||||
|
local retval = ""
|
||||||
|
local search = ""
|
||||||
|
|
||||||
|
if modstore.last_search ~= nil then
|
||||||
|
search = modstore.last_search
|
||||||
|
end
|
||||||
|
|
||||||
|
retval = retval ..
|
||||||
|
"button[9.5,0.2;2.5,0.5;btn_modstore_search;".. fgettext("Search") .. "]" ..
|
||||||
|
"field[0.5,0.5;9,0.5;te_modstore_search;;" .. search .. "]"
|
||||||
|
|
||||||
|
|
||||||
|
--show 4 mods only
|
||||||
|
modstore.modsperpage = 4
|
||||||
|
retval = retval ..
|
||||||
|
modstore.getmodlist(
|
||||||
|
modstore.currentlist,
|
||||||
|
1.75)
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
end
|
||||||
|
|
||||||
52
builtin/privileges.lua
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
-- Minetest: builtin/privileges.lua
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Privileges
|
||||||
|
--
|
||||||
|
|
||||||
|
minetest.registered_privileges = {}
|
||||||
|
|
||||||
|
function minetest.register_privilege(name, param)
|
||||||
|
local function fill_defaults(def)
|
||||||
|
if def.give_to_singleplayer == nil then
|
||||||
|
def.give_to_singleplayer = true
|
||||||
|
end
|
||||||
|
if def.description == nil then
|
||||||
|
def.description = "(no description)"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local def = {}
|
||||||
|
if type(param) == "table" then
|
||||||
|
def = param
|
||||||
|
else
|
||||||
|
def = {description = param}
|
||||||
|
end
|
||||||
|
fill_defaults(def)
|
||||||
|
minetest.registered_privileges[name] = def
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_privilege("interact", "Can interact with things and modify the world")
|
||||||
|
minetest.register_privilege("teleport", "Can use /teleport command")
|
||||||
|
minetest.register_privilege("bring", "Can teleport other players")
|
||||||
|
minetest.register_privilege("settime", "Can use /time")
|
||||||
|
minetest.register_privilege("privs", "Can modify privileges")
|
||||||
|
minetest.register_privilege("basic_privs", "Can modify 'shout' and 'interact' privileges")
|
||||||
|
minetest.register_privilege("server", "Can do server maintenance stuff")
|
||||||
|
minetest.register_privilege("shout", "Can speak in chat")
|
||||||
|
minetest.register_privilege("ban", "Can ban and unban players")
|
||||||
|
minetest.register_privilege("give", "Can use /give and /giveme")
|
||||||
|
minetest.register_privilege("password", "Can use /setpassword and /clearpassword")
|
||||||
|
minetest.register_privilege("fly", {
|
||||||
|
description = "Can fly using the free_move mode",
|
||||||
|
give_to_singleplayer = false,
|
||||||
|
})
|
||||||
|
minetest.register_privilege("fast", {
|
||||||
|
description = "Can walk fast using the fast_move mode",
|
||||||
|
give_to_singleplayer = false,
|
||||||
|
})
|
||||||
|
minetest.register_privilege("noclip", {
|
||||||
|
description = "Can fly through walls",
|
||||||
|
give_to_singleplayer = false,
|
||||||
|
})
|
||||||
|
minetest.register_privilege("rollback", "Can use the rollback functionality")
|
||||||
|
|
||||||
207
builtin/serialize.lua
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
-- Minetest: builtin/serialize.lua
|
||||||
|
|
||||||
|
-- https://github.com/fab13n/metalua/blob/no-dll/src/lib/serialize.lua
|
||||||
|
-- Copyright (c) 2006-2997 Fabien Fleutot <metalua@gmail.com>
|
||||||
|
-- License: MIT
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Serialize an object into a source code string. This string, when passed as
|
||||||
|
-- an argument to deserialize(), returns an object structurally identical
|
||||||
|
-- to the original one. The following are currently supported:
|
||||||
|
-- * strings, numbers, booleans, nil
|
||||||
|
-- * tables thereof. Tables can have shared part, but can't be recursive yet.
|
||||||
|
-- Caveat: metatables and environments aren't saved.
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local no_identity = { number=1, boolean=1, string=1, ['nil']=1 }
|
||||||
|
|
||||||
|
function minetest.serialize(x)
|
||||||
|
|
||||||
|
local gensym_max = 0 -- index of the gensym() symbol generator
|
||||||
|
local seen_once = { } -- element->true set of elements seen exactly once in the table
|
||||||
|
local multiple = { } -- element->varname set of elements seen more than once
|
||||||
|
local nested = { } -- transient, set of elements currently being traversed
|
||||||
|
local nest_points = { }
|
||||||
|
local nest_patches = { }
|
||||||
|
|
||||||
|
local function gensym()
|
||||||
|
gensym_max = gensym_max + 1 ; return gensym_max
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- nest_points are places where a table appears within itself, directly or not.
|
||||||
|
-- for instance, all of these chunks create nest points in table x:
|
||||||
|
-- "x = { }; x[x] = 1", "x = { }; x[1] = x", "x = { }; x[1] = { y = { x } }".
|
||||||
|
-- To handle those, two tables are created by mark_nest_point:
|
||||||
|
-- * nest_points [parent] associates all keys and values in table parent which
|
||||||
|
-- create a nest_point with boolean `true'
|
||||||
|
-- * nest_patches contain a list of { parent, key, value } tuples creating
|
||||||
|
-- a nest point. They're all dumped after all the other table operations
|
||||||
|
-- have been performed.
|
||||||
|
--
|
||||||
|
-- mark_nest_point (p, k, v) fills tables nest_points and nest_patches with
|
||||||
|
-- informations required to remember that key/value (k,v) create a nest point
|
||||||
|
-- in table parent. It also marks `parent' as occuring multiple times, since
|
||||||
|
-- several references to it will be required in order to patch the nest
|
||||||
|
-- points.
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local function mark_nest_point (parent, k, v)
|
||||||
|
local nk, nv = nested[k], nested[v]
|
||||||
|
assert (not nk or seen_once[k] or multiple[k])
|
||||||
|
assert (not nv or seen_once[v] or multiple[v])
|
||||||
|
local mode = (nk and nv and "kv") or (nk and "k") or ("v")
|
||||||
|
local parent_np = nest_points [parent]
|
||||||
|
local pair = { k, v }
|
||||||
|
if not parent_np then parent_np = { }; nest_points [parent] = parent_np end
|
||||||
|
parent_np [k], parent_np [v] = nk, nv
|
||||||
|
table.insert (nest_patches, { parent, k, v })
|
||||||
|
seen_once [parent], multiple [parent] = nil, true
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- First pass, list the tables and functions which appear more than once in x
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local function mark_multiple_occurences (x)
|
||||||
|
if no_identity [type(x)] then return end
|
||||||
|
if seen_once [x] then seen_once [x], multiple [x] = nil, true
|
||||||
|
elseif multiple [x] then -- pass
|
||||||
|
else seen_once [x] = true end
|
||||||
|
|
||||||
|
if type (x) == 'table' then
|
||||||
|
nested [x] = true
|
||||||
|
for k, v in pairs (x) do
|
||||||
|
if nested[k] or nested[v] then mark_nest_point (x, k, v) else
|
||||||
|
mark_multiple_occurences (k)
|
||||||
|
mark_multiple_occurences (v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
nested [x] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local dumped = { } -- multiply occuring values already dumped in localdefs
|
||||||
|
local localdefs = { } -- already dumped local definitions as source code lines
|
||||||
|
|
||||||
|
-- mutually recursive functions:
|
||||||
|
local dump_val, dump_or_ref_val
|
||||||
|
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
-- if x occurs multiple times, dump the local var rather than the
|
||||||
|
-- value. If it's the first time it's dumped, also dump the content
|
||||||
|
-- in localdefs.
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
function dump_or_ref_val (x)
|
||||||
|
if nested[x] then return 'false' end -- placeholder for recursive reference
|
||||||
|
if not multiple[x] then return dump_val (x) end
|
||||||
|
local var = dumped [x]
|
||||||
|
if var then return "_[" .. var .. "]" end -- already referenced
|
||||||
|
local val = dump_val(x) -- first occurence, create and register reference
|
||||||
|
var = gensym()
|
||||||
|
table.insert(localdefs, "_["..var.."]="..val)
|
||||||
|
dumped [x] = var
|
||||||
|
return "_[" .. var .. "]"
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Second pass, dump the object; subparts occuring multiple times are dumped
|
||||||
|
-- in local variables which can be referenced multiple times;
|
||||||
|
-- care is taken to dump locla vars in asensible order.
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
function dump_val(x)
|
||||||
|
local t = type(x)
|
||||||
|
if x==nil then return 'nil'
|
||||||
|
elseif t=="number" then return tostring(x)
|
||||||
|
elseif t=="string" then return string.format("%q", x)
|
||||||
|
elseif t=="boolean" then return x and "true" or "false"
|
||||||
|
elseif t=="table" then
|
||||||
|
local acc = { }
|
||||||
|
local idx_dumped = { }
|
||||||
|
local np = nest_points [x]
|
||||||
|
for i, v in ipairs(x) do
|
||||||
|
if np and np[v] then
|
||||||
|
table.insert (acc, 'false') -- placeholder
|
||||||
|
else
|
||||||
|
table.insert (acc, dump_or_ref_val(v))
|
||||||
|
end
|
||||||
|
idx_dumped[i] = true
|
||||||
|
end
|
||||||
|
for k, v in pairs(x) do
|
||||||
|
if np and (np[k] or np[v]) then
|
||||||
|
--check_multiple(k); check_multiple(v) -- force dumps in localdefs
|
||||||
|
elseif not idx_dumped[k] then
|
||||||
|
table.insert (acc, "[" .. dump_or_ref_val(k) .. "] = " .. dump_or_ref_val(v))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return "{ "..table.concat(acc,", ").." }"
|
||||||
|
else
|
||||||
|
error ("Can't serialize data of type "..t)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function dump_nest_patches()
|
||||||
|
for _, entry in ipairs(nest_patches) do
|
||||||
|
local p, k, v = unpack (entry)
|
||||||
|
assert (multiple[p])
|
||||||
|
local set = dump_or_ref_val (p) .. "[" .. dump_or_ref_val (k) .. "] = " ..
|
||||||
|
dump_or_ref_val (v) .. " -- rec "
|
||||||
|
table.insert (localdefs, set)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
mark_multiple_occurences (x)
|
||||||
|
local toplevel = dump_or_ref_val (x)
|
||||||
|
dump_nest_patches()
|
||||||
|
|
||||||
|
if next (localdefs) then
|
||||||
|
return "local _={ }\n" ..
|
||||||
|
table.concat (localdefs, "\n") ..
|
||||||
|
"\nreturn " .. toplevel
|
||||||
|
else
|
||||||
|
return "return " .. toplevel
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Deserialization.
|
||||||
|
-- http://stackoverflow.com/questions/5958818/loading-serialized-data-into-a-table
|
||||||
|
--
|
||||||
|
|
||||||
|
local function stringtotable(sdata)
|
||||||
|
if sdata:byte(1) == 27 then return nil, "binary bytecode prohibited" end
|
||||||
|
local f, message = assert(loadstring(sdata))
|
||||||
|
if not f then return nil, message end
|
||||||
|
setfenv(f, table)
|
||||||
|
return f()
|
||||||
|
end
|
||||||
|
|
||||||
|
function minetest.deserialize(sdata)
|
||||||
|
local table = {}
|
||||||
|
local okay,results = pcall(stringtotable, sdata)
|
||||||
|
if okay then
|
||||||
|
return results
|
||||||
|
end
|
||||||
|
minetest.log('error', 'minetest.deserialize(): '.. results)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Run some unit tests
|
||||||
|
local function unit_test()
|
||||||
|
function unitTest(name, success)
|
||||||
|
if not success then
|
||||||
|
error(name .. ': failed')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
unittest_input = {cat={sound="nyan", speed=400}, dog={sound="woof"}}
|
||||||
|
unittest_output = minetest.deserialize(minetest.serialize(unittest_input))
|
||||||
|
|
||||||
|
unitTest("test 1a", unittest_input.cat.sound == unittest_output.cat.sound)
|
||||||
|
unitTest("test 1b", unittest_input.cat.speed == unittest_output.cat.speed)
|
||||||
|
unitTest("test 1c", unittest_input.dog.sound == unittest_output.dog.sound)
|
||||||
|
|
||||||
|
unittest_input = {escapechars="\n\r\t\v\\\"\'", noneuropean="θשׁ٩∂"}
|
||||||
|
unittest_output = minetest.deserialize(minetest.serialize(unittest_input))
|
||||||
|
unitTest("test 3a", unittest_input.escapechars == unittest_output.escapechars)
|
||||||
|
unitTest("test 3b", unittest_input.noneuropean == unittest_output.noneuropean)
|
||||||
|
end
|
||||||
|
unit_test() -- Run it
|
||||||
|
unit_test = nil -- Hide it
|
||||||
|
|
||||||
33
builtin/static_spawn.lua
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
-- Minetest: builtin/static_spawn.lua
|
||||||
|
|
||||||
|
local function warn_invalid_static_spawnpoint()
|
||||||
|
if minetest.setting_get("static_spawnpoint") and
|
||||||
|
not minetest.setting_get_pos("static_spawnpoint") then
|
||||||
|
minetest.log('error', "The static_spawnpoint setting is invalid: \""..
|
||||||
|
minetest.setting_get("static_spawnpoint").."\"")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
warn_invalid_static_spawnpoint()
|
||||||
|
|
||||||
|
local function put_player_in_spawn(obj)
|
||||||
|
warn_invalid_static_spawnpoint()
|
||||||
|
local static_spawnpoint = minetest.setting_get_pos("static_spawnpoint")
|
||||||
|
if not static_spawnpoint then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
minetest.log('action', "Moving "..obj:get_player_name()..
|
||||||
|
" to static spawnpoint at "..
|
||||||
|
minetest.pos_to_string(static_spawnpoint))
|
||||||
|
obj:setpos(static_spawnpoint)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_on_newplayer(function(obj)
|
||||||
|
put_player_in_spawn(obj)
|
||||||
|
end)
|
||||||
|
|
||||||
|
minetest.register_on_respawnplayer(function(obj)
|
||||||
|
return put_player_in_spawn(obj)
|
||||||
|
end)
|
||||||
|
|
||||||
146
builtin/vector.lua
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
|
||||||
|
vector = {}
|
||||||
|
|
||||||
|
local function assert_vector(v)
|
||||||
|
assert(type(v) == "table" and v.x and v.y and v.z, "Invalid vector")
|
||||||
|
end
|
||||||
|
|
||||||
|
function vector.new(a, b, c)
|
||||||
|
if type(a) == "table" then
|
||||||
|
assert(a.x and a.y and a.z, "Invalid vector passed to vector.new()")
|
||||||
|
return {x=a.x, y=a.y, z=a.z}
|
||||||
|
elseif a then
|
||||||
|
assert(b and c, "Invalid arguments for vector.new()")
|
||||||
|
return {x=a, y=b, z=c}
|
||||||
|
end
|
||||||
|
return {x=0, y=0, z=0}
|
||||||
|
end
|
||||||
|
|
||||||
|
function vector.equals(a, b)
|
||||||
|
assert_vector(a)
|
||||||
|
assert_vector(b)
|
||||||
|
return a.x == b.x and
|
||||||
|
a.y == b.y and
|
||||||
|
a.z == b.z
|
||||||
|
end
|
||||||
|
|
||||||
|
function vector.length(v)
|
||||||
|
assert_vector(v)
|
||||||
|
return math.hypot(v.x, math.hypot(v.y, v.z))
|
||||||
|
end
|
||||||
|
|
||||||
|
function vector.normalize(v)
|
||||||
|
assert_vector(v)
|
||||||
|
local len = vector.length(v)
|
||||||
|
if len == 0 then
|
||||||
|
return {x=0, y=0, z=0}
|
||||||
|
else
|
||||||
|
return vector.divide(v, len)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function vector.round(v)
|
||||||
|
assert_vector(v)
|
||||||
|
return {
|
||||||
|
x = math.floor(v.x + 0.5),
|
||||||
|
y = math.floor(v.y + 0.5),
|
||||||
|
z = math.floor(v.z + 0.5)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function vector.distance(a, b)
|
||||||
|
assert_vector(a)
|
||||||
|
assert_vector(b)
|
||||||
|
local x = a.x - b.x
|
||||||
|
local y = a.y - b.y
|
||||||
|
local z = a.z - b.z
|
||||||
|
return math.hypot(x, math.hypot(y, z))
|
||||||
|
end
|
||||||
|
|
||||||
|
function vector.direction(pos1, pos2)
|
||||||
|
assert_vector(pos1)
|
||||||
|
assert_vector(pos2)
|
||||||
|
local x_raw = pos2.x - pos1.x
|
||||||
|
local y_raw = pos2.y - pos1.y
|
||||||
|
local z_raw = pos2.z - pos1.z
|
||||||
|
local x_abs = math.abs(x_raw)
|
||||||
|
local y_abs = math.abs(y_raw)
|
||||||
|
local z_abs = math.abs(z_raw)
|
||||||
|
if x_abs >= y_abs and
|
||||||
|
x_abs >= z_abs then
|
||||||
|
y_raw = y_raw * (1 / x_abs)
|
||||||
|
z_raw = z_raw * (1 / x_abs)
|
||||||
|
x_raw = x_raw / x_abs
|
||||||
|
end
|
||||||
|
if y_abs >= x_abs and
|
||||||
|
y_abs >= z_abs then
|
||||||
|
x_raw = x_raw * (1 / y_abs)
|
||||||
|
z_raw = z_raw * (1 / y_abs)
|
||||||
|
y_raw = y_raw / y_abs
|
||||||
|
end
|
||||||
|
if z_abs >= y_abs and
|
||||||
|
z_abs >= x_abs then
|
||||||
|
x_raw = x_raw * (1 / z_abs)
|
||||||
|
y_raw = y_raw * (1 / z_abs)
|
||||||
|
z_raw = z_raw / z_abs
|
||||||
|
end
|
||||||
|
return {x=x_raw, y=y_raw, z=z_raw}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function vector.add(a, b)
|
||||||
|
assert_vector(a)
|
||||||
|
if type(b) == "table" then
|
||||||
|
assert_vector(b)
|
||||||
|
return {x = a.x + b.x,
|
||||||
|
y = a.y + b.y,
|
||||||
|
z = a.z + b.z}
|
||||||
|
else
|
||||||
|
return {x = a.x + b,
|
||||||
|
y = a.y + b,
|
||||||
|
z = a.z + b}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function vector.subtract(a, b)
|
||||||
|
assert_vector(a)
|
||||||
|
if type(b) == "table" then
|
||||||
|
assert_vector(b)
|
||||||
|
return {x = a.x - b.x,
|
||||||
|
y = a.y - b.y,
|
||||||
|
z = a.z - b.z}
|
||||||
|
else
|
||||||
|
return {x = a.x - b,
|
||||||
|
y = a.y - b,
|
||||||
|
z = a.z - b}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function vector.multiply(a, b)
|
||||||
|
assert_vector(a)
|
||||||
|
if type(b) == "table" then
|
||||||
|
assert_vector(b)
|
||||||
|
return {x = a.x * b.x,
|
||||||
|
y = a.y * b.y,
|
||||||
|
z = a.z * b.z}
|
||||||
|
else
|
||||||
|
return {x = a.x * b,
|
||||||
|
y = a.y * b,
|
||||||
|
z = a.z * b}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function vector.divide(a, b)
|
||||||
|
assert_vector(a)
|
||||||
|
if type(b) == "table" then
|
||||||
|
assert_vector(b)
|
||||||
|
return {x = a.x / b.x,
|
||||||
|
y = a.y / b.y,
|
||||||
|
z = a.z / b.z}
|
||||||
|
else
|
||||||
|
return {x = a.x / b,
|
||||||
|
y = a.y / b,
|
||||||
|
z = a.z / b}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
103
builtin/voxelarea.lua
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
VoxelArea = {
|
||||||
|
MinEdge = {x=1, y=1, z=1},
|
||||||
|
MaxEdge = {x=0, y=0, z=0},
|
||||||
|
ystride = 0,
|
||||||
|
zstride = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
function VoxelArea:new(o)
|
||||||
|
o = o or {}
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
|
||||||
|
local e = o:getExtent()
|
||||||
|
o.ystride = e.x
|
||||||
|
o.zstride = e.x * e.y
|
||||||
|
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
|
||||||
|
function VoxelArea:getExtent()
|
||||||
|
return {
|
||||||
|
x = self.MaxEdge.x - self.MinEdge.x + 1,
|
||||||
|
y = self.MaxEdge.y - self.MinEdge.y + 1,
|
||||||
|
z = self.MaxEdge.z - self.MinEdge.z + 1,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function VoxelArea:getVolume()
|
||||||
|
local e = self:getExtent()
|
||||||
|
return e.x * e.y * e.z
|
||||||
|
end
|
||||||
|
|
||||||
|
function VoxelArea:index(x, y, z)
|
||||||
|
local i = (z - self.MinEdge.z) * self.zstride +
|
||||||
|
(y - self.MinEdge.y) * self.ystride +
|
||||||
|
(x - self.MinEdge.x) + 1
|
||||||
|
return math.floor(i)
|
||||||
|
end
|
||||||
|
|
||||||
|
function VoxelArea:indexp(p)
|
||||||
|
local i = (p.z - self.MinEdge.z) * self.zstride +
|
||||||
|
(p.y - self.MinEdge.y) * self.ystride +
|
||||||
|
(p.x - self.MinEdge.x) + 1
|
||||||
|
return math.floor(i)
|
||||||
|
end
|
||||||
|
|
||||||
|
function VoxelArea:position(i)
|
||||||
|
local p = {}
|
||||||
|
|
||||||
|
i = i - 1
|
||||||
|
|
||||||
|
p.z = math.floor(i / self.zstride) + self.MinEdge.z
|
||||||
|
i = i % self.zstride
|
||||||
|
|
||||||
|
p.y = math.floor(i / self.ystride) + self.MinEdge.y
|
||||||
|
i = i % self.ystride
|
||||||
|
|
||||||
|
p.x = math.floor(i) + self.MinEdge.x
|
||||||
|
|
||||||
|
return p
|
||||||
|
end
|
||||||
|
|
||||||
|
function VoxelArea:contains(x, y, z)
|
||||||
|
return (x >= self.MinEdge.x) and (x <= self.MaxEdge.x) and
|
||||||
|
(y >= self.MinEdge.y) and (y <= self.MaxEdge.y) and
|
||||||
|
(z >= self.MinEdge.z) and (z <= self.MaxEdge.z)
|
||||||
|
end
|
||||||
|
|
||||||
|
function VoxelArea:containsp(p)
|
||||||
|
return (p.x >= self.MinEdge.x) and (p.x <= self.MaxEdge.x) and
|
||||||
|
(p.y >= self.MinEdge.y) and (p.y <= self.MaxEdge.y) and
|
||||||
|
(p.z >= self.MinEdge.z) and (p.z <= self.MaxEdge.z)
|
||||||
|
end
|
||||||
|
|
||||||
|
function VoxelArea:containsi(i)
|
||||||
|
return (i >= 1) and (i <= self:getVolume())
|
||||||
|
end
|
||||||
|
|
||||||
|
function VoxelArea:iter(minx, miny, minz, maxx, maxy, maxz)
|
||||||
|
local i = self:index(minx, miny, minz) - 1
|
||||||
|
local last = self:index(maxx, maxy, maxz)
|
||||||
|
local ystride = self.ystride
|
||||||
|
local zstride = self.zstride
|
||||||
|
local yoff = (last+1) % ystride
|
||||||
|
local zoff = (last+1) % zstride
|
||||||
|
local ystridediff = (i - last) % ystride
|
||||||
|
local zstridediff = (i - last) % zstride
|
||||||
|
return function()
|
||||||
|
i = i + 1
|
||||||
|
if i % zstride == zoff then
|
||||||
|
i = i + zstridediff
|
||||||
|
elseif i % ystride == yoff then
|
||||||
|
i = i + ystridediff
|
||||||
|
end
|
||||||
|
if i <= last then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function VoxelArea:iterp(minp, maxp)
|
||||||
|
return self:iter(minp.x, minp.y, minp.z, maxp.x, maxp.y, maxp.z)
|
||||||
|
end
|
||||||
2
client/serverlist/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
||||||
1
client/shaders/alpha_shader/base.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
trans_alphach
|
||||||
71
client/shaders/alpha_shader/opengl_fragment.glsl
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
uniform sampler2D baseTexture;
|
||||||
|
uniform sampler2D normalTexture;
|
||||||
|
uniform sampler2D useNormalmap;
|
||||||
|
|
||||||
|
uniform vec4 skyBgColor;
|
||||||
|
uniform float fogDistance;
|
||||||
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
|
varying vec3 vPosition;
|
||||||
|
varying vec3 eyeVec;
|
||||||
|
|
||||||
|
#ifdef ENABLE_PARALLAX_OCCLUSION
|
||||||
|
varying vec3 tsEyeVec;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const float e = 2.718281828459;
|
||||||
|
|
||||||
|
void main (void)
|
||||||
|
{
|
||||||
|
vec3 color;
|
||||||
|
vec2 uv = gl_TexCoord[0].st;
|
||||||
|
|
||||||
|
#ifdef USE_NORMALMAPS
|
||||||
|
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_PARALLAX_OCCLUSION
|
||||||
|
float height;
|
||||||
|
vec2 tsEye = vec2(tsEyeVec.x,-tsEyeVec.y);
|
||||||
|
|
||||||
|
if (use_normalmap > 0.0) {
|
||||||
|
float map_height = texture2D(normalTexture, uv).a;
|
||||||
|
if (map_height < 1.0){
|
||||||
|
float height = PARALLAX_OCCLUSION_SCALE * map_height - PARALLAX_OCCLUSION_BIAS;
|
||||||
|
uv = uv + height * tsEye;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_BUMPMAPPING
|
||||||
|
if (use_normalmap > 0.0) {
|
||||||
|
vec3 base = texture2D(baseTexture, uv).rgb;
|
||||||
|
vec3 vVec = normalize(eyeVec);
|
||||||
|
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
|
||||||
|
vec3 R = reflect(-vVec, bump);
|
||||||
|
vec3 lVec = normalize(vVec);
|
||||||
|
float diffuse = max(dot(lVec, bump), 0.0);
|
||||||
|
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
|
||||||
|
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
|
||||||
|
} else {
|
||||||
|
color = texture2D(baseTexture, uv).rgb;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
color = texture2D(baseTexture, uv).rgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float alpha = texture2D(baseTexture, uv).a;
|
||||||
|
vec4 col = vec4(color.r, color.g, color.b, alpha);
|
||||||
|
col *= gl_Color;
|
||||||
|
col = col * col; // SRGB -> Linear
|
||||||
|
col *= 1.8;
|
||||||
|
col.r = 1.0 - exp(1.0 - col.r) / e;
|
||||||
|
col.g = 1.0 - exp(1.0 - col.g) / e;
|
||||||
|
col.b = 1.0 - exp(1.0 - col.b) / e;
|
||||||
|
col = sqrt(col); // Linear -> SRGB
|
||||||
|
if(fogDistance != 0.0){
|
||||||
|
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
||||||
|
col = mix(col, skyBgColor, d);
|
||||||
|
}
|
||||||
|
gl_FragColor = vec4(col.r, col.g, col.b, alpha);
|
||||||
|
}
|
||||||
102
client/shaders/alpha_shader/opengl_vertex.glsl
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
uniform mat4 mWorldViewProj;
|
||||||
|
uniform mat4 mInvWorld;
|
||||||
|
uniform mat4 mTransWorld;
|
||||||
|
uniform float dayNightRatio;
|
||||||
|
|
||||||
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
|
varying vec3 vPosition;
|
||||||
|
varying vec3 eyeVec;
|
||||||
|
|
||||||
|
#ifdef ENABLE_PARALLAX_OCCLUSION
|
||||||
|
varying vec3 tsEyeVec;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
gl_Position = mWorldViewProj * gl_Vertex;
|
||||||
|
vPosition = (mWorldViewProj * gl_Vertex).xyz;
|
||||||
|
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||||
|
|
||||||
|
#ifdef ENABLE_PARALLAX_OCCLUSION
|
||||||
|
vec3 normal,tangent,binormal;
|
||||||
|
normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||||
|
|
||||||
|
if (gl_Normal.x > 0.5) {
|
||||||
|
// 1.0, 0.0, 0.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, -1.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
|
||||||
|
} else if (gl_Normal.x < -0.5) {
|
||||||
|
// -1.0, 0.0, 0.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
|
||||||
|
} else if (gl_Normal.y > 0.5) {
|
||||||
|
// 0.0, 1.0, 0.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
|
||||||
|
} else if (gl_Normal.y < -0.5) {
|
||||||
|
// 0.0, -1.0, 0.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
|
||||||
|
} else if (gl_Normal.z > 0.5) {
|
||||||
|
// 0.0, 0.0, 1.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
|
||||||
|
} else if (gl_Normal.z < -0.5) {
|
||||||
|
// 0.0, 0.0, -1.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3(-1.0, 0.0, 0.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 tbnMatrix = mat3( tangent.x, binormal.x, normal.x,
|
||||||
|
tangent.y, binormal.y, normal.y,
|
||||||
|
tangent.z, binormal.z, normal.z);
|
||||||
|
|
||||||
|
tsEyeVec = normalize(eyeVec * tbnMatrix);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4 color;
|
||||||
|
//color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
float day = gl_Color.r;
|
||||||
|
float night = gl_Color.g;
|
||||||
|
float light_source = gl_Color.b;
|
||||||
|
|
||||||
|
/*color.r = mix(night, day, dayNightRatio);
|
||||||
|
color.g = color.r;
|
||||||
|
color.b = color.r;*/
|
||||||
|
|
||||||
|
float rg = mix(night, day, dayNightRatio);
|
||||||
|
rg += light_source * 2.5; // Make light sources brighter
|
||||||
|
float b = rg;
|
||||||
|
|
||||||
|
// Moonlight is blue
|
||||||
|
b += (day - night) / 13.0;
|
||||||
|
rg -= (day - night) / 13.0;
|
||||||
|
|
||||||
|
// Emphase blue a bit in darker places
|
||||||
|
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
|
||||||
|
b += max(0.0, (1.0 - abs(b - 0.13)/0.17) * 0.025);
|
||||||
|
|
||||||
|
// Artificial light is yellow-ish
|
||||||
|
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
|
||||||
|
rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);
|
||||||
|
|
||||||
|
color.r = clamp(rg,0.0,1.0);
|
||||||
|
color.g = clamp(rg,0.0,1.0);
|
||||||
|
color.b = clamp(b,0.0,1.0);
|
||||||
|
|
||||||
|
// Make sides and bottom darker than the top
|
||||||
|
color = color * color; // SRGB -> Linear
|
||||||
|
if(gl_Normal.y <= 0.5)
|
||||||
|
color *= 0.6;
|
||||||
|
//color *= 0.7;
|
||||||
|
color = sqrt(color); // Linear -> SRGB
|
||||||
|
|
||||||
|
color.a = gl_Color.a;
|
||||||
|
|
||||||
|
gl_FrontColor = gl_BackColor = color;
|
||||||
|
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
|
|
||||||
|
}
|
||||||
1
client/shaders/leaves_shader/base.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
trans_alphach_ref
|
||||||
54
client/shaders/leaves_shader/opengl_fragment.glsl
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
uniform sampler2D baseTexture;
|
||||||
|
uniform sampler2D normalTexture;
|
||||||
|
uniform sampler2D useNormalmap;
|
||||||
|
|
||||||
|
uniform vec4 skyBgColor;
|
||||||
|
uniform float fogDistance;
|
||||||
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
|
varying vec3 vPosition;
|
||||||
|
varying vec3 eyeVec;
|
||||||
|
|
||||||
|
const float e = 2.718281828459;
|
||||||
|
|
||||||
|
void main (void)
|
||||||
|
{
|
||||||
|
vec3 color;
|
||||||
|
vec2 uv = gl_TexCoord[0].st;
|
||||||
|
|
||||||
|
#ifdef USE_NORMALMAPS
|
||||||
|
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_BUMPMAPPING
|
||||||
|
if (use_normalmap > 0.0) {
|
||||||
|
vec3 base = texture2D(baseTexture, uv).rgb;
|
||||||
|
vec3 vVec = normalize(eyeVec);
|
||||||
|
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
|
||||||
|
vec3 R = reflect(-vVec, bump);
|
||||||
|
vec3 lVec = normalize(vVec);
|
||||||
|
float diffuse = max(dot(lVec, bump), 0.0);
|
||||||
|
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
|
||||||
|
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
|
||||||
|
} else {
|
||||||
|
color = texture2D(baseTexture, uv).rgb;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
color = texture2D(baseTexture, uv).rgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float alpha = texture2D(baseTexture, uv).a;
|
||||||
|
vec4 col = vec4(color.r, color.g, color.b, alpha);
|
||||||
|
col *= gl_Color;
|
||||||
|
col = col * col; // SRGB -> Linear
|
||||||
|
col *= 1.8;
|
||||||
|
col.r = 1.0 - exp(1.0 - col.r) / e;
|
||||||
|
col.g = 1.0 - exp(1.0 - col.g) / e;
|
||||||
|
col.b = 1.0 - exp(1.0 - col.b) / e;
|
||||||
|
col = sqrt(col); // Linear -> SRGB
|
||||||
|
if(fogDistance != 0.0){
|
||||||
|
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
||||||
|
col = mix(col, skyBgColor, d);
|
||||||
|
}
|
||||||
|
gl_FragColor = vec4(col.r, col.g, col.b, alpha);
|
||||||
|
}
|
||||||
87
client/shaders/leaves_shader/opengl_vertex.glsl
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
uniform mat4 mWorldViewProj;
|
||||||
|
uniform mat4 mInvWorld;
|
||||||
|
uniform mat4 mTransWorld;
|
||||||
|
uniform float dayNightRatio;
|
||||||
|
uniform float animationTimer;
|
||||||
|
|
||||||
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
|
varying vec3 vPosition;
|
||||||
|
varying vec3 eyeVec;
|
||||||
|
|
||||||
|
#ifdef ENABLE_WAVING_LEAVES
|
||||||
|
float smoothCurve( float x ) {
|
||||||
|
return x * x *( 3.0 - 2.0 * x );
|
||||||
|
}
|
||||||
|
float triangleWave( float x ) {
|
||||||
|
return abs( fract( x + 0.5 ) * 2.0 - 1.0 );
|
||||||
|
}
|
||||||
|
float smoothTriangleWave( float x ) {
|
||||||
|
return smoothCurve( triangleWave( x ) ) * 2.0 - 1.0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
|
|
||||||
|
#ifdef ENABLE_WAVING_LEAVES
|
||||||
|
vec4 pos = gl_Vertex;
|
||||||
|
vec4 pos2 = mTransWorld*gl_Vertex;
|
||||||
|
pos.x += (smoothTriangleWave(animationTimer*10.0 + pos2.x * 0.01 + pos2.z * 0.01) * 2.0 - 1.0) * 0.4;
|
||||||
|
pos.y += (smoothTriangleWave(animationTimer*15.0 + pos2.x * -0.01 + pos2.z * -0.01) * 2.0 - 1.0) * 0.2;
|
||||||
|
pos.z += (smoothTriangleWave(animationTimer*10.0 + pos2.x * -0.01 + pos2.z * -0.01) * 2.0 - 1.0) * 0.4;
|
||||||
|
gl_Position = mWorldViewProj * pos;
|
||||||
|
#else
|
||||||
|
gl_Position = mWorldViewProj * gl_Vertex;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vPosition = (mWorldViewProj * gl_Vertex).xyz;
|
||||||
|
|
||||||
|
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||||
|
|
||||||
|
vec4 color;
|
||||||
|
//color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
float day = gl_Color.r;
|
||||||
|
float night = gl_Color.g;
|
||||||
|
float light_source = gl_Color.b;
|
||||||
|
|
||||||
|
/*color.r = mix(night, day, dayNightRatio);
|
||||||
|
color.g = color.r;
|
||||||
|
color.b = color.r;*/
|
||||||
|
|
||||||
|
float rg = mix(night, day, dayNightRatio);
|
||||||
|
rg += light_source * 2.5; // Make light sources brighter
|
||||||
|
float b = rg;
|
||||||
|
|
||||||
|
// Moonlight is blue
|
||||||
|
b += (day - night) / 13.0;
|
||||||
|
rg -= (day - night) / 13.0;
|
||||||
|
|
||||||
|
// Emphase blue a bit in darker places
|
||||||
|
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
|
||||||
|
b += max(0.0, (1.0 - abs(b - 0.13)/0.17) * 0.025);
|
||||||
|
|
||||||
|
// Artificial light is yellow-ish
|
||||||
|
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
|
||||||
|
rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);
|
||||||
|
|
||||||
|
color.r = clamp(rg,0.0,1.0);
|
||||||
|
color.g = clamp(rg,0.0,1.0);
|
||||||
|
color.b = clamp(b,0.0,1.0);
|
||||||
|
|
||||||
|
// Make sides and bottom darker than the top
|
||||||
|
color = color * color; // SRGB -> Linear
|
||||||
|
if(gl_Normal.y <= 0.5)
|
||||||
|
color *= 0.6;
|
||||||
|
//color *= 0.7;
|
||||||
|
color = sqrt(color); // Linear -> SRGB
|
||||||
|
|
||||||
|
color.a = gl_Color.a;
|
||||||
|
|
||||||
|
gl_FrontColor = gl_BackColor = color;
|
||||||
|
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
|
|
||||||
|
}
|
||||||
1
client/shaders/liquids_shader/base.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
trans_alphach
|
||||||
54
client/shaders/liquids_shader/opengl_fragment.glsl
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
uniform sampler2D baseTexture;
|
||||||
|
uniform sampler2D normalTexture;
|
||||||
|
uniform sampler2D useNormalmap;
|
||||||
|
|
||||||
|
uniform vec4 skyBgColor;
|
||||||
|
uniform float fogDistance;
|
||||||
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
|
varying vec3 vPosition;
|
||||||
|
varying vec3 eyeVec;
|
||||||
|
|
||||||
|
const float e = 2.718281828459;
|
||||||
|
|
||||||
|
void main (void)
|
||||||
|
{
|
||||||
|
vec3 color;
|
||||||
|
vec2 uv = gl_TexCoord[0].st;
|
||||||
|
|
||||||
|
#ifdef USE_NORMALMAPS
|
||||||
|
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_BUMPMAPPING
|
||||||
|
if (use_normalmap > 0.0) {
|
||||||
|
vec3 base = texture2D(baseTexture, uv).rgb;
|
||||||
|
vec3 vVec = normalize(eyeVec);
|
||||||
|
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
|
||||||
|
vec3 R = reflect(-vVec, bump);
|
||||||
|
vec3 lVec = normalize(vVec);
|
||||||
|
float diffuse = max(dot(vec3(-1.0, -0.4, 0.5), bump), 0.0);
|
||||||
|
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
|
||||||
|
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
|
||||||
|
} else {
|
||||||
|
color = texture2D(baseTexture, uv).rgb;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
color = texture2D(baseTexture, uv).rgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float alpha = gl_Color.a;
|
||||||
|
vec4 col = vec4(color.r, color.g, color.b, alpha);
|
||||||
|
col *= gl_Color;
|
||||||
|
col = col * col; // SRGB -> Linear
|
||||||
|
col *= 1.8;
|
||||||
|
col.r = 1.0 - exp(1.0 - col.r) / e;
|
||||||
|
col.g = 1.0 - exp(1.0 - col.g) / e;
|
||||||
|
col.b = 1.0 - exp(1.0 - col.b) / e;
|
||||||
|
col = sqrt(col); // Linear -> SRGB
|
||||||
|
if(fogDistance != 0.0){
|
||||||
|
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
||||||
|
alpha = mix(alpha, 0.0, d);
|
||||||
|
}
|
||||||
|
gl_FragColor = vec4(col.r, col.g, col.b, alpha);
|
||||||
|
}
|
||||||
63
client/shaders/liquids_shader/opengl_vertex.glsl
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
uniform mat4 mWorldViewProj;
|
||||||
|
uniform mat4 mInvWorld;
|
||||||
|
uniform mat4 mTransWorld;
|
||||||
|
uniform float dayNightRatio;
|
||||||
|
uniform float animationTimer;
|
||||||
|
|
||||||
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
|
varying vec3 vPosition;
|
||||||
|
varying vec3 eyeVec;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_WAVING_WATER
|
||||||
|
vec4 pos2 = gl_Vertex;
|
||||||
|
pos2.y -= 2.0;
|
||||||
|
pos2.y -= sin (pos2.z/WATER_WAVE_LENGTH + animationTimer * WATER_WAVE_SPEED * WATER_WAVE_LENGTH) * WATER_WAVE_HEIGHT
|
||||||
|
+ sin ((pos2.z/WATER_WAVE_LENGTH + animationTimer * WATER_WAVE_SPEED * WATER_WAVE_LENGTH) / 7.0) * WATER_WAVE_HEIGHT;
|
||||||
|
gl_Position = mWorldViewProj * pos2;
|
||||||
|
#else
|
||||||
|
gl_Position = mWorldViewProj * gl_Vertex;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||||
|
vPosition = (mWorldViewProj * gl_Vertex).xyz;
|
||||||
|
|
||||||
|
vec4 color;
|
||||||
|
//color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
float day = gl_Color.r;
|
||||||
|
float night = gl_Color.g;
|
||||||
|
float light_source = gl_Color.b;
|
||||||
|
|
||||||
|
/*color.r = mix(night, day, dayNightRatio);
|
||||||
|
color.g = color.r;
|
||||||
|
color.b = color.r;*/
|
||||||
|
|
||||||
|
float rg = mix(night, day, dayNightRatio);
|
||||||
|
rg += light_source * 2.5; // Make light sources brighter
|
||||||
|
float b = rg;
|
||||||
|
|
||||||
|
// Moonlight is blue
|
||||||
|
b += (day - night) / 13.0;
|
||||||
|
rg -= (day - night) / 13.0;
|
||||||
|
|
||||||
|
// Emphase blue a bit in darker places
|
||||||
|
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
|
||||||
|
b += max(0.0, (1.0 - abs(b - 0.13)/0.17) * 0.025);
|
||||||
|
|
||||||
|
// Artificial light is yellow-ish
|
||||||
|
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
|
||||||
|
rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);
|
||||||
|
|
||||||
|
color.r = clamp(rg,0.0,1.0);
|
||||||
|
color.g = clamp(rg,0.0,1.0);
|
||||||
|
color.b = clamp(b,0.0,1.0);
|
||||||
|
color.a = gl_Color.a;
|
||||||
|
|
||||||
|
gl_FrontColor = gl_BackColor = color;
|
||||||
|
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
|
|
||||||
|
}
|
||||||
1
client/shaders/plants_shader/base.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
trans_alphach_ref
|
||||||
54
client/shaders/plants_shader/opengl_fragment.glsl
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
uniform sampler2D baseTexture;
|
||||||
|
uniform sampler2D normalTexture;
|
||||||
|
uniform sampler2D useNormalmap;
|
||||||
|
|
||||||
|
uniform vec4 skyBgColor;
|
||||||
|
uniform float fogDistance;
|
||||||
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
|
varying vec3 vPosition;
|
||||||
|
varying vec3 eyeVec;
|
||||||
|
|
||||||
|
const float e = 2.718281828459;
|
||||||
|
|
||||||
|
void main (void)
|
||||||
|
{
|
||||||
|
vec3 color;
|
||||||
|
vec2 uv = gl_TexCoord[0].st;
|
||||||
|
|
||||||
|
#ifdef USE_NORMALMAPS
|
||||||
|
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_BUMPMAPPING
|
||||||
|
if (use_normalmap > 0.0) {
|
||||||
|
vec3 base = texture2D(baseTexture, uv).rgb;
|
||||||
|
vec3 vVec = normalize(eyeVec);
|
||||||
|
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
|
||||||
|
vec3 R = reflect(-vVec, bump);
|
||||||
|
vec3 lVec = normalize(vVec);
|
||||||
|
float diffuse = max(dot(lVec, bump), 0.0);
|
||||||
|
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
|
||||||
|
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
|
||||||
|
} else {
|
||||||
|
color = texture2D(baseTexture, uv).rgb;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
color = texture2D(baseTexture, uv).rgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float alpha = texture2D(baseTexture, uv).a;
|
||||||
|
vec4 col = vec4(color.r, color.g, color.b, alpha);
|
||||||
|
col *= gl_Color;
|
||||||
|
col = col * col; // SRGB -> Linear
|
||||||
|
col *= 1.8;
|
||||||
|
col.r = 1.0 - exp(1.0 - col.r) / e;
|
||||||
|
col.g = 1.0 - exp(1.0 - col.g) / e;
|
||||||
|
col.b = 1.0 - exp(1.0 - col.b) / e;
|
||||||
|
col = sqrt(col); // Linear -> SRGB
|
||||||
|
if(fogDistance != 0.0){
|
||||||
|
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
||||||
|
col = mix(col, skyBgColor, d);
|
||||||
|
}
|
||||||
|
gl_FragColor = vec4(col.r, col.g, col.b, alpha);
|
||||||
|
}
|
||||||
86
client/shaders/plants_shader/opengl_vertex.glsl
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
uniform mat4 mWorldViewProj;
|
||||||
|
uniform mat4 mInvWorld;
|
||||||
|
uniform mat4 mTransWorld;
|
||||||
|
uniform float dayNightRatio;
|
||||||
|
uniform float animationTimer;
|
||||||
|
|
||||||
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
|
varying vec3 vPosition;
|
||||||
|
varying vec3 eyeVec;
|
||||||
|
|
||||||
|
#ifdef ENABLE_WAVING_PLANTS
|
||||||
|
float smoothCurve( float x ) {
|
||||||
|
return x * x *( 3.0 - 2.0 * x );
|
||||||
|
}
|
||||||
|
float triangleWave( float x ) {
|
||||||
|
return abs( fract( x + 0.5 ) * 2.0 - 1.0 );
|
||||||
|
}
|
||||||
|
float smoothTriangleWave( float x ) {
|
||||||
|
return smoothCurve( triangleWave( x ) ) * 2.0 - 1.0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
|
|
||||||
|
#ifdef ENABLE_WAVING_PLANTS
|
||||||
|
vec4 pos = gl_Vertex;
|
||||||
|
vec4 pos2 = mTransWorld * gl_Vertex;
|
||||||
|
if (gl_TexCoord[0].y < 0.05) {
|
||||||
|
pos.x += (smoothTriangleWave(animationTimer * 20.0 + pos2.x * 0.1 + pos2.z * 0.1) * 2.0 - 1.0) * 0.8;
|
||||||
|
pos.y -= (smoothTriangleWave(animationTimer * 10.0 + pos2.x * -0.5 + pos2.z * -0.5) * 2.0 - 1.0) * 0.4;
|
||||||
|
}
|
||||||
|
gl_Position = mWorldViewProj * pos;
|
||||||
|
#else
|
||||||
|
gl_Position = mWorldViewProj * gl_Vertex;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vPosition = (mWorldViewProj * gl_Vertex).xyz;
|
||||||
|
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||||
|
|
||||||
|
vec4 color;
|
||||||
|
//color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
float day = gl_Color.r;
|
||||||
|
float night = gl_Color.g;
|
||||||
|
float light_source = gl_Color.b;
|
||||||
|
|
||||||
|
/*color.r = mix(night, day, dayNightRatio);
|
||||||
|
color.g = color.r;
|
||||||
|
color.b = color.r;*/
|
||||||
|
|
||||||
|
float rg = mix(night, day, dayNightRatio);
|
||||||
|
rg += light_source * 2.5; // Make light sources brighter
|
||||||
|
float b = rg;
|
||||||
|
|
||||||
|
// Moonlight is blue
|
||||||
|
b += (day - night) / 13.0;
|
||||||
|
rg -= (day - night) / 13.0;
|
||||||
|
|
||||||
|
// Emphase blue a bit in darker places
|
||||||
|
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
|
||||||
|
b += max(0.0, (1.0 - abs(b - 0.13)/0.17) * 0.025);
|
||||||
|
|
||||||
|
// Artificial light is yellow-ish
|
||||||
|
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
|
||||||
|
rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);
|
||||||
|
|
||||||
|
color.r = clamp(rg,0.0,1.0);
|
||||||
|
color.g = clamp(rg,0.0,1.0);
|
||||||
|
color.b = clamp(b,0.0,1.0);
|
||||||
|
|
||||||
|
// Make sides and bottom darker than the top
|
||||||
|
color = color * color; // SRGB -> Linear
|
||||||
|
if(gl_Normal.y <= 0.5)
|
||||||
|
color *= 0.6;
|
||||||
|
//color *= 0.7;
|
||||||
|
color = sqrt(color); // Linear -> SRGB
|
||||||
|
|
||||||
|
color.a = gl_Color.a;
|
||||||
|
|
||||||
|
gl_FrontColor = gl_BackColor = color;
|
||||||
|
|
||||||
|
}
|
||||||
1
client/shaders/solids_shader/base.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
trans_alphach_ref
|
||||||
90
client/shaders/solids_shader/opengl_fragment.glsl
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
uniform sampler2D baseTexture;
|
||||||
|
uniform sampler2D normalTexture;
|
||||||
|
uniform sampler2D useNormalmap;
|
||||||
|
|
||||||
|
uniform vec4 skyBgColor;
|
||||||
|
uniform float fogDistance;
|
||||||
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
|
varying vec3 vPosition;
|
||||||
|
varying vec3 eyeVec;
|
||||||
|
|
||||||
|
#ifdef ENABLE_PARALLAX_OCCLUSION
|
||||||
|
varying vec3 tsEyeVec;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const float e = 2.718281828459;
|
||||||
|
|
||||||
|
void main (void)
|
||||||
|
{
|
||||||
|
vec3 color;
|
||||||
|
vec2 uv = gl_TexCoord[0].st;
|
||||||
|
|
||||||
|
#ifdef USE_NORMALMAPS
|
||||||
|
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_PARALLAX_OCCLUSION
|
||||||
|
float height;
|
||||||
|
vec2 tsEye = vec2(tsEyeVec.x,-tsEyeVec.y);
|
||||||
|
|
||||||
|
if (use_normalmap > 0.0) {
|
||||||
|
float map_height = texture2D(normalTexture, uv).a;
|
||||||
|
if (map_height < 1.0){
|
||||||
|
float height = PARALLAX_OCCLUSION_SCALE * map_height - PARALLAX_OCCLUSION_BIAS;
|
||||||
|
uv = uv + height * tsEye;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Steep parallax code, for future use
|
||||||
|
if ((parallaxMappingMode == 2.0) && (use_normalmap > 0.0)) {
|
||||||
|
const float numSteps = 40.0;
|
||||||
|
float height = 1.0;
|
||||||
|
float step = 1.0 / numSteps;
|
||||||
|
vec4 NB = texture2D(normalTexture, uv);
|
||||||
|
vec2 delta = tsEye * parallaxMappingScale / numSteps;
|
||||||
|
for (float i = 0.0; i < numSteps; i++) {
|
||||||
|
if (NB.a < height) {
|
||||||
|
height -= step;
|
||||||
|
uv += delta;
|
||||||
|
NB = texture2D(normalTexture, uv);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef ENABLE_BUMPMAPPING
|
||||||
|
if (use_normalmap > 0.0) {
|
||||||
|
vec3 base = texture2D(baseTexture, uv).rgb;
|
||||||
|
vec3 vVec = normalize(eyeVec);
|
||||||
|
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
|
||||||
|
vec3 R = reflect(-vVec, bump);
|
||||||
|
vec3 lVec = normalize(vVec);
|
||||||
|
float diffuse = max(dot(lVec, bump), 0.0);
|
||||||
|
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
|
||||||
|
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
|
||||||
|
} else {
|
||||||
|
color = texture2D(baseTexture, uv).rgb;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
color = texture2D(baseTexture, uv).rgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float alpha = texture2D(baseTexture, uv).a;
|
||||||
|
vec4 col = vec4(color.r, color.g, color.b, alpha);
|
||||||
|
col *= gl_Color;
|
||||||
|
col = col * col; // SRGB -> Linear
|
||||||
|
col *= 1.8;
|
||||||
|
col.r = 1.0 - exp(1.0 - col.r) / e;
|
||||||
|
col.g = 1.0 - exp(1.0 - col.g) / e;
|
||||||
|
col.b = 1.0 - exp(1.0 - col.b) / e;
|
||||||
|
col = sqrt(col); // Linear -> SRGB
|
||||||
|
if(fogDistance != 0.0){
|
||||||
|
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
||||||
|
col = mix(col, skyBgColor, d);
|
||||||
|
}
|
||||||
|
gl_FragColor = vec4(col.r, col.g, col.b, alpha);
|
||||||
|
}
|
||||||
102
client/shaders/solids_shader/opengl_vertex.glsl
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
uniform mat4 mWorldViewProj;
|
||||||
|
uniform mat4 mInvWorld;
|
||||||
|
uniform mat4 mTransWorld;
|
||||||
|
uniform float dayNightRatio;
|
||||||
|
|
||||||
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
|
varying vec3 vPosition;
|
||||||
|
varying vec3 eyeVec;
|
||||||
|
|
||||||
|
#ifdef ENABLE_PARALLAX_OCCLUSION
|
||||||
|
varying vec3 tsEyeVec;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
gl_Position = mWorldViewProj * gl_Vertex;
|
||||||
|
vPosition = (mWorldViewProj * gl_Vertex).xyz;
|
||||||
|
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||||
|
|
||||||
|
#ifdef ENABLE_PARALLAX_OCCLUSION
|
||||||
|
vec3 normal,tangent,binormal;
|
||||||
|
normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||||
|
|
||||||
|
if (gl_Normal.x > 0.5) {
|
||||||
|
// 1.0, 0.0, 0.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, -1.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
|
||||||
|
} else if (gl_Normal.x < -0.5) {
|
||||||
|
// -1.0, 0.0, 0.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
|
||||||
|
} else if (gl_Normal.y > 0.5) {
|
||||||
|
// 0.0, 1.0, 0.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
|
||||||
|
} else if (gl_Normal.y < -0.5) {
|
||||||
|
// 0.0, -1.0, 0.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
|
||||||
|
} else if (gl_Normal.z > 0.5) {
|
||||||
|
// 0.0, 0.0, 1.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
|
||||||
|
} else if (gl_Normal.z < -0.5) {
|
||||||
|
// 0.0, 0.0, -1.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3(-1.0, 0.0, 0.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 tbnMatrix = mat3( tangent.x, binormal.x, normal.x,
|
||||||
|
tangent.y, binormal.y, normal.y,
|
||||||
|
tangent.z, binormal.z, normal.z);
|
||||||
|
|
||||||
|
tsEyeVec = normalize(eyeVec * tbnMatrix);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4 color;
|
||||||
|
//color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
float day = gl_Color.r;
|
||||||
|
float night = gl_Color.g;
|
||||||
|
float light_source = gl_Color.b;
|
||||||
|
|
||||||
|
/*color.r = mix(night, day, dayNightRatio);
|
||||||
|
color.g = color.r;
|
||||||
|
color.b = color.r;*/
|
||||||
|
|
||||||
|
float rg = mix(night, day, dayNightRatio);
|
||||||
|
rg += light_source * 2.5; // Make light sources brighter
|
||||||
|
float b = rg;
|
||||||
|
|
||||||
|
// Moonlight is blue
|
||||||
|
b += (day - night) / 13.0;
|
||||||
|
rg -= (day - night) / 13.0;
|
||||||
|
|
||||||
|
// Emphase blue a bit in darker places
|
||||||
|
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
|
||||||
|
b += max(0.0, (1.0 - abs(b - 0.13)/0.17) * 0.025);
|
||||||
|
|
||||||
|
// Artificial light is yellow-ish
|
||||||
|
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
|
||||||
|
rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);
|
||||||
|
|
||||||
|
color.r = clamp(rg,0.0,1.0);
|
||||||
|
color.g = clamp(rg,0.0,1.0);
|
||||||
|
color.b = clamp(b,0.0,1.0);
|
||||||
|
|
||||||
|
// Make sides and bottom darker than the top
|
||||||
|
color = color * color; // SRGB -> Linear
|
||||||
|
if(gl_Normal.y <= 0.5)
|
||||||
|
color *= 0.6;
|
||||||
|
//color *= 0.7;
|
||||||
|
color = sqrt(color); // Linear -> SRGB
|
||||||
|
|
||||||
|
color.a = gl_Color.a;
|
||||||
|
|
||||||
|
gl_FrontColor = gl_BackColor = color;
|
||||||
|
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
|
|
||||||
|
}
|
||||||
47
cmake/Modules/FindCURL.cmake
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# - Find curl
|
||||||
|
# Find the native CURL headers and libraries.
|
||||||
|
#
|
||||||
|
# CURL_INCLUDE_DIR - where to find curl/curl.h, etc.
|
||||||
|
# CURL_LIBRARY - List of libraries when using curl.
|
||||||
|
# CURL_FOUND - True if curl found.
|
||||||
|
|
||||||
|
if( UNIX )
|
||||||
|
FIND_PATH(CURL_INCLUDE_DIR NAMES curl.h
|
||||||
|
PATHS
|
||||||
|
/usr/local/include/curl
|
||||||
|
/usr/include/curl
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(CURL_LIBRARY NAMES curl
|
||||||
|
PATHS
|
||||||
|
/usr/local/lib
|
||||||
|
/usr/lib
|
||||||
|
)
|
||||||
|
else( UNIX )
|
||||||
|
FIND_PATH(CURL_INCLUDE_DIR NAMES curl/curl.h) # Look for the header file.
|
||||||
|
FIND_LIBRARY(CURL_LIBRARY NAMES curl) # Look for the library.
|
||||||
|
FIND_FILE(CURL_DLL NAMES libcurl.dll
|
||||||
|
PATHS
|
||||||
|
"c:/windows/system32"
|
||||||
|
DOC "Path of the cURL dll (for installation)")
|
||||||
|
INCLUDE(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set CURL_FOUND to TRUE if
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(CURL DEFAULT_MSG CURL_LIBRARY CURL_INCLUDE_DIR) # all listed variables are TRUE
|
||||||
|
endif( UNIX )
|
||||||
|
|
||||||
|
if( WIN32 )
|
||||||
|
if( CURL_LIBRARY AND CURL_INCLUDE_DIR AND CURL_DLL ) # libcurl.dll is required on Windows
|
||||||
|
SET(CURL_FOUND TRUE)
|
||||||
|
else( CURL_LIBRARY AND CURL_INCLUDE_DIR AND CURL_DLL )
|
||||||
|
SET(CURL_FOUND FALSE)
|
||||||
|
endif( CURL_LIBRARY AND CURL_INCLUDE_DIR AND CURL_DLL )
|
||||||
|
else ( WIN32 )
|
||||||
|
if( CURL_LIBRARY AND CURL_INCLUDE_DIR )
|
||||||
|
SET(CURL_FOUND TRUE)
|
||||||
|
else( CURL_LIBRARY AND CURL_INCLUDE_DIR )
|
||||||
|
SET(CURL_FOUND FALSE)
|
||||||
|
endif( CURL_LIBRARY AND CURL_INCLUDE_DIR )
|
||||||
|
endif ( WIN32 )
|
||||||
|
|
||||||
|
MESSAGE(STATUS "CURL_INCLUDE_DIR = ${CURL_INCLUDE_DIR}")
|
||||||
|
MESSAGE(STATUS "CURL_LIBRARY = ${CURL_LIBRARY}")
|
||||||
|
MESSAGE(STATUS "CURL_DLL = ${CURL_DLL}")
|
||||||
@@ -59,7 +59,7 @@ ENDIF()
|
|||||||
IF(GETTEXT_FOUND)
|
IF(GETTEXT_FOUND)
|
||||||
SET(GETTEXT_PO_PATH ${CMAKE_SOURCE_DIR}/po)
|
SET(GETTEXT_PO_PATH ${CMAKE_SOURCE_DIR}/po)
|
||||||
SET(GETTEXT_MO_BUILD_PATH ${CMAKE_BINARY_DIR}/locale/<locale>/LC_MESSAGES)
|
SET(GETTEXT_MO_BUILD_PATH ${CMAKE_BINARY_DIR}/locale/<locale>/LC_MESSAGES)
|
||||||
SET(GETTEXT_MO_DEST_PATH ${DATADIR}/../locale/<locale>/LC_MESSAGES)
|
SET(GETTEXT_MO_DEST_PATH ${LOCALEDIR}/<locale>/LC_MESSAGES)
|
||||||
FILE(GLOB GETTEXT_AVAILABLE_LOCALES RELATIVE ${GETTEXT_PO_PATH} "${GETTEXT_PO_PATH}/*")
|
FILE(GLOB GETTEXT_AVAILABLE_LOCALES RELATIVE ${GETTEXT_PO_PATH} "${GETTEXT_PO_PATH}/*")
|
||||||
LIST(REMOVE_ITEM GETTEXT_AVAILABLE_LOCALES minetest.pot)
|
LIST(REMOVE_ITEM GETTEXT_AVAILABLE_LOCALES minetest.pot)
|
||||||
MACRO(SET_MO_PATHS _buildvar _destvar _locale)
|
MACRO(SET_MO_PATHS _buildvar _destvar _locale)
|
||||||
|
|||||||
18
cmake/Modules/FindJson.cmake
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Look for json, use our own if not found
|
||||||
|
|
||||||
|
#FIND_PATH(JSON_INCLUDE_DIR json.h)
|
||||||
|
|
||||||
|
#FIND_LIBRARY(JSON_LIBRARY NAMES jsoncpp)
|
||||||
|
|
||||||
|
#IF(JSON_LIBRARY AND JSON_INCLUDE_DIR)
|
||||||
|
# SET( JSON_FOUND TRUE )
|
||||||
|
#ENDIF(JSON_LIBRARY AND JSON_INCLUDE_DIR)
|
||||||
|
|
||||||
|
#IF(JSON_FOUND)
|
||||||
|
# MESSAGE(STATUS "Found system jsoncpp header file in ${JSON_INCLUDE_DIR}")
|
||||||
|
# MESSAGE(STATUS "Found system jsoncpp library ${JSON_LIBRARY}")
|
||||||
|
#ELSE(JSON_FOUND)
|
||||||
|
SET(JSON_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/json)
|
||||||
|
SET(JSON_LIBRARY jsoncpp)
|
||||||
|
MESSAGE(STATUS "Using project jsoncpp library")
|
||||||
|
#ENDIF(JSON_FOUND)
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# Look for jthread, use our own if not found
|
|
||||||
|
|
||||||
FIND_PATH(JTHREAD_INCLUDE_DIR jthread.h)
|
|
||||||
|
|
||||||
FIND_LIBRARY(JTHREAD_LIBRARY NAMES jthread)
|
|
||||||
|
|
||||||
IF(JTHREAD_LIBRARY AND JTHREAD_INCLUDE_DIR)
|
|
||||||
SET( JTHREAD_FOUND TRUE )
|
|
||||||
ENDIF(JTHREAD_LIBRARY AND JTHREAD_INCLUDE_DIR)
|
|
||||||
|
|
||||||
IF(JTHREAD_FOUND)
|
|
||||||
MESSAGE(STATUS "Found system jthread header file in ${JTHREAD_INCLUDE_DIR}")
|
|
||||||
MESSAGE(STATUS "Found system jthread library ${JTHREAD_LIBRARY}")
|
|
||||||
ELSE(JTHREAD_FOUND)
|
|
||||||
SET(JTHREAD_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/jthread)
|
|
||||||
SET(JTHREAD_LIBRARY jthread)
|
|
||||||
MESSAGE(STATUS "Using project jthread library")
|
|
||||||
ENDIF(JTHREAD_FOUND)
|
|
||||||
130
cmake/Modules/FindOpenGLES2.cmake
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
#-------------------------------------------------------------------
|
||||||
|
# This file is stolen from part of the CMake build system for OGRE (Object-oriented Graphics Rendering Engine) http://www.ogre3d.org/
|
||||||
|
#
|
||||||
|
# The contents of this file are placed in the public domain. Feel
|
||||||
|
# free to make use of it in any way you like.
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
# - Try to find OpenGLES and EGL
|
||||||
|
# Once done this will define
|
||||||
|
#
|
||||||
|
# OPENGLES2_FOUND - system has OpenGLES
|
||||||
|
# OPENGLES2_INCLUDE_DIR - the GL include directory
|
||||||
|
# OPENGLES2_LIBRARIES - Link these to use OpenGLES
|
||||||
|
#
|
||||||
|
# EGL_FOUND - system has EGL
|
||||||
|
# EGL_INCLUDE_DIR - the EGL include directory
|
||||||
|
# EGL_LIBRARIES - Link these to use EGL
|
||||||
|
|
||||||
|
# win32, apple, android NOT TESED
|
||||||
|
# linux tested and works
|
||||||
|
|
||||||
|
IF (WIN32)
|
||||||
|
IF (CYGWIN)
|
||||||
|
|
||||||
|
FIND_PATH(OPENGLES2_INCLUDE_DIR GLES2/gl2.h )
|
||||||
|
|
||||||
|
FIND_LIBRARY(OPENGLES2_gl_LIBRARY libGLESv2 )
|
||||||
|
|
||||||
|
ELSE (CYGWIN)
|
||||||
|
|
||||||
|
IF(BORLAND)
|
||||||
|
SET (OPENGLES2_gl_LIBRARY import32 CACHE STRING "OpenGL ES 2.x library for win32")
|
||||||
|
ELSE(BORLAND)
|
||||||
|
# todo
|
||||||
|
# SET (OPENGLES_gl_LIBRARY ${SOURCE_DIR}/Dependencies/lib/release/libGLESv2.lib CACHE STRING "OpenGL ES 2.x library for win32"
|
||||||
|
ENDIF(BORLAND)
|
||||||
|
|
||||||
|
ENDIF (CYGWIN)
|
||||||
|
|
||||||
|
ELSE (WIN32)
|
||||||
|
|
||||||
|
IF (APPLE)
|
||||||
|
|
||||||
|
create_search_paths(/Developer/Platforms)
|
||||||
|
findpkg_framework(OpenGLES2)
|
||||||
|
set(OPENGLES2_gl_LIBRARY "-framework OpenGLES")
|
||||||
|
|
||||||
|
ELSE(APPLE)
|
||||||
|
|
||||||
|
FIND_PATH(OPENGLES2_INCLUDE_DIR GLES2/gl2.h
|
||||||
|
/usr/openwin/share/include
|
||||||
|
/opt/graphics/OpenGL/include /usr/X11R6/include
|
||||||
|
/usr/include
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(OPENGLES2_gl_LIBRARY
|
||||||
|
NAMES GLESv2
|
||||||
|
PATHS /opt/graphics/OpenGL/lib
|
||||||
|
/usr/openwin/lib
|
||||||
|
/usr/shlib /usr/X11R6/lib
|
||||||
|
/usr/lib
|
||||||
|
)
|
||||||
|
|
||||||
|
IF (NOT BUILD_ANDROID)
|
||||||
|
FIND_PATH(EGL_INCLUDE_DIR EGL/egl.h
|
||||||
|
/usr/openwin/share/include
|
||||||
|
/opt/graphics/OpenGL/include /usr/X11R6/include
|
||||||
|
/usr/include
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(EGL_egl_LIBRARY
|
||||||
|
NAMES EGL
|
||||||
|
PATHS /opt/graphics/OpenGL/lib
|
||||||
|
/usr/openwin/lib
|
||||||
|
/usr/shlib /usr/X11R6/lib
|
||||||
|
/usr/lib
|
||||||
|
)
|
||||||
|
|
||||||
|
# On Unix OpenGL most certainly always requires X11.
|
||||||
|
# Feel free to tighten up these conditions if you don't
|
||||||
|
# think this is always true.
|
||||||
|
# It's not true on OSX.
|
||||||
|
|
||||||
|
IF (OPENGLES2_gl_LIBRARY)
|
||||||
|
IF(NOT X11_FOUND)
|
||||||
|
INCLUDE(FindX11)
|
||||||
|
ENDIF(NOT X11_FOUND)
|
||||||
|
IF (X11_FOUND)
|
||||||
|
IF (NOT APPLE)
|
||||||
|
SET (OPENGLES2_LIBRARIES ${X11_LIBRARIES})
|
||||||
|
ENDIF (NOT APPLE)
|
||||||
|
ENDIF (X11_FOUND)
|
||||||
|
ENDIF (OPENGLES2_gl_LIBRARY)
|
||||||
|
ENDIF ()
|
||||||
|
|
||||||
|
ENDIF(APPLE)
|
||||||
|
ENDIF (WIN32)
|
||||||
|
|
||||||
|
#SET( OPENGLES2_LIBRARIES ${OPENGLES2_gl_LIBRARY} ${OPENGLES2_LIBRARIES})
|
||||||
|
|
||||||
|
IF (BUILD_ANDROID)
|
||||||
|
IF(OPENGLES2_gl_LIBRARY)
|
||||||
|
SET( OPENGLES2_LIBRARIES ${OPENGLES2_gl_LIBRARY} ${OPENGLES2_LIBRARIES})
|
||||||
|
SET( EGL_LIBRARIES)
|
||||||
|
SET( OPENGLES2_FOUND "YES" )
|
||||||
|
ENDIF(OPENGLES2_gl_LIBRARY)
|
||||||
|
ELSE ()
|
||||||
|
|
||||||
|
SET( OPENGLES2_LIBRARIES ${OPENGLES2_gl_LIBRARY} ${OPENGLES2_LIBRARIES})
|
||||||
|
|
||||||
|
IF(OPENGLES2_gl_LIBRARY AND EGL_egl_LIBRARY)
|
||||||
|
SET( OPENGLES2_LIBRARIES ${OPENGLES2_gl_LIBRARY} ${OPENGLES2_LIBRARIES})
|
||||||
|
SET( EGL_LIBRARIES ${EGL_egl_LIBRARY} ${EGL_LIBRARIES})
|
||||||
|
SET( OPENGLES2_FOUND "YES" )
|
||||||
|
ENDIF(OPENGLES2_gl_LIBRARY AND EGL_egl_LIBRARY)
|
||||||
|
|
||||||
|
ENDIF ()
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(
|
||||||
|
OPENGLES2_INCLUDE_DIR
|
||||||
|
OPENGLES2_gl_LIBRARY
|
||||||
|
EGL_INCLUDE_DIR
|
||||||
|
EGL_egl_LIBRARY
|
||||||
|
)
|
||||||
|
|
||||||
|
IF(OPENGLES2_FOUND)
|
||||||
|
MESSAGE(STATUS "Found system opengles2 library ${OPENGLES2_LIBRARIES}")
|
||||||
|
ELSE ()
|
||||||
|
SET(OPENGLES2_LIBRARIES "")
|
||||||
|
ENDIF ()
|
||||||
46
cmake/Modules/FindVorbis.cmake
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# - Find vorbis
|
||||||
|
# Find the native vorbis includes and libraries
|
||||||
|
#
|
||||||
|
# VORBIS_INCLUDE_DIR - where to find vorbis.h, etc.
|
||||||
|
# OGG_INCLUDE_DIR - where to find ogg/ogg.h, etc.
|
||||||
|
# VORBIS_LIBRARIES - List of libraries when using vorbis(file).
|
||||||
|
# VORBIS_FOUND - True if vorbis found.
|
||||||
|
|
||||||
|
if(NOT GP2XWIZ)
|
||||||
|
if(VORBIS_INCLUDE_DIR)
|
||||||
|
# Already in cache, be silent
|
||||||
|
set(VORBIS_FIND_QUIETLY TRUE)
|
||||||
|
endif(VORBIS_INCLUDE_DIR)
|
||||||
|
find_path(OGG_INCLUDE_DIR ogg/ogg.h)
|
||||||
|
find_path(VORBIS_INCLUDE_DIR vorbis/vorbisfile.h)
|
||||||
|
# MSVC built ogg/vorbis may be named ogg_static and vorbis_static
|
||||||
|
find_library(OGG_LIBRARY NAMES ogg ogg_static)
|
||||||
|
find_library(VORBIS_LIBRARY NAMES vorbis vorbis_static)
|
||||||
|
find_library(VORBISFILE_LIBRARY NAMES vorbisfile vorbisfile_static)
|
||||||
|
# Handle the QUIETLY and REQUIRED arguments and set VORBIS_FOUND
|
||||||
|
# to TRUE if all listed variables are TRUE.
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(VORBIS DEFAULT_MSG
|
||||||
|
OGG_INCLUDE_DIR VORBIS_INCLUDE_DIR
|
||||||
|
OGG_LIBRARY VORBIS_LIBRARY VORBISFILE_LIBRARY)
|
||||||
|
else(NOT GP2XWIZ)
|
||||||
|
find_path(VORBIS_INCLUDE_DIR tremor/ivorbisfile.h)
|
||||||
|
find_library(VORBIS_LIBRARY NAMES vorbis_dec)
|
||||||
|
find_package_handle_standard_args(VORBIS DEFAULT_MSG
|
||||||
|
VORBIS_INCLUDE_DIR VORBIS_LIBRARY)
|
||||||
|
endif(NOT GP2XWIZ)
|
||||||
|
|
||||||
|
if(VORBIS_FOUND)
|
||||||
|
if(NOT GP2XWIZ)
|
||||||
|
set(VORBIS_LIBRARIES ${VORBISFILE_LIBRARY} ${VORBIS_LIBRARY}
|
||||||
|
${OGG_LIBRARY})
|
||||||
|
else(NOT GP2XWIZ)
|
||||||
|
set(VORBIS_LIBRARIES ${VORBIS_LIBRARY})
|
||||||
|
endif(NOT GP2XWIZ)
|
||||||
|
else(VORBIS_FOUND)
|
||||||
|
set(VORBIS_LIBRARIES)
|
||||||
|
endif(VORBIS_FOUND)
|
||||||
|
|
||||||
|
mark_as_advanced(OGG_INCLUDE_DIR VORBIS_INCLUDE_DIR)
|
||||||
|
mark_as_advanced(OGG_LIBRARY VORBIS_LIBRARY VORBISFILE_LIBRARY)
|
||||||
|
|
||||||
20
cmake/Modules/GenerateVersion.cmake
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Always run during 'make'
|
||||||
|
|
||||||
|
if(VERSION_EXTRA)
|
||||||
|
set(VERSION_GITHASH "${VERSION_STRING}")
|
||||||
|
else(VERSION_EXTRA)
|
||||||
|
execute_process(COMMAND git describe --always --tag --dirty
|
||||||
|
WORKING_DIRECTORY "${GENERATE_VERSION_SOURCE_DIR}"
|
||||||
|
OUTPUT_VARIABLE VERSION_GITHASH OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
ERROR_QUIET)
|
||||||
|
|
||||||
|
if(VERSION_GITHASH)
|
||||||
|
message(STATUS "*** Detected git version ${VERSION_GITHASH} ***")
|
||||||
|
else()
|
||||||
|
set(VERSION_GITHASH "${VERSION_STRING}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
configure_file(
|
||||||
|
${GENERATE_VERSION_SOURCE_DIR}/cmake_config_githash.h.in
|
||||||
|
${GENERATE_VERSION_BINARY_DIR}/cmake_config_githash.h)
|
||||||
872
data/builtin.lua
@@ -1,872 +0,0 @@
|
|||||||
--
|
|
||||||
-- This file contains built-in stuff in Minetest implemented in Lua.
|
|
||||||
--
|
|
||||||
-- It is always loaded and executed after registration of the C API,
|
|
||||||
-- before loading and running any mods.
|
|
||||||
--
|
|
||||||
|
|
||||||
function basic_dump2(o)
|
|
||||||
if type(o) == "number" then
|
|
||||||
return tostring(o)
|
|
||||||
elseif type(o) == "string" then
|
|
||||||
return string.format("%q", o)
|
|
||||||
elseif type(o) == "boolean" then
|
|
||||||
return tostring(o)
|
|
||||||
elseif type(o) == "function" then
|
|
||||||
return "<function>"
|
|
||||||
elseif type(o) == "userdata" then
|
|
||||||
return "<userdata>"
|
|
||||||
elseif type(o) == "nil" then
|
|
||||||
return "nil"
|
|
||||||
else
|
|
||||||
error("cannot dump a " .. type(o))
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function dump2(o, name, dumped)
|
|
||||||
name = name or "_"
|
|
||||||
dumped = dumped or {}
|
|
||||||
io.write(name, " = ")
|
|
||||||
if type(o) == "number" or type(o) == "string" or type(o) == "boolean"
|
|
||||||
or type(o) == "function" or type(o) == "nil"
|
|
||||||
or type(o) == "userdata" then
|
|
||||||
io.write(basic_dump2(o), "\n")
|
|
||||||
elseif type(o) == "table" then
|
|
||||||
if dumped[o] then
|
|
||||||
io.write(dumped[o], "\n")
|
|
||||||
else
|
|
||||||
dumped[o] = name
|
|
||||||
io.write("{}\n") -- new table
|
|
||||||
for k,v in pairs(o) do
|
|
||||||
local fieldname = string.format("%s[%s]", name, basic_dump2(k))
|
|
||||||
dump2(v, fieldname, dumped)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
error("cannot dump a " .. type(o))
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function dump(o, dumped)
|
|
||||||
dumped = dumped or {}
|
|
||||||
if type(o) == "number" then
|
|
||||||
return tostring(o)
|
|
||||||
elseif type(o) == "string" then
|
|
||||||
return string.format("%q", o)
|
|
||||||
elseif type(o) == "table" then
|
|
||||||
if dumped[o] then
|
|
||||||
return "<circular reference>"
|
|
||||||
end
|
|
||||||
dumped[o] = true
|
|
||||||
local t = {}
|
|
||||||
for k,v in pairs(o) do
|
|
||||||
t[#t+1] = "" .. k .. " = " .. dump(v, dumped)
|
|
||||||
end
|
|
||||||
return "{" .. table.concat(t, ", ") .. "}"
|
|
||||||
elseif type(o) == "boolean" then
|
|
||||||
return tostring(o)
|
|
||||||
elseif type(o) == "function" then
|
|
||||||
return "<function>"
|
|
||||||
elseif type(o) == "userdata" then
|
|
||||||
return "<userdata>"
|
|
||||||
elseif type(o) == "nil" then
|
|
||||||
return "nil"
|
|
||||||
else
|
|
||||||
error("cannot dump a " .. type(o))
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Item definition helpers
|
|
||||||
--
|
|
||||||
|
|
||||||
function minetest.inventorycube(img1, img2, img3)
|
|
||||||
img2 = img2 or img1
|
|
||||||
img3 = img3 or img1
|
|
||||||
return "[inventorycube"
|
|
||||||
.. "{" .. img1:gsub("%^", "&")
|
|
||||||
.. "{" .. img2:gsub("%^", "&")
|
|
||||||
.. "{" .. img3:gsub("%^", "&")
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.pos_to_string(pos)
|
|
||||||
return "(" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ")"
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.get_pointed_thing_position(pointed_thing, above)
|
|
||||||
if pointed_thing.type == "node" then
|
|
||||||
if above then
|
|
||||||
-- The position where a node would be placed
|
|
||||||
return pointed_thing.above
|
|
||||||
else
|
|
||||||
-- The position where a node would be dug
|
|
||||||
return pointed_thing.under
|
|
||||||
end
|
|
||||||
elseif pointed_thing.type == "object" then
|
|
||||||
obj = pointed.thing.ref
|
|
||||||
if obj ~= nil then
|
|
||||||
return obj:getpos()
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.dir_to_facedir(dir)
|
|
||||||
if math.abs(dir.x) > math.abs(dir.z) then
|
|
||||||
if dir.x < 0 then
|
|
||||||
return 3
|
|
||||||
else
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if dir.z < 0 then
|
|
||||||
return 2
|
|
||||||
else
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.dir_to_wallmounted(dir)
|
|
||||||
if math.abs(dir.y) > math.max(math.abs(dir.x), math.abs(dir.z)) then
|
|
||||||
if dir.y < 0 then
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
elseif math.abs(dir.x) > math.abs(dir.z) then
|
|
||||||
if dir.x < 0 then
|
|
||||||
return 3
|
|
||||||
else
|
|
||||||
return 2
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if dir.z < 0 then
|
|
||||||
return 5
|
|
||||||
else
|
|
||||||
return 4
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.get_node_drops(nodename, toolname)
|
|
||||||
local drop = ItemStack({name=nodename}):get_definition().drop
|
|
||||||
if drop == nil then
|
|
||||||
-- default drop
|
|
||||||
return {ItemStack({name=nodename})}
|
|
||||||
elseif type(drop) == "string" then
|
|
||||||
-- itemstring drop
|
|
||||||
return {ItemStack(drop)}
|
|
||||||
elseif drop.items == nil then
|
|
||||||
-- drop = {} to disable default drop
|
|
||||||
return {}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Extended drop table
|
|
||||||
local got_items = {}
|
|
||||||
local got_count = 0
|
|
||||||
local _, item, tool
|
|
||||||
for _, item in ipairs(drop.items) do
|
|
||||||
local good_rarity = true
|
|
||||||
local good_tool = true
|
|
||||||
if item.rarity ~= nil then
|
|
||||||
good_rarity = item.rarity < 1 or math.random(item.rarity) == 1
|
|
||||||
end
|
|
||||||
if item.tools ~= nil then
|
|
||||||
good_tool = false
|
|
||||||
for _, tool in ipairs(item.tools) do
|
|
||||||
if tool:sub(1, 1) == '~' then
|
|
||||||
good_tool = toolname:find(tool:sub(2)) ~= nil
|
|
||||||
else
|
|
||||||
good_tool = toolname == tool
|
|
||||||
end
|
|
||||||
if good_tool then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if good_rarity and good_tool then
|
|
||||||
got_count = got_count + 1
|
|
||||||
for _, add_item in ipairs(item.items) do
|
|
||||||
got_items[#got_items+1] = add_item
|
|
||||||
end
|
|
||||||
if drop.max_items ~= nil and got_count == drop.max_items then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return got_items
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.item_place_node(itemstack, placer, pointed_thing)
|
|
||||||
local item = itemstack:peek_item()
|
|
||||||
local def = itemstack:get_definition()
|
|
||||||
if def.type == "node" and pointed_thing.type == "node" then
|
|
||||||
local pos = pointed_thing.above
|
|
||||||
local oldnode = minetest.env:get_node(pos)
|
|
||||||
local olddef = ItemStack({name=oldnode.name}):get_definition()
|
|
||||||
|
|
||||||
if not olddef.buildable_to then
|
|
||||||
minetest.log("info", placer:get_player_name() .. " tried to place"
|
|
||||||
.. " node in invalid position " .. minetest.pos_to_string(pos)
|
|
||||||
.. ", replacing " .. oldnode.name)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.log("action", placer:get_player_name() .. " places node "
|
|
||||||
.. def.name .. " at " .. minetest.pos_to_string(pos))
|
|
||||||
|
|
||||||
local newnode = {name = def.name, param1 = 0, param2 = 0}
|
|
||||||
|
|
||||||
-- Calculate direction for wall mounted stuff like torches and signs
|
|
||||||
if def.paramtype2 == 'wallmounted' then
|
|
||||||
local under = pointed_thing.under
|
|
||||||
local above = pointed_thing.above
|
|
||||||
local dir = {x = under.x - above.x, y = under.y - above.y, z = under.z - above.z}
|
|
||||||
newnode.param2 = minetest.dir_to_wallmounted(dir)
|
|
||||||
-- Calculate the direction for furnaces and chests and stuff
|
|
||||||
elseif def.paramtype2 == 'facedir' then
|
|
||||||
local playerpos = placer:getpos()
|
|
||||||
local dir = {x = pos.x - playerpos.x, y = pos.y - playerpos.y, z = pos.z - playerpos.z}
|
|
||||||
newnode.param2 = minetest.dir_to_facedir(dir)
|
|
||||||
minetest.log("action", "facedir: " .. newnode.param2)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Add node and update
|
|
||||||
minetest.env:add_node(pos, newnode)
|
|
||||||
|
|
||||||
-- Set metadata owner
|
|
||||||
if def.metadata_name ~= "" then
|
|
||||||
minetest.env:get_meta(pos):set_owner(placer:get_player_name())
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Run script hook
|
|
||||||
local _, callback
|
|
||||||
for _, callback in ipairs(minetest.registered_on_placenodes) do
|
|
||||||
callback(pos, newnode, placer)
|
|
||||||
end
|
|
||||||
|
|
||||||
itemstack:take_item()
|
|
||||||
end
|
|
||||||
return itemstack
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.item_place_object(itemstack, placer, pointed_thing)
|
|
||||||
local pos = minetest.get_pointed_thing_position(pointed_thing, true)
|
|
||||||
if pos ~= nil then
|
|
||||||
local item = itemstack:take_item()
|
|
||||||
minetest.env:add_item(pos, item)
|
|
||||||
end
|
|
||||||
return itemstack
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.item_place(itemstack, placer, pointed_thing)
|
|
||||||
if itemstack:get_definition().type == "node" then
|
|
||||||
return minetest.item_place_node(itemstack, placer, pointed_thing)
|
|
||||||
else
|
|
||||||
return minetest.item_place_object(itemstack, placer, pointed_thing)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.item_drop(itemstack, dropper, pos)
|
|
||||||
minetest.env:add_item(pos, itemstack)
|
|
||||||
return ""
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.item_eat(hp_change, replace_with_item)
|
|
||||||
return function(itemstack, user, pointed_thing) -- closure
|
|
||||||
if itemstack:take_item() ~= nil then
|
|
||||||
user:set_hp(user:get_hp() + hp_change)
|
|
||||||
itemstack:add_item(replace_with_item) -- note: replace_with_item is optional
|
|
||||||
end
|
|
||||||
return itemstack
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.node_punch(pos, node, puncher)
|
|
||||||
-- Run script hook
|
|
||||||
local _, callback
|
|
||||||
for _, callback in ipairs(minetest.registered_on_punchnodes) do
|
|
||||||
callback(pos, node, puncher)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.node_dig(pos, node, digger)
|
|
||||||
minetest.debug("node_dig")
|
|
||||||
|
|
||||||
local def = ItemStack({name=node.name}):get_definition()
|
|
||||||
if not def.diggable then
|
|
||||||
minetest.debug("not diggable")
|
|
||||||
minetest.log("info", digger:get_player_name() .. " tried to dig "
|
|
||||||
.. node.name .. " which is not diggable "
|
|
||||||
.. minetest.pos_to_string(pos))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local meta = minetest.env:get_meta(pos)
|
|
||||||
if meta ~= nil and not meta:get_allow_removal() then
|
|
||||||
minetest.debug("dig prevented by metadata")
|
|
||||||
minetest.log("info", digger:get_player_name() .. " tried to dig "
|
|
||||||
.. node.name .. ", but removal is disabled by metadata "
|
|
||||||
.. minetest.pos_to_string(pos))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.log('action', digger:get_player_name() .. " digs "
|
|
||||||
.. node.name .. " at " .. minetest.pos_to_string(pos))
|
|
||||||
|
|
||||||
if not minetest.setting_getbool("creative_mode") then
|
|
||||||
local wielded = digger:get_wielded_item()
|
|
||||||
local drops = minetest.get_node_drops(node.name, wielded:get_name())
|
|
||||||
|
|
||||||
-- Wear out tool
|
|
||||||
mp = def.material
|
|
||||||
tp = wielded:get_tool_digging_properties()
|
|
||||||
dp = minetest.get_digging_properties(mp, tp)
|
|
||||||
wielded:add_wear(dp.wear)
|
|
||||||
digger:set_wielded_item(wielded)
|
|
||||||
|
|
||||||
-- Add dropped items
|
|
||||||
local _, dropped_item
|
|
||||||
for _, dropped_item in ipairs(drops) do
|
|
||||||
digger:get_inventory():add_item("main", dropped_item)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Remove node and update
|
|
||||||
minetest.env:remove_node(pos)
|
|
||||||
|
|
||||||
-- Run script hook
|
|
||||||
local _, callback
|
|
||||||
for _, callback in ipairs(minetest.registered_on_dignodes) do
|
|
||||||
callback(pos, node, digger)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Item definition defaults
|
|
||||||
--
|
|
||||||
|
|
||||||
minetest.nodedef_default = {
|
|
||||||
-- Item properties
|
|
||||||
type="node",
|
|
||||||
-- name intentionally not defined here
|
|
||||||
description = "",
|
|
||||||
groups = {},
|
|
||||||
inventory_image = "",
|
|
||||||
wield_image = "",
|
|
||||||
wield_scale = {x=1,y=1,z=1},
|
|
||||||
stack_max = 99,
|
|
||||||
usable = false,
|
|
||||||
liquids_pointable = false,
|
|
||||||
tool_digging_properties = nil,
|
|
||||||
|
|
||||||
-- Interaction callbacks
|
|
||||||
on_place = minetest.item_place,
|
|
||||||
on_drop = minetest.item_drop,
|
|
||||||
on_use = nil,
|
|
||||||
|
|
||||||
on_punch = minetest.node_punch,
|
|
||||||
on_dig = minetest.node_dig,
|
|
||||||
|
|
||||||
-- Node properties
|
|
||||||
drawtype = "normal",
|
|
||||||
visual_scale = 1.0,
|
|
||||||
tile_images = {""},
|
|
||||||
special_materials = {
|
|
||||||
{image="", backface_culling=true},
|
|
||||||
{image="", backface_culling=true},
|
|
||||||
},
|
|
||||||
alpha = 255,
|
|
||||||
post_effect_color = {a=0, r=0, g=0, b=0},
|
|
||||||
paramtype = "none",
|
|
||||||
paramtype2 = "none",
|
|
||||||
is_ground_content = false,
|
|
||||||
sunlight_propagates = false,
|
|
||||||
walkable = true,
|
|
||||||
pointable = true,
|
|
||||||
diggable = true,
|
|
||||||
climbable = false,
|
|
||||||
buildable_to = false,
|
|
||||||
metadata_name = "",
|
|
||||||
liquidtype = "none",
|
|
||||||
liquid_alternative_flowing = "",
|
|
||||||
liquid_alternative_source = "",
|
|
||||||
liquid_viscosity = 0,
|
|
||||||
light_source = 0,
|
|
||||||
damage_per_second = 0,
|
|
||||||
selection_box = {type="regular"},
|
|
||||||
material = {
|
|
||||||
diggablity = "normal",
|
|
||||||
weight = 0,
|
|
||||||
crackiness = 0,
|
|
||||||
crumbliness = 0,
|
|
||||||
cuttability = 0,
|
|
||||||
flammability = 0,
|
|
||||||
},
|
|
||||||
legacy_facedir_simple = false,
|
|
||||||
legacy_wallmounted = false,
|
|
||||||
}
|
|
||||||
|
|
||||||
minetest.craftitemdef_default = {
|
|
||||||
type="craft",
|
|
||||||
-- name intentionally not defined here
|
|
||||||
description = "",
|
|
||||||
groups = {},
|
|
||||||
inventory_image = "",
|
|
||||||
wield_image = "",
|
|
||||||
wield_scale = {x=1,y=1,z=1},
|
|
||||||
stack_max = 99,
|
|
||||||
liquids_pointable = false,
|
|
||||||
tool_digging_properties = nil,
|
|
||||||
|
|
||||||
-- Interaction callbacks
|
|
||||||
on_place = minetest.item_place,
|
|
||||||
on_drop = minetest.item_drop,
|
|
||||||
on_use = nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
minetest.tooldef_default = {
|
|
||||||
type="tool",
|
|
||||||
-- name intentionally not defined here
|
|
||||||
description = "",
|
|
||||||
groups = {},
|
|
||||||
inventory_image = "",
|
|
||||||
wield_image = "",
|
|
||||||
wield_scale = {x=1,y=1,z=1},
|
|
||||||
stack_max = 1,
|
|
||||||
liquids_pointable = false,
|
|
||||||
tool_digging_properties = nil,
|
|
||||||
|
|
||||||
-- Interaction callbacks
|
|
||||||
on_place = minetest.item_place,
|
|
||||||
on_drop = minetest.item_drop,
|
|
||||||
on_use = nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
minetest.noneitemdef_default = { -- This is used for the hand and unknown items
|
|
||||||
type="none",
|
|
||||||
-- name intentionally not defined here
|
|
||||||
description = "",
|
|
||||||
groups = {},
|
|
||||||
inventory_image = "",
|
|
||||||
wield_image = "",
|
|
||||||
wield_scale = {x=1,y=1,z=1},
|
|
||||||
stack_max = 99,
|
|
||||||
liquids_pointable = false,
|
|
||||||
tool_digging_properties = nil,
|
|
||||||
|
|
||||||
-- Interaction callbacks
|
|
||||||
on_place = nil,
|
|
||||||
on_drop = nil,
|
|
||||||
on_use = nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Make raw registration functions inaccessible to anyone except builtin.lua
|
|
||||||
--
|
|
||||||
|
|
||||||
local register_item_raw = minetest.register_item_raw
|
|
||||||
minetest.register_item_raw = nil
|
|
||||||
|
|
||||||
local register_alias_raw = minetest.register_alias_raw
|
|
||||||
minetest.register_item_raw = nil
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Item / entity / ABM registration functions
|
|
||||||
--
|
|
||||||
|
|
||||||
minetest.registered_abms = {}
|
|
||||||
minetest.registered_entities = {}
|
|
||||||
minetest.registered_items = {}
|
|
||||||
minetest.registered_nodes = {}
|
|
||||||
minetest.registered_craftitems = {}
|
|
||||||
minetest.registered_tools = {}
|
|
||||||
minetest.registered_aliases = {}
|
|
||||||
|
|
||||||
-- For tables that are indexed by item name:
|
|
||||||
-- If table[X] does not exist, default to table[minetest.registered_aliases[X]]
|
|
||||||
local function set_alias_metatable(table)
|
|
||||||
setmetatable(table, {
|
|
||||||
__index = function(name)
|
|
||||||
return rawget(table, minetest.registered_aliases[name])
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
set_alias_metatable(minetest.registered_items)
|
|
||||||
set_alias_metatable(minetest.registered_nodes)
|
|
||||||
set_alias_metatable(minetest.registered_craftitems)
|
|
||||||
set_alias_metatable(minetest.registered_tools)
|
|
||||||
|
|
||||||
-- These item names may not be used because they would interfere
|
|
||||||
-- with legacy itemstrings
|
|
||||||
local forbidden_item_names = {
|
|
||||||
MaterialItem = true,
|
|
||||||
MaterialItem2 = true,
|
|
||||||
MaterialItem3 = true,
|
|
||||||
NodeItem = true,
|
|
||||||
node = true,
|
|
||||||
CraftItem = true,
|
|
||||||
craft = true,
|
|
||||||
MBOItem = true,
|
|
||||||
ToolItem = true,
|
|
||||||
tool = true,
|
|
||||||
}
|
|
||||||
|
|
||||||
local function check_modname_prefix(name)
|
|
||||||
if name:sub(1,1) == ":" then
|
|
||||||
-- Escape the modname prefix enforcement mechanism
|
|
||||||
return name:sub(2)
|
|
||||||
else
|
|
||||||
-- Modname prefix enforcement
|
|
||||||
local expected_prefix = minetest.get_current_modname() .. ":"
|
|
||||||
if name:sub(1, #expected_prefix) ~= expected_prefix then
|
|
||||||
error("Name " .. name .. " does not follow naming conventions: " ..
|
|
||||||
"\"modname:\" or \":\" prefix required")
|
|
||||||
end
|
|
||||||
local subname = name:sub(#expected_prefix+1)
|
|
||||||
if subname:find("[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]") then
|
|
||||||
error("Name " .. name .. " does not follow naming conventions: " ..
|
|
||||||
"contains unallowed characters")
|
|
||||||
end
|
|
||||||
return name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.register_abm(spec)
|
|
||||||
-- Add to minetest.registered_abms
|
|
||||||
minetest.registered_abms[#minetest.registered_abms+1] = spec
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.register_entity(name, prototype)
|
|
||||||
-- Check name
|
|
||||||
if name == nil then
|
|
||||||
error("Unable to register entity: Name is nil")
|
|
||||||
end
|
|
||||||
name = check_modname_prefix(tostring(name))
|
|
||||||
|
|
||||||
prototype.name = name
|
|
||||||
prototype.__index = prototype -- so that it can be used as a metatable
|
|
||||||
|
|
||||||
-- Add to minetest.registered_entities
|
|
||||||
minetest.registered_entities[name] = prototype
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.register_item(name, itemdef)
|
|
||||||
-- Check name
|
|
||||||
if name == nil then
|
|
||||||
error("Unable to register item: Name is nil")
|
|
||||||
end
|
|
||||||
name = check_modname_prefix(tostring(name))
|
|
||||||
if forbidden_item_names[name] then
|
|
||||||
error("Unable to register item: Name is forbidden: " .. name)
|
|
||||||
end
|
|
||||||
itemdef.name = name
|
|
||||||
|
|
||||||
-- Apply defaults and add to registered_* table
|
|
||||||
if itemdef.type == "node" then
|
|
||||||
setmetatable(itemdef, {__index = minetest.nodedef_default})
|
|
||||||
minetest.registered_nodes[itemdef.name] = itemdef
|
|
||||||
elseif itemdef.type == "craft" then
|
|
||||||
setmetatable(itemdef, {__index = minetest.craftitemdef_default})
|
|
||||||
minetest.registered_craftitems[itemdef.name] = itemdef
|
|
||||||
elseif itemdef.type == "tool" then
|
|
||||||
setmetatable(itemdef, {__index = minetest.tooldef_default})
|
|
||||||
minetest.registered_tools[itemdef.name] = itemdef
|
|
||||||
elseif itemdef.type == "none" then
|
|
||||||
setmetatable(itemdef, {__index = minetest.noneitemdef_default})
|
|
||||||
else
|
|
||||||
error("Unable to register item: Type is invalid: " .. dump(itemdef))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Flowing liquid uses param2
|
|
||||||
if itemdef.type == "node" and itemdef.liquidtype == "flowing" then
|
|
||||||
itemdef.paramtype2 = "flowingliquid"
|
|
||||||
end
|
|
||||||
|
|
||||||
-- BEGIN Legacy stuff
|
|
||||||
if itemdef.cookresult_itemstring ~= nil and itemdef.cookresult_itemstring ~= "" then
|
|
||||||
minetest.register_craft({
|
|
||||||
type="cooking",
|
|
||||||
output=itemdef.cookresult_itemstring,
|
|
||||||
recipe=itemdef.name,
|
|
||||||
cooktime=itemdef.furnace_cooktime
|
|
||||||
})
|
|
||||||
end
|
|
||||||
if itemdef.furnace_burntime ~= nil and itemdef.furnace_burntime >= 0 then
|
|
||||||
minetest.register_craft({
|
|
||||||
type="fuel",
|
|
||||||
recipe=itemdef.name,
|
|
||||||
burntime=itemdef.furnace_burntime
|
|
||||||
})
|
|
||||||
end
|
|
||||||
-- END Legacy stuff
|
|
||||||
|
|
||||||
-- Disable all further modifications
|
|
||||||
getmetatable(itemdef).__newindex = {}
|
|
||||||
|
|
||||||
--minetest.log("Registering item: " .. itemdef.name)
|
|
||||||
minetest.registered_items[itemdef.name] = itemdef
|
|
||||||
minetest.registered_aliases[itemdef.name] = nil
|
|
||||||
register_item_raw(itemdef)
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.register_node(name, nodedef)
|
|
||||||
nodedef.type = "node"
|
|
||||||
minetest.register_item(name, nodedef)
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.register_craftitem(name, craftitemdef)
|
|
||||||
craftitemdef.type = "craft"
|
|
||||||
|
|
||||||
-- BEGIN Legacy stuff
|
|
||||||
if craftitemdef.inventory_image == nil and craftitemdef.image ~= nil then
|
|
||||||
craftitemdef.inventory_image = craftitemdef.image
|
|
||||||
end
|
|
||||||
-- END Legacy stuff
|
|
||||||
|
|
||||||
minetest.register_item(name, craftitemdef)
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.register_tool(name, tooldef)
|
|
||||||
tooldef.type = "tool"
|
|
||||||
tooldef.stack_max = 1
|
|
||||||
|
|
||||||
-- BEGIN Legacy stuff
|
|
||||||
if tooldef.inventory_image == nil and tooldef.image ~= nil then
|
|
||||||
tooldef.inventory_image = tooldef.image
|
|
||||||
end
|
|
||||||
if tooldef.tool_digging_properties == nil and
|
|
||||||
(tooldef.full_punch_interval ~= nil or
|
|
||||||
tooldef.basetime ~= nil or
|
|
||||||
tooldef.dt_weight ~= nil or
|
|
||||||
tooldef.dt_crackiness ~= nil or
|
|
||||||
tooldef.dt_crumbliness ~= nil or
|
|
||||||
tooldef.dt_cuttability ~= nil or
|
|
||||||
tooldef.basedurability ~= nil or
|
|
||||||
tooldef.dd_weight ~= nil or
|
|
||||||
tooldef.dd_crackiness ~= nil or
|
|
||||||
tooldef.dd_crumbliness ~= nil or
|
|
||||||
tooldef.dd_cuttability ~= nil) then
|
|
||||||
tooldef.tool_digging_properties = {
|
|
||||||
full_punch_interval = tooldef.full_punch_interval,
|
|
||||||
basetime = tooldef.basetime,
|
|
||||||
dt_weight = tooldef.dt_weight,
|
|
||||||
dt_crackiness = tooldef.dt_crackiness,
|
|
||||||
dt_crumbliness = tooldef.dt_crumbliness,
|
|
||||||
dt_cuttability = tooldef.dt_cuttability,
|
|
||||||
basedurability = tooldef.basedurability,
|
|
||||||
dd_weight = tooldef.dd_weight,
|
|
||||||
dd_crackiness = tooldef.dd_crackiness,
|
|
||||||
dd_crumbliness = tooldef.dd_crumbliness,
|
|
||||||
dd_cuttability = tooldef.dd_cuttability,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
-- END Legacy stuff
|
|
||||||
|
|
||||||
minetest.register_item(name, tooldef)
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.register_alias(name, convert_to)
|
|
||||||
if forbidden_item_names[name] then
|
|
||||||
error("Unable to register alias: Name is forbidden: " .. name)
|
|
||||||
end
|
|
||||||
if minetest.registered_items[name] ~= nil then
|
|
||||||
minetest.log("WARNING: Not registering alias, item with same name" ..
|
|
||||||
" is already defined: " .. name .. " -> " .. convert_to)
|
|
||||||
else
|
|
||||||
--minetest.log("Registering alias: " .. name .. " -> " .. convert_to)
|
|
||||||
minetest.registered_aliases[name] = convert_to
|
|
||||||
register_alias_raw(name, convert_to)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Alias the forbidden item names to "" so they can't be
|
|
||||||
-- created via itemstrings (e.g. /give)
|
|
||||||
local name
|
|
||||||
for name in pairs(forbidden_item_names) do
|
|
||||||
minetest.registered_aliases[name] = ""
|
|
||||||
register_alias_raw(name, "")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Deprecated:
|
|
||||||
-- Aliases for minetest.register_alias (how ironic...)
|
|
||||||
--minetest.alias_node = minetest.register_alias
|
|
||||||
--minetest.alias_tool = minetest.register_alias
|
|
||||||
--minetest.alias_craftitem = minetest.register_alias
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Built-in node definitions. Also defined in C.
|
|
||||||
--
|
|
||||||
|
|
||||||
minetest.register_item(":", {
|
|
||||||
type = "none",
|
|
||||||
wield_image = "wieldhand.png",
|
|
||||||
wield_scale = {x=1,y=1,z=2.5},
|
|
||||||
tool_digging_properties = {
|
|
||||||
full_punch_interval = 2.0,
|
|
||||||
basetime = 0.5,
|
|
||||||
dt_weight = 1,
|
|
||||||
dt_crackiness = 0,
|
|
||||||
dt_crumbliness = -1,
|
|
||||||
dt_cuttability = 0,
|
|
||||||
basedurability = 50,
|
|
||||||
dd_weight = 0,
|
|
||||||
dd_crackiness = 0,
|
|
||||||
dd_crumbliness = 0,
|
|
||||||
dd_cuttability = 0,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_item(":unknown", {
|
|
||||||
type = "none",
|
|
||||||
description = "Unknown Item",
|
|
||||||
inventory_image = "unknown_item.png",
|
|
||||||
on_place = minetest.item_place,
|
|
||||||
on_drop = minetest.item_drop,
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_node(":air", {
|
|
||||||
description = "Air (you hacker you!)",
|
|
||||||
inventory_image = "unknown_block.png",
|
|
||||||
wield_image = "unknown_block.png",
|
|
||||||
drawtype = "airlike",
|
|
||||||
paramtype = "light",
|
|
||||||
sunlight_propagates = true,
|
|
||||||
walkable = false,
|
|
||||||
pointable = false,
|
|
||||||
diggable = false,
|
|
||||||
buildable_to = true,
|
|
||||||
air_equivalent = true,
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_node(":ignore", {
|
|
||||||
description = "Ignore (you hacker you!)",
|
|
||||||
inventory_image = "unknown_block.png",
|
|
||||||
wield_image = "unknown_block.png",
|
|
||||||
drawtype = "airlike",
|
|
||||||
paramtype = "none",
|
|
||||||
sunlight_propagates = false,
|
|
||||||
walkable = false,
|
|
||||||
pointable = false,
|
|
||||||
diggable = false,
|
|
||||||
buildable_to = true, -- A way to remove accidentally placed ignores
|
|
||||||
air_equivalent = true,
|
|
||||||
})
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Default material types
|
|
||||||
--
|
|
||||||
|
|
||||||
function minetest.digprop_constanttime(time)
|
|
||||||
return {
|
|
||||||
diggability = "constant",
|
|
||||||
constant_time = time,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.digprop_stonelike(toughness)
|
|
||||||
return {
|
|
||||||
diggablity = "normal",
|
|
||||||
weight = toughness * 5,
|
|
||||||
crackiness = 1,
|
|
||||||
crumbliness = -0.1,
|
|
||||||
cuttability = -0.2,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.digprop_dirtlike(toughness)
|
|
||||||
return {
|
|
||||||
diggablity = "normal",
|
|
||||||
weight = toughness * 1.2,
|
|
||||||
crackiness = 0,
|
|
||||||
crumbliness = 1.2,
|
|
||||||
cuttability = -0.4,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.digprop_gravellike(toughness)
|
|
||||||
return {
|
|
||||||
diggablity = "normal",
|
|
||||||
weight = toughness * 2,
|
|
||||||
crackiness = 0.2,
|
|
||||||
crumbliness = 1.5,
|
|
||||||
cuttability = -1.0,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.digprop_woodlike(toughness)
|
|
||||||
return {
|
|
||||||
diggablity = "normal",
|
|
||||||
weight = toughness * 1.0,
|
|
||||||
crackiness = 0.75,
|
|
||||||
crumbliness = -1.0,
|
|
||||||
cuttability = 1.5,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.digprop_leaveslike(toughness)
|
|
||||||
return {
|
|
||||||
diggablity = "normal",
|
|
||||||
weight = toughness * (-0.5),
|
|
||||||
crackiness = 0,
|
|
||||||
crumbliness = 0,
|
|
||||||
cuttability = 2.0,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
function minetest.digprop_glasslike(toughness)
|
|
||||||
return {
|
|
||||||
diggablity = "normal",
|
|
||||||
weight = toughness * 0.1,
|
|
||||||
crackiness = 2.0,
|
|
||||||
crumbliness = -1.0,
|
|
||||||
cuttability = -1.0,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Creative inventory
|
|
||||||
--
|
|
||||||
|
|
||||||
minetest.creative_inventory = {}
|
|
||||||
|
|
||||||
minetest.add_to_creative_inventory = function(itemstring)
|
|
||||||
table.insert(minetest.creative_inventory, itemstring)
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Callback registration
|
|
||||||
--
|
|
||||||
|
|
||||||
local function make_registration()
|
|
||||||
local t = {}
|
|
||||||
local registerfunc = function(func) table.insert(t, func) end
|
|
||||||
return t, registerfunc
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.registered_on_chat_messages, minetest.register_on_chat_message = make_registration()
|
|
||||||
minetest.registered_globalsteps, minetest.register_globalstep = make_registration()
|
|
||||||
minetest.registered_on_placenodes, minetest.register_on_placenode = make_registration()
|
|
||||||
minetest.registered_on_dignodes, minetest.register_on_dignode = make_registration()
|
|
||||||
minetest.registered_on_punchnodes, minetest.register_on_punchnode = make_registration()
|
|
||||||
minetest.registered_on_generateds, minetest.register_on_generated = make_registration()
|
|
||||||
minetest.registered_on_newplayers, minetest.register_on_newplayer = make_registration()
|
|
||||||
minetest.registered_on_dieplayers, minetest.register_on_dieplayer = make_registration()
|
|
||||||
minetest.registered_on_respawnplayers, minetest.register_on_respawnplayer = make_registration()
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Set random seed
|
|
||||||
--
|
|
||||||
|
|
||||||
math.randomseed(os.time())
|
|
||||||
|
|
||||||
-- END
|
|
||||||
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 498 B |
|
Before Width: | Height: | Size: 582 B |
|
Before Width: | Height: | Size: 710 B |
|
Before Width: | Height: | Size: 489 B |
|
Before Width: | Height: | Size: 329 B |
|
Before Width: | Height: | Size: 363 B |
|
Before Width: | Height: | Size: 369 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 203 B |
|
Before Width: | Height: | Size: 292 B |
|
Before Width: | Height: | Size: 597 B |
|
Before Width: | Height: | Size: 604 B |
|
Before Width: | Height: | Size: 279 B |
|
Before Width: | Height: | Size: 236 B |
|
Before Width: | Height: | Size: 167 B |
|
Before Width: | Height: | Size: 224 B |
|
Before Width: | Height: | Size: 151 B |
|
Before Width: | Height: | Size: 142 B |
|
Before Width: | Height: | Size: 613 B |
|
Before Width: | Height: | Size: 249 B |
|
Before Width: | Height: | Size: 210 B |
|
Before Width: | Height: | Size: 118 B |
|
Before Width: | Height: | Size: 933 B |
|
Before Width: | Height: | Size: 830 B |
|
Before Width: | Height: | Size: 539 B |
|
Before Width: | Height: | Size: 246 B |
|
Before Width: | Height: | Size: 236 B |
|
Before Width: | Height: | Size: 978 B |
|
Before Width: | Height: | Size: 874 B |
|
Before Width: | Height: | Size: 856 B |
|
Before Width: | Height: | Size: 591 B |
|
Before Width: | Height: | Size: 936 B |
|
Before Width: | Height: | Size: 672 B |
|
Before Width: | Height: | Size: 502 B |
|
Before Width: | Height: | Size: 507 B |
|
Before Width: | Height: | Size: 395 B |
|
Before Width: | Height: | Size: 357 B |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 203 B |
|
Before Width: | Height: | Size: 952 B |
|
Before Width: | Height: | Size: 1.6 KiB |