Compare commits
559 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f5ce2391c | ||
|
|
6d1a208018 | ||
|
|
d500241e3d | ||
|
|
61f3812f73 | ||
|
|
f2be1c39c8 | ||
|
|
244dc7ac06 | ||
|
|
3a0152c491 | ||
|
|
52e36b06e6 | ||
|
|
f1f1fce2db | ||
|
|
4aae915e4f | ||
|
|
814eb21def | ||
|
|
b5eb11c0ae | ||
|
|
72b14910da | ||
|
|
bca99fc723 | ||
|
|
b6fe5fee43 | ||
|
|
23e208c7aa | ||
|
|
8b3e80f534 | ||
|
|
4f77a91e04 | ||
|
|
c2a4d5f82d | ||
|
|
4238aa423b | ||
|
|
ae35167a5e | ||
|
|
499f2284bd | ||
|
|
274d8a7c65 | ||
|
|
8f98b4f243 | ||
|
|
e3ec044ed0 | ||
|
|
dd3530dc79 | ||
|
|
421835a30e | ||
|
|
db8cd2121c | ||
|
|
ec790a3884 | ||
|
|
ee45f2db43 | ||
|
|
ca62268d16 | ||
|
|
e217961b25 | ||
|
|
7485844880 | ||
|
|
32d10f8309 | ||
|
|
87dd2184a4 | ||
|
|
10328435e8 | ||
|
|
1c710ac003 | ||
|
|
4019be74a9 | ||
|
|
887fff9709 | ||
|
|
0e6b4d11d0 | ||
|
|
fd7dbb6d45 | ||
|
|
7e68262c0c | ||
|
|
112672594b | ||
|
|
1aa3efba4a | ||
|
|
bdd08fde57 | ||
|
|
6f96c14aba | ||
|
|
2a76a50d98 | ||
|
|
773f9f14d4 | ||
|
|
a104a55348 | ||
|
|
e653f9ea66 | ||
|
|
d71609da08 | ||
|
|
bf5718144f | ||
|
|
61df8b8dc7 | ||
|
|
5d097b5533 | ||
|
|
2c0094b9bd | ||
|
|
f531b7fd72 | ||
|
|
729e60da79 | ||
|
|
6c671cc48d | ||
|
|
a9fba46454 | ||
|
|
8baca62434 | ||
|
|
254005f3e5 | ||
|
|
dc3aeea697 | ||
|
|
1086af7bc6 | ||
|
|
5f5ea13251 | ||
|
|
4c29bf6923 | ||
|
|
d5ddee6cbf | ||
|
|
20f8eb9a6c | ||
|
|
08b7870c79 | ||
|
|
afd681d013 | ||
|
|
2eded3f078 | ||
|
|
9972639e26 | ||
|
|
39f2727503 | ||
|
|
ecabcb5c58 | ||
|
|
70fbef112c | ||
|
|
2cab46280b | ||
|
|
fc6bef7de6 | ||
|
|
29490cb0f7 | ||
|
|
d932f34693 | ||
|
|
cc6b56b034 | ||
|
|
053ca6287a | ||
|
|
fcd9c73f2f | ||
|
|
f714ac0611 | ||
|
|
b6a23b1bcc | ||
|
|
69497200f9 | ||
|
|
c9d4c33174 | ||
|
|
176cadc377 | ||
|
|
5672b93007 | ||
|
|
0b66465f33 | ||
|
|
c7d45fe51a | ||
|
|
46ef0bf313 | ||
|
|
56bc7814de | ||
|
|
d24a7001ab | ||
|
|
024e1d2d27 | ||
|
|
e86d2fea8d | ||
|
|
2ef085967d | ||
|
|
f390137d6e | ||
|
|
7cbe62fe7b | ||
|
|
3f0f7f4285 | ||
|
|
04d9bd518f | ||
|
|
550b042076 | ||
|
|
ce8e8f6bf4 | ||
|
|
079169612d | ||
|
|
baaab310fe | ||
|
|
36b5374715 | ||
|
|
bb74b9d488 | ||
|
|
54d48decad | ||
|
|
1d53ec4892 | ||
|
|
e835673c5e | ||
|
|
f2eb5e7a93 | ||
|
|
6da927a548 | ||
|
|
fd3588d49c | ||
|
|
7c88996210 | ||
|
|
b6065797ce | ||
|
|
21a76d8c88 | ||
|
|
e2e571ca1f | ||
|
|
81e08fc890 | ||
|
|
2a96b31ffc | ||
|
|
a5197a6719 | ||
|
|
bbade5d3bc | ||
|
|
7a99fdf490 | ||
|
|
0b21c93324 | ||
|
|
55cca34ee9 | ||
|
|
0b9ae73369 | ||
|
|
b1cb5fcb9f | ||
|
|
ae97435d80 | ||
|
|
ecc876045f | ||
|
|
c611a1f9e8 | ||
|
|
65d498f78e | ||
|
|
a0547b3435 | ||
|
|
93dd22b901 | ||
|
|
60cd83a332 | ||
|
|
0c12c1f400 | ||
|
|
affe299215 | ||
|
|
39417cf7a7 | ||
|
|
5ab66da6f7 | ||
|
|
919b7c5433 | ||
|
|
613ba689ff | ||
|
|
26aab6ecf2 | ||
|
|
d949f5ffcb | ||
|
|
9ff38bdf7f | ||
|
|
d679261488 | ||
|
|
7345b54f18 | ||
|
|
0deee5eaf0 | ||
|
|
d8640759d6 | ||
|
|
535db2be76 | ||
|
|
d60f909566 | ||
|
|
c9230c5c09 | ||
|
|
643d1cbd8d | ||
|
|
251488b3aa | ||
|
|
3cb8ce69d2 | ||
|
|
77dd86a79c | ||
|
|
0eabc252b8 | ||
|
|
e8e5ef0369 | ||
|
|
158bfa6442 | ||
|
|
23bf50a07c | ||
|
|
33940021a1 | ||
|
|
3dd99e1492 | ||
|
|
15f41eb82e | ||
|
|
ef7f1ac28f | ||
|
|
e1b057ca56 | ||
|
|
717e686ac3 | ||
|
|
adf6fe95e7 | ||
|
|
751bfad09d | ||
|
|
22c3c04f24 | ||
|
|
84b13998e6 | ||
|
|
b8f870f0e2 | ||
|
|
37f922b500 | ||
|
|
8e03e94ea9 | ||
|
|
ce2380b58e | ||
|
|
f71e1447c9 | ||
|
|
4f42b4308c | ||
|
|
e0f8243629 | ||
|
|
61551cfc3a | ||
|
|
7e22c72492 | ||
|
|
51a453ca7b | ||
|
|
2a8ee686d9 | ||
|
|
af4c182286 | ||
|
|
f93d076fa2 | ||
|
|
d945792053 | ||
|
|
dbb96b71a2 | ||
|
|
d4491d5f2f | ||
|
|
a41a24dc6c | ||
|
|
a51b518648 | ||
|
|
94c9636d7c | ||
|
|
47c0be86be | ||
|
|
4bfbfccbe0 | ||
|
|
d1d33ae4bc | ||
|
|
5b714aa932 | ||
|
|
4378757820 | ||
|
|
5026ea18f5 | ||
|
|
8e7fbed4e4 | ||
|
|
69ad83d9c9 | ||
|
|
639edcddcf | ||
|
|
21df20185c | ||
|
|
3865287b8b | ||
|
|
d7b876ba0e | ||
|
|
ec7119327a | ||
|
|
2f94347af9 | ||
|
|
17b3d5f381 | ||
|
|
9a1e83036b | ||
|
|
c3d669266e | ||
|
|
5f428ffe76 | ||
|
|
846a3baf68 | ||
|
|
a61a53db9a | ||
|
|
1472379f39 | ||
|
|
599c93633a | ||
|
|
1a58a2fd2b | ||
|
|
5b37614d23 | ||
|
|
08bc036311 | ||
|
|
83a7e22cf7 | ||
|
|
80be9bf76e | ||
|
|
43aad3711b | ||
|
|
fd0ca20ce9 | ||
|
|
fcbf05fc30 | ||
|
|
2d36d32da8 | ||
|
|
2733df78c4 | ||
|
|
6545710c8e | ||
|
|
0ea89d4112 | ||
|
|
8eceabd812 | ||
|
|
0794145b64 | ||
|
|
90c3479520 | ||
|
|
da0f8cd6b5 | ||
|
|
48ef7fff23 | ||
|
|
1297ccc537 | ||
|
|
fdc149f316 | ||
|
|
d41de3da79 | ||
|
|
49f48e0a7c | ||
|
|
81d62d01d1 | ||
|
|
225d2cf916 | ||
|
|
f75d16c1e6 | ||
|
|
aba2b6638e | ||
|
|
e452c2900f | ||
|
|
f431c12b85 | ||
|
|
38255cb6bb | ||
|
|
b9af44b194 | ||
|
|
29a9056731 | ||
|
|
4454d71d7d | ||
|
|
fde6384a09 | ||
|
|
0bb87eb1ff | ||
|
|
56a7f0b7cf | ||
|
|
a2460df316 | ||
|
|
535d757563 | ||
|
|
660b1cf9bf | ||
|
|
fcddac6c07 | ||
|
|
9f7501d20a | ||
|
|
aa1bab2156 | ||
|
|
6274a8dec4 | ||
|
|
41651c7317 | ||
|
|
e03957ec0c | ||
|
|
79e0d834fd | ||
|
|
b580c66b61 | ||
|
|
9ce9d7f433 | ||
|
|
957ebf7368 | ||
|
|
5c2599315c | ||
|
|
6ca9d75f0b | ||
|
|
ec16fb33d0 | ||
|
|
a5263dc7ed | ||
|
|
ae35f37bc3 | ||
|
|
986cd32f28 | ||
|
|
94a9b94baf | ||
|
|
da7897a822 | ||
|
|
fa0c09d202 | ||
|
|
e9b32843a5 | ||
|
|
1214a1d4a6 | ||
|
|
452160cd00 | ||
|
|
d17f22f536 | ||
|
|
2f1171e2a7 | ||
|
|
69c4d742f8 | ||
|
|
66aa5f3fac | ||
|
|
4022d35c46 | ||
|
|
d6f590878c | ||
|
|
71d9f1771c | ||
|
|
96fbc52071 | ||
|
|
7556bf43a6 | ||
|
|
722c0044b1 | ||
|
|
b93cce11d8 | ||
|
|
6bdd5c6773 | ||
|
|
a8e7e261b9 | ||
|
|
73c29e7763 | ||
|
|
e27757fa3a | ||
|
|
4e3b8db2b9 | ||
|
|
336f8d4dc7 | ||
|
|
7737906d2e | ||
|
|
a6f1242a11 | ||
|
|
53c2fbb4c4 | ||
|
|
1d042a977d | ||
|
|
166782040e | ||
|
|
9e198fc22c | ||
|
|
ecf535ee83 | ||
|
|
f79a51c265 | ||
|
|
bd25a06f44 | ||
|
|
1caf26f18b | ||
|
|
5861192752 | ||
|
|
02db521c80 | ||
|
|
ba65eb953c | ||
|
|
dbf2d26a85 | ||
|
|
60694cbd30 | ||
|
|
baafec9e9f | ||
|
|
65d4335922 | ||
|
|
5094838837 | ||
|
|
93ac2ed894 | ||
|
|
c011fa0188 | ||
|
|
c2057eee4b | ||
|
|
d445638265 | ||
|
|
f61f6626b7 | ||
|
|
857ba25115 | ||
|
|
00774bc28b | ||
|
|
f572266f19 | ||
|
|
c3893064a3 | ||
|
|
4183443f02 | ||
|
|
5715434d5e | ||
|
|
ab2419db24 | ||
|
|
35a83c3514 | ||
|
|
de09cac1e9 | ||
|
|
b64f4bdb3a | ||
|
|
008310aad9 | ||
|
|
4d024d737c | ||
|
|
50edb30a18 | ||
|
|
00f6bd0f08 | ||
|
|
81e40a1172 | ||
|
|
fe4f89f3fa | ||
|
|
0d372250c1 | ||
|
|
367720020c | ||
|
|
0dab82085d | ||
|
|
cb211d63cd | ||
|
|
2e497cc471 | ||
|
|
587f6656a4 | ||
|
|
4377c03168 | ||
|
|
1e0520074c | ||
|
|
b9f6832347 | ||
|
|
f8bb0cd3d1 | ||
|
|
129aef758e | ||
|
|
94f55cf406 | ||
|
|
a20b758e19 | ||
|
|
128842becf | ||
|
|
d51331f51f | ||
|
|
4ef221a645 | ||
|
|
79010e972e | ||
|
|
0ca530e251 | ||
|
|
57b4d46dbc | ||
|
|
50df5e2f59 | ||
|
|
b6db2c7262 | ||
|
|
9441b69ad2 | ||
|
|
08e3d16a58 | ||
|
|
3f3049fdba | ||
|
|
41fb7a8a7e | ||
|
|
5b9828e094 | ||
|
|
96e35585b0 | ||
|
|
f035fe9336 | ||
|
|
44c2e33c78 | ||
|
|
2785dcbbbf | ||
|
|
9b03bd3243 | ||
|
|
8f30456ee3 | ||
|
|
38557ff635 | ||
|
|
7bc2cde4dd | ||
|
|
f065d3a06b | ||
|
|
21f7e3a987 | ||
|
|
9f688bc433 | ||
|
|
6e9d31d4fb | ||
|
|
e81c48526b | ||
|
|
b405985b80 | ||
|
|
8b010c5a9f | ||
|
|
1e7b5d6fdb | ||
|
|
a55982e7f0 | ||
|
|
1ac378063e | ||
|
|
d497c92684 | ||
|
|
677dc2c155 | ||
|
|
beea8deeb5 | ||
|
|
0d0f1a2fb2 | ||
|
|
439701ed7a | ||
|
|
d945d0129c | ||
|
|
cc91477308 | ||
|
|
ac139ec03d | ||
|
|
b4f0e834bf | ||
|
|
6e6cdc834f | ||
|
|
4b81ae1b35 | ||
|
|
d569dc45a8 | ||
|
|
23d49fda29 | ||
|
|
62ad2c3bc1 | ||
|
|
25373ad294 | ||
|
|
26d0c0fd8d | ||
|
|
3afffcd36b | ||
|
|
5440de1785 | ||
|
|
25a56f11c8 | ||
|
|
8271c6481f | ||
|
|
83e26f839d | ||
|
|
c3f7905d82 | ||
|
|
05b54a8d18 | ||
|
|
e5cfdd369e | ||
|
|
c61d8cfb85 | ||
|
|
27f4195471 | ||
|
|
b2596eda32 | ||
|
|
9379440fcb | ||
|
|
b7c502c8d1 | ||
|
|
3c16d2d9b4 | ||
|
|
6cbc03a418 | ||
|
|
15ecc0fa65 | ||
|
|
7f2f8cdad1 | ||
|
|
a64646cb7b | ||
|
|
05f531c538 | ||
|
|
7ca335446b | ||
|
|
99e96a6581 | ||
|
|
7200d8f90e | ||
|
|
7038837aca | ||
|
|
541dcc0e5a | ||
|
|
1060b5aabf | ||
|
|
6ea73c4982 | ||
|
|
cff847273a | ||
|
|
e669f8db9b | ||
|
|
461cc30842 | ||
|
|
13d7cb957c | ||
|
|
47a439a905 | ||
|
|
053fb96694 | ||
|
|
b72c1f7367 | ||
|
|
e90738575f | ||
|
|
35718eec9c | ||
|
|
8285a53152 | ||
|
|
116fe7815b | ||
|
|
4c2efd7da3 | ||
|
|
1a433e3185 | ||
|
|
fa98a00916 | ||
|
|
f4dd46ad60 | ||
|
|
41825ccfbb | ||
|
|
4d1a5f12c0 | ||
|
|
cc58d56c6d | ||
|
|
683ef07312 | ||
|
|
c77c78cef5 | ||
|
|
88517030a4 | ||
|
|
45471e8e63 | ||
|
|
4e620beb75 | ||
|
|
e7ab875b47 | ||
|
|
be74ed9ab6 | ||
|
|
52b2eacd37 | ||
|
|
6b4210a2ea | ||
|
|
740d0da5ee | ||
|
|
34883d356e | ||
|
|
aeafcce314 | ||
|
|
ae1d82c325 | ||
|
|
1c89a07226 | ||
|
|
43e262f13e | ||
|
|
e5f802ab5c | ||
|
|
847860fc5c | ||
|
|
77e936445f | ||
|
|
41beb74ef7 | ||
|
|
67be50b706 | ||
|
|
cd840b7c9d | ||
|
|
07903949ec | ||
|
|
d2156ddaad | ||
|
|
a84ff4b3ff | ||
|
|
c02f13d33f | ||
|
|
f6490859fd | ||
|
|
4b7816dbf4 | ||
|
|
86ffbc3ec5 | ||
|
|
67257f44a5 | ||
|
|
3086f5567a | ||
|
|
bb8acb095d | ||
|
|
24be3cbb5f | ||
|
|
9773191103 | ||
|
|
ddc703c3ec | ||
|
|
09ec204e4b | ||
|
|
8b6cafa0e0 | ||
|
|
1ee8be9d43 | ||
|
|
91bc190d21 | ||
|
|
4dc833b642 | ||
|
|
895e9f8d5c | ||
|
|
12906ff631 | ||
|
|
9c9bcff107 | ||
|
|
443ca5c63b | ||
|
|
1102b1fc4c | ||
|
|
0d089eab21 | ||
|
|
b44fada29e | ||
|
|
859ea160e6 | ||
|
|
1c49e2ffc0 | ||
|
|
140245c58d | ||
|
|
47adcced60 | ||
|
|
a2054deb12 | ||
|
|
30fdfd9ded | ||
|
|
a87a86eb92 | ||
|
|
49dfbcfbc8 | ||
|
|
c558a4f4f6 | ||
|
|
4f49a2248f | ||
|
|
4e57da42c1 | ||
|
|
4f6c9e206c | ||
|
|
699e1d4b77 | ||
|
|
fa2978b3b9 | ||
|
|
ffcdf741fc | ||
|
|
429d7f33d4 | ||
|
|
b6a229775e | ||
|
|
0a4580368a | ||
|
|
e5b191e1f1 | ||
|
|
a07acc067b | ||
|
|
01e763f879 | ||
|
|
a95e75261a | ||
|
|
dcaa7ac609 | ||
|
|
7d2ae10849 | ||
|
|
642cac3759 | ||
|
|
662af2edba | ||
|
|
6f97e15a8f | ||
|
|
ab2fa2ca9d | ||
|
|
4666c99b27 | ||
|
|
e38415c56d | ||
|
|
3f3fce4664 | ||
|
|
1407a7bc8a | ||
|
|
1d268f4b83 | ||
|
|
92aab79d27 | ||
|
|
0823bb1276 | ||
|
|
18e42efa01 | ||
|
|
0ea16328df | ||
|
|
b037efc5c6 | ||
|
|
839bb71389 | ||
|
|
2ef7df5cfe | ||
|
|
f5d2d79f75 | ||
|
|
8e5fa96ffc | ||
|
|
6dbbe07d50 | ||
|
|
3c23410753 | ||
|
|
8e35ab78b4 | ||
|
|
7f2911b7f0 | ||
|
|
d877e90301 | ||
|
|
93db4be726 | ||
|
|
1f419ad19f | ||
|
|
3c7f6508ad | ||
|
|
39449d4b63 | ||
|
|
28e05295fa | ||
|
|
60c18d3550 | ||
|
|
482ab186a2 | ||
|
|
4814195dc4 | ||
|
|
d215b7a10e | ||
|
|
0e52b78590 | ||
|
|
b3a9d607c4 | ||
|
|
c00081b62c | ||
|
|
5e4739b460 | ||
|
|
0d8f598df2 | ||
|
|
2ef04cc308 | ||
|
|
7a0884e2cd | ||
|
|
fa858530cc | ||
|
|
1c61fe5ed9 | ||
|
|
57409ef382 | ||
|
|
06ba826803 | ||
|
|
6e6ef9489f | ||
|
|
45bbe39d1f | ||
|
|
6c9fc13083 | ||
|
|
4c8a642388 | ||
|
|
6208c9d64f | ||
|
|
76325d0ba9 | ||
|
|
cf1802a6de | ||
|
|
538a7b12bd | ||
|
|
57e0f52aaa | ||
|
|
1ae0335b62 | ||
|
|
ca1bff6b66 | ||
|
|
10cc62d2ca | ||
|
|
dd451a8a00 | ||
|
|
444ec1e412 | ||
|
|
82739f4d7d | ||
|
|
19825d853e | ||
|
|
d8ece2e3e9 | ||
|
|
bf4deb0ce6 | ||
|
|
da4739a26c | ||
|
|
fc24bf0915 | ||
|
|
9329b99cba |
20
.github/CONTRIBUTING.md
vendored
20
.github/CONTRIBUTING.md
vendored
@@ -25,16 +25,16 @@ Contributions are welcome! Here's how you can help:
|
||||
the work, to avoid disappointment.
|
||||
|
||||
You may also benefit from discussing on our IRC development channel
|
||||
[#luanti-dev](http://www.luanti.org/irc/). Note that a proper IRC client
|
||||
[#luanti-dev](https://docs.luanti.org/about/irc/). Note that a proper IRC client
|
||||
is required to speak on this channel.
|
||||
|
||||
3. Start coding!
|
||||
- Refer to the
|
||||
[Lua API](https://github.com/luanti-org/luanti/blob/master/doc/lua_api.md),
|
||||
[Developer Wiki](https://dev.luanti.org/) and other
|
||||
[Luanti Documentation](https://docs.luanti.org/) and other
|
||||
[documentation](https://github.com/luanti-org/luanti/tree/master/doc).
|
||||
- Follow the [C/C++](https://dev.luanti.org/Code_style_guidelines) and
|
||||
[Lua](https://dev.luanti.org/Lua_code_style_guidelines) code style guidelines.
|
||||
- Follow the [C/C++](https://docs.luanti.org/for-engine-devs/code-style-guidelines/) and
|
||||
[Lua](https://docs.luanti.org/for-engine-devs/lua-code-style-guidelines/) code style guidelines.
|
||||
- Check your code works as expected and document any changes to the Lua API.
|
||||
- To avoid conflicting changes between contributions, do not do the following manually. They will be done before each release.
|
||||
- Run `updatepo.sh` or update `luanti.po{,t}` even if your code adds new translatable strings.
|
||||
@@ -64,8 +64,8 @@ Contributions are welcome! Here's how you can help:
|
||||
picture of the project.
|
||||
2. It works.
|
||||
3. It follows the code style for
|
||||
[C/C++](https://dev.luanti.org/Code_style_guidelines) or
|
||||
[Lua](https://dev.luanti.org/Lua_code_style_guidelines).
|
||||
[C/C++](https://docs.luanti.org/for-engine-devs/code-style-guidelines/) or
|
||||
[Lua](https://docs.luanti.org/for-engine-devs/lua-code-style-guidelines/).
|
||||
4. The code's interfaces are well designed, regardless of other aspects that
|
||||
might need more work in the future.
|
||||
5. It uses protocols and formats which include the required compatibility.
|
||||
@@ -106,7 +106,7 @@ the project page with a list of current languages
|
||||
Builtin (the component which contains things like server messages, chat command
|
||||
descriptions, privilege descriptions) is translated separately; it needs to be
|
||||
translated by editing a `.tr` text file. See
|
||||
[Translation](https://dev.luanti.org/Translation) for more information.
|
||||
[Translation](https://docs.luanti.org/for-creators/translation/) for more information.
|
||||
|
||||
## Donations
|
||||
|
||||
@@ -116,11 +116,11 @@ methods on [our website](http://www.luanti.org/development/#donate).
|
||||
# Maintaining
|
||||
|
||||
* This is a concise version of the
|
||||
[Rules & Guidelines](https://dev.luanti.org/engine-dev-process/) on the developer wiki.*
|
||||
[Rules & Guidelines](https://docs.luanti.org/for-engine-devs/) on the Luanti Documentation.*
|
||||
|
||||
These notes are for those who have push access Luanti (core developers / maintainers).
|
||||
|
||||
- See the [project organisation](https://dev.luanti.org/Organisation) for the people involved.
|
||||
- See the [project organisation](https://docs.luanti.org/for-engine-devs/organization/) for the people involved.
|
||||
|
||||
## Concept approvals and roadmaps
|
||||
|
||||
@@ -169,4 +169,4 @@ Submit a :+1: (+1) or "Looks good" comment to show you believe the pull-request
|
||||
|
||||
## Releasing a new version
|
||||
|
||||
*Refer to [dev.luanti.org/Releasing_Luanti](https://dev.luanti.org/Releasing_Luanti)*
|
||||
*Refer to [docs.luanti.org/for-engine-devs/releasing-luanti](https://docs.luanti.org/for-engine-devs/releasing-luanti/)*
|
||||
|
||||
37
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
37
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -1,5 +1,5 @@
|
||||
name: Bug report
|
||||
description: Create a report to help us improve
|
||||
description: Report a problem or mistake
|
||||
labels: ["Unconfirmed bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
@@ -7,16 +7,17 @@ body:
|
||||
value: |
|
||||
Please note the following:
|
||||
|
||||
1. **Please update Luanti to the latest stable or dev version** before submitting bug reports. Make sure the bug is still reproducible on the latest version.
|
||||
2. This page is for reporting the bugs of **the engine itself**. For bugs in a particular game, please [search for the game in the ContentDB](https://content.luanti.org/packages/?type=game) and submit a bug report in their issue trackers.
|
||||
* For example, you can submit issues about the Minetest Game [in its own repository](https://github.com/luanti-org/minetest_game/issues).
|
||||
3. Please provide as many details as possible for us to spot the problem quicker.
|
||||
1. **Update Luanti to the latest stable or dev version** before submitting a bug report. Make sure the bug is still reproducible on the latest version.
|
||||
2. This page is for reporting the bugs of **the engine itself**. For bugs in a particular game, please [search for the game on ContentDB](https://content.luanti.org/packages/?type=game) and submit a bug report to its developers.
|
||||
* For example, issues about Minetest Game are submitted to [its own repository](https://github.com/luanti-org/minetest_game/issues).
|
||||
3. Please provide as many relevant details as possible.
|
||||
4. If you have used an LLM/AI to format your issue description, disclose this. Try to keep it concise. No walls of text please.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Luanti version
|
||||
description: |
|
||||
Paste the Luanti version below.
|
||||
If you are on a dev version, please also indicate the git commit hash.
|
||||
Refer to the "About" tab of the menu or run `luanti --version` on the command line.
|
||||
placeholder: |
|
||||
Example:
|
||||
@@ -34,27 +35,28 @@ body:
|
||||
render: "true"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Operating system and version
|
||||
description: It is recommended to upgrade your operating system to see if the problem persists.
|
||||
description: Keeping your OS up-to-date can solve some problems on its own.
|
||||
placeholder: "Example: Ubuntu 22.04"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: CPU model
|
||||
description: Usually found in OS/system settings.
|
||||
description: Usually found in OS/system settings
|
||||
placeholder: "Example: Intel Core i5-2410M"
|
||||
validations:
|
||||
required: false
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: The GPU model and renderer can be omitted if the bug is not a graphical issue.
|
||||
value: If the bug is server-side please skip the "GPU model" and "Active renderer" fields.
|
||||
- type: input
|
||||
attributes:
|
||||
label: GPU model
|
||||
description: Usually found in OS/system settings.
|
||||
description: Usually found in OS/system settings
|
||||
placeholder: "Example: NVIDIA GeForce GTX 1660"
|
||||
validations:
|
||||
required: false
|
||||
@@ -65,15 +67,26 @@ body:
|
||||
placeholder: "Example: ES 3.2 / ogles2 / X11"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Summary
|
||||
description: Describe your problem here.
|
||||
description: |
|
||||
Describe your problem here.
|
||||
|
||||
Make sure to include the all error messages you see and/or screenshots in case of visual bugs.
|
||||
Attaching a copy of your `debug.txt` and `minetest.conf` can be helpful as well.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Explain how the problem has happened, providing a minimal test (e.g. a minimized code snippet) where possible.
|
||||
description: |
|
||||
Explain how the problem has happened.
|
||||
|
||||
To the extent possible, the reproduction steps should describe not just what you did (e.g. "I open my world and it crashes")
|
||||
but be detailed enough so that anyone with a fresh installation of Luanti could follow these steps to encounter the same problem.
|
||||
In case of modding issues it is often useful to include a code snippet.
|
||||
This will help us diagnose the problem quicker and more efficiently. Thank you.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
1
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
1
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
@@ -8,6 +8,7 @@ body:
|
||||
Please note the following:
|
||||
1. Only submit a feature request if the feature does not exist on the latest dev version.
|
||||
2. This page is for suggesting changes to **the engine itself**. To suggest changes to games, please [search for the game in the ContentDB](https://content.luanti.org/packages/?type=game) and submit a feature request in their issue trackers.
|
||||
3. If you have used an LLM/AI to format your issue description, disclose this. Try to keep it concise. No walls of text please.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Problem
|
||||
|
||||
18
.github/workflows/linux.yml
vendored
18
.github/workflows/linux.yml
vendored
@@ -14,6 +14,7 @@ on:
|
||||
- 'cmake/Modules/**'
|
||||
- 'po/**.po'
|
||||
- 'util/ci/**'
|
||||
- 'util/helper_mod/**'
|
||||
- '.github/workflows/linux.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
@@ -27,6 +28,7 @@ on:
|
||||
- 'cmake/Modules/**'
|
||||
- 'po/**.po'
|
||||
- 'util/ci/**'
|
||||
- 'util/helper_mod/**'
|
||||
- '.github/workflows/linux.yml'
|
||||
|
||||
env:
|
||||
@@ -76,6 +78,8 @@ jobs:
|
||||
env:
|
||||
CC: gcc-14
|
||||
CXX: g++-14
|
||||
# just to check that they compile correctly
|
||||
CMAKE_FLAGS: '-DBUILD_BENCHMARKS=1'
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
@@ -132,16 +136,16 @@ jobs:
|
||||
run: |
|
||||
./util/test_multiplayer.sh
|
||||
|
||||
# Build with prometheus-cpp (server-only)
|
||||
clang_11_prometheus:
|
||||
name: "clang_11 (PROMETHEUS=1)"
|
||||
runs-on: ubuntu-22.04
|
||||
# Build with prometheus-cpp (server-only), also runs on ARM64
|
||||
clang_prometheus_arm:
|
||||
name: "clang (with Prometheus, ARM64)"
|
||||
runs-on: ubuntu-24.04-arm
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install deps
|
||||
run: |
|
||||
source ./util/ci/common.sh
|
||||
install_linux_deps clang-11
|
||||
install_linux_deps --headless clang libluajit-5.1-dev
|
||||
|
||||
- name: Build prometheus-cpp
|
||||
run: ./util/ci/build_prometheus_cpp.sh
|
||||
@@ -150,8 +154,8 @@ jobs:
|
||||
run: |
|
||||
./util/ci/build.sh
|
||||
env:
|
||||
CC: clang-11
|
||||
CXX: clang++-11
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
CMAKE_FLAGS: "-DENABLE_PROMETHEUS=1 -DBUILD_CLIENT=0 -DENABLE_CURSES=0"
|
||||
|
||||
- name: Test
|
||||
|
||||
8
.github/workflows/windows.yml
vendored
8
.github/workflows/windows.yml
vendored
@@ -68,8 +68,8 @@ jobs:
|
||||
if-no-files-found: error
|
||||
|
||||
msvc:
|
||||
name: VS 2019 ${{ matrix.config.arch }}-${{ matrix.type }}
|
||||
runs-on: windows-2019
|
||||
name: VS 2022 ${{ matrix.config.arch }}-${{ matrix.type }}
|
||||
runs-on: windows-2025
|
||||
env:
|
||||
VCPKG_DEFAULT_TRIPLET: ${{matrix.config.vcpkg_triplet}}
|
||||
strategy:
|
||||
@@ -78,12 +78,12 @@ jobs:
|
||||
config:
|
||||
- {
|
||||
arch: x86,
|
||||
generator: "-G'Visual Studio 16 2019' -A Win32",
|
||||
generator: "-G'Visual Studio 17 2022' -A Win32",
|
||||
vcpkg_triplet: x86-windows
|
||||
}
|
||||
- {
|
||||
arch: x64,
|
||||
generator: "-G'Visual Studio 16 2019' -A x64",
|
||||
generator: "-G'Visual Studio 17 2022' -A x64",
|
||||
vcpkg_triplet: x64-windows
|
||||
}
|
||||
type: [portable]
|
||||
|
||||
@@ -20,6 +20,7 @@ read_globals = {
|
||||
"profiler",
|
||||
"Settings",
|
||||
"ValueNoise", "ValueNoiseMap",
|
||||
"tracy",
|
||||
|
||||
string = {fields = {"split", "trim"}},
|
||||
table = {fields = {"copy", "copy_with_metatables", "getn", "indexof", "keyof", "insert_all"}},
|
||||
@@ -40,7 +41,7 @@ stds.menu_common = {
|
||||
},
|
||||
}
|
||||
|
||||
files["builtin/client/register.lua"] = {
|
||||
files["builtin/client/init.lua"] = {
|
||||
globals = {
|
||||
debug = {fields={"getinfo"}},
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ set(CLANG_MINIMUM_VERSION "7.0.1")
|
||||
|
||||
# You should not need to edit these manually, use util/bump_version.sh
|
||||
set(VERSION_MAJOR 5)
|
||||
set(VERSION_MINOR 12)
|
||||
set(VERSION_MINOR 14)
|
||||
set(VERSION_PATCH 0)
|
||||
set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ Table of Contents
|
||||
Further documentation
|
||||
----------------------
|
||||
- Website: https://www.luanti.org/
|
||||
- Wiki: https://wiki.luanti.org/
|
||||
- Luanti Documentation: https://docs.luanti.org/
|
||||
- Forum: https://forum.luanti.org/
|
||||
- GitHub: https://github.com/luanti-org/luanti/
|
||||
- [Developer documentation](doc/developing/)
|
||||
|
||||
@@ -6,7 +6,7 @@ android {
|
||||
applicationId 'net.minetest.minetest'
|
||||
minSdkVersion 21
|
||||
compileSdk 34
|
||||
targetSdkVersion 34
|
||||
targetSdkVersion 35
|
||||
versionName "${versionMajor}.${versionMinor}.${versionPatch}"
|
||||
versionCode versionMajor * 1000000 + versionMinor * 10000 + versionPatch * 100 + versionBuild
|
||||
}
|
||||
|
||||
4
android/app/src/main/res/values-az/strings.xml
Normal file
4
android/app/src/main/res/values-az/strings.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="label">Luanti</string>
|
||||
</resources>
|
||||
12
android/app/src/main/res/values-el/strings.xml
Normal file
12
android/app/src/main/res/values-el/strings.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="label">Luanti</string>
|
||||
<string name="loading">Φόρτωση…</string>
|
||||
<string name="notification_channel_name">Γενική ειδοποίηση</string>
|
||||
<string name="notification_channel_description">Ειδοποιήσεις από το Luanti</string>
|
||||
<string name="unzip_notification_title">Φόρτωση του Luanti</string>
|
||||
<string name="unzip_notification_description">Λιγότερο από 1 λεπτό…</string>
|
||||
<string name="game_notification_title">Το Luanti εκτελείται</string>
|
||||
<string name="ime_dialog_done">Ολοκληρώθηκε</string>
|
||||
<string name="no_web_browser">Δεν βρέθηκε πρόγραμμα περιήγησης ιστού</string>
|
||||
</resources>
|
||||
10
android/app/src/main/res/values-fil/strings.xml
Normal file
10
android/app/src/main/res/values-fil/strings.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="unzip_notification_title">Loading ang Luanti</string>
|
||||
<string name="unzip_notification_description">Sa loob ng isang minuto…</string>
|
||||
<string name="notification_channel_name">Notification na general</string>
|
||||
<string name="notification_channel_description">Notification mula sa Luanti</string>
|
||||
<string name="game_notification_title">Pina-pagana ang Luanti</string>
|
||||
<string name="ime_dialog_done">Tapos na</string>
|
||||
<string name="no_web_browser">Walang mahanap na web browser</string>
|
||||
</resources>
|
||||
@@ -8,4 +8,5 @@
|
||||
<string name="unzip_notification_description">Menos de 1 minuto…</string>
|
||||
<string name="ime_dialog_done">Feito</string>
|
||||
<string name="no_web_browser">Non se atopou ningún navegador web</string>
|
||||
<string name="game_notification_title">Luanti está en funcionamento</string>
|
||||
</resources>
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
<string name="loading">Betöltés…</string>
|
||||
<string name="notification_channel_name">Általános értesítés</string>
|
||||
<string name="notification_channel_description">Értesítések a Luanti-től</string>
|
||||
<string name="unzip_notification_title">Luanti betöltése…</string>
|
||||
<string name="unzip_notification_title">A Luanti épp betölt</string>
|
||||
<string name="ime_dialog_done">Kész</string>
|
||||
<string name="no_web_browser">Nem található webböngésző</string>
|
||||
<string name="label">Luanti</string>
|
||||
<string name="unzip_notification_description">Kevesebb, mint 1 perc…</string>
|
||||
</resources>
|
||||
<string name="game_notification_title">A Luanti jelenleg fut</string>
|
||||
</resources>
|
||||
|
||||
4
android/app/src/main/res/values-hy/strings.xml
Normal file
4
android/app/src/main/res/values-hy/strings.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="label">Luanti</string>
|
||||
</resources>
|
||||
12
android/app/src/main/res/values-iw/strings.xml
Normal file
12
android/app/src/main/res/values-iw/strings.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="label">לואנטי</string>
|
||||
<string name="loading">טוען…</string>
|
||||
<string name="notification_channel_name">הודעה כללית</string>
|
||||
<string name="notification_channel_description">התראות מלואנטי</string>
|
||||
<string name="unzip_notification_title">טוען לואנטי</string>
|
||||
<string name="game_notification_title">לואנטי רץ</string>
|
||||
<string name="ime_dialog_done">בוצע</string>
|
||||
<string name="no_web_browser">לא נמצא דפדפן אינטרנט</string>
|
||||
<string name="unzip_notification_description">פחות מדקה אחת…</string>
|
||||
</resources>
|
||||
4
android/app/src/main/res/values-kmr/strings.xml
Normal file
4
android/app/src/main/res/values-kmr/strings.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="label">Luanti</string>
|
||||
</resources>
|
||||
12
android/app/src/main/res/values-pt-rBR/strings.xml
Normal file
12
android/app/src/main/res/values-pt-rBR/strings.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="label">Luanti</string>
|
||||
<string name="loading">Carregando…</string>
|
||||
<string name="notification_channel_name">Notificação geral</string>
|
||||
<string name="notification_channel_description">Notificações do Luanti</string>
|
||||
<string name="unzip_notification_title">Carregando Luanti</string>
|
||||
<string name="unzip_notification_description">Menos de 1 minuto…</string>
|
||||
<string name="game_notification_title">O Luanti está em execução</string>
|
||||
<string name="ime_dialog_done">Concluído</string>
|
||||
<string name="no_web_browser">Nenhum navegador encontrado</string>
|
||||
</resources>
|
||||
12
android/app/src/main/res/values-sk/strings.xml
Normal file
12
android/app/src/main/res/values-sk/strings.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="label">Luanti</string>
|
||||
<string name="loading">Načítavam…</string>
|
||||
<string name="notification_channel_name">Hlavné oznámenie</string>
|
||||
<string name="notification_channel_description">Oznámenia Luanti</string>
|
||||
<string name="unzip_notification_title">Načítanie Luanti</string>
|
||||
<string name="unzip_notification_description">Už iba minútka…</string>
|
||||
<string name="game_notification_title">Luanti už frčí</string>
|
||||
<string name="ime_dialog_done">Hotovo</string>
|
||||
<string name="no_web_browser">Nenašiel som žiaden prehliadač</string>
|
||||
</resources>
|
||||
@@ -8,4 +8,5 @@
|
||||
<string name="notification_channel_description">Obvestilo od Luantia</string>
|
||||
<string name="ime_dialog_done">Končano!l</string>
|
||||
<string name="unzip_notification_title">Nalaganje Luantia</string>
|
||||
<string name="game_notification_title">Luanti deluje</string>
|
||||
</resources>
|
||||
|
||||
4
android/app/src/main/res/values-tl/strings.xml
Normal file
4
android/app/src/main/res/values-tl/strings.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="label">ᜎᜓᜏᜈ᜔ᜆᜒ</string>
|
||||
</resources>
|
||||
@@ -5,7 +5,8 @@
|
||||
<string name="loading">Завантаження…</string>
|
||||
<string name="notification_channel_name">Загальні сповіщення</string>
|
||||
<string name="unzip_notification_title">Luanti завантажується</string>
|
||||
<string name="unzip_notification_description">Менше за 1 хвилину…</string>
|
||||
<string name="unzip_notification_description">Менше 1 хвилини…</string>
|
||||
<string name="ime_dialog_done">Готово</string>
|
||||
<string name="notification_channel_description">Сповіщення від Luanti</string>
|
||||
</resources>
|
||||
<string name="game_notification_title">Luanti працює</string>
|
||||
</resources>
|
||||
|
||||
@@ -8,4 +8,5 @@
|
||||
<string name="unzip_notification_description">不到1分钟…</string>
|
||||
<string name="ime_dialog_done">完成</string>
|
||||
<string name="no_web_browser">未找到网页浏览器</string>
|
||||
<string name="game_notification_title">Luanti正在运行</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
project.ext.set("versionMajor", 5) // Version Major
|
||||
project.ext.set("versionMinor", 12) // Version Minor
|
||||
project.ext.set("versionMinor", 14) // Version Minor
|
||||
project.ext.set("versionPatch", 0) // Version Patch
|
||||
// ^ keep in sync with cmake
|
||||
|
||||
@@ -9,14 +9,14 @@ project.ext.set("versionBuild", 0) // Version Build
|
||||
// ^ fourth version number to allow releasing Android-only fixes and beta versions
|
||||
|
||||
buildscript {
|
||||
ext.ndk_version = '27.2.12479018'
|
||||
ext.ndk_version = '27.3.13750724'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.5.1'
|
||||
classpath 'de.undercouch:gradle-download-task:4.1.1'
|
||||
classpath 'com.android.tools.build:gradle:8.12.3'
|
||||
classpath 'de.undercouch:gradle-download-task:5.6.0'
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
@@ -30,5 +30,5 @@ allprojects {
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
delete rootProject.layout.buildDirectory
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -68,5 +68,5 @@ if (new File(depsDir, 'armeabi-v7a').exists()) {
|
||||
preBuild.dependsOn getDeps
|
||||
|
||||
clean {
|
||||
delete new File(buildDir.parent, 'deps')
|
||||
delete depsDir
|
||||
}
|
||||
|
||||
@@ -13,3 +13,6 @@ dofile(commonpath .. "information_formspecs.lua")
|
||||
dofile(clientpath .. "chatcommands.lua")
|
||||
dofile(clientpath .. "misc.lua")
|
||||
assert(loadfile(commonpath .. "item_s.lua"))({}) -- Just for push/read node functions
|
||||
|
||||
-- unset, as promised in initializeSecurityClient()
|
||||
debug.getinfo = nil
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--------------------------------------------------------------------------------
|
||||
-- Localize functions to avoid table lookups (better performance).
|
||||
local string_sub, string_find = string.sub, string.find
|
||||
local string_sub, string_find, string_rep = string.sub, string.find, string.rep
|
||||
local math = math
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -179,7 +179,7 @@ function dump(value, indent)
|
||||
write(newline)
|
||||
|
||||
local function write_entry(k, v)
|
||||
write(indent:rep(level))
|
||||
write(string_rep(indent, level))
|
||||
write("[")
|
||||
write_value(k, level + 1)
|
||||
write("] = ")
|
||||
@@ -201,7 +201,7 @@ function dump(value, indent)
|
||||
for _, k in ipairs(keys.string) do
|
||||
local v = val[k]
|
||||
if is_valid_identifier(k) then
|
||||
write(indent:rep(level))
|
||||
write(string_rep(indent, level))
|
||||
write(k)
|
||||
write(" = ")
|
||||
write_value(v, level + 1)
|
||||
@@ -219,7 +219,7 @@ function dump(value, indent)
|
||||
end
|
||||
if #keys.number == len then -- table is a list
|
||||
for _, v in ipairs(tbl) do
|
||||
write(indent:rep(level))
|
||||
write(string_rep(indent, level))
|
||||
write_value(v, level + 1)
|
||||
write(",")
|
||||
write(newline)
|
||||
@@ -238,7 +238,7 @@ function dump(value, indent)
|
||||
end
|
||||
end
|
||||
|
||||
write(indent:rep(level - 1))
|
||||
write(string_rep(indent, level - 1))
|
||||
write("}")
|
||||
end
|
||||
write_value(value, 1)
|
||||
@@ -658,7 +658,7 @@ function core.colorize(color, message)
|
||||
lines[i] = color_code .. line
|
||||
end
|
||||
|
||||
return table.concat(lines, "\n") .. core.get_color_escape_sequence("#ffffff")
|
||||
return table.concat(lines, "\n") .. core.get_color_escape_sequence("#fff")
|
||||
end
|
||||
|
||||
|
||||
@@ -674,6 +674,7 @@ function core.strip_colors(str)
|
||||
return (str:gsub(ESCAPE_CHAR .. "%([bc]@[^)]+%)", ""))
|
||||
end
|
||||
|
||||
|
||||
local function translate(textdomain, str, num, ...)
|
||||
local start_seq
|
||||
if textdomain == "" and num == "" then
|
||||
@@ -853,22 +854,22 @@ Intended to be used in chat command parameter parsing.
|
||||
|
||||
Parameters:
|
||||
* x, y, z: Parsed x, y, and z coordinates as strings
|
||||
* relative_to: Position to which to compare the position
|
||||
* relative_to: Optional position vector as reference point
|
||||
|
||||
Syntax of x, y and z:
|
||||
* "<number>": return as number
|
||||
* "~<number>": return <number> + player position on this axis
|
||||
* "~": return player position on this axis
|
||||
* "<number>": use as number
|
||||
* "~<number>": use <number> + reference point on this axis
|
||||
* "~": use reference point on this axis
|
||||
|
||||
Returns: a vector or nil for invalid input or if player does not exist
|
||||
Returns: a vector or nil for invalid input
|
||||
]]
|
||||
function core.parse_coordinates(x, y, z, relative_to)
|
||||
if not relative_to then
|
||||
x, y, z = tonumber(x), tonumber(y), tonumber(z)
|
||||
return x and y and z and { x = x, y = y, z = z }
|
||||
return x and y and z and vector.new(x, y, z)
|
||||
end
|
||||
local rx = core.parse_relative_number(x, relative_to.x)
|
||||
local ry = core.parse_relative_number(y, relative_to.y)
|
||||
local rz = core.parse_relative_number(z, relative_to.z)
|
||||
return rx and ry and rz and { x = rx, y = ry, z = rz }
|
||||
return rx and ry and rz and vector.new(rx, ry, rz)
|
||||
end
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local builtin_shared = ...
|
||||
local debug_getinfo = debug.getinfo
|
||||
|
||||
do
|
||||
local default = {mod = "??", name = "??"}
|
||||
@@ -56,7 +57,7 @@ function builtin_shared.make_registration()
|
||||
core.callback_origins[func] = {
|
||||
-- may be nil or return nil
|
||||
mod = core.get_current_modname and core.get_current_modname() or "??",
|
||||
name = debug.getinfo(1, "n").name or "??"
|
||||
name = debug_getinfo(1, "n").name or "??"
|
||||
}
|
||||
end
|
||||
return t, registerfunc
|
||||
@@ -69,7 +70,7 @@ function builtin_shared.make_registration_reverse()
|
||||
core.callback_origins[func] = {
|
||||
-- may be nil or return nil
|
||||
mod = core.get_current_modname and core.get_current_modname() or "??",
|
||||
name = debug.getinfo(1, "n").name or "??"
|
||||
name = debug_getinfo(1, "n").name or "??"
|
||||
}
|
||||
end
|
||||
return t, registerfunc
|
||||
|
||||
@@ -438,11 +438,28 @@ function make.key(setting)
|
||||
if value == "" then
|
||||
return height
|
||||
end
|
||||
|
||||
local critical_keys = {
|
||||
keymap_drop = true,
|
||||
keymap_dig = true,
|
||||
keymap_place = true,
|
||||
}
|
||||
|
||||
for _, o in ipairs(core.full_settingtypes) do
|
||||
if o.type == "key" and o.name ~= setting.name and core.are_keycodes_equal(core.settings:get(o.name), value) then
|
||||
table.insert(fs, ("label[0,%f;%s]"):format(height + 0.3,
|
||||
core.colorize(mt_color_orange, fgettext([[Conflicts with "$1"]], fgettext(o.readable_name)))))
|
||||
height = height + 0.6
|
||||
if o.type == "key" and o.name ~= setting.name and
|
||||
core.are_keycodes_equal(core.settings:get(o.name), value) then
|
||||
|
||||
local is_current_close_world = setting.name == "keymap_close_world"
|
||||
local is_other_close_world = o.name == "keymap_close_world"
|
||||
local is_current_critical = critical_keys[setting.name]
|
||||
local is_other_critical = critical_keys[o.name]
|
||||
|
||||
if (is_other_critical or is_current_critical) or
|
||||
(not is_current_close_world and not is_other_close_world) then
|
||||
table.insert(fs, ("label[0,%f;%s]"):format(height + 0.3,
|
||||
core.colorize(mt_color_orange, fgettext([[Conflicts with "$1"]], fgettext(o.readable_name)))))
|
||||
height = height + 0.6
|
||||
end
|
||||
end
|
||||
end
|
||||
return height
|
||||
@@ -454,12 +471,12 @@ function make.key(setting)
|
||||
|
||||
get_formspec = function(self, avail_w)
|
||||
self.resettable = core.settings:has(setting.name)
|
||||
local btn_bind_width = math.max(2.5, avail_w/2)
|
||||
local btn_bind_width = math.max(2.5, avail_w / 2)
|
||||
local value = core.settings:get(setting.name)
|
||||
local fs = {
|
||||
("label[0,0.4;%s]"):format(get_label(setting)),
|
||||
("button_key[%f,0;%f,0.8;%s;%s]"):format(
|
||||
btn_bind_width, btn_bind_width-0.8,
|
||||
btn_bind_width, btn_bind_width - 0.8,
|
||||
btn_bind, core.formspec_escape(value)),
|
||||
("image_button[%f,0;0.8,0.8;%s;%s;]"):format(avail_w - 0.8,
|
||||
core.formspec_escape(defaulttexturedir .. "clear.png"),
|
||||
|
||||
@@ -16,7 +16,7 @@ local minetest_example_header = [[
|
||||
# to the program, eg. "luanti.exe --config ../minetest.conf.example".
|
||||
|
||||
# Further documentation:
|
||||
# https://wiki.luanti.org/
|
||||
# https://docs.luanti.org/
|
||||
|
||||
]]
|
||||
|
||||
@@ -44,15 +44,18 @@ local function create_minetest_conf_example(settings)
|
||||
insert(result, rep("#", entry.level))
|
||||
insert(result, "# " .. entry.name .. "\n\n")
|
||||
end
|
||||
else
|
||||
else -- any `type` as listed in `settingtypes.txt`
|
||||
local group_format = false
|
||||
if entry.noise_params and entry.values then
|
||||
if entry.type == "noise_params_2d" or entry.type == "noise_params_3d" then
|
||||
group_format = true
|
||||
end
|
||||
end
|
||||
if entry.comment ~= "" then
|
||||
for _, comment_line in ipairs(entry.comment:split("\n", true)) do
|
||||
|
||||
local comment = entry.comment ~= "" and entry.comment
|
||||
or entry.readable_name -- fallback to the short description
|
||||
if comment ~= "" then
|
||||
for _, comment_line in ipairs(comment:split("\n", true)) do
|
||||
if comment_line == "" then
|
||||
insert(result, "#\n")
|
||||
else
|
||||
@@ -102,23 +105,45 @@ end
|
||||
local translation_file_header = [[
|
||||
// This file is automatically generated
|
||||
// It contains a bunch of fake gettext calls, to tell xgettext about the strings in config files
|
||||
// To update it, refer to the bottom of builtin/mainmenu/dlg_settings_advanced.lua
|
||||
// To update it, refer to the bottom of builtin/common/settings/init.lua
|
||||
|
||||
fake_function() {]]
|
||||
|
||||
local function add_translation_string(result, str, seen)
|
||||
if seen[str] then
|
||||
return
|
||||
end
|
||||
seen[str] = true
|
||||
|
||||
-- Prevent gettext from interpreting e.g. "50% of volume" as C-formatted string
|
||||
-- Documentation: https://www.gnu.org/software/gettext/manual/html_node/c_002dformat-Flag.html
|
||||
local force_no_c_format = str:find("%", 1, true)
|
||||
local prefix = force_no_c_format and "/* xgettext:no-c-format */ " or ""
|
||||
|
||||
local have_newlines = str:find("\n", 1, true)
|
||||
if have_newlines then
|
||||
-- Formatting as "%q" inserts literal newlines. But we want '\n'.
|
||||
-- Hence, use "%s" and escape relevant characters manually.
|
||||
str = str:gsub("\n", "\\n")
|
||||
str = str:gsub("\"", "\\\"")
|
||||
insert(result, sprintf("\t%sgettext(\"%s\");", prefix, str))
|
||||
else
|
||||
insert(result, sprintf("\t%sgettext(%q);", prefix, str))
|
||||
end
|
||||
end
|
||||
|
||||
local function create_translation_file(settings)
|
||||
local seen = {} -- to deduplicate entries
|
||||
local result = { translation_file_header }
|
||||
for _, entry in ipairs(settings) do
|
||||
if entry.type == "category" then
|
||||
insert(result, sprintf("\tgettext(%q);", entry.name))
|
||||
add_translation_string(result, entry.name, seen)
|
||||
else
|
||||
if entry.readable_name then
|
||||
insert(result, sprintf("\tgettext(%q);", entry.readable_name))
|
||||
add_translation_string(result, entry.readable_name, seen)
|
||||
end
|
||||
if entry.comment ~= "" then
|
||||
local comment_escaped = entry.comment:gsub("\n", "\\n")
|
||||
comment_escaped = comment_escaped:gsub("\"", "\\\"")
|
||||
insert(result, "\tgettext(\"" .. comment_escaped .. "\");")
|
||||
add_translation_string(result, entry.comment, seen)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
local getinfo, rawget, rawset = debug.getinfo, rawget, rawset
|
||||
local debug_getinfo, rawget, rawset = debug.getinfo, rawget, rawset
|
||||
|
||||
function core.global_exists(name)
|
||||
if type(name) ~= "string" then
|
||||
@@ -18,13 +18,15 @@ function meta:__newindex(name, value)
|
||||
if declared[name] then
|
||||
return
|
||||
end
|
||||
local info = getinfo(2, "Sl")
|
||||
local desc = ("%s:%d"):format(info.short_src, info.currentline)
|
||||
local warn_key = ("%s\0%d\0%s"):format(info.source, info.currentline, name)
|
||||
if not warned[warn_key] and info.what ~= "main" and info.what ~= "C" then
|
||||
core.log("warning", ("Assignment to undeclared global %q inside a function at %s.")
|
||||
:format(name, desc))
|
||||
warned[warn_key] = true
|
||||
local info = debug_getinfo(2, "Sl")
|
||||
if info ~= nil then
|
||||
local desc = ("%s:%d"):format(info.short_src, info.currentline)
|
||||
local warn_key = ("%s\0%d\0%s"):format(info.source, info.currentline, name)
|
||||
if not warned[warn_key] and info.what ~= "main" and info.what ~= "C" then
|
||||
core.log("warning", ("Assignment to undeclared global %q inside a function at %s.")
|
||||
:format(name, desc))
|
||||
warned[warn_key] = true
|
||||
end
|
||||
end
|
||||
declared[name] = true
|
||||
end
|
||||
@@ -34,7 +36,10 @@ function meta:__index(name)
|
||||
if declared[name] then
|
||||
return
|
||||
end
|
||||
local info = getinfo(2, "Sl")
|
||||
local info = debug_getinfo(2, "Sl")
|
||||
if info == nil then
|
||||
return
|
||||
end
|
||||
local warn_key = ("%s\0%d\0%s"):format(info.source, info.currentline, name)
|
||||
if not warned[warn_key] and info.what ~= "C" then
|
||||
core.log("warning", ("Undeclared global variable %q accessed at %s:%s")
|
||||
|
||||
@@ -432,7 +432,32 @@ describe("vector", function()
|
||||
assert.True(almost_equal({x = 1, y = 0, z = 0},
|
||||
vector.rotate({x = 1, y = 0, z = 0}, {x = math.pi / 123, y = 0, z = 0})))
|
||||
end)
|
||||
it("is counterclockwise", function()
|
||||
it("rotation order is Z-X-Y", function()
|
||||
local r = vector.new(1, 2, 3)
|
||||
for _, v in ipairs({
|
||||
vector.new(1, 0, 0),
|
||||
vector.new(0, 1, 0),
|
||||
vector.new(0, 0, 1),
|
||||
}) do
|
||||
local expected = v:rotate(r)
|
||||
local function try(order)
|
||||
local rotated = v
|
||||
for axis in order:gmatch(".") do
|
||||
local r_axis = vector.zero()
|
||||
r_axis[axis] = r[axis]
|
||||
rotated = vector.rotate(rotated, r_axis)
|
||||
end
|
||||
return almost_equal(rotated, expected)
|
||||
end
|
||||
assert.False(try("xyz"))
|
||||
assert.False(try("xzy"))
|
||||
assert.False(try("yxz"))
|
||||
assert.False(try("yzx"))
|
||||
assert.True(try("zxy"))
|
||||
assert.False(try("zyx"))
|
||||
end
|
||||
end)
|
||||
it("is right handed", function()
|
||||
local v_before1 = {x = 0, y = 1, z = -1}
|
||||
local v_after1 = vector.rotate(v_before1, {x = math.pi / 4, y = 0, z = 0})
|
||||
assert.True(almost_equal(vector.normalize(vector.cross(v_after1, v_before1)), {x = 1, y = 0, z = 0}))
|
||||
|
||||
@@ -118,7 +118,7 @@ function ui.update()
|
||||
|
||||
if (active_toplevel_ui_elements > 1) then
|
||||
core.log("warning", "more than one active ui "..
|
||||
"element, self most likely isn't intended")
|
||||
"element, this most likely isn't intended")
|
||||
end
|
||||
|
||||
if (active_toplevel_ui_elements == 0) then
|
||||
|
||||
@@ -8,15 +8,24 @@ function core.async_event_handler(jobid, retval)
|
||||
core.async_jobs[jobid] = nil
|
||||
end
|
||||
|
||||
local job_metatable = {__index = {}}
|
||||
|
||||
function job_metatable.__index:cancel()
|
||||
local cancelled = core.cancel_async_callback(self.id)
|
||||
if cancelled then
|
||||
core.async_jobs[self.id] = nil
|
||||
end
|
||||
return cancelled
|
||||
end
|
||||
|
||||
function core.handle_async(func, callback, ...)
|
||||
assert(type(func) == "function" and type(callback) == "function",
|
||||
"Invalid core.handle_async invocation")
|
||||
local args = {n = select("#", ...), ...}
|
||||
local mod_origin = core.get_last_run_mod()
|
||||
|
||||
local jobid = core.do_async_callback(func, args, mod_origin)
|
||||
core.async_jobs[jobid] = callback
|
||||
local id = core.do_async_callback(func, args, mod_origin)
|
||||
core.async_jobs[id] = callback
|
||||
|
||||
return true
|
||||
return setmetatable({id = id}, job_metatable)
|
||||
end
|
||||
|
||||
|
||||
@@ -47,6 +47,10 @@ core.features = {
|
||||
particle_blend_clip = true,
|
||||
remove_item_match_meta = true,
|
||||
httpfetch_additional_methods = true,
|
||||
object_guids = true,
|
||||
on_timer_four_args = true,
|
||||
particlespawner_exclude_player = true,
|
||||
generate_decorations_biomes = true,
|
||||
}
|
||||
|
||||
function core.has_feature(arg)
|
||||
|
||||
@@ -353,7 +353,7 @@ function core.item_place(itemstack, placer, pointed_thing, param2)
|
||||
return itemstack, nil
|
||||
end
|
||||
|
||||
function core.item_secondary_use(itemstack, placer)
|
||||
function core.item_secondary_use(itemstack, user)
|
||||
return itemstack
|
||||
end
|
||||
|
||||
@@ -390,7 +390,7 @@ function core.item_pickup(itemstack, picker, pointed_thing, ...)
|
||||
end
|
||||
end
|
||||
|
||||
-- Pickup item.
|
||||
-- Pick up item
|
||||
local inv = picker and picker:get_inventory()
|
||||
if inv then
|
||||
return inv:add_item("main", itemstack)
|
||||
@@ -569,6 +569,26 @@ function core.node_dig(pos, node, digger)
|
||||
exclude_player = diggername,
|
||||
}, true)
|
||||
end
|
||||
-- Particles also
|
||||
if diggername ~= "" and def and def.drawtype ~= "airlike" then
|
||||
-- cf. ParticleManager::addDiggingParticles() et al
|
||||
local gravity = tonumber(core.settings:get("movement_gravity")) or 9.81
|
||||
core.add_particlespawner({
|
||||
amount = 16,
|
||||
time = 0.001,
|
||||
minpos = vector.offset(pos, -0.25, -0.25, -0.25),
|
||||
maxpos = vector.offset(pos, 0.25, 0.25, 0.25),
|
||||
minvel = vector.new(-1.5, 0, -1.5),
|
||||
maxvel = vector.new(1.5, 3, 1.5),
|
||||
minacc = vector.new(0, -gravity, 0),
|
||||
maxacc = vector.new(0, -gravity, 0),
|
||||
minexptime = 0, maxexptime = 1,
|
||||
minsize = 0, maxsize = 0, -- random
|
||||
node = node,
|
||||
blend = (def and def.use_texture_alpha == "blend") and "blend" or "clip",
|
||||
exclude_player = diggername,
|
||||
})
|
||||
end
|
||||
|
||||
-- Run callback
|
||||
if def and def.after_dig_node then
|
||||
@@ -639,6 +659,7 @@ core.nodedef_default = {
|
||||
on_drop = redef_wrapper(core, 'item_drop'), -- core.item_drop
|
||||
on_pickup = redef_wrapper(core, 'item_pickup'), -- core.item_pickup
|
||||
on_use = nil,
|
||||
after_use = nil,
|
||||
can_dig = nil,
|
||||
|
||||
on_punch = redef_wrapper(core, 'node_punch'), -- core.node_punch
|
||||
@@ -740,16 +761,16 @@ core.noneitemdef_default = { -- This is used for the hand and unknown items
|
||||
--
|
||||
|
||||
local get_node_raw = core.get_node_raw
|
||||
core.get_node_raw = nil
|
||||
local get_name_from_content_id = core.get_name_from_content_id
|
||||
|
||||
function core.get_node(pos)
|
||||
local content, param1, param2 = get_node_raw(pos.x, pos.y, pos.z)
|
||||
return {name = core.get_name_from_content_id(content), param1 = param1, param2 = param2}
|
||||
return {name = get_name_from_content_id(content), param1 = param1, param2 = param2}
|
||||
end
|
||||
|
||||
function core.get_node_or_nil(pos)
|
||||
local content, param1, param2, pos_ok = get_node_raw(pos.x, pos.y, pos.z)
|
||||
return pos_ok and
|
||||
{name = core.get_name_from_content_id(content), param1 = param1, param2 = param2}
|
||||
{name = get_name_from_content_id(content), param1 = param1, param2 = param2}
|
||||
or nil
|
||||
end
|
||||
|
||||
@@ -130,6 +130,8 @@ core.protocol_versions = {
|
||||
["5.10.0"] = 46,
|
||||
["5.11.0"] = 47,
|
||||
["5.12.0"] = 48,
|
||||
["5.13.0"] = 49,
|
||||
["5.14.0"] = 50,
|
||||
}
|
||||
|
||||
setmetatable(core.protocol_versions, {__newindex = function()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
local builtin_shared = ...
|
||||
local S = core.get_translator("__builtin")
|
||||
local debug_getinfo = debug.getinfo
|
||||
|
||||
--
|
||||
-- Make raw registration functions inaccessible to anyone except this file
|
||||
@@ -548,7 +549,7 @@ function core.registered_on_player_hpchange(player, hp_change, reason)
|
||||
local func = core.registered_on_player_hpchanges.modifiers[i]
|
||||
hp_change, last = func(player, hp_change, reason)
|
||||
if type(hp_change) ~= "number" then
|
||||
local debuginfo = debug.getinfo(func)
|
||||
local debuginfo = debug_getinfo(func)
|
||||
error("The register_on_hp_changes function has to return a number at " ..
|
||||
debuginfo.short_src .. " line " .. debuginfo.linedefined)
|
||||
end
|
||||
@@ -570,7 +571,7 @@ function core.register_on_player_hpchange(func, modifier)
|
||||
end
|
||||
core.callback_origins[func] = {
|
||||
mod = core.get_current_modname() or "??",
|
||||
name = debug.getinfo(1, "n").name or "??"
|
||||
name = debug_getinfo(1, "n").name or "??"
|
||||
}
|
||||
end
|
||||
|
||||
@@ -584,6 +585,7 @@ core.unregister_biome = make_wrap_deregistration(core.register_biome,
|
||||
local make_registration = builtin_shared.make_registration
|
||||
local make_registration_reverse = builtin_shared.make_registration_reverse
|
||||
|
||||
-- keep in sync with profiler/instrumentation.lua
|
||||
core.registered_on_chat_messages, core.register_on_chat_message = make_registration()
|
||||
core.registered_on_chatcommands, core.register_on_chatcommand = make_registration()
|
||||
core.registered_globalsteps, core.register_globalstep = make_registration()
|
||||
|
||||
@@ -1,3 +1,246 @@
|
||||
# textdomain: __builtin
|
||||
Empty command.=Празна команда.
|
||||
Invalid command: @1=Неприемлива команда: @1
|
||||
Invalid command usage.=Неприемлива употреба на команда.
|
||||
(@1 s)= (@1 сек)
|
||||
Command execution took @1 s=Изпълнението на командата отне @1 сек.
|
||||
You don't have permission to run this command (missing privileges: @1).=Нямате права да изпълните тази команда (липсващи права: @1).
|
||||
Unable to get position of player @1.=Неуспешно получаване на позицията на играч @1.
|
||||
Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)=Неправилен формат на област. Очаква се: (x1,y1,z1) (x2,y2,z2)
|
||||
<action>=<действие>
|
||||
Show chat action (e.g., '/me orders a pizza' displays '<player name> orders a pizza')=Показва действие в разговорите (напр. „/me поръчва пица“ показва „<име на играч> поръчва пица“)
|
||||
Show the name of the server owner=Показва името на собственика на сървъра
|
||||
The administrator of this server is @1.=Администраторът на този сървър е @1.
|
||||
There's no administrator named in the config file.=Във файла с настройки не е зададен администратор.
|
||||
@1 does not have any privileges.=@1 няма никакви права.
|
||||
Privileges of @1: @2=Правата на @1: @2
|
||||
[<name>]=[<име>]
|
||||
Show privileges of yourself or another player=Показва вашите права или тези на друг играч
|
||||
Player @1 does not exist.=Играчът @1 не съществува.
|
||||
<privilege>=<права>
|
||||
Return list of all online players with privilege=Показва списък на играчите на линия с дадени права
|
||||
Invalid parameters (see /help haspriv).=Неприемливи параметри (вижте /help haspriv).
|
||||
Unknown privilege!=Неизвестно право!
|
||||
No online player has the "@1" privilege.=Няма играч на линия с правата „@1“.
|
||||
Players online with the "@1" privilege: @2=Играчи на линия с правата „@1“: @2
|
||||
Your privileges are insufficient.=Нямате достатъчно права.
|
||||
Your privileges are insufficient. '@1' only allows you to grant: @2=Нямате достатъчно права. „@1“ ви позволява да давате само: @2
|
||||
Unknown privilege: @1=Неизвестни права: @1
|
||||
@1 granted you privileges: @2=@1 ви даде правото: @2
|
||||
<name> (<privilege> [, <privilege2> [<...>]] | all)=<име> (<право> [, <право2> [<…>]] | all)
|
||||
Give privileges to player=Дава права на играч
|
||||
Invalid parameters (see /help grant).=Неприемливи параметри (вижте /help grant).
|
||||
<privilege> [, <privilege2> [<...>]] | all=<право> [, <право2> [<…>]] | all
|
||||
Grant privileges to yourself=Дава права на себе си
|
||||
Invalid parameters (see /help grantme).=Неприемливи параметри (вижте /help grantme).
|
||||
Your privileges are insufficient. '@1' only allows you to revoke: @2=Нямате достатъчно права. „@1“ ви позволява да отнемате само: @2
|
||||
Note: Cannot revoke in singleplayer: @1=Забележка: Не може да отнемате права в режим един играч: @1
|
||||
Note: Cannot revoke from admin: @1=Забележка: Не може да отнемате права на администратор: @1
|
||||
No privileges were revoked.=Не са отнети права.
|
||||
@1 revoked privileges from you: @2=@1 ви отне права: @2
|
||||
Remove privileges from player=Отнема права от играч
|
||||
Invalid parameters (see /help revoke).=Неприемливи параметри (вижте /help revoke).
|
||||
Revoke privileges from yourself=Отнема права от себе си
|
||||
Invalid parameters (see /help revokeme).=Неприемливи параметри (вижте /help revokeme).
|
||||
<name> <password>=<име> <парола>
|
||||
Set player's password (sent unencrypted, thus insecure)=Задава парола на играч (изпраща се нешифрована, следователно несигурно)
|
||||
Name field required.=Полето за име е задължително.
|
||||
Your password was cleared by @1.=Вашата парола е премахната от @1.
|
||||
Password of player "@1" cleared.=Паролата на играч „@1“ е премахната.
|
||||
Your password was set by @1.=Вашата парола е зададена от @1.
|
||||
Password of player "@1" set.=Паролата на играча „@1“ е зададена.
|
||||
<name>=<име>
|
||||
Set empty password for a player=Задава празна парола на играч
|
||||
Reload authentication data=Презарежда данните за удостоверяване
|
||||
Done.=Готово.
|
||||
Failed.=Грешка.
|
||||
Remove a player's data=Премахва данните на играч
|
||||
Player "@1" removed.=Играч „@1“ е премахнат.
|
||||
No such player "@1" to remove.=Няма такъв играч „@1“, който да бъде премахнат.
|
||||
Player "@1" is connected, cannot remove.=Играч „@1“ е свързан, не може да бъде премахнат.
|
||||
Unhandled remove_player return code @1.=Неподдържан код на състояние remove_player @1.
|
||||
Cannot teleport out of map bounds!=Не може да се телепортира извън границите на света!
|
||||
Cannot get player with name @1.=Не може да бъде намерен играч с име @1.
|
||||
Cannot teleport, @1 is attached to an object!=Не може да се телепортира, @1 е прикрепен към обект!
|
||||
Teleporting @1 to @2.=Телепортиране на @1 до @2.
|
||||
One does not teleport to oneself.=Не може да се телепортирате към себе си.
|
||||
Cannot get teleportee with name @1.=Не може да бъде намерен телепортиран играч с име @1.
|
||||
Cannot get target player with name @1.=Не може да бъде намерен целеви играч с име @1.
|
||||
Teleporting @1 to @2 at @3.=Телепортиране на @1 до @2 на @3.
|
||||
<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>=<X>,<Y>,<Z> | <до_име> | <име> <X>,<Y>,<Z> | <име> <до_име>
|
||||
Teleport to position or player=Телепортира до координати или играч
|
||||
You don't have permission to teleport other players (missing privilege: @1).=Нямате право да телепортирате други играчи (липсващи права: @1).
|
||||
([-n] <name> <value>) | <name>=([-n] <име> <стойност>) | <име>
|
||||
Set or read server configuration setting=Задава или извежда на екрата настройка на сървъра
|
||||
Failed. Cannot modify secure settings. Edit the settings file manually.=Грешка! Настройките за сигурност не могат да бъдат променяни. Променете файла с настройки ръчно.
|
||||
Failed. Use '/set -n <name> <value>' to create a new setting.=Грешка! Използвайте „/set -n <име> <стойност>“, за да създадете нова настройка.
|
||||
@1 @= @2=@1 @= @2
|
||||
<not set>=<не е зададено>
|
||||
Invalid parameters (see /help set).=Неприемливи параметри (вижте /help set).
|
||||
Finished emerging @1 blocks in @2ms.=Зареждането на @1 блока завърши за @2 мс.
|
||||
emergeblocks update: @1/@2 blocks emerged (@3%)=обновяване на emergeblocks: @1/@2 блока заредени (@3%)
|
||||
(here [<radius>]) | (<pos1> <pos2>)=(тук [<радиус>]) | (<коорд1> <коорд2>)
|
||||
Load (or, if nonexistent, generate) map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=Зарежда (или ако липсват, генерира) блокове от света в областта от коорд1 до коорд2 (<коорд1> и <коорд2> трябва да са в скоби)
|
||||
Started emerge of area ranging from @1 to @2.=Започна зареждане на областта от @1 до @2.
|
||||
Delete map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=Премахва блокове от света в областта от коорд1 до коорд2 (<коорд1> и <коорд2> трябва да са в скоби)
|
||||
Successfully cleared area ranging from @1 to @2.=Успешно изчистена област от @1 до @2.
|
||||
Failed to clear one or more blocks in area.=Неуспешно изчистване на един или повече блока в областта.
|
||||
Resets lighting in the area between pos1 and pos2 (<pos1> and <pos2> must be in parentheses)=Нулира осветлението в областта между коорд1 и коорд2 (<коорд1> и <коорд2> трябва да са в скоби)
|
||||
Successfully reset light in the area ranging from @1 to @2.=Успешно нулирано осветление в област от @1 до @2.
|
||||
Failed to load one or more blocks in area.=Неуспешно зареждане на един или повече блока в областта.
|
||||
List mods installed on the server=Показва списък с модификациите, инсталирани на сървъра
|
||||
No mods installed.=Няма инсталирани модификации.
|
||||
Cannot give an empty item.=Не може да бъде даден празен предмет.
|
||||
Cannot give an unknown item.=Не може да бъде даден неизвестен предмет.
|
||||
Giving 'ignore' is not allowed.=Не е позволено да бъде даван „ignore“.
|
||||
@1 is not a known player.=@1 не е известен играч.
|
||||
@1 partially added to inventory.=@1 частично добавен в инвентара.
|
||||
@1 could not be added to inventory.=@1 не може да бъде добавен в инвентара.
|
||||
@1 added to inventory.=@1 добавен в инвентара.
|
||||
@1 partially added to inventory of @2.=@1 частично добавен в инвентара на @2.
|
||||
@1 could not be added to inventory of @2.=@1 не може да бъде добавен в инвентара на @2.
|
||||
@1 added to inventory of @2.=@1 добавен в инвентара на @2.
|
||||
<name> <ItemString> [<count> [<wear>]]=<име> <име-на-предмет> [<брой> [<износване>]]
|
||||
Give item to player=Дава предмет на играч
|
||||
Name and ItemString required.=Изисква се име и име-на-предмет.
|
||||
<ItemString> [<count> [<wear>]]=<име-на-предмет> [<брой> [<износване>]]
|
||||
Give item to yourself=Дава предмет на себе си
|
||||
ItemString required.=Изисква се име-на-предмет.
|
||||
<EntityName> [<X>,<Y>,<Z>]=<име-на-същество> [<X>,<Y>,<Z>]
|
||||
Spawn entity at given (or your) position=Създава същество на дадена (или вашата) позиция
|
||||
EntityName required.=Изисква се име-на-същество.
|
||||
Unable to spawn entity, player is nil.=Неуспешно създаване на същество, играчът е null.
|
||||
Cannot spawn an unknown entity.=Не може да бъде създадено неизвестно същество.
|
||||
Invalid parameters (@1).=Неприемливи параметри (@1).
|
||||
@1 spawned.=@1 е създаден.
|
||||
@1 failed to spawn.=@1 не можа да бъде създаден.
|
||||
Destroy item in hand=Унищожава предмета в ръката
|
||||
Unable to pulverize, no player.=Неуспешно смачкване, няма играч.
|
||||
Unable to pulverize, no item in hand.=Неуспешно смачкване, няма предмет в ръката.
|
||||
An item was pulverized.=Предмет беше смачкан.
|
||||
[<range>] [<seconds>] [<limit>]=[<обхват>] [<секунди>] [<ограничение>]
|
||||
Check who last touched a node or a node near it within the time specified by <seconds>. Default: range @= 0, seconds @= 86400 @= 24h, limit @= 5. Set <seconds> to inf for no time limit=Проверява кой последно е докоснал възел или близък възел в рамките на времето, зададено от <секунди>. По подразбиране: обхват @= 0, секунди @= 86400 @= 24ч, ограничение @= 5. Задайте <секунди> на inf за без ограничение.
|
||||
Rollback functions are disabled.=Функциите за отменяне на действия са изключени.
|
||||
That limit is too high!=Ограничението е твърде голямо!
|
||||
Checking @1 ...=Проверка @1…
|
||||
Nobody has touched the specified location in @1 seconds.=Никой не е докосвал указаното място през последните @1 секунди.
|
||||
@1 @2 @3 -> @4 @5 seconds ago.=@1 @2 @3 -> @4 преди @5 секунди.
|
||||
Punch a node (range@=@1, seconds@=@2, limit@=@3).=Удар на възел (обхват@=@1, секунди@=@2, ограничение@=@3).
|
||||
(<name> [<seconds>]) | (:<actor> [<seconds>])=(<име> [<секунди>]) | (:<променящ> [<секунди>])
|
||||
Revert actions of a player. Default for <seconds> is 60. Set <seconds> to inf for no time limit=Отменя действията на играч. По подразбиране <секунди> е 60. Задайте <секунди> на inf за без ограничение.
|
||||
Invalid parameters. See /help rollback and /help rollback_check.=Неприемливи параметри. Вижте /help rollback и /help rollback_check.
|
||||
Reverting actions of player '@1' since @2 seconds.=Отменяне действията на играча „@1“ отпреди @2 секунди.
|
||||
Reverting actions of @1 since @2 seconds.=Отменяне действията на @1 отпреди @2 секунди.
|
||||
(log is too long to show)=(дневникът е твърде дълъг, за да бъде показан)
|
||||
Reverting actions succeeded.=Действията са отменени.
|
||||
Reverting actions FAILED.=Грешка при отменяне на действията.
|
||||
Show server status=Показва състоянието на сървъра
|
||||
This command was disabled by a mod or game.=Тази команда е изключена от модификация или игра.
|
||||
[<0..23>:<0..59> | <0..24000>]=[<0..23>:<0..59> | <0..24000>]
|
||||
Show or set time of day=Показва или задава часа на деня
|
||||
Current time is @1:@2.=Текущото време е @1:@2.
|
||||
You don't have permission to run this command (missing privilege: @1).=Нямате право да изпълните тази команда (липсващи права: @1).
|
||||
Invalid time (must be between 0 and 24000).=Неправилно време (трябва да бъде между 0 и 24000).
|
||||
Time of day changed.=Часът на деня е променен.
|
||||
Invalid hour (must be between 0 and 23 inclusive).=Неверен час (трябва да бъде между 0 и 23 включително).
|
||||
Invalid minute (must be between 0 and 59 inclusive).=Невярна минута (трябва да бъде между 0 и 59 включително).
|
||||
Show day count since world creation=Показва броя дни от създаването на света
|
||||
Current day is @1.=Текущият ден е @1.
|
||||
[<delay_in_seconds> | -1] [-r] [<message>]=[<забавяне_в_секунди> | -1] [-r] [<съобщение>]
|
||||
Shutdown server (-1 cancels a delayed shutdown, -r allows players to reconnect)=Изключва сървъра (-1 отменя забавено спиране, -r позволява на играчите повторно да се свързват)
|
||||
Server shutting down (operator request).=Сървърът се изключва (по искане на оператор).
|
||||
Ban the IP of a player or show the ban list=Забранява играч/IP или извежда списък със забранените
|
||||
The ban list is empty.=Списъкът със забранени е празен.
|
||||
Ban list: @1=Списък със забранени: @1
|
||||
You cannot ban players in singleplayer!=Не можете да забраните играчи в режим един играч!
|
||||
Player is not online.=Играчът не е на линия.
|
||||
Failed to ban player.=Грешка при забраняване на играч.
|
||||
Banned @1.=Играчът @1 е забранен.
|
||||
<name> | <IP_address>=<име> | <IP_адрес>
|
||||
Remove IP ban belonging to a player/IP=Премахва забрана по IP на играч/IP.
|
||||
Failed to unban player/IP.=Грешка при премахване забраната на играч/IP.
|
||||
Unbanned @1.=Премахната забрана на @1.
|
||||
<name> [<reason>]=<име> [<причина>]
|
||||
Kick a player=Изгонва играч
|
||||
Failed to kick player @1.=Грешка при изгонване на играча @1.
|
||||
Kicked @1.=Играчът @1 е изгонен.
|
||||
[full | quick]=[пълно | бързо]
|
||||
Clear all objects in world=Премахва всички обекти в света
|
||||
Invalid usage, see /help clearobjects.=Неприемливи параметри. Вижте /help clearobjects.
|
||||
Clearing all objects. This may take a long time. You may experience a timeout. (by @1)=Премахване на всички обекти. Може да отнеме време. Може и времето за връзка да изтече. (by @1)
|
||||
Cleared all objects.=Премахнати са всички обекти.
|
||||
<name> <message>=<име> <съобщение>
|
||||
Send a direct message to a player=Изпраща лично съобщение на играч
|
||||
Invalid usage, see /help msg.=Неприемливи параметри. Вижте /help msg.
|
||||
The player @1 is not online.=Играчът @1 не е на линия.
|
||||
DM from @1: @2=ЛС от @1: @2
|
||||
DM sent to @1: @2=ЛС изпратено до @1: @2
|
||||
Get the last login time of a player or yourself=Получава последното влизане на играч или себе си
|
||||
@1's last login time was @2.=Последното влизане на @1 е @2.
|
||||
@1's last login time is unknown.=Последното влизане на @1 е неизвестно.
|
||||
Clear the inventory of yourself or another player=Изчиства инвентара на друг играч или вас
|
||||
You don't have permission to clear another player's inventory (missing privilege: @1).=Нямате право да изчиствате инвентара на друг играч (липсващи права: @1).
|
||||
@1 cleared your inventory.=@1 изчисти вашия инвентар.
|
||||
Cleared @1's inventory.=Инвентарът на @1 е изчистен.
|
||||
Player must be online to clear inventory!=Играчът трябва да е онлайн, за да изчистите инвентара му!
|
||||
Players can't be killed, damage has been disabled.=Играчите не могат да бъдат убивани, щетите са изключени.
|
||||
Player @1 is not online.=Играчът @1 не е на линия.
|
||||
You are already dead.=Вече сте мъртви.
|
||||
@1 is already dead.=@1 вече е мъртъв.
|
||||
@1 has been killed.=@1 е убит.
|
||||
Kill player or yourself=Убива играч или себе си
|
||||
Invalid parameters (see /help @1).=Неприемливи параметри (вижте /help @1).
|
||||
Too many arguments, try using just /help <command>=Твърде много аргументи, опитайте /help <команда>
|
||||
Available commands: @1=Достъпни команди: @1
|
||||
Use '/help <cmd>' to get more information, or '/help all' to list everything.=Използвайте „/help <cmd>“, за да получите повече информация, или „/help all“, за да видите списък с всички команди.
|
||||
Available commands:=Достъпни команди:
|
||||
Command not available: @1=Командата не е достъпна: @1
|
||||
[all | privs | <cmd>] [-t]=[all | privs | <команда>] [-t]
|
||||
Get help for commands or list privileges (-t: output in chat)=Получава помощ за команди или списък с права (-t: извежда в панела за разговори)
|
||||
Available privileges:=Достъпни права:
|
||||
You died=Умряхте
|
||||
Respawn=Прераждане
|
||||
Command=Команда
|
||||
Parameters=Параметри
|
||||
For more information, click on any entry in the list.=За повече информация щракнете върху елемент от списъка.
|
||||
Double-click to copy the entry to the chat history.=Двоен клик за копиране на елемента в историята на разговори.
|
||||
Command: @1 @2=Команда: @1 @2
|
||||
Available commands: (see also: /help <cmd>)=Достъпни команди: (вижте /help <команда>)
|
||||
Close=Затваряне
|
||||
Privilege=Права
|
||||
Description=Описание
|
||||
print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=
|
||||
Handle the profiler and profiling data. Can output to chat (print), action log (dump), or file in world (save). Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change). Filter is a lua pattern used to limit output to matching mod names.=Управлява инструмента за профилиране и данните от него. Може да изведе в панела за разговори (print), в дневника (dump) или във файл в света (save). Форматът може да бъде txt, csv, lua, json, json_pretty (структурите може да бъдат променени). Филтърът е шаблон на lua за ограничаване на изхода до съвпадащи имена на модификации.
|
||||
Statistics written to action log.=Статистиката е записана в дневника.
|
||||
Statistics were reset.=Статистиката е нулирана.
|
||||
@1 joined the game.=@1 се присъедини.
|
||||
@1 left the game.=@1 напусна играта.
|
||||
@1 left the game (timed out).=@1 напусна играта (изтекло време).
|
||||
(no description)=(няма описание)
|
||||
Can interact with things and modify the world=Може да взаимодейства с неща и променя света
|
||||
Can speak in chat=Може да пише съобщения
|
||||
Can modify basic privileges (@1)=Може да променя основните права (@1)
|
||||
Can modify privileges=Може да променя права
|
||||
Can teleport self=Може да телепортира себе си
|
||||
Can teleport other players=Може да телепортира играчи
|
||||
Can set the time of day using /time=Може да задава часа през деня чрез /time
|
||||
Can do server maintenance stuff=Може да извършва поддръжка на сървъра
|
||||
Can bypass node protection in the world=Може да заобикаля защитата на възли в света
|
||||
Can ban and unban players=Може да забранява и разрешава играчи
|
||||
Can kick players=Може да изгонва играчи
|
||||
Can use /give and /giveme=Може да използва /give и /giveme
|
||||
Can use /setpassword and /clearpassword=Може да използва /setpassword и /clearpassword
|
||||
Can use fly mode=Може да използва режим на летене
|
||||
Can use fast mode=Може да използва режим на бързо придвижване
|
||||
Can fly through solid nodes using noclip mode=Може да преминава през твърди възли в режим „без изрязване“
|
||||
Can use the rollback functionality=Може да използва възможността за отменяне на действия
|
||||
Can enable wireframe=Може да включва телени рамки
|
||||
Unknown Item=Неизвестен предмет
|
||||
Air=Въздух
|
||||
Ignore=Пренебрегване
|
||||
You can't place 'ignore' nodes!=Не можете да поставяте възли „пренебрегване“!
|
||||
Values below show absolute/relative times spend per server step by the instrumented function.=Стойностите по-долу показват абсолютното/относителното време за всяка стъпка на сървъра от замерваната функция.
|
||||
A total of @1 sample(s) were taken.=Взети са общи @1 проби.
|
||||
The output is limited to '@1'.=Изходът е ограничен до „@1“.
|
||||
Saving of profile failed: @1=Грешка при запазване на профила: @1
|
||||
Profile saved to @1=Профилът е запазен в @1
|
||||
|
||||
@@ -192,7 +192,7 @@ Send a direct message to a player=Eine Direktnachricht an einen Spieler senden
|
||||
Invalid usage, see /help msg.=Ungültige Verwendung, siehe /help msg.
|
||||
The player @1 is not online.=Der Spieler @1 ist nicht online.
|
||||
DM from @1: @2=DN von @1: @2
|
||||
Message sent.=Nachricht gesendet.
|
||||
DM sent to @1: @2=DN an @1 gesendet: @2
|
||||
Get the last login time of a player or yourself=Den letzten Loginzeitpunkt eines Spielers oder Ihren eigenen anfragen
|
||||
@1's last login time was @2.=Letzter Loginzeitpunkt von @1 war @2.
|
||||
@1's last login time is unknown.=Letzter Loginzeitpunkt von @1 ist unbekannt.
|
||||
@@ -207,6 +207,8 @@ You are already dead.=Sie sind schon tot.
|
||||
@1 is already dead.=@1 ist bereits tot.
|
||||
@1 has been killed.=@1 wurde getötet.
|
||||
Kill player or yourself=Einen Spieler oder Sie selbst töten
|
||||
You died=Sie sind gestorben
|
||||
Respawn=Wiederbeleben
|
||||
@1 joined the game.=@1 ist dem Spiel beigetreten.
|
||||
@1 left the game.=@1 hat das Spiel verlassen.
|
||||
@1 left the game (timed out).=@1 hat das Spiel verlassen (Netzwerkzeitüberschreitung).
|
||||
@@ -234,15 +236,11 @@ Air=Luft
|
||||
Ignore=Ignorieren
|
||||
You can't place 'ignore' nodes!=Sie können keine „ignore“-Blöcke platzieren!
|
||||
print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=print [<Filter>] | dump [<Filter>] | save [<Format> [<Filter>]] | reset
|
||||
Handle the profiler and profiling data=Den Profiler und Profilingdaten verwalten
|
||||
Handle the profiler and profiling data. Can output to chat (print), action log (dump), or file in world (save). Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change). Filter is a lua pattern used to limit output to matching mod names.=Den Profiler benutzen und mit Profiling-Daten arbeiten. Kann in den Chat (print), in das Action-Protokoll (dump) oder in eine Datei in der Welt (save) ausgeben. Das Format kann „txt“, „csv“, „lua“, „json“ oder „json_pretty“ sein (die Strukturen könnten sich in Zukunft ändern). Filter ist ein Lua-Pattern, das benutzt wird, um die Ausgabe auf passende Modnamen einzuschränken.
|
||||
Statistics written to action log.=Statistiken zum Aktionsprotokoll geschrieben.
|
||||
Statistics were reset.=Statistiken wurden zurückgesetzt.
|
||||
Usage: @1=Verwendung: @1
|
||||
Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=Format kann entweder „txt“, „csv“, „lua“, „json“ oder „json_pretty“ sein (die Struktur kann sich in Zukunft ändern).
|
||||
Values below show absolute/relative times spend per server step by the instrumented function.=Die unten angegebenen Werte zeigen absolute/relative Zeitspannen, die je Server-Step von der instrumentierten Funktion in Anspruch genommen wurden.
|
||||
A total of @1 sample(s) were taken.=Es wurden insgesamt @1 Datenpunkt(e) aufgezeichnet.
|
||||
The output is limited to '@1'.=Die Ausgabe ist beschränkt auf „@1“.
|
||||
Saving of profile failed: @1=Speichern des Profils fehlgeschlagen: @1
|
||||
Profile saved to @1=Profil abgespeichert nach @1
|
||||
You died=Sie sind gestorben
|
||||
Respawn=Wiederbeleben
|
||||
|
||||
@@ -192,7 +192,7 @@ Send a direct message to a player=Sendu rekte privatan mesaĝon al ludanto
|
||||
Invalid usage, see /help msg.=Nevalida uzo, vidu /help msg.
|
||||
The player @1 is not online.=La ludanto @1 ne ĉeretas.
|
||||
DM from @1: @2=Privata mesaĝo de @1: @2
|
||||
Message sent.=Mesaĝo sendita.
|
||||
DM sent to @1: @2=
|
||||
Get the last login time of a player or yourself=Vidi la lastan salutotempon de ludanto, aŭ vi mem
|
||||
@1's last login time was @2.=Lasta salutotempo de @1 estas @2.
|
||||
@1's last login time is unknown.=Lasta salutotempo de @1 estas nesciata.
|
||||
@@ -207,6 +207,8 @@ You are already dead.=Vi jam estas mortinta.
|
||||
@1 is already dead.=@1 estas mortinta.
|
||||
@1 has been killed.=@1 estas murdita.
|
||||
Kill player or yourself=Mortigi ludanton aŭ vin mem
|
||||
You died=Vi mortis
|
||||
Respawn=Renaskiĝi
|
||||
@1 joined the game.=@1 aliĝis la ludon.
|
||||
@1 left the game.=@1 foriris de la ludo.
|
||||
@1 left the game (timed out).=@1 foriris de la ludo (tempo-elĉerpo)
|
||||
@@ -234,15 +236,11 @@ Air=Aero
|
||||
Ignore=Malatenti
|
||||
You can't place 'ignore' nodes!=Vi ne povas meti «malatentajn» monderojn!
|
||||
print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=print [<filtrilo>] | dump [<filtrilo>] | save [<formo> [<filtrilo>]] | reset
|
||||
Handle the profiler and profiling data=Trakti la analizilon kaj analizajn datumojn
|
||||
Handle the profiler and profiling data. Can output to chat (print), action log (dump), or file in world (save). Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change). Filter is a lua pattern used to limit output to matching mod names.=
|
||||
Statistics written to action log.=Analizoj skribitaj al agoprotokolo.
|
||||
Statistics were reset.=Analizoj forviŝitaj.
|
||||
Usage: @1=Uzado: @1
|
||||
Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=Formo povas estas txt, csv, lua, json, aŭ json_pretty (struktuoj eble iam ŝanĝiĝos).
|
||||
Values below show absolute/relative times spend per server step by the instrumented function.=Valoroj subaj montras la malrelativan/relativan tempon pasigitan de la servilo je ĉiu paŝo de la funkcio.
|
||||
A total of @1 sample(s) were taken.=Sume @1 ekzemplero(j) konserviĝis.
|
||||
The output is limited to '@1'.=La eligo estas limigita al «@1».
|
||||
Saving of profile failed: @1=Konservado de profilo malsukcesis: @1
|
||||
Profile saved to @1=Profilo konservita al @1
|
||||
You died=Vi mortis
|
||||
Respawn=Renaskiĝi
|
||||
|
||||
@@ -192,7 +192,7 @@ Send a direct message to a player=Envoyer un message privé à un joueur.
|
||||
Invalid usage, see /help msg.=Usage invalide, voir /help msg.
|
||||
The player @1 is not online.=Le joueur @1 n'est pas en ligne.
|
||||
DM from @1: @2=Message privé de @1 : @2
|
||||
Message sent.=Message privé envoyé.
|
||||
DM sent to @1: @2=
|
||||
Get the last login time of a player or yourself=Obtenir l'horodatage de la dernière connexion d'un joueur ou de vous-même.
|
||||
@1's last login time was @2.=@1 s'est connecté pour la dernière fois au @2.
|
||||
@1's last login time is unknown.=L'horodatage de la dernière connexion de @1 est inconnu.
|
||||
@@ -207,6 +207,8 @@ You are already dead.=Vous êtes déjà mort.
|
||||
@1 is already dead.=@1 est déjà mort.
|
||||
@1 has been killed.=@1 a été tué.
|
||||
Kill player or yourself=Tuer un joueur ou vous-même.
|
||||
You died=Vous êtes mort
|
||||
Respawn=Réapparaître
|
||||
@1 joined the game.=@1 a rejoint la partie.
|
||||
@1 left the game.=@1 a quitté la partie.
|
||||
@1 left the game (timed out).=@1 a quitté la partie (inactivité).
|
||||
@@ -234,15 +236,11 @@ Air=Air
|
||||
Ignore=Ignorer
|
||||
You can't place 'ignore' nodes!=Vous ne pouvez pas placé de nœuds 'ignorés' !
|
||||
print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=print [<filtre>] | dump [<filtre>] | save [<format> [<filtre>]] | reset
|
||||
Handle the profiler and profiling data=Traiter le profileur et les données de profilage
|
||||
Handle the profiler and profiling data. Can output to chat (print), action log (dump), or file in world (save). Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change). Filter is a lua pattern used to limit output to matching mod names.=
|
||||
Statistics written to action log.=Les statistiques sont écrites dans les journaux d'actions.
|
||||
Statistics were reset.=Les statistiques ont été réinitialisées.
|
||||
Usage: @1=Usage : @1
|
||||
Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=Le format peut être txt, csv, lua, json ou json_pretty (les structures sont sujettes au changement).
|
||||
Values below show absolute/relative times spend per server step by the instrumented function.=Les valeurs inférieures affichent les temps absolu et relatif dépensés par étape du serveur par la fonction utilisée.
|
||||
A total of @1 sample(s) were taken.=@1 échantillons ont été collectés.
|
||||
The output is limited to '@1'.=La sortie est limitée à '@1'.
|
||||
Saving of profile failed: @1=La sauvegarde du profil a échoué : @1
|
||||
Profile saved to @1=Le profil a été sauvegardé dans @1
|
||||
You died=Vous êtes mort
|
||||
Respawn=Réapparaître
|
||||
|
||||
@@ -192,7 +192,7 @@ Send a direct message to a player=Kirim pesan langsung kepada pemain
|
||||
Invalid usage, see /help msg.=Penggunaan tidak sah. Lihat /help msg.
|
||||
The player @1 is not online.=Pemain @1 tidak daring.
|
||||
DM from @1: @2=Pesan langsung dari @1: @2
|
||||
Message sent.=Pesan terkirim.
|
||||
DM sent to @1: @2=
|
||||
Get the last login time of a player or yourself=Ambil waktu masuk terakhir pemain atau diri Anda
|
||||
@1's last login time was @2.=Waktu masuk terakhir @1 adalah @2.
|
||||
@1's last login time is unknown.=Waktu masuk terakhir @1 tidak diketahui.
|
||||
@@ -207,6 +207,8 @@ You are already dead.=Anda telah mati.
|
||||
@1 is already dead.=@1 telah mati.
|
||||
@1 has been killed.=@1 telah dibunuh.
|
||||
Kill player or yourself=Bunuh pemain atau diri Anda
|
||||
You died=Anda mati
|
||||
Respawn=Bangkit kembali
|
||||
@1 joined the game.=@1 bergabung dalam permainan.
|
||||
@1 left the game.=@1 keluar permainan.
|
||||
@1 left the game (timed out).=@1 keluar permainan (kehabisan waktu).
|
||||
@@ -234,15 +236,11 @@ Air=Udara
|
||||
Ignore=Ignore
|
||||
You can't place 'ignore' nodes!=Anda tidak dapat menaruh nodus 'ignore'!
|
||||
print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset
|
||||
Handle the profiler and profiling data=Menangani profiler dan data profiling
|
||||
Handle the profiler and profiling data. Can output to chat (print), action log (dump), or file in world (save). Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change). Filter is a lua pattern used to limit output to matching mod names.=
|
||||
Statistics written to action log.=Statistik ditulis ke log action.
|
||||
Statistics were reset.=Statistik diatur ulang.
|
||||
Usage: @1=Penggunaan: @1
|
||||
Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=Format berupa salah satu dari txt, csv, lua, json, json_pretty (struktur mungkin berubah).
|
||||
Values below show absolute/relative times spend per server step by the instrumented function.=Nilai berikut menampilkan waktu mutlak/relatif yang dihabiskan tiap langkah server oleh fungsi instrumen.
|
||||
A total of @1 sample(s) were taken.=Total @1 sampel yang diambil.
|
||||
The output is limited to '@1'.=Keluaran dibatasi ke '@1'.
|
||||
Saving of profile failed: @1=Penyimpanan profil gagal: @1
|
||||
Profile saved to @1=Profil disimpan ke @1
|
||||
You died=Anda mati
|
||||
Respawn=Bangkit kembali
|
||||
|
||||
@@ -193,7 +193,7 @@ Send a direct message to a player=Invia un messaggio privato a unə giocatore
|
||||
Invalid usage, see /help msg.=Uso incorretto, vedi /help msg
|
||||
The player @1 is not online.=Lə giocatore @1 non è connessə.
|
||||
DM from @1: @2=Messaggio privato da @1: @2
|
||||
Message sent.=Messaggio inviato.
|
||||
DM sent to @1: @2=
|
||||
Get the last login time of a player or yourself=Ritorna l'ultimo accesso di unə giocatore o di te stessǝ
|
||||
@1's last login time was @2.=L'ultimo accesso di @1 è avvenuto il @2.
|
||||
@1's last login time is unknown.=L'ultimo accesso di @1 è ignoto.
|
||||
@@ -208,6 +208,8 @@ You are already dead.=Sei già mortǝ.
|
||||
@1 is already dead.=@1 è già mortǝ.
|
||||
@1 has been killed.=@1 è stato uccisǝ.
|
||||
Kill player or yourself=Uccide unə giocatore o te stessǝ
|
||||
You died=Sei morto
|
||||
Respawn=Rinasci
|
||||
@1 joined the game.=@1 si è connessə.
|
||||
@1 left the game.=@1 si è disconnessə.
|
||||
@1 left the game (timed out).=@1 si è disconnessə (connessione scaduta).
|
||||
@@ -235,15 +237,11 @@ Air=Aria
|
||||
Ignore=Ignora
|
||||
You can't place 'ignore' nodes!=Non puoi piazzare nodi 'ignore'!
|
||||
print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=print [<filtro>] | dump [<filtro>] | save [<formato> [<filtro>]] | reset
|
||||
Handle the profiler and profiling data=Gestisce il profiler e i dati da esso elaborati
|
||||
Handle the profiler and profiling data. Can output to chat (print), action log (dump), or file in world (save). Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change). Filter is a lua pattern used to limit output to matching mod names.=
|
||||
Statistics written to action log.=Statistiche scritte nel registro delle azioni.
|
||||
Statistics were reset.=Le statistiche sono state resettate.
|
||||
Usage: @1=Utilizzo: @1
|
||||
Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=I formati supportati sono txt, csv, lua, json e json_pretty (le strutture potrebbero essere soggetti a cambiamenti).
|
||||
Values below show absolute/relative times spend per server step by the instrumented function.=I valori sottostanti mostrano i tempi assoluti/relativi impiegati su ogni singolo step dalla funzione analizzata
|
||||
A total of @1 sample(s) were taken.=Son stati ottenuti campioni per un totale di @1.
|
||||
The output is limited to '@1'.=L'output è limitato a '@1'.
|
||||
Saving of profile failed: @1=Errore nel salvare il profilo: @1
|
||||
Profile saved to @1=Profilo salvato in @1
|
||||
You died=Sei morto
|
||||
Respawn=Rinasci
|
||||
|
||||
@@ -192,7 +192,7 @@ Send a direct message to a player=Menghantar mesej terus kepada seorang pemain
|
||||
Invalid usage, see /help msg.=Kegunaan tidak sah, sila lihat /help msg.
|
||||
The player @1 is not online.=Pemain @1 tidak berada dalam talian.
|
||||
DM from @1: @2=DM daripada @1: @2
|
||||
Message sent.=Mesej telah dihantar.
|
||||
DM sent to @1: @2=
|
||||
Get the last login time of a player or yourself=Dapatkan waktu log masuk terakhir bagi seorang pemain atau diri sendiri
|
||||
@1's last login time was @2.=Waktu log masuk terakhir @1 ialah pada @2.
|
||||
@1's last login time is unknown.=Waktu log masuk terakhir @1 tidak diketahui.
|
||||
@@ -207,6 +207,8 @@ You are already dead.=Anda sudah pun mati.
|
||||
@1 is already dead.=@1 sudah pun mati.
|
||||
@1 has been killed.=@1 telah berjaya dibunuh.
|
||||
Kill player or yourself=Bunuh pemain atau diri sendiri
|
||||
You died=Anda telah meninggal
|
||||
Respawn=Jelma semula
|
||||
@1 joined the game.=@1 telah menyertai permainan.
|
||||
@1 left the game.=@1 telah meninggalkan permainan.
|
||||
@1 left the game (timed out).=@1 telah meninggalkan permainan (tamat tempoh masa).
|
||||
@@ -234,15 +236,11 @@ Air=Udara
|
||||
Ignore=Abai
|
||||
You can't place 'ignore' nodes!=Anda tidak boleh meletakkan nod 'abai'!
|
||||
print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=print [<tapisan>] | dump [<tapisan>] | save [<format> [<tapisan>]] | reset
|
||||
Handle the profiler and profiling data=Uruskan pembukah dan data pembukahan
|
||||
Handle the profiler and profiling data. Can output to chat (print), action log (dump), or file in world (save). Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change). Filter is a lua pattern used to limit output to matching mod names.=
|
||||
Statistics written to action log.=Statistik telah ditulis ke log perlakuan.
|
||||
Statistics were reset.=Statistik telah ditetapkan semula.
|
||||
Usage: @1=Kegunaan: @1
|
||||
Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=Format boleh jadi salah satu daripada txt, csv, lua, json, json_pretty (struktur boleh berubah kemudian).
|
||||
Values below show absolute/relative times spend per server step by the instrumented function.=Nilai di bawah menunjukkan masa mutlak/relatif yang digunakan oleh fungsi yang dipasangkan pada setiap langkah pelayan
|
||||
A total of @1 sample(s) were taken.=Sebanyak @1 sampel telah diambil secara keseluruhan.
|
||||
The output is limited to '@1'.=Output dihadkan kepada '@1'.
|
||||
Saving of profile failed: @1=Penyimpanan profil telah gagal: @1
|
||||
Profile saved to @1=Profil telah disimpan ke @1
|
||||
You died=Anda telah meninggal
|
||||
Respawn=Jelma semula
|
||||
|
||||
@@ -192,7 +192,7 @@ Send a direct message to a player=Enviar uma mensagem direta a um jogador
|
||||
Invalid usage, see /help msg.=Uso inválido, veja /help msg.
|
||||
The player @1 is not online.=O jogador @1 não está online.
|
||||
DM from @1: @2=DM de @1: @2
|
||||
Message sent.=Mensagem enviada.
|
||||
DM sent to @1: @2=
|
||||
Get the last login time of a player or yourself=Pegue o último horário de login de um jogador ou de você mesmo
|
||||
@1's last login time was @2.=O último login de @1 foi às @2.
|
||||
@1's last login time is unknown.=O último login de @1 é desconhecido.
|
||||
@@ -207,6 +207,8 @@ You are already dead.=Você já está morto.
|
||||
@1 is already dead.=@1 já está morto.
|
||||
@1 has been killed.=@1 foi morto.
|
||||
Kill player or yourself=Matar jogador ou a si mesmo
|
||||
You died=Você morreu
|
||||
Respawn=Reviver
|
||||
@1 joined the game.=@1 entrou no jogo.
|
||||
@1 left the game.=@1 saiu do jogo.
|
||||
@1 left the game (timed out).=@1 saiu do jogo (tempo esgotado)
|
||||
@@ -234,15 +236,11 @@ Air=Ar
|
||||
Ignore=Ignorar
|
||||
You can't place 'ignore' nodes!=Você não pode colocar nós 'ignorar'!
|
||||
print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=print [<filtro>] | dump [<filtro>] | save [<formato> [<filtro>]] | reset
|
||||
Handle the profiler and profiling data=Lidar com o criador de perfil e os dados de criação de perfil
|
||||
Handle the profiler and profiling data. Can output to chat (print), action log (dump), or file in world (save). Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change). Filter is a lua pattern used to limit output to matching mod names.=
|
||||
Statistics written to action log.=Estatísticas salvas no log de ações.
|
||||
Statistics were reset.=As estatísticas foram redefinidas.
|
||||
Usage: @1=Uso: @1
|
||||
Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=O formato pode ser txt, csv, lua, json, json_pretty (as estruturas podem estar sujeitas a alterações).
|
||||
Values below show absolute/relative times spend per server step by the instrumented function.=Os valores abaixo mostram os tempos absolutos/relativos gastos por etapa do servidor pela função instrumentada.
|
||||
A total of @1 sample(s) were taken.=Um total de @1 amostra(s) foi coletada.
|
||||
The output is limited to '@1'.=A saída é limitada a '@1'.
|
||||
Saving of profile failed: @1=Falha ao salvar o perfil: @1
|
||||
Profile saved to @1=Perfil salvo em @1
|
||||
You died=Você morreu
|
||||
Respawn=Reviver
|
||||
|
||||
@@ -192,7 +192,7 @@ Send a direct message to a player=Отправить прямое сообщен
|
||||
Invalid usage, see /help msg.=Недопустимое использование, см. /help msg.
|
||||
The player @1 is not online.=Игрок @1 не находится в игре.
|
||||
DM from @1: @2=DM от @1: @2
|
||||
Message sent.=Сообщение отправлено.
|
||||
DM sent to @1: @2=
|
||||
Get the last login time of a player or yourself=Вывести время последнего входа игрока или своё
|
||||
@1's last login time was @2.=Время последнего входа @1: @2.
|
||||
@1's last login time is unknown.=Время последнего входа @1 неизвестно.
|
||||
@@ -207,6 +207,8 @@ You are already dead.=Ты уже мертв.
|
||||
@1 is already dead.=@1 уже мертв.
|
||||
@1 has been killed.=@1 был убит.
|
||||
Kill player or yourself=Убить игрока или себя
|
||||
You died=Вы умерли
|
||||
Respawn=Возродиться
|
||||
@1 joined the game.=@1 присоединился к игре.
|
||||
@1 left the game.=@1 вышел из игры.
|
||||
@1 left the game (timed out).=@1 вышел из игры (тайм-аут).
|
||||
@@ -234,15 +236,11 @@ Air=Воздух
|
||||
Ignore=Игнорируемая встроенная нода (":ignore")
|
||||
You can't place 'ignore' nodes!=Вы не можете установить ноду 'ignore'!
|
||||
print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset
|
||||
Handle the profiler and profiling data=Работа с профайлером и данными профилирования
|
||||
Handle the profiler and profiling data. Can output to chat (print), action log (dump), or file in world (save). Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change). Filter is a lua pattern used to limit output to matching mod names.=
|
||||
Statistics written to action log.=Статистика записывается в журнал действий.
|
||||
Statistics were reset.=Статистика была сброшена.
|
||||
Usage: @1=Использование: @1
|
||||
Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=Формат может быть одним из txt, csv, lua, json, json_pretty (структуры могут быть изменены).
|
||||
Values below show absolute/relative times spend per server step by the instrumented function.=Приведенные ниже значения показывают абсолютное/относительное время, затрачиваемое функцией на каждый шаг сервера.
|
||||
A total of @1 sample(s) were taken.=Всего было взято @1 образец(ов).
|
||||
The output is limited to '@1'.=Вывод ограничен значением '@1'.
|
||||
Saving of profile failed: @1=Не удалось сохранить данные профилирования: @1
|
||||
Profile saved to @1=Данные профилирования сохранены в @1
|
||||
You died=Вы умерли
|
||||
Respawn=Возродиться
|
||||
|
||||
@@ -192,7 +192,7 @@ Send a direct message to a player=
|
||||
Invalid usage, see /help msg.=
|
||||
The player @1 is not online.=
|
||||
DM from @1: @2=
|
||||
Message sent.=
|
||||
DM sent to @1: @2=
|
||||
Get the last login time of a player or yourself=
|
||||
@1's last login time was @2.=
|
||||
@1's last login time is unknown.=
|
||||
@@ -207,6 +207,8 @@ You are already dead.=
|
||||
@1 is already dead.=
|
||||
@1 has been killed.=
|
||||
Kill player or yourself=
|
||||
You died=
|
||||
Respawn=
|
||||
@1 joined the game.=
|
||||
@1 left the game.=
|
||||
@1 left the game (timed out).=
|
||||
@@ -234,11 +236,9 @@ Air=
|
||||
Ignore=
|
||||
You can't place 'ignore' nodes!=
|
||||
print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=
|
||||
Handle the profiler and profiling data=
|
||||
Handle the profiler and profiling data. Can output to chat (print), action log (dump), or file in world (save). Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change). Filter is a lua pattern used to limit output to matching mod names.=
|
||||
Statistics written to action log.=
|
||||
Statistics were reset.=
|
||||
Usage: @1=
|
||||
Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=
|
||||
Values below show absolute/relative times spend per server step by the instrumented function.=
|
||||
A total of @1 sample(s) were taken.=
|
||||
The output is limited to '@1'.=
|
||||
|
||||
@@ -3,18 +3,61 @@
|
||||
-- SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
|
||||
local function get_info_formspec(size, padding, text)
|
||||
return table.concat({
|
||||
"formspec_version[6]",
|
||||
"size[", size.x, ",", size.y, "]",
|
||||
"padding[0,0]",
|
||||
"bgcolor[;true]",
|
||||
local function get_description_hypertext(package, info, loading_error)
|
||||
-- Screenshots and description
|
||||
local hypertext = "<big><b>" .. core.hypertext_escape(package.short_description) .. "</b></big>\n"
|
||||
|
||||
"label[4,4.35;", text, "]",
|
||||
"container[", padding.x, ",", size.y - 0.8 - padding.y, "]",
|
||||
"button[0,0;2,0.8;back;", fgettext("Back"), "]",
|
||||
"container_end[]",
|
||||
})
|
||||
local screenshots = info and info.screenshots or {{url = package.thumbnail}}
|
||||
|
||||
local winfo = core.get_window_info()
|
||||
local fs_to_px = winfo.size.x / winfo.max_formspec_size.x
|
||||
for i, ss in ipairs(screenshots) do
|
||||
local path = get_screenshot(package, ss.url, 2)
|
||||
hypertext = hypertext .. "<action name=\"ss_".. i .. "\"><img name=\"" ..
|
||||
core.hypertext_escape(path) .. "\" width=" .. (3 * fs_to_px) ..
|
||||
" height=" .. (2 * fs_to_px) .. "></action>"
|
||||
if i ~= #screenshots then
|
||||
hypertext = hypertext .. "<img name=\"blank.png\" width=" .. (0.25 * fs_to_px) ..
|
||||
" height=" .. (2.25 * fs_to_px).. ">"
|
||||
end
|
||||
end
|
||||
|
||||
if info then
|
||||
hypertext = hypertext .. "\n" .. info.long_description.head
|
||||
|
||||
local first = true
|
||||
local function add_link_button(label, name)
|
||||
if info[name] then
|
||||
if not first then
|
||||
hypertext = hypertext .. " | "
|
||||
end
|
||||
hypertext = hypertext .. "<action name=link_" .. name .. ">" .. label .. "</action>"
|
||||
info.long_description.links["link_" .. name] = info[name]
|
||||
first = false
|
||||
end
|
||||
end
|
||||
|
||||
add_link_button(hgettext("Donate"), "donate_url")
|
||||
add_link_button(hgettext("Website"), "website")
|
||||
add_link_button(hgettext("Source"), "repo")
|
||||
add_link_button(hgettext("Issue Tracker"), "issue_tracker")
|
||||
add_link_button(hgettext("Translate"), "translation_url")
|
||||
add_link_button(hgettext("Forum Topic"), "forum_url")
|
||||
|
||||
hypertext = hypertext .. "\n\n" .. info.long_description.body
|
||||
|
||||
elseif loading_error then
|
||||
hypertext = hypertext .. "\n\n" .. hgettext("Error loading package information")
|
||||
else
|
||||
hypertext = hypertext .. "\n\n" .. hgettext("Loading...")
|
||||
end
|
||||
|
||||
-- Fix the path to blank.png. This is needed for bullet indentation,
|
||||
-- and also used for screenshot spacing.
|
||||
hypertext = hypertext:gsub("<img name=\"?blank.png\"? ",
|
||||
"<img name=\"" .. core.hypertext_escape(defaulttexturedir) .. "blank.png\" ")
|
||||
|
||||
return hypertext
|
||||
end
|
||||
|
||||
|
||||
@@ -41,18 +84,10 @@ local function get_formspec(data)
|
||||
|
||||
assert(data.package.name == info.name)
|
||||
data.info = info
|
||||
-- note: get_full_package_info can also return cached info immediately
|
||||
ui.update()
|
||||
end)
|
||||
end
|
||||
|
||||
-- get_full_package_info can return cached info immediately, so
|
||||
-- check to see if that happened
|
||||
if not data.info then
|
||||
if data.loading_error then
|
||||
return get_info_formspec(size, window_padding, fgettext("Error loading package information"))
|
||||
end
|
||||
return get_info_formspec(size, window_padding, fgettext("Loading..."))
|
||||
end
|
||||
end
|
||||
|
||||
-- Check installation status
|
||||
@@ -60,10 +95,14 @@ local function get_formspec(data)
|
||||
|
||||
local info = data.info
|
||||
|
||||
local info_line =
|
||||
fgettext("by $1 — $2 downloads — +$3 / $4 / -$5",
|
||||
local info_line
|
||||
if info then
|
||||
info_line = fgettext_ne("by $1 — $2 downloads — +$3 / $4 / -$5",
|
||||
info.author, info.downloads,
|
||||
info.reviews.positive, info.reviews.neutral, info.reviews.negative)
|
||||
else
|
||||
info_line = fgettext_ne("by $1", package.author)
|
||||
end
|
||||
|
||||
local bottom_buttons_y = H - 0.8
|
||||
|
||||
@@ -79,7 +118,7 @@ local function get_formspec(data)
|
||||
"button[", W - 3, ",", bottom_buttons_y, ";3,0.8;open_contentdb;", fgettext("ContentDB page"), "]",
|
||||
|
||||
"style_type[label;font_size=+24;font=bold]",
|
||||
"label[0,0.4;", core.formspec_escape(info.title), "]",
|
||||
"label[0,0.4;", core.formspec_escape(package.title), "]",
|
||||
"style_type[label;font_size=;font=]",
|
||||
|
||||
"label[0,1.2;", core.formspec_escape(info_line), "]",
|
||||
@@ -100,11 +139,13 @@ local function get_formspec(data)
|
||||
formspec[#formspec + 1] = "image_button[5,0;1,1;" .. core.formspec_escape(defaulttexturedir)
|
||||
formspec[#formspec + 1] = "cdb_queued.png;queued;]"
|
||||
elseif not package.path then
|
||||
local label = info and fgettext("Install [$1]", info.download_size) or
|
||||
fgettext("Install")
|
||||
formspec[#formspec + 1] = "style[install;bgcolor=green]"
|
||||
formspec[#formspec + 1] = "button["
|
||||
formspec[#formspec + 1] = right_button_rect
|
||||
formspec[#formspec + 1] =";install;"
|
||||
formspec[#formspec + 1] = fgettext("Install [$1]", info.download_size)
|
||||
formspec[#formspec + 1] = label
|
||||
formspec[#formspec + 1] = "]"
|
||||
else
|
||||
if package.installed_release < package.release then
|
||||
@@ -125,13 +166,15 @@ local function get_formspec(data)
|
||||
formspec[#formspec + 1] = "]"
|
||||
end
|
||||
|
||||
local review_count = info.reviews.positive + info.reviews.neutral + info.reviews.negative
|
||||
local current_tab = data.current_tab or 1
|
||||
local tab_titles = {
|
||||
fgettext("Description"),
|
||||
fgettext("Information"),
|
||||
fgettext("Reviews") .. core.formspec_escape(" [" .. review_count .. "]"),
|
||||
}
|
||||
if info then
|
||||
local review_count = info.reviews.positive + info.reviews.neutral + info.reviews.negative
|
||||
table.insert(tab_titles, fgettext("Information"))
|
||||
table.insert(tab_titles, fgettext("Reviews") .. core.formspec_escape(" [" .. review_count .. "]"))
|
||||
end
|
||||
|
||||
local tab_body_height = bottom_buttons_y - 2.8
|
||||
|
||||
@@ -147,59 +190,21 @@ local function get_formspec(data)
|
||||
})
|
||||
|
||||
if current_tab == 1 then
|
||||
-- Screenshots and description
|
||||
local hypertext = "<big><b>" .. core.hypertext_escape(info.short_description) .. "</b></big>\n"
|
||||
local winfo = core.get_window_info()
|
||||
local fs_to_px = winfo.size.x / winfo.max_formspec_size.x
|
||||
for i, ss in ipairs(info.screenshots) do
|
||||
local path = get_screenshot(package, ss.url, 2)
|
||||
hypertext = hypertext .. "<action name=\"ss_".. i .. "\"><img name=\"" ..
|
||||
core.hypertext_escape(path) .. "\" width=" .. (3 * fs_to_px) ..
|
||||
" height=" .. (2 * fs_to_px) .. "></action>"
|
||||
if i ~= #info.screenshots then
|
||||
hypertext = hypertext .. "<img name=\"blank.png\" width=" .. (0.25 * fs_to_px) ..
|
||||
" height=" .. (2.25 * fs_to_px).. ">"
|
||||
end
|
||||
end
|
||||
hypertext = hypertext .. "\n" .. info.long_description.head
|
||||
|
||||
local first = true
|
||||
local function add_link_button(label, name)
|
||||
if info[name] then
|
||||
if not first then
|
||||
hypertext = hypertext .. " | "
|
||||
end
|
||||
hypertext = hypertext .. "<action name=link_" .. name .. ">" .. core.hypertext_escape(label) .. "</action>"
|
||||
info.long_description.links["link_" .. name] = info[name]
|
||||
first = false
|
||||
end
|
||||
end
|
||||
|
||||
add_link_button(fgettext("Donate"), "donate_url")
|
||||
add_link_button(fgettext("Website"), "website")
|
||||
add_link_button(fgettext("Source"), "repo")
|
||||
add_link_button(fgettext("Issue Tracker"), "issue_tracker")
|
||||
add_link_button(fgettext("Translate"), "translation_url")
|
||||
add_link_button(fgettext("Forum Topic"), "forum_url")
|
||||
|
||||
hypertext = hypertext .. "\n\n" .. info.long_description.body
|
||||
|
||||
-- Fix the path to blank.png. This is needed for bullet indentation.
|
||||
hypertext = hypertext:gsub("<img name=\"?blank.png\"? ",
|
||||
"<img name=\"" .. core.hypertext_escape(defaulttexturedir) .. "blank.png\" ")
|
||||
|
||||
local hypertext = get_description_hypertext(package, info, data.loading_error)
|
||||
table.insert_all(formspec, {
|
||||
"hypertext[0,0;", W, ",", tab_body_height - 0.375,
|
||||
";desc;", core.formspec_escape(hypertext), "]",
|
||||
})
|
||||
|
||||
elseif current_tab == 2 then
|
||||
assert(info)
|
||||
local hypertext = info.info_hypertext.head .. info.info_hypertext.body
|
||||
table.insert_all(formspec, {
|
||||
"hypertext[0,0;", W, ",", tab_body_height - 0.375,
|
||||
";info;", core.formspec_escape(hypertext), "]",
|
||||
})
|
||||
elseif current_tab == 3 then
|
||||
assert(info)
|
||||
if not package.reviews and not data.reviews_error and not data.reviews_loading then
|
||||
data.reviews_loading = true
|
||||
|
||||
@@ -286,10 +291,6 @@ local function handle_submit(this, fields)
|
||||
return true
|
||||
end
|
||||
|
||||
if not info then
|
||||
return false
|
||||
end
|
||||
|
||||
if fields.open_contentdb then
|
||||
local version = core.get_version()
|
||||
local url = core.settings:get("contentdb_url") .. "/packages/" .. package.url_part ..
|
||||
@@ -312,6 +313,12 @@ local function handle_submit(this, fields)
|
||||
return true
|
||||
end
|
||||
|
||||
-- The events handled below are only valid if the package info has finished
|
||||
-- loading.
|
||||
if not info then
|
||||
return false
|
||||
end
|
||||
|
||||
if fields.tabs then
|
||||
this.data.current_tab = tonumber(fields.tabs)
|
||||
return true
|
||||
|
||||
@@ -114,9 +114,12 @@ function update_detector.get_all()
|
||||
local ret = {}
|
||||
local all_content = pkgmgr.get_all()
|
||||
for _, content in ipairs(all_content) do
|
||||
assert(content.path and content.path ~= "")
|
||||
local cdb_id = pkgmgr.get_contentdb_id(content)
|
||||
|
||||
if cdb_id then
|
||||
-- Do not consider content that we cannot modify to be out-of-date.
|
||||
-- This would be technically correct but confusing for the user.
|
||||
if cdb_id and core.may_modify_path(content.path) then
|
||||
-- The backend will account for aliases in `latest_releases`
|
||||
local latest_release = latest_releases[cdb_id]
|
||||
if not latest_release and content.type == "game" then
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"v-rob <robinsonvincent89@gmail.com>",
|
||||
"Desour/DS",
|
||||
"srifqi",
|
||||
"Gregor Parzefall (grorp)",
|
||||
"grorp",
|
||||
"Lars Müller (luatic)",
|
||||
"cx384",
|
||||
"sfence",
|
||||
@@ -47,15 +47,11 @@
|
||||
],
|
||||
"#": "For updating active/previous contributors, see the script in ./util/gather_git_credits.py",
|
||||
"contributors": [
|
||||
"Erich Schubert",
|
||||
"wrrrzr",
|
||||
"siliconsniffer",
|
||||
"JosiahWI",
|
||||
"veprogames",
|
||||
"Miguel P.L",
|
||||
"AFCMS"
|
||||
"Lucas OH",
|
||||
"Xeno333"
|
||||
],
|
||||
"previous_contributors": [
|
||||
"Wuzzy (Wuzzy2)",
|
||||
"Ælla Chiana Moskopp (erle) <erle@dieweltistgarnichtso.net> [Logo]",
|
||||
"numzero",
|
||||
"red-001 <red-001@outlook.ie>",
|
||||
@@ -67,6 +63,7 @@
|
||||
"Jean-Patrick Guerrero (kilbith)",
|
||||
"MoNTE48",
|
||||
"Constantin Wenger (SpeedProg)",
|
||||
"JosiahWI",
|
||||
"Ciaran Gultnieks (CiaranG)",
|
||||
"ROllerozxa",
|
||||
"Paul Ouellette (pauloue)",
|
||||
|
||||
@@ -33,13 +33,13 @@ end
|
||||
|
||||
local function buttonhandler(this, fields)
|
||||
if fields.reconfigure then
|
||||
local parent = this.parent
|
||||
|
||||
close_dialog(this)
|
||||
|
||||
local maintab = ui.find_by_name("maintab")
|
||||
|
||||
local dlg = create_settings_dlg("controls_keyboard_and_mouse")
|
||||
dlg:set_parent(maintab)
|
||||
maintab:hide()
|
||||
dlg:set_parent(parent)
|
||||
parent:hide()
|
||||
dlg:show()
|
||||
|
||||
return true
|
||||
@@ -74,7 +74,7 @@ local function create_rebind_keys_dlg()
|
||||
return dlg
|
||||
end
|
||||
|
||||
function migrate_keybindings()
|
||||
function migrate_keybindings(parent)
|
||||
-- Show migration dialog if the user upgraded from an earlier version
|
||||
-- and this has not yet been shown before, *or* if keys settings had to be changed
|
||||
if core.is_first_run then
|
||||
@@ -95,14 +95,14 @@ function migrate_keybindings()
|
||||
end
|
||||
|
||||
if not has_migration then
|
||||
return
|
||||
return parent
|
||||
end
|
||||
|
||||
local maintab = ui.find_by_name("maintab")
|
||||
|
||||
local dlg = create_rebind_keys_dlg()
|
||||
dlg:set_parent(maintab)
|
||||
maintab:hide()
|
||||
dlg:set_parent(parent)
|
||||
parent:hide()
|
||||
dlg:show()
|
||||
ui.update()
|
||||
|
||||
return dlg
|
||||
end
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
local SETTING_NAME = "no_mtg_notification"
|
||||
|
||||
function check_reinstall_mtg()
|
||||
function check_reinstall_mtg(parent)
|
||||
-- used to be in minetest.conf
|
||||
if core.settings:get_bool(SETTING_NAME) then
|
||||
cache_settings:set_bool(SETTING_NAME, true)
|
||||
@@ -19,14 +19,14 @@ function check_reinstall_mtg()
|
||||
end
|
||||
|
||||
if cache_settings:get_bool(SETTING_NAME) then
|
||||
return
|
||||
return parent
|
||||
end
|
||||
|
||||
local games = core.get_games()
|
||||
for _, game in ipairs(games) do
|
||||
if game.id == "minetest" then
|
||||
cache_settings:set_bool(SETTING_NAME, true)
|
||||
return
|
||||
return parent
|
||||
end
|
||||
end
|
||||
|
||||
@@ -40,16 +40,16 @@ function check_reinstall_mtg()
|
||||
end
|
||||
if not mtg_world_found then
|
||||
cache_settings:set_bool(SETTING_NAME, true)
|
||||
return
|
||||
return parent
|
||||
end
|
||||
|
||||
local maintab = ui.find_by_name("maintab")
|
||||
|
||||
local dlg = create_reinstall_mtg_dlg()
|
||||
dlg:set_parent(maintab)
|
||||
maintab:hide()
|
||||
dlg:set_parent(parent)
|
||||
parent:hide()
|
||||
dlg:show()
|
||||
ui.update()
|
||||
|
||||
return dlg
|
||||
end
|
||||
|
||||
local function get_formspec(dialogdata)
|
||||
@@ -74,22 +74,22 @@ end
|
||||
|
||||
local function buttonhandler(this, fields)
|
||||
if fields.reinstall then
|
||||
local parent = this.parent
|
||||
|
||||
-- Don't set "no_mtg_notification" here so that the dialog will be shown
|
||||
-- again if downloading MTG fails for whatever reason.
|
||||
this:delete()
|
||||
|
||||
local maintab = ui.find_by_name("maintab")
|
||||
|
||||
local dlg = create_contentdb_dlg(nil, "minetest/minetest")
|
||||
dlg:set_parent(maintab)
|
||||
maintab:hide()
|
||||
dlg:set_parent(parent)
|
||||
parent:hide()
|
||||
dlg:show()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.dismiss then
|
||||
cache_settings:set_bool("no_mtg_notification", true)
|
||||
cache_settings:set_bool(SETTING_NAME, true)
|
||||
this:delete()
|
||||
return true
|
||||
end
|
||||
|
||||
@@ -112,8 +112,12 @@ local function init_globals()
|
||||
tv_main:show()
|
||||
ui.update()
|
||||
|
||||
check_reinstall_mtg()
|
||||
migrate_keybindings()
|
||||
-- synchronous, chain parents to only show one at a time
|
||||
local parent = tv_main
|
||||
parent = migrate_keybindings(parent)
|
||||
check_reinstall_mtg(parent)
|
||||
|
||||
-- asynchronous, will only be shown if we're still on "maintab"
|
||||
check_new_version()
|
||||
end
|
||||
|
||||
|
||||
@@ -165,11 +165,15 @@ local function get_formspec(tabview, name, tabdata)
|
||||
|
||||
local retval = ""
|
||||
|
||||
local index = filterlist.get_current_index(menudata.worldlist,
|
||||
tonumber(core.settings:get("mainmenu_last_selected_world")))
|
||||
local index = core.get_textlist_index("sp_worlds") or filterlist.get_current_index(menudata.worldlist,
|
||||
tonumber(core.settings:get("mainmenu_last_selected_world"))) or 0
|
||||
|
||||
local list = menudata.worldlist:get_list()
|
||||
local world = list and index and list[index]
|
||||
-- When changing tabs to a world list with fewer entries, the last index is selected (visually).
|
||||
-- However, the formspec fields lag behind, thus 'index > #list' can be a valid choice.
|
||||
local world = list and list[math.min(index, #list)]
|
||||
local game
|
||||
|
||||
if world then
|
||||
game = pkgmgr.find_by_gameid(world.gameid)
|
||||
else
|
||||
@@ -183,27 +187,33 @@ local function get_formspec(tabview, name, tabdata)
|
||||
local y = 0.2
|
||||
local yo = 0.5625
|
||||
|
||||
if disabled_settings["creative_mode"] == nil then
|
||||
creative = "checkbox[0,"..y..";cb_creative_mode;".. fgettext("Creative Mode") .. ";" ..
|
||||
dump(core.settings:get_bool("creative_mode")) .. "]"
|
||||
y = y + yo
|
||||
end
|
||||
if disabled_settings["enable_damage"] == nil then
|
||||
damage = "checkbox[0,"..y..";cb_enable_damage;".. fgettext("Enable Damage") .. ";" ..
|
||||
dump(core.settings:get_bool("enable_damage")) .. "]"
|
||||
y = y + yo
|
||||
end
|
||||
if disabled_settings["enable_server"] == nil then
|
||||
host = "checkbox[0,"..y..";cb_server;".. fgettext("Host Server") ..";" ..
|
||||
dump(core.settings:get_bool("enable_server")) .. "]"
|
||||
y = y + yo
|
||||
if world then
|
||||
if disabled_settings["creative_mode"] == nil then
|
||||
creative = "checkbox[0,"..y..";cb_creative_mode;".. fgettext("Creative Mode") .. ";" ..
|
||||
dump(core.settings:get_bool("creative_mode")) .. "]"
|
||||
y = y + yo
|
||||
end
|
||||
if disabled_settings["enable_damage"] == nil then
|
||||
damage = "checkbox[0,"..y..";cb_enable_damage;".. fgettext("Enable Damage") .. ";" ..
|
||||
dump(core.settings:get_bool("enable_damage")) .. "]"
|
||||
y = y + yo
|
||||
end
|
||||
if disabled_settings["enable_server"] == nil then
|
||||
host = "checkbox[0,"..y..";cb_server;".. fgettext("Host Server") ..";" ..
|
||||
dump(core.settings:get_bool("enable_server")) .. "]"
|
||||
y = y + yo
|
||||
end
|
||||
end
|
||||
|
||||
retval = retval ..
|
||||
"container[5.25,4.875]" ..
|
||||
"button[0,0;3.225,0.8;world_delete;".. fgettext("Delete") .. "]" ..
|
||||
"button[3.325,0;3.225,0.8;world_configure;".. fgettext("Select Mods") .. "]" ..
|
||||
"button[6.65,0;3.225,0.8;world_create;".. fgettext("New") .. "]" ..
|
||||
"button[6.65,0;3.225,0.8;world_create;".. fgettext("New") .. "]"
|
||||
if world then
|
||||
retval = retval ..
|
||||
"button[0,0;3.225,0.8;world_delete;".. fgettext("Delete") .. "]" ..
|
||||
"button[3.325,0;3.225,0.8;world_configure;".. fgettext("Select Mods") .. "]"
|
||||
end
|
||||
retval = retval ..
|
||||
"container_end[]" ..
|
||||
"container[0.375,0.375]" ..
|
||||
creative ..
|
||||
@@ -251,7 +261,7 @@ local function get_formspec(tabview, name, tabdata)
|
||||
end
|
||||
|
||||
retval = retval .. "container_end[]"
|
||||
else
|
||||
elseif world then
|
||||
retval = retval ..
|
||||
"button[10.1875,5.925;4.9375,0.8;play;" .. fgettext("Play Game") .. "]"
|
||||
end
|
||||
@@ -348,8 +358,6 @@ local function main_button_handler(this, fields, name, tabdata)
|
||||
gamedata.selected_world = menudata.worldlist:get_raw_index(selected)
|
||||
|
||||
if selected == nil or gamedata.selected_world == 0 then
|
||||
gamedata.errormessage =
|
||||
fgettext_ne("No world created or selected!")
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
@@ -4,18 +4,10 @@
|
||||
|
||||
local S = core.get_translator("__builtin")
|
||||
|
||||
local function get_bool_default(name, default)
|
||||
local val = core.settings:get_bool(name)
|
||||
if val == nil then
|
||||
return default
|
||||
end
|
||||
return val
|
||||
end
|
||||
|
||||
local profiler_path = core.get_builtin_path().."profiler"..DIR_DELIM
|
||||
local profiler = {}
|
||||
local sampler = assert(loadfile(profiler_path .. "sampling.lua"))(profiler)
|
||||
local instrumentation = assert(loadfile(profiler_path .. "instrumentation.lua"))(profiler, sampler, get_bool_default)
|
||||
local instrumentation = assert(loadfile(profiler_path .. "instrumentation.lua"))(profiler, sampler)
|
||||
local reporter = dofile(profiler_path .. "reporter.lua")
|
||||
profiler.instrument = instrumentation.instrument
|
||||
|
||||
@@ -24,14 +16,17 @@ profiler.instrument = instrumentation.instrument
|
||||
-- Is called later, after `core.register_chatcommand` was set up.
|
||||
--
|
||||
function profiler.init_chatcommand()
|
||||
local instrument_profiler = get_bool_default("instrument.profiler", false)
|
||||
local instrument_profiler = core.settings:get_bool("instrument.profiler", false)
|
||||
if instrument_profiler then
|
||||
instrumentation.init_chatcommand()
|
||||
end
|
||||
|
||||
local param_usage = S("print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset")
|
||||
core.register_chatcommand("profiler", {
|
||||
description = S("Handle the profiler and profiling data"),
|
||||
description = S("Handle the profiler and profiling data. "
|
||||
.. "Can output to chat (print), action log (dump), or file in world (save). "
|
||||
.. "Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change). "
|
||||
.. "Filter is a lua pattern used to limit output to matching mod names."),
|
||||
params = param_usage,
|
||||
privs = { server=true },
|
||||
func = function(name, param)
|
||||
@@ -39,10 +34,10 @@ function profiler.init_chatcommand()
|
||||
local args = arg0 and string.split(arg0, " ")
|
||||
|
||||
if command == "dump" then
|
||||
core.log("action", reporter.print(sampler.profile, arg0))
|
||||
core.log("action", reporter.print(sampler.profile, arg0, false))
|
||||
return true, S("Statistics written to action log.")
|
||||
elseif command == "print" then
|
||||
return true, reporter.print(sampler.profile, arg0)
|
||||
return true, reporter.print(sampler.profile, arg0, true)
|
||||
elseif command == "save" then
|
||||
return reporter.save(sampler.profile, args[1] or "txt", args[2])
|
||||
elseif command == "reset" then
|
||||
@@ -50,9 +45,7 @@ function profiler.init_chatcommand()
|
||||
return true, S("Statistics were reset.")
|
||||
end
|
||||
|
||||
return false,
|
||||
S("Usage: @1", param_usage) .. "\n" ..
|
||||
S("Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).")
|
||||
return false
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
@@ -2,35 +2,58 @@
|
||||
-- Copyright (C) 2016 T4im
|
||||
-- SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
local format, pairs, type = string.format, pairs, type
|
||||
local format, ipairs, type = string.format, ipairs, type
|
||||
local core, get_current_modname = core, core.get_current_modname
|
||||
local profiler, sampler, get_bool_default = ...
|
||||
local profiler, sampler = ...
|
||||
local debug_getinfo = debug.getinfo
|
||||
|
||||
local instrument_builtin = get_bool_default("instrument.builtin", false)
|
||||
local instrument_builtin = core.settings:get_bool("instrument.builtin", false)
|
||||
|
||||
local do_measure = core.settings:get_bool("profiler.measure", true)
|
||||
local do_tracy = core.settings:get_bool("profiler.tracy", false)
|
||||
if do_tracy and not core.global_exists("tracy") then
|
||||
core.log("warning", "profiler.tracy is enabled, but `tracy` was not found. Did you build with Tracy?")
|
||||
do_tracy = false
|
||||
end
|
||||
|
||||
-- keep in sync with game/register.lua
|
||||
local register_functions = {
|
||||
register_globalstep = 0,
|
||||
register_playerevent = 0,
|
||||
register_on_placenode = 0,
|
||||
register_on_dignode = 0,
|
||||
register_on_punchnode = 0,
|
||||
register_on_generated = 0,
|
||||
register_on_newplayer = 0,
|
||||
register_on_dieplayer = 0,
|
||||
register_on_respawnplayer = 0,
|
||||
register_on_prejoinplayer = 0,
|
||||
register_on_joinplayer = 0,
|
||||
register_on_leaveplayer = 0,
|
||||
register_on_cheat = 0,
|
||||
register_on_chat_message = 0,
|
||||
register_on_player_receive_fields = 0,
|
||||
register_on_craft = 0,
|
||||
register_craft_predict = 0,
|
||||
register_on_protection_violation = 0,
|
||||
register_on_item_eat = 0,
|
||||
register_on_punchplayer = 0,
|
||||
register_on_player_hpchange = 0,
|
||||
register_on_mapblocks_changed = 0,
|
||||
"register_on_player_hpchange",
|
||||
|
||||
"register_on_chat_message",
|
||||
"register_on_chatcommand",
|
||||
"register_globalstep",
|
||||
"register_playerevent",
|
||||
"register_on_mods_loaded",
|
||||
"register_on_shutdown",
|
||||
"register_on_punchnode",
|
||||
"register_on_placenode",
|
||||
"register_on_dignode",
|
||||
"register_on_generated",
|
||||
"register_on_newplayer",
|
||||
"register_on_dieplayer",
|
||||
"register_on_respawnplayer",
|
||||
"register_on_prejoinplayer",
|
||||
"register_on_joinplayer",
|
||||
"register_on_leaveplayer",
|
||||
"register_on_player_receive_fields",
|
||||
"register_on_cheat",
|
||||
"register_on_craft",
|
||||
"register_craft_predict",
|
||||
"register_on_protection_violation",
|
||||
"register_on_item_eat",
|
||||
"register_on_item_pickup",
|
||||
"register_on_punchplayer",
|
||||
"register_on_priv_grant",
|
||||
"register_on_priv_revoke",
|
||||
"register_on_authplayer",
|
||||
"register_can_bypass_userlimit",
|
||||
"register_on_modchannel_message",
|
||||
"register_on_player_inventory_action",
|
||||
"register_allow_player_inventory_action",
|
||||
"register_on_rightclickplayer",
|
||||
"register_on_liquid_transformed",
|
||||
"register_on_mapblocks_changed",
|
||||
}
|
||||
|
||||
local function regex_escape(s)
|
||||
@@ -38,28 +61,14 @@ local function regex_escape(s)
|
||||
end
|
||||
|
||||
---
|
||||
-- Create an unique instrument name.
|
||||
-- Generate a missing label with a running index number.
|
||||
-- Format `filepath#linenumber` of function, with a relative filepath.
|
||||
--
|
||||
local counts = {}
|
||||
-- FIXME: these paths are not canonicalized (i.e. can be .../luanti/bin/..)
|
||||
local worldmods_path = regex_escape(core.get_worldpath())
|
||||
local user_path = regex_escape(core.get_user_path())
|
||||
local builtin_path = regex_escape(core.get_builtin_path())
|
||||
local function generate_name(def)
|
||||
local class, label, func_name = def.class, def.label, def.func_name
|
||||
if label then
|
||||
if class or func_name then
|
||||
return format("%s '%s' %s", class or "", label, func_name or ""):trim()
|
||||
end
|
||||
return format("%s", label):trim()
|
||||
elseif label == false then
|
||||
return format("%s", class or func_name):trim()
|
||||
end
|
||||
|
||||
local index_id = def.mod .. (class or func_name)
|
||||
local index = counts[index_id] or 1
|
||||
counts[index_id] = index + 1
|
||||
local info = debug.getinfo(def.func)
|
||||
local function generate_source_location(def)
|
||||
local info = debug_getinfo(def.func)
|
||||
local modpath = regex_escape(core.get_modpath(def.mod) or "")
|
||||
local source = info.source
|
||||
if modpath ~= "" then
|
||||
@@ -68,7 +77,32 @@ local function generate_name(def)
|
||||
source = source:gsub(worldmods_path, "")
|
||||
source = source:gsub(builtin_path, "builtin" .. DIR_DELIM)
|
||||
source = source:gsub(user_path, "")
|
||||
return format("%s[%d] %s#%s", class or func_name, index, source, info.linedefined)
|
||||
return string.format("%s#%s", source, info.linedefined)
|
||||
end
|
||||
|
||||
---
|
||||
-- Create an unique instrument name.
|
||||
-- Generate a missing label with a running index number.
|
||||
-- Returns name, name_has_source.
|
||||
--
|
||||
local generate_name_counts = {}
|
||||
local function generate_name(def)
|
||||
local class, label, func_name = def.class, def.label, def.func_name
|
||||
local source = generate_source_location(def)
|
||||
|
||||
if label then
|
||||
if class or func_name then
|
||||
return format("%s '%s' %s", class or "", label, func_name or ""):trim(), false
|
||||
end
|
||||
return format("%s", label):trim(), false
|
||||
elseif label == false then
|
||||
return format("%s", class or func_name):trim(), false
|
||||
else
|
||||
local index_id = def.mod .. (class or func_name)
|
||||
local index = generate_name_counts[index_id] or 1
|
||||
generate_name_counts[index_id] = index + 1
|
||||
return format("%s[%d] %s", class or func_name, index, source), true
|
||||
end
|
||||
end
|
||||
|
||||
---
|
||||
@@ -80,6 +114,10 @@ local function measure(modname, instrument_name, start, ...)
|
||||
log(modname, instrument_name, time() - start)
|
||||
return ...
|
||||
end
|
||||
local function tracy_ZoneEnd_and_return(...)
|
||||
tracy.ZoneEnd()
|
||||
return ...
|
||||
end
|
||||
--- Automatically instrument a function to measure and log to the sampler.
|
||||
-- def = {
|
||||
-- mod = "",
|
||||
@@ -94,22 +132,38 @@ local function instrument(def)
|
||||
end
|
||||
def.mod = def.mod or get_current_modname() or "??"
|
||||
local modname = def.mod
|
||||
local instrument_name = generate_name(def)
|
||||
local instrument_name, name_has_source = generate_name(def)
|
||||
local instrument_name_with_source = name_has_source and instrument_name or
|
||||
string.format("%s %s", instrument_name, generate_source_location(def))
|
||||
local func = def.func
|
||||
|
||||
if not instrument_builtin and modname == "*builtin*" then
|
||||
return func
|
||||
end
|
||||
|
||||
return function(...)
|
||||
-- This tail-call allows passing all return values of `func`
|
||||
-- also called https://en.wikipedia.org/wiki/Continuation_passing_style
|
||||
-- Compared to table creation and unpacking it won't lose `nil` returns
|
||||
-- and is expected to be faster
|
||||
-- `measure` will be executed after func(...)
|
||||
local start = time()
|
||||
return measure(modname, instrument_name, start, func(...))
|
||||
-- These tail-calls allows passing all return values of `func_o`
|
||||
-- also called https://en.wikipedia.org/wiki/Continuation_passing_style
|
||||
-- Compared to table creation and unpacking it won't lose `nil` returns
|
||||
-- and is expected to be faster
|
||||
-- `tracy_ZoneEnd_and_return` / `measure` will be executed after `func_o(...)`
|
||||
|
||||
if do_tracy then
|
||||
local func_o = func
|
||||
func = function(...)
|
||||
tracy.ZoneBeginN(instrument_name_with_source)
|
||||
return tracy_ZoneEnd_and_return(func_o(...))
|
||||
end
|
||||
end
|
||||
|
||||
if do_measure then
|
||||
local func_o = func
|
||||
func = function(...)
|
||||
local start = time()
|
||||
return measure(modname, instrument_name, start, func_o(...))
|
||||
end
|
||||
end
|
||||
|
||||
return func
|
||||
end
|
||||
|
||||
local function can_be_called(func)
|
||||
@@ -135,7 +189,6 @@ local function instrument_register(func, func_name)
|
||||
local register_name = func_name:gsub("^register_", "", 1)
|
||||
return function(callback, ...)
|
||||
assert_can_be_called(callback, func_name, 2)
|
||||
register_functions[func_name] = register_functions[func_name] + 1
|
||||
return func(instrument {
|
||||
func = callback,
|
||||
func_name = register_name
|
||||
@@ -144,7 +197,7 @@ local function instrument_register(func, func_name)
|
||||
end
|
||||
|
||||
local function init_chatcommand()
|
||||
if get_bool_default("instrument.chatcommand", true) then
|
||||
if core.settings:get_bool("instrument.chatcommand", true) then
|
||||
local orig_register_chatcommand = core.register_chatcommand
|
||||
core.register_chatcommand = function(cmd, def)
|
||||
def.func = instrument {
|
||||
@@ -160,7 +213,7 @@ end
|
||||
-- Start instrumenting selected functions
|
||||
--
|
||||
local function init()
|
||||
if get_bool_default("instrument.entity", true) then
|
||||
if core.settings:get_bool("instrument.entity", true) then
|
||||
-- Explicitly declare entity api-methods.
|
||||
-- Simple iteration would ignore lookup via __index.
|
||||
local entity_instrumentation = {
|
||||
@@ -168,26 +221,30 @@ local function init()
|
||||
"on_deactivate",
|
||||
"on_step",
|
||||
"on_punch",
|
||||
"on_death",
|
||||
"on_rightclick",
|
||||
"on_attach_child",
|
||||
"on_detach_child",
|
||||
"on_detach",
|
||||
"get_staticdata",
|
||||
}
|
||||
-- Wrap register_entity() to instrument them on registration.
|
||||
local orig_register_entity = core.register_entity
|
||||
core.register_entity = function(name, prototype)
|
||||
core.register_entity = function(name, def)
|
||||
local modname = get_current_modname()
|
||||
for _, func_name in pairs(entity_instrumentation) do
|
||||
prototype[func_name] = instrument {
|
||||
func = prototype[func_name],
|
||||
for _, func_name in ipairs(entity_instrumentation) do
|
||||
def[func_name] = instrument {
|
||||
func = def[func_name],
|
||||
mod = modname,
|
||||
func_name = func_name,
|
||||
label = prototype.label,
|
||||
label = name,
|
||||
}
|
||||
end
|
||||
orig_register_entity(name,prototype)
|
||||
orig_register_entity(name, def)
|
||||
end
|
||||
end
|
||||
|
||||
if get_bool_default("instrument.abm", true) then
|
||||
if core.settings:get_bool("instrument.abm", true) then
|
||||
-- Wrap register_abm() to automatically instrument abms.
|
||||
local orig_register_abm = core.register_abm
|
||||
core.register_abm = function(spec)
|
||||
@@ -200,7 +257,7 @@ local function init()
|
||||
end
|
||||
end
|
||||
|
||||
if get_bool_default("instrument.lbm", true) then
|
||||
if core.settings:get_bool("instrument.lbm", true) then
|
||||
-- Wrap register_lbm() to automatically instrument lbms.
|
||||
local orig_register_lbm = core.register_lbm
|
||||
core.register_lbm = function(spec)
|
||||
@@ -214,13 +271,13 @@ local function init()
|
||||
end
|
||||
end
|
||||
|
||||
if get_bool_default("instrument.global_callback", true) then
|
||||
for func_name, _ in pairs(register_functions) do
|
||||
if core.settings:get_bool("instrument.global_callback", true) then
|
||||
for _, func_name in ipairs(register_functions) do
|
||||
core[func_name] = instrument_register(core[func_name], func_name)
|
||||
end
|
||||
end
|
||||
|
||||
if get_bool_default("instrument.profiler", false) then
|
||||
if core.settings:get_bool("instrument.profiler", false) then
|
||||
-- Measure overhead of instrumentation, but keep it down for functions
|
||||
-- So keep the `return` for better optimization.
|
||||
profiler.empty_instrument = instrument {
|
||||
@@ -233,7 +290,6 @@ local function init()
|
||||
end
|
||||
|
||||
return {
|
||||
register_functions = register_functions,
|
||||
instrument = instrument,
|
||||
init = init,
|
||||
init_chatcommand = init_chatcommand,
|
||||
|
||||
@@ -168,7 +168,7 @@ local CsvFormatter = Formatter:new {
|
||||
end
|
||||
}
|
||||
|
||||
local function format_statistics(profile, format, filter)
|
||||
local function format_statistics(profile, format, filter, enable_translation)
|
||||
local formatter
|
||||
if format == "csv" then
|
||||
formatter = CsvFormatter:new {
|
||||
@@ -180,16 +180,20 @@ local function format_statistics(profile, format, filter)
|
||||
}
|
||||
end
|
||||
formatter:format(filter)
|
||||
return formatter:flush()
|
||||
local out = formatter:flush()
|
||||
if not enable_translation then
|
||||
out = core.strip_escapes(out)
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
---
|
||||
-- Format the profile ready for display and
|
||||
-- @return string to be printed to the console
|
||||
--
|
||||
function reporter.print(profile, filter)
|
||||
function reporter.print(profile, filter, enable_translation)
|
||||
if filter == "" then filter = nil end
|
||||
return format_statistics(profile, "txt", filter)
|
||||
return format_statistics(profile, "txt", filter, enable_translation)
|
||||
end
|
||||
|
||||
---
|
||||
@@ -215,7 +219,7 @@ local function serialize_profile(profile, format, filter)
|
||||
end
|
||||
end
|
||||
-- Fall back to textual formats.
|
||||
return format_statistics(profile, format, filter)
|
||||
return format_statistics(profile, format, filter, false)
|
||||
end
|
||||
|
||||
local worldpath = core.get_worldpath()
|
||||
|
||||
@@ -182,23 +182,17 @@ invert_hotbar_mouse_wheel (Hotbar: Invert mouse wheel direction) bool false
|
||||
|
||||
[**Keybindings]
|
||||
|
||||
# Key for moving the player forward.
|
||||
keymap_forward (Move forward) key SYSTEM_SCANCODE_26
|
||||
|
||||
# Key for moving the player backward.
|
||||
# Will also disable autoforward, when active.
|
||||
keymap_backward (Move backward) key SYSTEM_SCANCODE_22
|
||||
|
||||
# Key for moving the player left.
|
||||
keymap_left (Move left) key SYSTEM_SCANCODE_4
|
||||
|
||||
# Key for moving the player right.
|
||||
keymap_right (Move right) key SYSTEM_SCANCODE_7
|
||||
|
||||
# Key for jumping.
|
||||
keymap_jump (Jump) key SYSTEM_SCANCODE_44
|
||||
|
||||
# Key for sneaking.
|
||||
# Also used for climbing down and descending in water if aux1_descends is disabled.
|
||||
keymap_sneak (Sneak) key SYSTEM_SCANCODE_225
|
||||
|
||||
@@ -210,13 +204,11 @@ keymap_dig (Dig/punch/use) key KEY_LBUTTON
|
||||
# (Note: The actual meaning might vary on a per-game basis.)
|
||||
keymap_place (Place/use) key KEY_RBUTTON
|
||||
|
||||
# Key for opening the inventory.
|
||||
keymap_inventory (Open inventory) key SYSTEM_SCANCODE_12
|
||||
|
||||
# Key for moving fast in fast mode.
|
||||
keymap_aux1 (Aux1) key SYSTEM_SCANCODE_8
|
||||
|
||||
# Key for opening the chat window.
|
||||
keymap_chat (Open chat) key SYSTEM_SCANCODE_23
|
||||
|
||||
# Key for opening the chat window to type commands.
|
||||
@@ -225,70 +217,48 @@ keymap_cmd (Command) key SYSTEM_SCANCODE_56
|
||||
# Key for opening the chat window to type local commands.
|
||||
keymap_cmd_local (Local command) key SYSTEM_SCANCODE_55
|
||||
|
||||
# Key for toggling unlimited view range.
|
||||
keymap_rangeselect (Range select) key
|
||||
keymap_rangeselect (Toggle unlimited view range) key
|
||||
|
||||
# Key for toggling flying.
|
||||
keymap_freemove (Toggle fly) key SYSTEM_SCANCODE_14
|
||||
|
||||
# Key for toggling pitch move mode.
|
||||
keymap_pitchmove (Toggle pitchmove) key
|
||||
|
||||
# Key for toggling fast mode.
|
||||
keymap_fastmove (Toggle fast) key SYSTEM_SCANCODE_13
|
||||
|
||||
# Key for toggling noclip mode.
|
||||
keymap_noclip (Toggle noclip) key SYSTEM_SCANCODE_11
|
||||
|
||||
# Key for selecting the next item in the hotbar.
|
||||
keymap_hotbar_next (Hotbar: select next item) key SYSTEM_SCANCODE_17
|
||||
|
||||
# Key for selecting the previous item in the hotbar.
|
||||
keymap_hotbar_previous (Hotbar: select previous item) key SYSTEM_SCANCODE_5
|
||||
|
||||
# Key for muting the game.
|
||||
keymap_mute (Mute) key SYSTEM_SCANCODE_16
|
||||
|
||||
# Key for increasing the volume.
|
||||
keymap_increase_volume (Increase volume) key
|
||||
|
||||
# Key for decreasing the volume.
|
||||
keymap_decrease_volume (Decrease volume) key
|
||||
|
||||
# Key for toggling autoforward.
|
||||
keymap_autoforward (Toggle automatic forward) key
|
||||
|
||||
# Key for toggling cinematic mode.
|
||||
keymap_cinematic (Toggle cinematic mode) key
|
||||
|
||||
# Key for toggling display of minimap.
|
||||
keymap_minimap (Toggle minimap) key SYSTEM_SCANCODE_25
|
||||
|
||||
# Key for taking screenshots.
|
||||
keymap_screenshot (Screenshot) key SYSTEM_SCANCODE_69
|
||||
|
||||
# Key for toggling fullscreen mode.
|
||||
keymap_fullscreen (Toggle fullscreen) key SYSTEM_SCANCODE_68
|
||||
|
||||
# Key for dropping the currently selected item.
|
||||
keymap_drop (Drop item) key SYSTEM_SCANCODE_20
|
||||
|
||||
# Key to use view zoom when possible.
|
||||
keymap_zoom (Zoom) key SYSTEM_SCANCODE_29
|
||||
|
||||
# Key for toggling the display of the HUD.
|
||||
keymap_toggle_hud (Toggle HUD) key SYSTEM_SCANCODE_58
|
||||
|
||||
# Key for toggling the display of chat.
|
||||
keymap_toggle_chat (Toggle chat log) key SYSTEM_SCANCODE_59
|
||||
|
||||
# Key for toggling the display of the large chat console.
|
||||
keymap_console (Large chat console) key SYSTEM_SCANCODE_67
|
||||
keymap_console (Toggle large chat console) key SYSTEM_SCANCODE_67
|
||||
|
||||
# Key for toggling the display of fog.
|
||||
keymap_toggle_fog (Toggle fog) key SYSTEM_SCANCODE_60
|
||||
|
||||
# Key for toggling the display of debug info.
|
||||
keymap_toggle_debug (Toggle debug info) key SYSTEM_SCANCODE_62
|
||||
|
||||
# Key for toggling the display of the profiler. Used for development.
|
||||
@@ -297,109 +267,78 @@ keymap_toggle_profiler (Toggle profiler) key SYSTEM_SCANCODE_63
|
||||
# Key for toggling the display of mapblock boundaries.
|
||||
keymap_toggle_block_bounds (Toggle block bounds) key
|
||||
|
||||
# Key for switching between first- and third-person camera.
|
||||
keymap_camera_mode (Toggle camera mode) key SYSTEM_SCANCODE_6
|
||||
|
||||
# Key for increasing the viewing range.
|
||||
keymap_increase_viewing_range_min (Increase view range) key SYSTEM_SCANCODE_46
|
||||
|
||||
# Key for decreasing the viewing range.
|
||||
keymap_decrease_viewing_range_min (Decrease view range) key SYSTEM_SCANCODE_45
|
||||
|
||||
# Key for selecting the first hotbar slot.
|
||||
# Modifier key bind for closing your world.
|
||||
# Requires ESC + the selected key to work.
|
||||
keymap_close_world (Return to Main Menu) key
|
||||
|
||||
keymap_slot1 (Hotbar slot 1) key SYSTEM_SCANCODE_30
|
||||
|
||||
# Key for selecting the second hotbar slot.
|
||||
keymap_slot2 (Hotbar slot 2) key SYSTEM_SCANCODE_31
|
||||
|
||||
# Key for selecting the third hotbar slot.
|
||||
keymap_slot3 (Hotbar slot 3) key SYSTEM_SCANCODE_32
|
||||
|
||||
# Key for selecting the fourth hotbar slot.
|
||||
keymap_slot4 (Hotbar slot 4) key SYSTEM_SCANCODE_33
|
||||
|
||||
# Key for selecting the fifth hotbar slot.
|
||||
keymap_slot5 (Hotbar slot 5) key SYSTEM_SCANCODE_34
|
||||
|
||||
# Key for selecting the sixth hotbar slot.
|
||||
keymap_slot6 (Hotbar slot 6) key SYSTEM_SCANCODE_35
|
||||
|
||||
# Key for selecting the seventh hotbar slot.
|
||||
keymap_slot7 (Hotbar slot 7) key SYSTEM_SCANCODE_36
|
||||
|
||||
# Key for selecting the eighth hotbar slot.
|
||||
keymap_slot8 (Hotbar slot 8) key SYSTEM_SCANCODE_37
|
||||
|
||||
# Key for selecting the ninth hotbar slot.
|
||||
keymap_slot9 (Hotbar slot 9) key SYSTEM_SCANCODE_38
|
||||
|
||||
# Key for selecting the tenth hotbar slot.
|
||||
keymap_slot10 (Hotbar slot 10) key SYSTEM_SCANCODE_39
|
||||
|
||||
# Key for selecting the 11th hotbar slot.
|
||||
keymap_slot11 (Hotbar slot 11) key
|
||||
|
||||
# Key for selecting the 12th hotbar slot.
|
||||
keymap_slot12 (Hotbar slot 12) key
|
||||
|
||||
# Key for selecting the 13th hotbar slot.
|
||||
keymap_slot13 (Hotbar slot 13) key
|
||||
|
||||
# Key for selecting the 14th hotbar slot.
|
||||
keymap_slot14 (Hotbar slot 14) key
|
||||
|
||||
# Key for selecting the 15th hotbar slot.
|
||||
keymap_slot15 (Hotbar slot 15) key
|
||||
|
||||
# Key for selecting the 16th hotbar slot.
|
||||
keymap_slot16 (Hotbar slot 16) key
|
||||
|
||||
# Key for selecting the 17th hotbar slot.
|
||||
keymap_slot17 (Hotbar slot 17) key
|
||||
|
||||
# Key for selecting the 18th hotbar slot.
|
||||
keymap_slot18 (Hotbar slot 18) key
|
||||
|
||||
# Key for selecting the 19th hotbar slot.
|
||||
keymap_slot19 (Hotbar slot 19) key
|
||||
|
||||
# Key for selecting the 20th hotbar slot.
|
||||
keymap_slot20 (Hotbar slot 20) key
|
||||
|
||||
# Key for selecting the 21st hotbar slot.
|
||||
keymap_slot21 (Hotbar slot 21) key
|
||||
|
||||
# Key for selecting the 22nd hotbar slot.
|
||||
keymap_slot22 (Hotbar slot 22) key
|
||||
|
||||
# Key for selecting the 23rd hotbar slot.
|
||||
keymap_slot23 (Hotbar slot 23) key
|
||||
|
||||
# Key for selecting the 24th hotbar slot.
|
||||
keymap_slot24 (Hotbar slot 24) key
|
||||
|
||||
# Key for selecting the 25th hotbar slot.
|
||||
keymap_slot25 (Hotbar slot 25) key
|
||||
|
||||
# Key for selecting the 26th hotbar slot.
|
||||
keymap_slot26 (Hotbar slot 26) key
|
||||
|
||||
# Key for selecting the 27th hotbar slot.
|
||||
keymap_slot27 (Hotbar slot 27) key
|
||||
|
||||
# Key for selecting the 28th hotbar slot.
|
||||
keymap_slot28 (Hotbar slot 28) key
|
||||
|
||||
# Key for selecting the 29th hotbar slot.
|
||||
keymap_slot29 (Hotbar slot 29) key
|
||||
|
||||
# Key for selecting the 30th hotbar slot.
|
||||
keymap_slot30 (Hotbar slot 30) key
|
||||
|
||||
# Key for selecting the 31st hotbar slot.
|
||||
keymap_slot31 (Hotbar slot 31) key
|
||||
|
||||
# Key for selecting the 32nd hotbar slot.
|
||||
keymap_slot32 (Hotbar slot 32) key
|
||||
|
||||
[*Touchscreen]
|
||||
@@ -535,13 +474,12 @@ undersampling (Undersampling) int 1 1 8
|
||||
|
||||
# 3D support.
|
||||
# Currently supported:
|
||||
# - none: no 3d output.
|
||||
# - anaglyph: cyan/magenta color 3d.
|
||||
# - interlaced: odd/even line based polarization screen support.
|
||||
# - topbottom: split screen top/bottom.
|
||||
# - sidebyside: split screen side by side.
|
||||
# - crossview: Cross-eyed 3d
|
||||
3d_mode (3D mode) enum none none,anaglyph,interlaced,topbottom,sidebyside,crossview
|
||||
# - none: no 3D output
|
||||
# - anaglyph: cyan/magenta color 3D
|
||||
# - topbottom: split screen top/bottom
|
||||
# - sidebyside: split screen side-by-side
|
||||
# - crossview: cross-eyed 3D
|
||||
3d_mode (3D mode) enum none none,anaglyph,topbottom,sidebyside,crossview
|
||||
|
||||
# Strength of 3D mode parallax.
|
||||
3d_paralax_strength (3D mode parallax strength) float 0.025 -0.087 0.087
|
||||
@@ -2005,6 +1943,14 @@ enable_mod_channels (Mod channels) [server] bool false
|
||||
# Useful for mod developers and server operators.
|
||||
profiler.load (Load the game profiler) bool false
|
||||
|
||||
# Disable if you only want to instrument with Tracy.
|
||||
profiler.measure (Measure time samples) bool true
|
||||
|
||||
# Capture Tracy zones with the profiler's instrumentation.
|
||||
# You need to build with Tracy to use this, see doc/developing/profiling.md
|
||||
# for details.
|
||||
profiler.tracy (Capture Tracy zones) bool false
|
||||
|
||||
# The default format in which profiles are being saved,
|
||||
# when calling `/profiler save [format]` without format.
|
||||
profiler.default_report_format (Default report format) enum txt txt,csv,lua,json,json_pretty
|
||||
@@ -2074,11 +2020,11 @@ transparency_sorting_group_by_buffers (Transparency Sorting Group by Buffers) bo
|
||||
cloud_radius (Cloud radius) int 12 8 62
|
||||
|
||||
# Delay between mesh updates on the client in ms. Increasing this will slow
|
||||
# down the rate of mesh updates, thus reducing jitter on slower clients.
|
||||
mesh_generation_interval (Mapblock mesh generation delay) int 0 0 50
|
||||
# down the rate of mesh updates, which can help reduce jitter.
|
||||
mesh_generation_interval (Mapblock mesh generation delay) int 0 0 25
|
||||
|
||||
# Number of threads to use for mesh generation.
|
||||
# Value of 0 (default) will let Luanti autodetect the number of available threads.
|
||||
# Value of 0 (default) will let Luanti automatically choose the number of threads.
|
||||
mesh_generation_threads (Mapblock mesh generation threads) int 0 0 8
|
||||
|
||||
# All mesh buffers with less than this number of vertices will be merged
|
||||
|
||||
60
doc/README.md
Normal file
60
doc/README.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Documentation
|
||||
|
||||
This directory contains mostly reference documentation for the Luanti engine.
|
||||
For a less prescriptive and more guiding documentation, also look at:
|
||||
https://docs.luanti.org
|
||||
|
||||
Note that the inner workings of the engine are not well documented. It's most
|
||||
often better to read the code.
|
||||
|
||||
Markdown files are written in a way that they can also be read in plain text.
|
||||
When modifying, please keep it that way!
|
||||
|
||||
Here is a list with descriptions of relevant files:
|
||||
|
||||
## Server Modding
|
||||
|
||||
- [lua_api.md](lua_api.md): Server Modding API reference. (Not only the Lua part,
|
||||
but also file structure and everything else.)
|
||||
If you want to make a mod or game, look here!
|
||||
A rendered version is also available at <https://api.luanti.org/>.
|
||||
- [builtin_entities.md](builtin_entities.md): Doc for entities predefined by the
|
||||
engine (in builtin), i.e. dropped items and falling nodes.
|
||||
|
||||
## Client-Side Content
|
||||
|
||||
- [texture_packs.md](texture_packs.md): Layout and description of Luanti's
|
||||
texture packs structure and configuration.
|
||||
- [client_lua_api.md](client_lua_api.md): Client-Provided Client-Side Modding
|
||||
(CPCSM) API reference.
|
||||
|
||||
## Mainmenu scripting
|
||||
|
||||
- [menu_lua_api.md](menu_lua_api.md): API reference for the mainmenu scripting
|
||||
environment.
|
||||
- [fst_api.txt](fst_api.txt): Formspec Toolkit API, included in builtin for the
|
||||
main menu.
|
||||
|
||||
## Formats and Protocols
|
||||
|
||||
- [world_format.md](world_format.md): Structure of Luanti world directories and
|
||||
format of the files therein.
|
||||
Note: If you want to write your own deserializer, it will be easier to read
|
||||
the `serialize()` and `deSerialize()` functions of the various structures in
|
||||
C++, e.g. `MapBlock::deSerialize()`.
|
||||
- [protocol.txt](protocol.txt): *Rough* outline of Luanti's network protocol.
|
||||
|
||||
## Misc.
|
||||
|
||||
- [compiling/](compiling/): Compilation instructions, and options.
|
||||
- [ides/](ides/): Instructions for configuring certain IDEs for engine development.
|
||||
- [developing/](developing/): Information about Luanti development.
|
||||
Note: [developing/profiling.md](developing/profiling.md) can be useful for
|
||||
modders and server owners!
|
||||
- [android.md](android.md): Android quirks.
|
||||
- [direction.md](direction.md): Information related to the future direction of
|
||||
Luanti. Commonly referred to as the roadmap document.
|
||||
- [breakages.md](breakages.md): List of planned breakages for the next major
|
||||
release, i.e. 6.0.0.
|
||||
- [docker_server.md](docker_server.md): Information about our Docker server
|
||||
images in the ghcr.
|
||||
@@ -42,7 +42,7 @@ configuration file can usually be found at:
|
||||
* After 5.4.2:
|
||||
* `/sdcard/Android/data/net.minetest.minetest/` or `/storage/emulated/0/Android/data/net.minetest.minetest/` if stored on the device
|
||||
* `/storage/emulated/(varying folder name)/Android/data/net.minetest.minetest/` if stored on the SD card
|
||||
* [Learn more about Android directory](https://wiki.luanti.org/Accessing_Android_Data_Directory)
|
||||
* [Learn more about Android directory](https://docs.luanti.org/for-players/mobile/)
|
||||
|
||||
## Useful settings
|
||||
|
||||
@@ -77,30 +77,28 @@ some shader settings cannot be used on OpenGL ES.
|
||||
Changing the graphic driver setting to OpenGL will not work.
|
||||
|
||||
## Building Requirements
|
||||
In order to build, your PC has to be set up to build Luanti in the usual
|
||||
manner (see the regular Luanti documentation for how to get this done).
|
||||
In addition to what is required for Luanti in general, you will need the
|
||||
following software packages. The version number in parenthesis denotes the
|
||||
version that was tested at the time this README was drafted; newer/older
|
||||
versions may or may not work.
|
||||
|
||||
* Android SDK 29
|
||||
* Android NDK r21
|
||||
* Android Studio 3 [optional]
|
||||
In order to build, you will need the following development tools:
|
||||
|
||||
* Java JDK
|
||||
* Android SDK
|
||||
* `gettext` command line tools
|
||||
* Android Studio [optional]
|
||||
|
||||
Additionally, you'll need to have an Internet connection available on the
|
||||
build system, as the Android build will download some source packages.
|
||||
|
||||
## Build
|
||||
|
||||
The new build system Luanti Android is fully functional and is designed to
|
||||
speed up and simplify the work, as well as adding the possibility of
|
||||
cross-platform build.
|
||||
You can use `./gradlew assemblerelease` or `./gradlew assembledebug` from the
|
||||
You can use `./gradlew assembleRelease` or `./gradlew assembleDebug` from the
|
||||
command line or use Android Studio and click the build button.
|
||||
|
||||
When using gradlew, the newest NDK will be downloaded and installed
|
||||
automatically. Or you can create a `local.properties` file and specify
|
||||
`sdk.dir` and `ndk.dir` yourself.
|
||||
automatically. You have to create a `local.properties` file and specify
|
||||
`sdk.dir` yourself if you want to use an existing installation.
|
||||
|
||||
* In order to make a release build you'll have to have a keystore setup to sign
|
||||
the resulting apk package. How this is done is not part of this README. There
|
||||
|
||||
@@ -25,3 +25,4 @@ This list is largely advisory and items may be reevaluated once the time comes.
|
||||
* remove built-in knockback and related functions entirely
|
||||
* remove `safe` parameter from `core.serialize`, always enforce `safe = true`.
|
||||
possibly error when `loadstring` calls are encountered in `core.deserialize`.
|
||||
* introduce strict type checking for all instances of `v3s16` / `v3f` read from Lua
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
Luanti Lua Client Modding API Reference 5.12.0
|
||||
Luanti Lua Client Modding API Reference 5.14.0
|
||||
==============================================
|
||||
|
||||
**WARNING**: if you're looking for the `minetest` namespace (e.g. `minetest.something`),
|
||||
it's now called `core` due to the renaming of Luanti (formerly Minetest).
|
||||
`minetest` will keep existing as an alias, so that old code won't break.
|
||||
|
||||
Note that `core` has already existed since version 0.4.10, so you can use it
|
||||
safely without breaking backwards compatibility.
|
||||
|
||||
* More information at <http://www.luanti.org/>
|
||||
* Developer Wiki: <https://dev.luanti.org/>
|
||||
* Additional documentation: <https://docs.luanti.org/>
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
@@ -14,10 +14,10 @@ It is highly recommended to use vcpkg as package manager.
|
||||
|
||||
After you successfully built vcpkg you can easily install the required libraries:
|
||||
```powershell
|
||||
vcpkg install zlib zstd curl[winssl] openal-soft libvorbis libogg libjpeg-turbo sqlite3 freetype luajit gmp jsoncpp gettext[tools] sdl2 --triplet x64-windows
|
||||
vcpkg install zlib zstd curl[ssl] openal-soft libvorbis libogg libjpeg-turbo sqlite3 freetype luajit gmp jsoncpp gettext[tools] sdl2 --triplet x64-windows
|
||||
```
|
||||
|
||||
- `curl` is optional, but required to read the serverlist, `curl[winssl]` is required to use the content store.
|
||||
- `curl` is optional, but required to read the serverlist, `curl[ssl]` is required to use the content store.
|
||||
- `openal-soft`, `libvorbis` and `libogg` are optional, but required to use sound.
|
||||
- `luajit` is optional, it replaces the integrated Lua interpreter with a faster just-in-time interpreter.
|
||||
- `gmp` and `jsoncpp` are optional, otherwise the bundled versions will be compiled
|
||||
|
||||
@@ -1,26 +1,27 @@
|
||||
# Developer documentation
|
||||
|
||||
## Wiki
|
||||
## Luanti Documentation
|
||||
|
||||
Some important development docs are found in the wiki: https://dev.luanti.org/
|
||||
Some important development docs are found on the docs site: https://docs.luanti.org/
|
||||
|
||||
Notable pages:
|
||||
|
||||
- [Releasing Luanti](https://dev.luanti.org/Releasing_Luanti)
|
||||
- [Engine translations](https://dev.luanti.org/Translation#Maintaining_engine_translations)
|
||||
- [Changelog](https://dev.luanti.org/Changelog)
|
||||
- [Organisation](https://dev.luanti.org/Organisation)
|
||||
- [Code style guidelines](https://dev.luanti.org/Code_style_guidelines)
|
||||
- [Releasing Luanti](https://docs.luanti.org/for-engine-devs/releasing-luanti/)
|
||||
- [Engine translations](https://docs.luanti.org/for-creators/translation/)
|
||||
- [Changelog](https://docs.luanti.org/about/changelog/)
|
||||
- [Organisation](https://docs.luanti.org/for-engine-devs/organization/)
|
||||
- [Code style guidelines](https://docs.luanti.org/for-engine-devs/code-style-guidelines/)
|
||||
and [Lua code style guidelines](https://docs.luanti.org/for-engine-devs/lua-code-style-guidelines/)
|
||||
|
||||
## In this folder
|
||||
|
||||
- [Developing minetestserver with Docker](docker.md)
|
||||
- [Android tips & tricks](android.md)
|
||||
- [OS/library compatibility policy](os-compatibility.md)
|
||||
- [Miscellaneous](misc.md)
|
||||
- [docker.md](docker.md): Developing luantiserver with Docker
|
||||
- [android.md](android.md): Android tips & tricks
|
||||
- [os-compatibility.md](os-compatibility.md): OS/library compatibility policy
|
||||
- [profiling.md](profiling.md): Profiling instructions
|
||||
|
||||
## IRC
|
||||
|
||||
Oftentimes knowledge hasn't been written down (yet) and your best bet is to ask someone experienced and/or the core developers.
|
||||
|
||||
Feel free to join the [#minetest-dev IRC](https://wiki.luanti.org/IRC) and ask questions related to **engine development**.
|
||||
Feel free to join the [#luanti-dev IRC](https://docs.luanti.org/about/irc/) and ask questions related to **engine development**.
|
||||
|
||||
@@ -26,7 +26,7 @@ adb install -r -d ./app-arm64-v8a-release-unsigned.apk
|
||||
In case debug.txt isn't enough (e.g. when debugging a crash), you can get debug
|
||||
output using logcat:
|
||||
|
||||
`adb logcat -s 'Minetest:*' '*:F'`
|
||||
`adb logcat -s Luanti '*:F'`
|
||||
|
||||
Note that you can do this even *after* the app has crashed,
|
||||
since Android keeps an internal buffer.
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
# Miscellaneous
|
||||
# Profiling
|
||||
|
||||
## Using builtin's mod profiler
|
||||
|
||||
Builtin has a profiler for callbacks registered by mods. It measures how much
|
||||
time each callback took per server-step (on average / min / max).
|
||||
|
||||
To start, enable the `profiler.load` setting.
|
||||
(There are more settings, see `profiler.*` and `instrument.*`.)
|
||||
|
||||
Use the `profiler` chatcommand to look at the results.
|
||||
|
||||
|
||||
## Profiling Luanti on Linux with perf
|
||||
|
||||
@@ -22,12 +33,12 @@ It will give you flamegraphs, per-thread, per-function views and much more.
|
||||
|
||||
Attach perf to your running server, press *^C* to stop:
|
||||
```bash
|
||||
perf record -z --call-graph dwarf -F 400 -p "$(pidof minetestserver)"
|
||||
perf record -z --call-graph dwarf -F 400 -p "$(pidof luantiserver)"
|
||||
```
|
||||
|
||||
Collect a copy of the required libraries/executables:
|
||||
```bash
|
||||
perf buildid-list | grep -Eo '/[^ ]+(minetestserver|\.so)[^ ]*$' | \
|
||||
perf buildid-list | grep -Eo '/[^ ]+(luantiserver|\.so)[^ ]*$' | \
|
||||
tar -cvahf debug.tgz --files-from=- --ignore-failed-read
|
||||
```
|
||||
|
||||
@@ -65,13 +76,16 @@ Build Luanti with `-DDBUILD_WITH_TRACY=1`, this will fetch Tracy for building
|
||||
the Tracy client. And use `FETCH_TRACY_GIT_TAG` to get a version matching your
|
||||
Tracy server, e.g. `-DFETCH_TRACY_GIT_TAG=v0.11.0` if it's `0.11.0`.
|
||||
|
||||
To actually use Tracy, you also have to enable it with Tracy's build options:
|
||||
```
|
||||
-DTRACY_ENABLE=1 -DTRACY_ONLY_LOCALHOST=1
|
||||
```
|
||||
To actually use Tracy, you also have to enable it with Tracy's build options
|
||||
(`-DTRACY_ENABLE=1`).
|
||||
|
||||
See Tracy's documentation for more build options.
|
||||
|
||||
TL;DR:
|
||||
```
|
||||
-DDBUILD_WITH_TRACY=1 -DFETCH_TRACY_GIT_TAG=<your_version> -DTRACY_ENABLE=1 -DTRACY_ONLY_LOCALHOST=1
|
||||
```
|
||||
|
||||
### Using in C++
|
||||
|
||||
Start the Tracy server and Luanti. You should see Luanti in the menu.
|
||||
@@ -87,3 +101,6 @@ See Tracy's official documentation for more information.
|
||||
|
||||
Note: The whole Tracy Lua API is accessible to all mods. And we don't check if it
|
||||
is or becomes insecure. Run untrusted mods at your own risk.
|
||||
|
||||
Enable `profiler.load` and `profiler.tracy` to automatically instrument mod
|
||||
callback functions.
|
||||
@@ -37,7 +37,7 @@ Examples include
|
||||
[general view distance](https://github.com/luanti-org/luanti/issues/7222).
|
||||
|
||||
This includes work on maintaining
|
||||
[our Irrlicht fork](https://github.com/minetest/irrlicht), and switching to
|
||||
[our Irrlicht fork](https://github.com/luanti-org/luanti/tree/master/irr), and switching to
|
||||
alternative libraries to replace Irrlicht functionality as needed
|
||||
|
||||
### 2.2 Internal code refactoring
|
||||
|
||||
@@ -3,8 +3,10 @@ Formspec toolkit api 0.0.3
|
||||
|
||||
Formspec toolkit is a set of functions to create basic ui elements.
|
||||
|
||||
You can find the files in builtin/fstk/.
|
||||
|
||||
File: fst/ui.lua
|
||||
|
||||
File: fstk/ui.lua
|
||||
----------------
|
||||
|
||||
ui.lua adds base ui interface to add additional components to.
|
||||
@@ -25,7 +27,7 @@ ui.find_by_name(name) --> returns component or nil
|
||||
^ find a component within ui
|
||||
^ name: name of component to look for
|
||||
|
||||
File: fst/tabview.lua
|
||||
File: fstk/tabview.lua
|
||||
---------------------
|
||||
|
||||
tabview_create(name, size, tabheaderpos) --> returns tabview component
|
||||
@@ -92,7 +94,7 @@ methods:
|
||||
* icon: path to icon
|
||||
* on_click(tabview): callback function
|
||||
|
||||
File: fst/dialog.lua
|
||||
File: fstk/dialog.lua
|
||||
---------------------
|
||||
Only one dialog can be shown at a time. If a dialog is closed it's parent is
|
||||
gonna be activated and shown again.
|
||||
@@ -129,7 +131,7 @@ members:
|
||||
- parent
|
||||
^ parent component to return to on exit
|
||||
|
||||
File: fst/buttonbar.lua
|
||||
File: fstk/buttonbar.lua
|
||||
-----------------------
|
||||
|
||||
buttonbar_create(name, pos, size, bgcolor, cbf_buttonhandler)
|
||||
|
||||
628
doc/lua_api.md
628
doc/lua_api.md
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
Luanti Lua Mainmenu API Reference 5.12.0
|
||||
Luanti Lua Mainmenu API Reference 5.14.0
|
||||
========================================
|
||||
|
||||
Introduction
|
||||
@@ -23,8 +23,8 @@ Callbacks
|
||||
* `core.button_handler(fields)`: called when a button is pressed.
|
||||
* `fields` = `{name1 = value1, name2 = value2, ...}`
|
||||
* `core.event_handler(event)`
|
||||
* `event`: `"MenuQuit"`, `"KeyEnter"`, `"ExitButton"`, `"EditBoxEnter"` or
|
||||
`"FullscreenChange"`
|
||||
* `event`: `"MenuQuit"` (derived from `quit`) or `"FullscreenChange"`
|
||||
The main menu may issue custom events, such as `"Refresh"` (server list).
|
||||
* `core.on_before_close()`: called before the menu is closed, either to exit or
|
||||
to join a game
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ Updated 2011-06-18
|
||||
|
||||
A custom protocol over UDP.
|
||||
Integers are big endian.
|
||||
Refer to connection.{h,cpp} for further reference.
|
||||
Refer to network/mtp/internal.h, network/networkprotocol.{h,cpp}, and
|
||||
server/clientiface.h for further reference.
|
||||
|
||||
Initialization:
|
||||
- A dummy reliable packet with peer_id=PEER_ID_INEXISTENT=0 is sent to the server:
|
||||
|
||||
@@ -401,7 +401,7 @@ See below for description.
|
||||
Luanti will correct lighting in the day light bank when the block at
|
||||
`(1, 0, 0)` is also loaded.
|
||||
|
||||
Timestamp and node ID mappings were introduced in map format version 29.
|
||||
Timestamp and node ID mappings come here if map format version >= 29.
|
||||
* `u32` timestamp
|
||||
* Timestamp when last saved, as seconds from starting the game.
|
||||
* `0xffffffff` = invalid/unknown timestamp, nothing should be done with the time
|
||||
@@ -482,13 +482,7 @@ Timestamp and node ID mappings were introduced in map format version 29.
|
||||
* `s32` timeout * 1000
|
||||
* `s32` elapsed * 1000
|
||||
|
||||
* Since map format version 25:
|
||||
* `u8` length of the data of a single timer (always 2+4+4=10)
|
||||
* `u16` `num_of_timers`
|
||||
* foreach `num_of_timers`:
|
||||
* `u16` timer position (`(z*16*16 + y*16 + x)`)
|
||||
* `s32` timeout * 1000
|
||||
* `s32` elapsed * 1000
|
||||
* Map format version >= 25: see below
|
||||
|
||||
`u8` static object version:
|
||||
* Always 0
|
||||
@@ -516,6 +510,14 @@ Before map format version 29:
|
||||
* `u16` `name_len`
|
||||
* `u8[name_len]` `name`
|
||||
|
||||
Since map format version 25, node timers come here:
|
||||
* `u8` length of the data of a single timer (always 2+4+4=10)
|
||||
* `u16` `num_of_timers`
|
||||
* foreach `num_of_timers`:
|
||||
* `u16` timer position (`(z*16*16 + y*16 + x)`)
|
||||
* `s32` timeout * 1000
|
||||
* `s32` elapsed * 1000
|
||||
|
||||
End of File (EOF).
|
||||
|
||||
# Format of Nodes
|
||||
@@ -594,9 +596,11 @@ Object types:
|
||||
* `s32` yaw * 1000
|
||||
|
||||
Since protocol version 37:
|
||||
* `u8` `version2` (=1)
|
||||
* `u8` `version2` (=1 or 2)
|
||||
* `s32` pitch * 1000
|
||||
* `s32` roll * 1000
|
||||
* if version2 >= 2:
|
||||
* `u8[16]` guid
|
||||
|
||||
# Itemstring Format
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ core.register_chatcommand("bench_bulk_set_node", {
|
||||
core.chat_send_player(name, "Warming up finished, now benchmarking ...")
|
||||
|
||||
local start_time = core.get_us_time()
|
||||
for i=1,#pos_list do
|
||||
for i = 1, #pos_list do
|
||||
core.set_node(pos_list[i], {name = "mapgen_stone"})
|
||||
end
|
||||
local middle_time = core.get_us_time()
|
||||
@@ -116,6 +116,7 @@ core.register_chatcommand("bench_bulk_set_node", {
|
||||
((middle_time - start_time)) / 1000,
|
||||
((end_time - middle_time)) / 1000
|
||||
)
|
||||
print(msg)
|
||||
return true, msg
|
||||
end,
|
||||
})
|
||||
@@ -129,16 +130,13 @@ core.register_chatcommand("bench_bulk_get_node", {
|
||||
return false, "No player."
|
||||
end
|
||||
local pos_list = get_positions_cube(player:get_pos())
|
||||
local dummy = 0
|
||||
local function bench()
|
||||
local start_time = core.get_us_time()
|
||||
for i=1,#pos_list do
|
||||
for i = 1, #pos_list do
|
||||
local n = core.get_node(pos_list[i])
|
||||
-- Make sure the name lookup is never optimized away.
|
||||
-- Table allocation might still be omitted. But only accessing
|
||||
-- the name of a node is a common pattern anyways.
|
||||
if n.name == "benchmarks:nonexistent_node" then
|
||||
error("should never happen")
|
||||
end
|
||||
-- Make sure the name lookup is not optimized away (can this even happen?)
|
||||
dummy = dummy + #n.name
|
||||
end
|
||||
return core.get_us_time() - start_time
|
||||
end
|
||||
@@ -151,6 +149,115 @@ core.register_chatcommand("bench_bulk_get_node", {
|
||||
|
||||
local msg = string.format("Benchmark results: core.get_node loop 1: %.2f ms",
|
||||
result_us / 1000)
|
||||
print(msg)
|
||||
return true, msg
|
||||
end,
|
||||
})
|
||||
|
||||
core.register_chatcommand("bench_bulk_get_node_raw", {
|
||||
params = "",
|
||||
description = "Benchmark: Bulk-get 99×99×99 nodes with raw API",
|
||||
func = function(name, param)
|
||||
local player = core.get_player_by_name(name)
|
||||
if not player then
|
||||
return false, "No player."
|
||||
end
|
||||
local pos_list = get_positions_cube(player:get_pos())
|
||||
local dummy = 0
|
||||
local function bench()
|
||||
local start_time = core.get_us_time()
|
||||
for i = 1, #pos_list do
|
||||
local pos_i = pos_list[i]
|
||||
local nid = core.get_node_raw(pos_i.x, pos_i.y, pos_i.z)
|
||||
-- Make sure the result is not optimized away
|
||||
dummy = dummy + nid
|
||||
end
|
||||
return core.get_us_time() - start_time
|
||||
end
|
||||
|
||||
core.chat_send_player(name, "Benchmarking core.get_node_raw. Warming up ...")
|
||||
bench()
|
||||
|
||||
core.chat_send_player(name, "Warming up finished, now benchmarking ...")
|
||||
local result_us = bench()
|
||||
|
||||
local msg = string.format("Benchmark results: core.get_node_raw loop 1: %.2f ms",
|
||||
result_us / 1000)
|
||||
print(msg)
|
||||
return true, msg
|
||||
end,
|
||||
})
|
||||
|
||||
core.register_chatcommand("bench_bulk_get_node_raw2", {
|
||||
params = "",
|
||||
description = "Benchmark: Bulk-get 99×99×99 nodes with raw API and lookup names",
|
||||
func = function(name, param)
|
||||
local player = core.get_player_by_name(name)
|
||||
if not player then
|
||||
return false, "No player."
|
||||
end
|
||||
local pos_list = get_positions_cube(player:get_pos())
|
||||
local dummy = 0
|
||||
local function bench()
|
||||
local start_time = core.get_us_time()
|
||||
for i = 1, #pos_list do
|
||||
local pos_i = pos_list[i]
|
||||
local nid = core.get_node_raw(pos_i.x, pos_i.y, pos_i.z)
|
||||
local name = core.get_name_from_content_id(nid)
|
||||
-- Make sure the name lookup is not optimized away
|
||||
dummy = dummy + #name
|
||||
end
|
||||
return core.get_us_time() - start_time
|
||||
end
|
||||
|
||||
core.chat_send_player(name, "Benchmarking core.get_node_raw+get_name_from_content_id. Warming up ...")
|
||||
bench()
|
||||
|
||||
core.chat_send_player(name, "Warming up finished, now benchmarking ...")
|
||||
local result_us = bench()
|
||||
|
||||
local msg = string.format("Benchmark results: core.get_node_raw+get_name_from_content_id loop 1: %.2f ms",
|
||||
result_us / 1000)
|
||||
print(msg)
|
||||
return true, msg
|
||||
end,
|
||||
})
|
||||
|
||||
core.register_chatcommand("bench_bulk_get_node_vm", {
|
||||
params = "",
|
||||
description = "Benchmark: Bulk-get 99×99×99 nodes with voxel manipulator",
|
||||
func = function(name, param)
|
||||
local player = core.get_player_by_name(name)
|
||||
if not player then
|
||||
return false, "No player."
|
||||
end
|
||||
local pos = player:get_pos()
|
||||
local dummy = 0
|
||||
local function bench()
|
||||
local start_time = core.get_us_time()
|
||||
local vm = core.get_voxel_manip(pos:offset(1,1,1), pos:offset(100,100,100))
|
||||
local data = vm:get_data()
|
||||
local mid_time = core.get_us_time()
|
||||
-- Note that the VManip will actually retrieve more than just the 100³ nodes
|
||||
-- and also we don't need to iterate pos_list here, so it's not an entirely
|
||||
-- fair comparison.
|
||||
for i = 1, 99*99*99 do
|
||||
local nid = data[i]
|
||||
-- Make sure the table lookup is not optimized away
|
||||
dummy = dummy + nid
|
||||
end
|
||||
return core.get_us_time() - start_time, mid_time - start_time
|
||||
end
|
||||
|
||||
core.chat_send_player(name, "Benchmarking core.get_voxel_vmanip+get_data+loop . Warming up ...")
|
||||
bench()
|
||||
|
||||
core.chat_send_player(name, "Warming up finished, now benchmarking ...")
|
||||
local result_us, get_data_us = bench()
|
||||
|
||||
local msg = string.format("Benchmark results: core.get_voxel_vmanip+get_data+loop loop 1: %.2f ms of which get_data() %.2f ms",
|
||||
result_us / 1000, get_data_us / 1000)
|
||||
print(msg)
|
||||
return true, msg
|
||||
end,
|
||||
})
|
||||
@@ -174,7 +281,7 @@ core.register_chatcommand("bench_bulk_swap_node", {
|
||||
core.chat_send_player(name, "Warming up finished, now benchmarking ...")
|
||||
|
||||
local start_time = core.get_us_time()
|
||||
for i=1,#pos_list do
|
||||
for i = 1, #pos_list do
|
||||
core.swap_node(pos_list[i], {name = "mapgen_stone"})
|
||||
end
|
||||
local middle_time = core.get_us_time()
|
||||
@@ -184,6 +291,7 @@ core.register_chatcommand("bench_bulk_swap_node", {
|
||||
((middle_time - start_time)) / 1000,
|
||||
((end_time - middle_time)) / 1000
|
||||
)
|
||||
print(msg)
|
||||
return true, msg
|
||||
end,
|
||||
})
|
||||
|
||||
@@ -43,8 +43,9 @@ core.register_node("callbacks:callback_node", {
|
||||
print_to_everything("callbacks:callback_node:after_dig_node("..core.pos_to_string(pos)..")")
|
||||
end,
|
||||
|
||||
on_timer = function(pos, elapsed)
|
||||
print_to_everything("callbacks:callback_node:on_timer(): elapsed="..dump(elapsed))
|
||||
on_timer = function(pos, elapsed, node, timeout)
|
||||
print_to_everything("callbacks:callback_node:on_timer(): elapsed="..
|
||||
elapsed .. " node=" .. dump(node) .. " timeout=" .. timeout)
|
||||
return true
|
||||
end,
|
||||
})
|
||||
|
||||
@@ -12,4 +12,10 @@ Jordach (CC BY-SA 3.0):
|
||||
|
||||
Zeg9 (CC BY-SA 3.0):
|
||||
testentities_lava_flan.x
|
||||
testentities_lava_flan.png
|
||||
testentities_lava_flan.png
|
||||
|
||||
"Cool Guy":
|
||||
|
||||
hecks (refer to irr/LICENSE):
|
||||
testentities_cool_guy.x
|
||||
testentities_cool_guy.png
|
||||
|
||||
BIN
games/devtest/mods/testentities/models/testentities_cool_guy.png
Normal file
BIN
games/devtest/mods/testentities/models/testentities_cool_guy.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
BIN
games/devtest/mods/testentities/models/testentities_cool_guy.x
Executable file
BIN
games/devtest/mods/testentities/models/testentities_cool_guy.x
Executable file
Binary file not shown.
@@ -85,6 +85,28 @@ core.register_entity("testentities:sam", {
|
||||
},
|
||||
on_activate = function(self)
|
||||
self.object:set_animation({x = 0, y = 219}, 30, 0, true)
|
||||
self._timer = 0
|
||||
self._grow_head = true
|
||||
self:_animate_head()
|
||||
end,
|
||||
_head_anim_duration = 2,
|
||||
_animate_head = function(self)
|
||||
local s = self._grow_head and 2 or 1
|
||||
self.object:set_bone_override("Head", {
|
||||
scale = {
|
||||
vec = vector.new(s, s, s),
|
||||
absolute = true,
|
||||
interpolation = self._head_anim_duration,
|
||||
},
|
||||
})
|
||||
end,
|
||||
on_step = function(self, dtime)
|
||||
self._timer = self._timer + dtime
|
||||
if self._timer >= self._head_anim_duration then
|
||||
self._timer = 0
|
||||
self._grow_head = not self._grow_head
|
||||
self:_animate_head()
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
@@ -102,6 +124,19 @@ core.register_entity("testentities:lava_flan", {
|
||||
end,
|
||||
})
|
||||
|
||||
core.register_entity("testentities:cool_guy", {
|
||||
initial_properties = {
|
||||
visual = "mesh",
|
||||
mesh = "testentities_cool_guy.x",
|
||||
textures = {
|
||||
"testentities_cool_guy.png"
|
||||
},
|
||||
},
|
||||
on_activate = function(self)
|
||||
self.object:set_animation({x = 0, y = 29}, 30, 0, true)
|
||||
end,
|
||||
})
|
||||
|
||||
-- Advanced visual tests
|
||||
|
||||
-- An entity for testing animated and yaw-modulated sprites
|
||||
|
||||
@@ -207,3 +207,32 @@ local function test_vector_preserve(cb)
|
||||
end, {vec})
|
||||
end
|
||||
unittests.register("test_async_vector", test_vector_preserve, {async=true})
|
||||
|
||||
local function test_async_job_replacement(cb)
|
||||
core.ipc_set("unittests:end_blocking", nil)
|
||||
local capacity = core.get_async_threading_capacity()
|
||||
for _ = 1, capacity do
|
||||
core.handle_async(function()
|
||||
core.ipc_poll("unittests:end_blocking", 1000)
|
||||
end, function() end)
|
||||
end
|
||||
local job = core.handle_async(function()
|
||||
end, function()
|
||||
return cb("Canceled async job ran")
|
||||
end)
|
||||
if not job:cancel() then
|
||||
return cb("AsyncJob:cancel sanity check failed")
|
||||
end
|
||||
core.ipc_set("unittests:end_blocking", true)
|
||||
|
||||
-- Try to cancel a job that is already run.
|
||||
job = core.handle_async(function(x)
|
||||
return x
|
||||
end, function(ret)
|
||||
if job:cancel() then
|
||||
return cb("AsyncJob:cancel canceled a completed job")
|
||||
end
|
||||
cb()
|
||||
end, 1)
|
||||
end
|
||||
unittests.register("test_async_job_replacement", test_async_job_replacement, {async=true})
|
||||
|
||||
@@ -255,3 +255,17 @@ local function test_item_drop(_, pos)
|
||||
assert(itemstack_ret:equals(itemstack_src))
|
||||
end
|
||||
unittests.register("test_item_drop", test_item_drop, {map=true})
|
||||
|
||||
local function test_entity_guid(_, pos)
|
||||
local obj0 = core.add_entity(pos, "unittests:dummy")
|
||||
local obj1 = core.add_entity(pos, "unittests:dummy")
|
||||
|
||||
assert(obj0 ~= obj1)
|
||||
assert(obj0:get_guid() ~= obj1:get_guid())
|
||||
assert(core.objects_by_guid[obj0:get_guid()] == obj0)
|
||||
assert(core.objects_by_guid[obj1:get_guid()] == obj1)
|
||||
|
||||
obj0:remove()
|
||||
obj1:remove()
|
||||
end
|
||||
unittests.register("test_entity_guid", test_entity_guid, {map=true})
|
||||
|
||||
@@ -29,6 +29,6 @@ if core.ipc_cas("unittests:mg_once", nil, true) then
|
||||
end
|
||||
|
||||
core.register_on_generated(function(vm, pos1, pos2, blockseed)
|
||||
local n = tonumber(core.get_mapgen_setting("chunksize")) * 16 - 1
|
||||
assert(pos2:subtract(pos1) == vector.new(n, n, n))
|
||||
local cs = core.get_mapgen_chunksize()
|
||||
assert(pos2:subtract(pos1) == cs:multiply(core.MAP_BLOCKSIZE):subtract(1))
|
||||
end)
|
||||
|
||||
@@ -52,6 +52,7 @@ local function test_dynamic_media(cb, player)
|
||||
local ok = core.dynamic_add_media({
|
||||
filepath = path,
|
||||
to_player = player:get_player_name(),
|
||||
client_cache = false,
|
||||
}, function(name)
|
||||
if not call_ok then
|
||||
return cb("impossible condition")
|
||||
@@ -67,18 +68,6 @@ local function test_dynamic_media(cb, player)
|
||||
end
|
||||
unittests.register("test_dynamic_media", test_dynamic_media, {async=true, player=true})
|
||||
|
||||
local function test_v3f_metatable(player)
|
||||
assert(vector.check(player:get_pos()))
|
||||
end
|
||||
unittests.register("test_v3f_metatable", test_v3f_metatable, {player=true})
|
||||
|
||||
local function test_v3s16_metatable(player, pos)
|
||||
local node = core.get_node(pos)
|
||||
local found_pos = core.find_node_near(pos, 0, node.name, true)
|
||||
assert(vector.check(found_pos))
|
||||
end
|
||||
unittests.register("test_v3s16_metatable", test_v3s16_metatable, {map=true})
|
||||
|
||||
local function test_clear_meta(_, pos)
|
||||
local ref = core.get_meta(pos)
|
||||
|
||||
|
||||
@@ -204,3 +204,12 @@ local function run_player_hotbar_clamp_tests(player)
|
||||
player:hud_set_hotbar_itemcount(old_bar_size)
|
||||
end
|
||||
unittests.register("test_player_hotbar_clamp", run_player_hotbar_clamp_tests, {player=true})
|
||||
|
||||
--
|
||||
-- Player GUID
|
||||
--
|
||||
local function test_player_guid(player)
|
||||
assert(player:get_guid() == player:get_player_name())
|
||||
assert(core.objects_by_guid[player:get_guid()] == player)
|
||||
end
|
||||
unittests.register("test_player_guid", test_player_guid, {player=true})
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
IrrlichtMt version 1.9
|
||||
======================
|
||||
|
||||
IrrlichtMt is the 3D engine of [Minetest](https://github.com/minetest).
|
||||
IrrlichtMt is the 3D engine of [Luanti](https://github.com/luanti-org).
|
||||
It is based on the [Irrlicht Engine](https://irrlicht.sourceforge.io/) but is now developed independently.
|
||||
It is intentionally not compatible to upstream and is planned to be eventually absorbed into Minetest.
|
||||
It is intentionally not compatible to upstream and is planned to be eventually absorbed into Luanti.
|
||||
|
||||
Build
|
||||
-----
|
||||
|
||||
@@ -8,10 +8,11 @@
|
||||
#include "irrArray.h"
|
||||
#include "IOSOperator.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class IGUIScrollBar;
|
||||
|
||||
class CGUIEditBox : public IGUIEditBox
|
||||
{
|
||||
public:
|
||||
@@ -117,10 +118,10 @@ class CGUIEditBox : public IGUIEditBox
|
||||
|
||||
//! Set the blinktime for the cursor. 2x blinktime is one full cycle.
|
||||
//** \param timeMs Blinktime in milliseconds. When set to 0 the cursor is constantly on without blinking */
|
||||
void setCursorBlinkTime(irr::u32 timeMs) override;
|
||||
void setCursorBlinkTime(u32 timeMs) override;
|
||||
|
||||
//! Get the cursor blinktime
|
||||
irr::u32 getCursorBlinkTime() const override;
|
||||
u32 getCursorBlinkTime() const override;
|
||||
|
||||
//! Sets whether the edit box is a password box. Setting this to true will
|
||||
/** disable MultiLine, WordWrap and the ability to copy with ctrl+c or ctrl+x
|
||||
@@ -135,7 +136,10 @@ class CGUIEditBox : public IGUIEditBox
|
||||
void updateAbsolutePosition() override;
|
||||
|
||||
//! Returns whether the element takes input from the IME
|
||||
bool acceptsIME() override;
|
||||
bool acceptsIME() override { return isEnabled() && IsWritable; };
|
||||
|
||||
//! set true if this EditBox is writable
|
||||
void setWritable(bool writable) { IsWritable = writable; }
|
||||
|
||||
protected:
|
||||
//! Breaks the single text line.
|
||||
@@ -156,10 +160,23 @@ class CGUIEditBox : public IGUIEditBox
|
||||
void sendGuiEvent(EGUI_EVENT_TYPE type);
|
||||
//! set text markers
|
||||
void setTextMarkers(s32 begin, s32 end);
|
||||
//! delete current selection or next char
|
||||
bool keyDelete();
|
||||
//! update the vertical scrollBar (visibilty & position)
|
||||
void updateVScrollBar();
|
||||
|
||||
bool processKey(const SEvent &event);
|
||||
//! KEY_LEFT / KEY_RIGHT inputs
|
||||
void processKeyLR(const SEvent::SKeyInput &input, s32 &new_mark_begin,
|
||||
s32 &new_mark_end);
|
||||
|
||||
bool onKeyUp(const SEvent &event, s32 &mark_begin, s32 &mark_end);
|
||||
bool onKeyDown(const SEvent &event, s32 &mark_begin, s32 &mark_end);
|
||||
void onKeyControlC(const SEvent &event);
|
||||
bool onKeyControlX(const SEvent &event, s32 &mark_begin, s32 &mark_end);
|
||||
bool onKeyControlV(const SEvent &event, s32 &mark_begin, s32 &mark_end);
|
||||
bool onKeyBack();
|
||||
//! delete current selection or next char
|
||||
bool onKeyDelete();
|
||||
|
||||
bool processMouse(const SEvent &event);
|
||||
s32 getCursorPos(s32 x, s32 y);
|
||||
|
||||
@@ -171,18 +188,26 @@ class CGUIEditBox : public IGUIEditBox
|
||||
s32 MarkBegin;
|
||||
s32 MarkEnd;
|
||||
|
||||
video::SColor OverrideBgColor = 0;
|
||||
video::SColor OverrideColor;
|
||||
gui::IGUIFont *OverrideFont, *LastBreakFont;
|
||||
IOSOperator *Operator;
|
||||
|
||||
u32 BlinkStartTime;
|
||||
irr::u32 CursorBlinkTime;
|
||||
u32 CursorBlinkTime;
|
||||
core::stringw CursorChar; // IGUIFont::draw needs stringw instead of wchar_t
|
||||
s32 CursorPos;
|
||||
s32 HScrollPos, VScrollPos; // scroll position in characters
|
||||
u32 Max;
|
||||
u32 VScrollBarWidth = 0;
|
||||
IGUIScrollBar *VScrollBar = nullptr;
|
||||
|
||||
bool WordWrap = false,
|
||||
MultiLine = false,
|
||||
AutoScroll = true,
|
||||
PasswordBox = false,
|
||||
IsWritable = true;
|
||||
|
||||
bool WordWrap, MultiLine, AutoScroll, PasswordBox;
|
||||
wchar_t PasswordChar;
|
||||
EGUI_ALIGNMENT HAlign, VAlign;
|
||||
|
||||
@@ -193,4 +218,3 @@ class CGUIEditBox : public IGUIEditBox
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
@@ -14,8 +14,6 @@
|
||||
#include "../src/os.h"
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
//! Template implementation of the IIndexBuffer interface
|
||||
@@ -95,4 +93,3 @@ class CIndexBuffer final : public IIndexBuffer
|
||||
typedef CIndexBuffer<u16> SIndexBuffer;
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
#include "CVertexBuffer.h"
|
||||
#include "CIndexBuffer.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
//! Template implementation of the IMeshBuffer interface
|
||||
@@ -87,7 +85,7 @@ class CMeshBuffer final : public IMeshBuffer
|
||||
{
|
||||
if (Vertices->getCount()) {
|
||||
BoundingBox.reset(Vertices->getPosition(0));
|
||||
const irr::u32 vsize = Vertices->getCount();
|
||||
const u32 vsize = Vertices->getCount();
|
||||
for (u32 i = 1; i < vsize; ++i)
|
||||
BoundingBox.addInternalPoint(Vertices->getPosition(i));
|
||||
} else
|
||||
@@ -146,4 +144,3 @@ typedef CMeshBuffer<video::S3DVertex2TCoords> SMeshBufferLightMap;
|
||||
//! Meshbuffer with vertices having tangents stored, e.g. for normal mapping
|
||||
typedef CMeshBuffer<video::S3DVertexTangents> SMeshBufferTangents;
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
#include "../src/os.h"
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
//! Template implementation of the IVertexBuffer interface
|
||||
@@ -128,4 +126,3 @@ typedef CVertexBuffer<video::S3DVertex2TCoords> SVertexBufferLightMap;
|
||||
typedef CVertexBuffer<video::S3DVertexTangents> SVertexBufferTangents;
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
|
||||
#include "irrTypes.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
@@ -32,4 +30,3 @@ const c8 *const AutomaticCullingNames[] = {
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
@@ -38,4 +36,3 @@ enum E_DEBUG_SCENE_TYPE
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
//! An enum for the different device types supported by the Irrlicht Engine.
|
||||
enum E_DEVICE_TYPE
|
||||
{
|
||||
@@ -42,5 +39,3 @@ enum E_DEVICE_TYPE
|
||||
May support hw-acceleration via OpenGL-ES */
|
||||
EIDT_ANDROID,
|
||||
};
|
||||
|
||||
} // end namespace irr
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
@@ -140,4 +138,3 @@ enum E_VIDEO_DRIVER_FEATURE
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
@@ -36,4 +34,3 @@ enum E_DRIVER_TYPE
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
@@ -31,4 +29,3 @@ enum EFOCUS_FLAG
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
} // namespace irr
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
|
||||
#include "irrTypes.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
enum EGUI_ALIGNMENT
|
||||
@@ -32,4 +30,3 @@ const c8 *const GUIAlignmentNames[] = {
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
} // namespace irr
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
|
||||
#include "irrTypes.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
@@ -72,4 +70,3 @@ enum EGUI_ELEMENT_TYPE
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
@@ -37,4 +35,3 @@ enum E_BUFFER_TYPE
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user