Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a748a6b2c0 | ||
|
|
5f8eb14c92 | ||
|
|
1fc5034a77 | ||
|
|
5130d1659e | ||
|
|
f68cba21f0 | ||
|
|
6c7d1eba32 | ||
|
|
9713db862a | ||
|
|
fbee22d785 | ||
|
|
0ee39728e5 | ||
|
|
37aa69b64e | ||
|
|
22ddad85ab | ||
|
|
261a81586f | ||
|
|
f0abc99b61 | ||
|
|
b669871ff1 | ||
|
|
174c58b642 | ||
|
|
28431ef136 | ||
|
|
5f25bf97ba | ||
|
|
f6359d2f77 | ||
|
|
727c500b17 | ||
|
|
bebf2988fb | ||
|
|
e3cde1968b | ||
|
|
ef6b668c70 | ||
|
|
fef62e796b | ||
|
|
0d4b1dbce2 | ||
|
|
43d210dbf8 | ||
|
|
e0d2209e97 | ||
|
|
720cae3e94 | ||
|
|
f2ea34a717 | ||
|
|
2c33747e1b | ||
|
|
5f9d72eb90 | ||
|
|
3abcc1d96f | ||
|
|
7d458422c7 | ||
|
|
0feee14bfb | ||
|
|
0023cfcafb | ||
|
|
08f0d7f635 | ||
|
|
73a5b14084 | ||
|
|
da8befca86 | ||
|
|
33cc64a441 | ||
|
|
a13fb02c75 | ||
|
|
c9d9a8f04a | ||
|
|
5de6c850ed | ||
|
|
d98044c51c | ||
|
|
0575bf0239 | ||
|
|
992c96dd52 | ||
|
|
4d969ab320 | ||
|
|
283713ff8a | ||
|
|
231aa89686 | ||
|
|
d67372b72f | ||
|
|
93046154a9 | ||
|
|
2966f57d42 | ||
|
|
951cb260c5 | ||
|
|
2256e9ef77 | ||
|
|
188e0ea932 | ||
|
|
6e6848e007 | ||
|
|
fc83f0fec6 | ||
|
|
034a4b6b7c | ||
|
|
30593c1bfd | ||
|
|
89e69591e0 | ||
|
|
147279a8ca | ||
|
|
517ac4403f | ||
|
|
b4e88e570f | ||
|
|
9b5385ed61 | ||
|
|
284e3e91f3 | ||
|
|
0fb6519617 | ||
|
|
e2452f2780 | ||
|
|
f1c763861b | ||
|
|
ea99736142 | ||
|
|
21d661bd22 | ||
|
|
fc0666fe46 | ||
|
|
869c6191b6 | ||
|
|
a53f41336d | ||
|
|
ff4e82d2cc | ||
|
|
2de7e3bd7e | ||
|
|
c72e0c5108 | ||
|
|
11814e0fd2 | ||
|
|
d41d2e74bd | ||
|
|
122b54caee | ||
|
|
3a67785be6 | ||
|
|
01e2457611 | ||
|
|
dd13d244c0 | ||
|
|
fba8983f46 | ||
|
|
4a2af1f37a | ||
|
|
2b82c45176 | ||
|
|
3203c64287 | ||
|
|
1683e1faf6 | ||
|
|
eb9de8cc3f | ||
|
|
df6a8281a6 | ||
|
|
05568296d9 | ||
|
|
c024b28a45 | ||
|
|
0b0c457cdc | ||
|
|
001e26cbb0 | ||
|
|
3d75520863 | ||
|
|
63bc73fd98 | ||
|
|
b47e7d2d3b | ||
|
|
cf7b0eed28 | ||
|
|
b3b0652222 | ||
|
|
8e78e4e9ce | ||
|
|
f9d60a224a | ||
|
|
396678d996 | ||
|
|
fae2d7a532 | ||
|
|
73ab71d7c0 | ||
|
|
ec6eb51515 | ||
|
|
02a9f25148 | ||
|
|
ea4c16a162 | ||
|
|
c7e8c891e2 | ||
|
|
651580078c | ||
|
|
2c3a7a2256 | ||
|
|
47b3579fde | ||
|
|
8147fd4edf | ||
|
|
4c6fd3282b | ||
|
|
363f5c7e5e | ||
|
|
229f7d665b | ||
|
|
ff2dd5d1d5 | ||
|
|
37f1763d9c | ||
|
|
962adc683d | ||
|
|
6f4f6b71ff | ||
|
|
6576c53235 | ||
|
|
3d939c2a39 | ||
|
|
9564e2cdf8 | ||
|
|
2ed7cb794e | ||
|
|
f2d4a6bee7 | ||
|
|
63be8824f6 | ||
|
|
e95a5597fe | ||
|
|
ea1dc94c60 | ||
|
|
2079505a6f | ||
|
|
1a52f3de21 | ||
|
|
87321fe6d9 | ||
|
|
e3afa04f90 | ||
|
|
4a7fb76011 | ||
|
|
4c0b79ef25 | ||
|
|
0d6e71ad9b | ||
|
|
4025eb5426 | ||
|
|
a26ab401b6 | ||
|
|
1846eab87e | ||
|
|
c860fc33fb | ||
|
|
9a3f5b4322 | ||
|
|
fb58ca99ae | ||
|
|
b490d79929 | ||
|
|
fb6044c3c1 | ||
|
|
d518e8c463 | ||
|
|
196ab4d61d | ||
|
|
2e406f3d1c | ||
|
|
8d6c17806c | ||
|
|
d60ffccd2a | ||
|
|
5be3016e90 | ||
|
|
55befc4d0c | ||
|
|
4a4f15ed52 | ||
|
|
0f294a47b0 | ||
|
|
4ee766a6f9 | ||
|
|
a3103ea0c9 | ||
|
|
bef190ddd7 | ||
|
|
cf320b3fa2 | ||
|
|
34c8745fa9 | ||
|
|
8096ff7f98 | ||
|
|
dad3006f84 | ||
|
|
0e35f15a86 | ||
|
|
d423740273 | ||
|
|
49f489c4dc | ||
|
|
ac71bf2111 | ||
|
|
6d40dd12fa | ||
|
|
a732abcdd6 | ||
|
|
c2f90f9daf | ||
|
|
898f56c32a | ||
|
|
2ebc4384f5 | ||
|
|
687b8d5e29 | ||
|
|
d09d95e069 | ||
|
|
4dffc1ffe9 | ||
|
|
f3b2cfbb87 | ||
|
|
4af57308d3 | ||
|
|
28ecf8666c | ||
|
|
1f3d1beb8f | ||
|
|
96d21bc544 | ||
|
|
f5cb2b5a1d | ||
|
|
d1d6e73bbc | ||
|
|
2321ae1c0c | ||
|
|
982ee5b6bf | ||
|
|
dbe699843b | ||
|
|
fda19760bd | ||
|
|
97d42152cd | ||
|
|
5981607783 | ||
|
|
7b7927f328 | ||
|
|
a8e2730f2f | ||
|
|
7ae18187bc | ||
|
|
02634c531f | ||
|
|
5e8ff89c43 | ||
|
|
2f307c492f | ||
|
|
e4b3e17c14 | ||
|
|
66d14a0754 | ||
|
|
cb47dcbe12 | ||
|
|
ea15b40e05 | ||
|
|
93cfd74fc0 | ||
|
|
79eb6a9078 | ||
|
|
2e9e5042e1 | ||
|
|
bb520edd53 | ||
|
|
2beb9563bb | ||
|
|
87c15f7611 | ||
|
|
655bc176fa | ||
|
|
66cb30d235 | ||
|
|
cbe0b25b5f | ||
|
|
a8ccf4e1c9 | ||
|
|
cce29c51e3 | ||
|
|
242015b0cc | ||
|
|
f209e1b0f9 | ||
|
|
8a1ab06585 | ||
|
|
50e817a86d | ||
|
|
dbd596f079 | ||
|
|
f8e3a07e6f | ||
|
|
ccd4ac3271 | ||
|
|
fce1925448 | ||
|
|
335eb5ef4d | ||
|
|
654c40b892 | ||
|
|
a937243cdf | ||
|
|
665d6baf1c | ||
|
|
b4d326b52c | ||
|
|
3aacec826b | ||
|
|
3261856385 | ||
|
|
8cf479bf3b | ||
|
|
3c3ef636eb | ||
|
|
3bd0b13740 | ||
|
|
92349227a2 | ||
|
|
4dfc2a638a | ||
|
|
d7c73a8072 | ||
|
|
297acc0322 | ||
|
|
1126b3b471 | ||
|
|
ac59973283 | ||
|
|
4b130ed71d | ||
|
|
ce90a33ce9 | ||
|
|
50fee32218 | ||
|
|
39334a4cd9 | ||
|
|
fec2131ba8 | ||
|
|
7c63436da4 | ||
|
|
de8fe63bd0 | ||
|
|
1c22f2387b | ||
|
|
e1b277582a | ||
|
|
94acc4f356 | ||
|
|
9afb62a6a4 | ||
|
|
95ed957d54 | ||
|
|
58814bc2da | ||
|
|
9e7556c3c1 | ||
|
|
abaf723fb7 | ||
|
|
f52e99c86e | ||
|
|
d6e70c35d8 | ||
|
|
4c91e73f0e | ||
|
|
d083fc6e43 | ||
|
|
ff2df25e3b | ||
|
|
86c2342097 | ||
|
|
6dbd176683 | ||
|
|
141aab1c22 | ||
|
|
126ea4f456 | ||
|
|
a0e5a97594 | ||
|
|
0420c11937 | ||
|
|
27472fd387 | ||
|
|
104bdc646f | ||
|
|
cbc4c275d1 | ||
|
|
372d51f873 | ||
|
|
0dfd404215 | ||
|
|
21b7393274 | ||
|
|
dcd5f5a3e6 | ||
|
|
bf313b3ba1 | ||
|
|
5b4e3c479c | ||
|
|
6dedb05c29 | ||
|
|
5f78e01342 | ||
|
|
881506a3d5 | ||
|
|
e26fc661b2 | ||
|
|
f921758ec0 | ||
|
|
01d65ba780 | ||
|
|
d77e2d6f45 | ||
|
|
7c30f55f31 | ||
|
|
c2d63865d5 | ||
|
|
f406b518c0 | ||
|
|
78f8c99f11 | ||
|
|
f97b9a419f | ||
|
|
f2b88b8cd6 | ||
|
|
cd06700c82 | ||
|
|
fa69040e00 | ||
|
|
fd88c1c0bb | ||
|
|
cae7d8d061 | ||
|
|
2e1e24c225 | ||
|
|
da0307b14f | ||
|
|
082c94ac07 | ||
|
|
2ed4b1b6fc | ||
|
|
8c7c8042e5 | ||
|
|
cca15a2b04 | ||
|
|
5f40411be0 | ||
|
|
191273a728 | ||
|
|
9eb9e9589f | ||
|
|
fdd45952c7 | ||
|
|
98378b222d | ||
|
|
15a0446d70 | ||
|
|
7bd1b7c670 | ||
|
|
46aaa47fdd | ||
|
|
2027e9f58e | ||
|
|
162e4690e9 | ||
|
|
c360575dec | ||
|
|
5b0354c2c0 | ||
|
|
52b0f21bd9 | ||
|
|
1e3cbde3b3 | ||
|
|
267fb727c7 | ||
|
|
68904f58ec | ||
|
|
5cbb1bb5dd | ||
|
|
038d221206 | ||
|
|
22d6ebd0d4 | ||
|
|
e8dd46c701 | ||
|
|
1150d07dbe | ||
|
|
5c294f4ad3 | ||
|
|
1b5bf0aab7 | ||
|
|
8d8a03602e | ||
|
|
df7bdb7a0c | ||
|
|
00a5eb2588 | ||
|
|
90631c66e0 | ||
|
|
c1ba692a79 | ||
|
|
8f3324e0d8 | ||
|
|
5a09a9ce78 | ||
|
|
33fcee7641 | ||
|
|
12b91940c7 | ||
|
|
0e6246f044 | ||
|
|
7f7cf97408 | ||
|
|
090fe9ccb6 | ||
|
|
ffae161282 | ||
|
|
1443850344 | ||
|
|
63f9daf334 | ||
|
|
b277d0973a | ||
|
|
33c0f1672a | ||
|
|
4224922ebb | ||
|
|
6eb30d84b4 | ||
|
|
592a75b53f | ||
|
|
8e08ea4e44 | ||
|
|
cff1e831d0 | ||
|
|
83b5a0f88a | ||
|
|
2ba535111e | ||
|
|
4bbf0bb0f1 | ||
|
|
1e80070d2d | ||
|
|
0afe0f28e1 | ||
|
|
fbc04b1183 | ||
|
|
bdd2a139e1 | ||
|
|
e956e59888 | ||
|
|
1debc54db6 | ||
|
|
37786935c3 | ||
|
|
425748af12 | ||
|
|
c0deaa40ed | ||
|
|
70be098f8a | ||
|
|
838ef437d8 | ||
|
|
44d7473c71 | ||
|
|
b8a7dfe543 | ||
|
|
4c4bf79371 | ||
|
|
a4b4bd0146 | ||
|
|
9553e310e4 | ||
|
|
e00caddb1e | ||
|
|
898887225d | ||
|
|
8eef805418 | ||
|
|
8509718d32 | ||
|
|
f2cb7c564f | ||
|
|
9335e5af65 | ||
|
|
5a5eadac1f | ||
|
|
bcd015b6eb | ||
|
|
91c6b8f08e | ||
|
|
c7251295a1 | ||
|
|
db2110b11e | ||
|
|
be1122ce50 | ||
|
|
cf265987db | ||
|
|
cd82e75514 | ||
|
|
74d36f1ab5 | ||
|
|
67da0ff32b | ||
|
|
aabad04e28 | ||
|
|
9236da40dd | ||
|
|
88ff78b7e3 | ||
|
|
21ebd68607 | ||
|
|
9adad40aa9 | ||
|
|
f63b3de63a | ||
|
|
767933e522 | ||
|
|
0fb86ddf6c | ||
|
|
d52969597f | ||
|
|
70e1537bc0 | ||
|
|
605a09b290 | ||
|
|
8e2f8d67f3 | ||
|
|
d00764e548 | ||
|
|
953472a41a | ||
|
|
6be5bb4757 | ||
|
|
b48a9e4f22 | ||
|
|
6d42e252a1 | ||
|
|
ef98b15c86 | ||
|
|
6945e8ee81 | ||
|
|
9c9edbff75 | ||
|
|
b8e3a07980 | ||
|
|
06279e3708 | ||
|
|
9812345f71 | ||
|
|
e1f667079a | ||
|
|
6edc3babc8 | ||
|
|
309c67969a | ||
|
|
bd681229db | ||
|
|
4f0a4feb03 | ||
|
|
2d84a60c84 | ||
|
|
0f66bc7264 | ||
|
|
9283f969c4 | ||
|
|
dbcad7b11d | ||
|
|
8e96fc1595 | ||
|
|
fa46427b1f | ||
|
|
5a112bff22 | ||
|
|
1a8bc5ee34 | ||
|
|
1001bcd507 | ||
|
|
2f6f5f4958 | ||
|
|
863cceb175 | ||
|
|
d07d604f7c | ||
|
|
9035f8b57f | ||
|
|
43bc22b8be | ||
|
|
1d59eb5787 | ||
|
|
5383b87c3f | ||
|
|
5c3815aee0 | ||
|
|
69b9acdc83 | ||
|
|
3b68fe9bdd | ||
|
|
4d9dd1cf83 | ||
|
|
0854fd674f | ||
|
|
75478b59ae | ||
|
|
d39f6fd061 | ||
|
|
a532cd4fc1 | ||
|
|
a6afd9de0a | ||
|
|
9a8df8c890 | ||
|
|
cd435cc716 | ||
|
|
b0bdc36b59 | ||
|
|
1971513acc | ||
|
|
99646f2113 | ||
|
|
78349176d6 | ||
|
|
92115ed493 | ||
|
|
4ef8508c65 | ||
|
|
1feafa884e | ||
|
|
02bff23b1f | ||
|
|
d80742bf20 | ||
|
|
7bde3d9996 | ||
|
|
4d86beb268 | ||
|
|
b039cbb7b6 | ||
|
|
7d8af7efc9 | ||
|
|
7019044837 | ||
|
|
5916ec5d07 | ||
|
|
4508fcf4b3 | ||
|
|
2de69557d2 | ||
|
|
b01e793a26 | ||
|
|
1f67ab7bdb | ||
|
|
43ae5add60 | ||
|
|
971620818b | ||
|
|
c997b99935 | ||
|
|
ae83ce1f42 | ||
|
|
2410717510 | ||
|
|
5270a156b3 | ||
|
|
07d807a7bd | ||
|
|
5fb80f5661 | ||
|
|
ce6bef7f19 | ||
|
|
facedfdea7 | ||
|
|
e8fa66dac0 | ||
|
|
997d824d12 | ||
|
|
86baf27ca0 | ||
|
|
2b8b5303c8 | ||
|
|
24bd58130b | ||
|
|
907bbdb52b | ||
|
|
26c491ce22 | ||
|
|
73def64743 | ||
|
|
d021d213f6 | ||
|
|
dfd5ccf525 | ||
|
|
a4cfe9f81b | ||
|
|
8402088cba | ||
|
|
2adcc0d45b | ||
|
|
da25752b73 | ||
|
|
ac348cf207 | ||
|
|
6afe8f0081 | ||
|
|
86c294592f | ||
|
|
3deba4a0f3 | ||
|
|
cfb3d10a7d | ||
|
|
458fa4e416 | ||
|
|
6e7d2338a4 | ||
|
|
d0bd1b4b0b | ||
|
|
2076b589b4 | ||
|
|
a4b8c2b730 | ||
|
|
0cc83325bc | ||
|
|
f2fa63315e | ||
|
|
9631abf430 | ||
|
|
084123132a | ||
|
|
4e9d2df0b2 | ||
|
|
e3a3a65987 | ||
|
|
17feac0501 | ||
|
|
84e280a562 | ||
|
|
906e304018 | ||
|
|
48cdeb7283 | ||
|
|
4efb55f685 | ||
|
|
3ed6f8158d | ||
|
|
c89a38b0da | ||
|
|
eb40cf873f | ||
|
|
892c626312 | ||
|
|
7e0d447e75 | ||
|
|
49b2723c19 | ||
|
|
5140d912e1 | ||
|
|
0fa1165652 | ||
|
|
375d2297e7 | ||
|
|
fbd089d87a | ||
|
|
5076c80e2c | ||
|
|
4fcbec7a4a | ||
|
|
cb82d3ad13 | ||
|
|
a6172c705d | ||
|
|
3c2c480c11 | ||
|
|
da1a839014 | ||
|
|
bf6628c6a2 | ||
|
|
42674bbfdd | ||
|
|
225164b7b6 | ||
|
|
35ce37acf8 | ||
|
|
2df5b00e07 | ||
|
|
3fa25c0662 | ||
|
|
b7e233834e | ||
|
|
ff80a4807f | ||
|
|
c56592c19a | ||
|
|
e93df8e38d | ||
|
|
15664bc9fb | ||
|
|
9cedbabd75 | ||
|
|
a98ecee8f3 | ||
|
|
f64d0d7b41 | ||
|
|
7a1f1ed484 | ||
|
|
85ade0dd15 | ||
|
|
9c70f5a187 | ||
|
|
f622d0c8b3 | ||
|
|
a3c4362a90 | ||
|
|
05609ca436 | ||
|
|
fde7fefe9f | ||
|
|
19f45aeb4d | ||
|
|
540eafc41b | ||
|
|
1ba62e0ae9 | ||
|
|
07b213d0af | ||
|
|
0528baaa64 | ||
|
|
264b8e69d8 | ||
|
|
b4c6da418d | ||
|
|
3811f942a1 | ||
|
|
6d295960d5 | ||
|
|
983d6a055b | ||
|
|
9de3fc4bbb | ||
|
|
f4c986f0de | ||
|
|
434f629c0b | ||
|
|
dac32b6daf | ||
|
|
dd845013ce | ||
|
|
b9bad50dbd | ||
|
|
56540df419 | ||
|
|
d0b0c55ab8 | ||
|
|
6f2b92e044 | ||
|
|
5da16e8055 | ||
|
|
a522ea9902 | ||
|
|
36801184a5 | ||
|
|
d212eb108d | ||
|
|
cbc1de0f33 | ||
|
|
fcdc04e228 | ||
|
|
890f1ee131 | ||
|
|
f3aec47ac3 | ||
|
|
bcf1c828b5 | ||
|
|
5fd319a152 | ||
|
|
abecb58a8d | ||
|
|
135166b01e | ||
|
|
0770293452 | ||
|
|
f3c40ad582 | ||
|
|
aacc115a36 | ||
|
|
b7ba07b78d | ||
|
|
e13445f55d | ||
|
|
bd527d3868 | ||
|
|
f288112eb2 | ||
|
|
6b415e64a8 | ||
|
|
cfb2cb6b0a | ||
|
|
622deb6fd7 | ||
|
|
7f41421d65 | ||
|
|
73e706465a | ||
|
|
a8c543ca9e | ||
|
|
9594ff452b | ||
|
|
d5c81298dd | ||
|
|
88faacb240 | ||
|
|
0d2a04b3a5 | ||
|
|
f8a90b28b5 | ||
|
|
a948febb18 | ||
|
|
8e33481b97 | ||
|
|
f54be214f9 | ||
|
|
d50b47acb5 | ||
|
|
31011c243a | ||
|
|
f4aa03f20d | ||
|
|
28aacaea45 | ||
|
|
d4fd9a2b78 | ||
|
|
663e0be357 | ||
|
|
14d29577c5 | ||
|
|
951f8072c1 | ||
|
|
05f042eda0 | ||
|
|
b00c2fbcb4 | ||
|
|
dde4866e50 | ||
|
|
9fa6b21c08 | ||
|
|
e95e6fc20c | ||
|
|
c7a3b00c3c | ||
|
|
74bc0e0cb7 | ||
|
|
6248008b4d | ||
|
|
2d91e165ce | ||
|
|
b1220550eb | ||
|
|
680ff3412f | ||
|
|
799f6b8215 | ||
|
|
1be224b7de | ||
|
|
a32adfbfc7 | ||
|
|
dda415351a | ||
|
|
685e4b9faa | ||
|
|
1f842563b3 | ||
|
|
f237b61065 | ||
|
|
19d6d06791 | ||
|
|
6873c59505 | ||
|
|
e7ae62db7b | ||
|
|
d4362f2ed2 | ||
|
|
9247f3d4fb | ||
|
|
b4993b657e | ||
|
|
b73aa93d01 | ||
|
|
bce689e672 | ||
|
|
f4468261cf | ||
|
|
cc926ff974 | ||
|
|
6c3831ded4 | ||
|
|
3c55866d46 | ||
|
|
dfc9359f04 | ||
|
|
ea0897db31 | ||
|
|
25cf6c95e8 | ||
|
|
f5e2910e0b | ||
|
|
fda35986a4 | ||
|
|
b97e86c2ed | ||
|
|
ebb02717b5 | ||
|
|
1b82ebfd25 | ||
|
|
3fb788ef6d | ||
|
|
11bc06182c | ||
|
|
2fe5dc833d | ||
|
|
317cb975ce | ||
|
|
9bb2a97e50 | ||
|
|
53dcc60587 | ||
|
|
db347bc192 | ||
|
|
608b8307dd | ||
|
|
4c027da093 | ||
|
|
bef60e688c | ||
|
|
b987ad99f4 | ||
|
|
3036e2d523 | ||
|
|
1bab2d0025 | ||
|
|
4cac6c659e | ||
|
|
c7c59238e1 | ||
|
|
f51e74c066 | ||
|
|
52f8801638 | ||
|
|
4e5c5a7073 | ||
|
|
436f3879c4 | ||
|
|
c1395e26d4 | ||
|
|
3750d6ddb1 | ||
|
|
45c3601b49 | ||
|
|
957da1d040 | ||
|
|
43932eb6b3 | ||
|
|
024ddeefb4 | ||
|
|
94190b5cd7 | ||
|
|
5d72f90a0f | ||
|
|
90c30023c2 | ||
|
|
d39a89659b | ||
|
|
79f4386b62 | ||
|
|
39c4d8ae96 | ||
|
|
c8b2abbb3e | ||
|
|
06b7bbd711 | ||
|
|
11afd15610 | ||
|
|
4951025e61 | ||
|
|
2337a122da | ||
|
|
072333bf48 | ||
|
|
2bd8924df7 | ||
|
|
23cdc3721d | ||
|
|
957e4ba0c0 | ||
|
|
71a19c63d8 | ||
|
|
657327e7ee | ||
|
|
efeea7cf0f | ||
|
|
7a4637368d | ||
|
|
2e6ccd078b | ||
|
|
827197f916 | ||
|
|
c8454ec0c1 | ||
|
|
7127a77d92 | ||
|
|
b23912b52f | ||
|
|
4b21148a03 | ||
|
|
2d5ef95e54 | ||
|
|
b5e2d376dd | ||
|
|
c40b337edc | ||
|
|
f8583642a8 | ||
|
|
707f28df16 | ||
|
|
dd78da089d | ||
|
|
c4ea65ed70 | ||
|
|
aabba806c4 | ||
|
|
88167fc42d | ||
|
|
e4d7005e46 | ||
|
|
5ee27f7ed7 | ||
|
|
9a4492c401 | ||
|
|
39a2aee5a0 | ||
|
|
5184ef170f | ||
|
|
29a35cf1cc | ||
|
|
f26516ecae | ||
|
|
f26a7ad2b1 | ||
|
|
96e0a29573 | ||
|
|
f30d667ca8 | ||
|
|
8db7a1d6d9 | ||
|
|
d285a0512e | ||
|
|
256d0d5c84 | ||
|
|
b808e1f9d1 | ||
|
|
07cd781ec1 | ||
|
|
9115b687f4 | ||
|
|
7c51377203 | ||
|
|
193cd02072 | ||
|
|
dbb6d91f0c | ||
|
|
a82714e811 | ||
|
|
bcd1bbac62 | ||
|
|
2fde0e68ca | ||
|
|
e6e9b1c5ae | ||
|
|
48b789c51d | ||
|
|
433b39209d | ||
|
|
b6df7a9f33 | ||
|
|
ad1d55537f | ||
|
|
9982d2c6ef | ||
|
|
1e3f622a98 | ||
|
|
ce05d5f6a6 | ||
|
|
19378e2095 | ||
|
|
0d992f1e50 | ||
|
|
de7cabfd54 | ||
|
|
cfe73a00ee | ||
|
|
35a7acbbd9 | ||
|
|
20eebca395 | ||
|
|
7c2a4deb1a | ||
|
|
e227e6a0f4 | ||
|
|
e015c29a3d | ||
|
|
a2859937e2 | ||
|
|
cd26252444 | ||
|
|
47894a6e74 | ||
|
|
bcf94180d5 | ||
|
|
6d2eeda28c | ||
|
|
049c768013 | ||
|
|
ffae488d1e | ||
|
|
3ea0ae6e5b | ||
|
|
530c25655c | ||
|
|
ca830fd64c | ||
|
|
4272476230 | ||
|
|
b7e44246ce | ||
|
|
33b9578fd1 | ||
|
|
df0a96843d | ||
|
|
5b5f7dfc12 | ||
|
|
8b094adcca | ||
|
|
de9d9ab844 | ||
|
|
2fd6d2f50b | ||
|
|
349c9eca4b | ||
|
|
1f119233d7 | ||
|
|
17c2d63892 | ||
|
|
79c76e913d | ||
|
|
6501480980 | ||
|
|
5ad9bbba37 | ||
|
|
f012448758 | ||
|
|
99b6d635d7 | ||
|
|
5f742627e9 | ||
|
|
a9e725002a | ||
|
|
49150f9b1e | ||
|
|
89aa1ba94c | ||
|
|
6aca313bd8 | ||
|
|
f76d5a958f | ||
|
|
b833a10de4 | ||
|
|
f3ce5632fb | ||
|
|
f5bf4c3831 | ||
|
|
08a3acc5e0 | ||
|
|
5b63034607 | ||
|
|
d4543032d9 | ||
|
|
254a91c3bd | ||
|
|
4c01ddaaef | ||
|
|
2993d1450a | ||
|
|
582c3a4c1a | ||
|
|
dd6b964405 | ||
|
|
16827bfbac | ||
|
|
3c4d72bb71 | ||
|
|
004036e019 | ||
|
|
ba06f80baa | ||
|
|
ee47428a80 | ||
|
|
1e40cae27b | ||
|
|
f5b7bb5549 | ||
|
|
115883f8d0 | ||
|
|
a73446a1c5 | ||
|
|
7501c4f76b | ||
|
|
9f038fae63 | ||
|
|
a61a520570 | ||
|
|
885783cd9a | ||
|
|
181f850c58 | ||
|
|
fe8742b580 | ||
|
|
daeba7caa9 | ||
|
|
1340e6dc1b | ||
|
|
cba7655f0d | ||
|
|
ac7e2a9aef | ||
|
|
fcc0bfbf32 | ||
|
|
a7e86bdb64 | ||
|
|
c3eecd8d14 | ||
|
|
25e6da3ac5 | ||
|
|
a7e5786fee | ||
|
|
a6bccc3dd3 | ||
|
|
d8cd39dc3e | ||
|
|
6eacf833f5 | ||
|
|
dbdd417e0d | ||
|
|
4c8dd52f28 | ||
|
|
31a2d8a02b | ||
|
|
f246d57a7e | ||
|
|
4ae856630f | ||
|
|
8652baf2ae | ||
|
|
4a18853e8c | ||
|
|
a60be9d8c1 | ||
|
|
e16b47409c | ||
|
|
6f14cbe746 | ||
|
|
ea79c9c5dd | ||
|
|
650d13ed71 | ||
|
|
169b8b8e94 | ||
|
|
8cef4a5bcb | ||
|
|
70b40802cc | ||
|
|
416e707cda | ||
|
|
12578293bc | ||
|
|
042ab6850b | ||
|
|
09fc042630 | ||
|
|
c73d351bf1 | ||
|
|
4d4e0a9c2a | ||
|
|
2fd29b2347 | ||
|
|
f332068318 | ||
|
|
186c79f93c | ||
|
|
3770066485 | ||
|
|
17b0ffe52b | ||
|
|
d259b5bb78 | ||
|
|
f6c8d24177 | ||
|
|
ab3bd61d3c | ||
|
|
6a5cee8f0e | ||
|
|
549732fc8b | ||
|
|
09d400c6fb | ||
|
|
7e1cdafa78 | ||
|
|
434c0216d5 | ||
|
|
d5a0ae8e71 | ||
|
|
79e56c6a30 | ||
|
|
11cc1c3f25 | ||
|
|
8b343bcfb6 | ||
|
|
ecd83beb7d | ||
|
|
438f21fb11 | ||
|
|
dd1524cf31 | ||
|
|
0f85aa5384 | ||
|
|
4644a0ae96 | ||
|
|
84b3efe0fc | ||
|
|
511acbd5ff | ||
|
|
8749b3b354 | ||
|
|
b66e63d242 | ||
|
|
ba951238c3 | ||
|
|
a4eb76f1cf | ||
|
|
c486899dcf | ||
|
|
b212f0d5be | ||
|
|
caa534ff7f | ||
|
|
9c2fac6749 | ||
|
|
2a4f918a10 | ||
|
|
b45e2afe4c | ||
|
|
2c7237e5d9 | ||
|
|
26477e3150 | ||
|
|
cba8cb57d5 | ||
|
|
599b4822e5 | ||
|
|
fbd150b353 | ||
|
|
10b252e934 | ||
|
|
e9dfcdeb10 | ||
|
|
9cb2f27754 | ||
|
|
a090a83b7d | ||
|
|
992e661e4c | ||
|
|
3b993d114e | ||
|
|
d181d62466 | ||
|
|
968cef7a12 | ||
|
|
390c2395eb | ||
|
|
adc9444794 | ||
|
|
f086318082 | ||
|
|
1cef4400b9 | ||
|
|
1f879ac91e | ||
|
|
bec129d98e | ||
|
|
152c04e68f | ||
|
|
d6cdacef43 | ||
|
|
09891a075d | ||
|
|
9500bab5b7 | ||
|
|
231edd4bd4 | ||
|
|
433572e759 | ||
|
|
3ec772e87f | ||
|
|
ae8287157c | ||
|
|
f005907b41 | ||
|
|
8ea16044f1 | ||
|
|
e787a28353 | ||
|
|
6925d9564c | ||
|
|
ccd4ea785a | ||
|
|
63e88c09d4 | ||
|
|
296191b502 | ||
|
|
af0151f446 | ||
|
|
2bdfaa167e | ||
|
|
cd96476f9e | ||
|
|
9b0545aa1a | ||
|
|
63823123f8 | ||
|
|
e91728be98 | ||
|
|
e7ecbf1245 | ||
|
|
28c2363b67 | ||
|
|
21a3d4fb55 | ||
|
|
4b459a3ed1 | ||
|
|
ebc6a1b842 | ||
|
|
b72b0f269a | ||
|
|
4cbcd69ed2 | ||
|
|
6ef8b7748c | ||
|
|
8b567cb976 | ||
|
|
d8c231b9ce | ||
|
|
cc4347c881 | ||
|
|
7cc572feb5 | ||
|
|
96d1d1feb4 | ||
|
|
a7d9bd9ab5 | ||
|
|
1cdfdf1d43 | ||
|
|
0762a5e689 | ||
|
|
3e2906ccf8 | ||
|
|
13761e032c | ||
|
|
fb8fa3fa54 | ||
|
|
b89bf5933b | ||
|
|
1c4f404fd2 | ||
|
|
9fe1560f1a | ||
|
|
6a9cca37c6 | ||
|
|
bfde75d4b1 | ||
|
|
a83f98580d | ||
|
|
673542d8e4 | ||
|
|
81c5d89a25 | ||
|
|
bf0bcb0b96 | ||
|
|
ac7a664303 | ||
|
|
182dc67a49 | ||
|
|
27ee82d17c | ||
|
|
9405e4e45d | ||
|
|
8616769e32 | ||
|
|
5d85c4697b | ||
|
|
c54a2b7353 | ||
|
|
35075e88e3 | ||
|
|
1266d34176 | ||
|
|
66ddf0e3ca | ||
|
|
88ab129737 | ||
|
|
bcd293a255 | ||
|
|
4a5ebe6dbd | ||
|
|
ef1c3b1b3b | ||
|
|
f7e68ffb6b | ||
|
|
2cf2153c4d | ||
|
|
7e7d0025fa | ||
|
|
8252b6486e | ||
|
|
378041cb16 | ||
|
|
ee5ff07565 | ||
|
|
80c63dd414 | ||
|
|
e182366566 | ||
|
|
acee89cce3 | ||
|
|
3ef3d14c10 | ||
|
|
74365780a7 | ||
|
|
f6ad80370f | ||
|
|
87eb544936 | ||
|
|
cde0389380 | ||
|
|
9e46ffc4e1 | ||
|
|
f3c35de780 | ||
|
|
75f5378c8c | ||
|
|
19d32127e8 | ||
|
|
2f00aa7750 | ||
|
|
07f5dc68b5 | ||
|
|
96a39d7037 | ||
|
|
409f1c4230 | ||
|
|
c3d2f9aeea | ||
|
|
380b3dd1f6 | ||
|
|
c15a6009a2 | ||
|
|
e4e7c364fd | ||
|
|
438361eed2 | ||
|
|
684b35f2df | ||
|
|
1d603ae76f | ||
|
|
a342b23890 | ||
|
|
c0dde2eaa7 | ||
|
|
6245fe9553 | ||
|
|
fb5be9e2aa | ||
|
|
918620a7dc | ||
|
|
d2855449f0 | ||
|
|
f59326c0ae | ||
|
|
033b9ed035 | ||
|
|
5c299767ec | ||
|
|
818701cd07 | ||
|
|
9b5e63aa25 | ||
|
|
1ad285bd79 | ||
|
|
4507bb179a | ||
|
|
2dd79295a9 | ||
|
|
b21d840e60 | ||
|
|
f3fa40bb0a | ||
|
|
d8e14de0cf | ||
|
|
f7b96eceeb | ||
|
|
6f760939f3 | ||
|
|
5273ad0c5f | ||
|
|
ac12abfb8b | ||
|
|
e5146e7f53 | ||
|
|
62d1210872 | ||
|
|
0d0177cd40 | ||
|
|
227ecf9c9d | ||
|
|
562cd50762 | ||
|
|
ec56d530a6 | ||
|
|
6350714508 | ||
|
|
1b251dad6a | ||
|
|
7765b51a55 | ||
|
|
ff6ba6a8e9 | ||
|
|
ce3485c823 | ||
|
|
90a99d3a79 | ||
|
|
7248dc4fef | ||
|
|
d704db55fa | ||
|
|
0f581e47b1 | ||
|
|
48013f9b3c | ||
|
|
258c8ce989 | ||
|
|
c56a703028 | ||
|
|
4b9ce1b067 | ||
|
|
39b56725dd | ||
|
|
b281b18a4e | ||
|
|
b85487375d | ||
|
|
9ccdc0cf7e | ||
|
|
51b1bcf507 | ||
|
|
0afe598f3c | ||
|
|
4227b0c702 | ||
|
|
2a4e4a4e2e | ||
|
|
a9fa8291de | ||
|
|
007c0abc95 | ||
|
|
f9752b7090 | ||
|
|
b44b91f8cc | ||
|
|
352721540a | ||
|
|
1ab5f49c3b | ||
|
|
976e6e397a | ||
|
|
e95139b79e | ||
|
|
a75f50dcf6 | ||
|
|
87334c586c | ||
|
|
eddec70a99 | ||
|
|
d1d3279c8e | ||
|
|
13ff1dfb18 | ||
|
|
e0d09132dd | ||
|
|
99478e7f33 | ||
|
|
02087c735a | ||
|
|
cd13d588d6 | ||
|
|
6efc23cc15 | ||
|
|
5c28711b26 | ||
|
|
e9ae57aff5 | ||
|
|
92e4b1749e | ||
|
|
854eed74d7 | ||
|
|
7c5ef3aa8a | ||
|
|
78670b5d90 | ||
|
|
f43d54b6f6 | ||
|
|
db0dd75e27 | ||
|
|
d6d1649975 | ||
|
|
f0f0e40897 | ||
|
|
43c1116ac7 | ||
|
|
225f30a257 | ||
|
|
ae03436592 | ||
|
|
8a6014fd02 | ||
|
|
dcc0fafe66 | ||
|
|
bc33679a1f | ||
|
|
d69efe76e5 | ||
|
|
11babe4293 | ||
|
|
2ba7492f24 | ||
|
|
6c65ffb701 | ||
|
|
864e30b3db | ||
|
|
b9124ef873 | ||
|
|
77165a5ffb | ||
|
|
54a519de0b | ||
|
|
462d38373f | ||
|
|
44234422d0 | ||
|
|
c71fcf51c1 | ||
|
|
33cc4b2aad | ||
|
|
6485356c74 | ||
|
|
d0476a93ba | ||
|
|
2eb3548008 | ||
|
|
028a58c2ae | ||
|
|
7675fc11b6 | ||
|
|
7a10a9e8f2 | ||
|
|
8ee869830b | ||
|
|
63ecd7b2a2 | ||
|
|
a125076033 | ||
|
|
12153f5783 | ||
|
|
fdcec16181 | ||
|
|
0c4d653921 | ||
|
|
f488f18a55 | ||
|
|
6164dd8f5f | ||
|
|
270062cfe4 | ||
|
|
014e197a41 | ||
|
|
bed587d6ba | ||
|
|
c15934fdea | ||
|
|
385516f373 | ||
|
|
c50f5e7728 | ||
|
|
494bd7368d | ||
|
|
b6e8f4c1a7 | ||
|
|
392e97df2c | ||
|
|
45dbd8c4b2 | ||
|
|
a0ac7d3324 | ||
|
|
4dd7ce5b98 | ||
|
|
1a96101672 | ||
|
|
88f40ab457 | ||
|
|
70403042d2 | ||
|
|
ff5a9fa3a9 | ||
|
|
5ead664cf9 | ||
|
|
bba2b6f2e8 | ||
|
|
4b25571e1a | ||
|
|
407d0eaeac | ||
|
|
05bb3a5fa9 | ||
|
|
714a72c849 | ||
|
|
9ba8f149f7 | ||
|
|
c9bb38c036 | ||
|
|
3241f1cf41 | ||
|
|
8a7099a6ab | ||
|
|
65c6adcdb2 | ||
|
|
f3f2e69bcf | ||
|
|
335f0a3d6f | ||
|
|
a7e711850c | ||
|
|
6fb2a7ce76 | ||
|
|
56a6e34847 | ||
|
|
cfa4c869ca | ||
|
|
d548fbcb74 | ||
|
|
d40fbced1a | ||
|
|
21c251b40b | ||
|
|
ec3371085b | ||
|
|
3779f38c5d | ||
|
|
5b62fe2be7 | ||
|
|
ea223bbcb4 | ||
|
|
7f4a56149a | ||
|
|
52a620c479 | ||
|
|
593aaf8039 | ||
|
|
cebb6ea626 | ||
|
|
337dc1c4d5 | ||
|
|
e110f942e8 | ||
|
|
6bd5f9dab1 | ||
|
|
09149c559d | ||
|
|
f9a1130e4b | ||
|
|
91304233aa | ||
|
|
99286578c1 | ||
|
|
81888d9aa5 | ||
|
|
f2e4b1b94a | ||
|
|
ab269ad740 | ||
|
|
5a1df75526 | ||
|
|
b74ed1d14e | ||
|
|
d087db38e3 | ||
|
|
ff8c406823 | ||
|
|
7e12a75bea | ||
|
|
aa7fb09399 | ||
|
|
a805b3fe90 | ||
|
|
63d9122440 | ||
|
|
f9293c9c92 | ||
|
|
4892fd5817 | ||
|
|
cf4a8ae98d | ||
|
|
f0edfeeebf | ||
|
|
4d54ad35ff | ||
|
|
b6b512f788 | ||
|
|
a6076eb6ac | ||
|
|
01b74f0a6e | ||
|
|
6c6752c348 | ||
|
|
73873ac193 | ||
|
|
6542dad7bd | ||
|
|
9bf4a2b555 | ||
|
|
66d18a4469 | ||
|
|
7a489067e6 | ||
|
|
600d6de132 | ||
|
|
48e35e7abd | ||
|
|
8613e9d734 | ||
|
|
9ed277d80d | ||
|
|
26345d00a3 | ||
|
|
be70eea0f8 | ||
|
|
01357d9ce4 | ||
|
|
05afafbc45 | ||
|
|
68f7272128 | ||
|
|
caa0ab723a | ||
|
|
ee0d6002c8 | ||
|
|
48f0d04305 | ||
|
|
6516b80bf0 | ||
|
|
b0403ff94b | ||
|
|
77f88edf08 | ||
|
|
be70664c84 | ||
|
|
37ca992233 | ||
|
|
620904de1c | ||
|
|
9c0fac5c44 | ||
|
|
8846c5a9fe | ||
|
|
880d2a8570 | ||
|
|
45b6591518 | ||
|
|
c6ce99d527 | ||
|
|
7a7861fd9c | ||
|
|
3c11630a6c | ||
|
|
3b9f4c9884 | ||
|
|
0757fc4352 | ||
|
|
c1af721ad2 | ||
|
|
0ea04394f9 | ||
|
|
576c178b4f | ||
|
|
674708cea6 | ||
|
|
179b05f992 | ||
|
|
e2c768bb56 | ||
|
|
79e492b230 | ||
|
|
708bc5c302 | ||
|
|
9543cd5b5f | ||
|
|
0bc8313897 | ||
|
|
91986926cb | ||
|
|
ac638add7a | ||
|
|
9551783d49 | ||
|
|
85cf2b3e91 | ||
|
|
f98ccb9e44 | ||
|
|
066d50e492 | ||
|
|
6c823e86fe | ||
|
|
6d3ea577d5 | ||
|
|
2826e39ea2 | ||
|
|
d855f04612 | ||
|
|
99eb93e66f | ||
|
|
e91110d049 | ||
|
|
8e1bb8519c | ||
|
|
61df01ed1c | ||
|
|
c219aa83b1 | ||
|
|
71109b397d | ||
|
|
4fe4c2981d | ||
|
|
2f9f2f722c | ||
|
|
40009d018c | ||
|
|
251480fd4a | ||
|
|
6295145d5b | ||
|
|
17f2e67334 | ||
|
|
fe4130a846 | ||
|
|
141201b7aa | ||
|
|
3b3c511572 | ||
|
|
8c6cf8ee22 | ||
|
|
231fd36ce9 | ||
|
|
fb9dd0a899 | ||
|
|
d98bcdb4e8 | ||
|
|
f94a87e6d5 | ||
|
|
1501d5e71e | ||
|
|
a7d955266d | ||
|
|
9633a6c176 | ||
|
|
9d50090dbd | ||
|
|
8b96a8e654 | ||
|
|
453288bf77 | ||
|
|
26fb0ec2e9 | ||
|
|
2671052cad | ||
|
|
7f1bcd69c8 | ||
|
|
5fe83af514 | ||
|
|
89dc2f09fc | ||
|
|
7ce564409a | ||
|
|
2e34069d14 | ||
|
|
e435501501 | ||
|
|
51402637c6 | ||
|
|
44593f7a75 | ||
|
|
48596efa77 | ||
|
|
3e323df70d | ||
|
|
0d89cef519 | ||
|
|
f758fdf8f3 | ||
|
|
44b9f06087 | ||
|
|
d1155d5e7a | ||
|
|
51ccd029ca | ||
|
|
1df83dac91 | ||
|
|
a3c1d643fd | ||
|
|
4350e311e7 | ||
|
|
89ec9355bd | ||
|
|
f2be7220f3 | ||
|
|
0cbac252a5 | ||
|
|
3ea60971be | ||
|
|
8ea76e2016 | ||
|
|
86d2d732eb | ||
|
|
55ce84a5ae | ||
|
|
0f0e4de682 | ||
|
|
ad60372cf2 | ||
|
|
3cf5fd7cbd | ||
|
|
ce090566cc | ||
|
|
866f645eed | ||
|
|
64f3bebd3d | ||
|
|
239cc461d5 | ||
|
|
b832784977 | ||
|
|
0f37b0be54 | ||
|
|
bb428af3af | ||
|
|
1c4d9704f2 | ||
|
|
53a5eae721 | ||
|
|
049ab257e2 | ||
|
|
0ece5319ea | ||
|
|
b847cc1178 | ||
|
|
422da3e1ba | ||
|
|
868c6baebf | ||
|
|
9a3cf167ed | ||
|
|
cdf47ebab0 | ||
|
|
929d1f945b | ||
|
|
2671242d2c | ||
|
|
78cff8dea8 | ||
|
|
7ac3840831 | ||
|
|
556ee6df01 | ||
|
|
2eca28e497 | ||
|
|
76ff5d49e2 | ||
|
|
2a919aa6b7 | ||
|
|
c83f806e4c | ||
|
|
afbfd38dfd | ||
|
|
6874916ce0 | ||
|
|
143c4fc7e4 | ||
|
|
f85e945a32 | ||
|
|
d0110c9a4f | ||
|
|
4307768bee | ||
|
|
88773e3232 | ||
|
|
8f32772f83 | ||
|
|
17b3c28d91 | ||
|
|
45945d9a13 | ||
|
|
ba9741a084 | ||
|
|
3bcad371d2 | ||
|
|
1e9bf68671 | ||
|
|
f57df6a536 | ||
|
|
793536d2d3 | ||
|
|
9a348da34f | ||
|
|
4819bf63b6 | ||
|
|
5777d49861 | ||
|
|
7540c61fde | ||
|
|
308da4cbac | ||
|
|
615af41de8 | ||
|
|
7c473a4e3f | ||
|
|
79b4f9821b | ||
|
|
80825ee701 | ||
|
|
aa0e60b091 | ||
|
|
718cfb682d | ||
|
|
66f0426e6a | ||
|
|
145671ecdd | ||
|
|
43d71f7e49 | ||
|
|
150de771d5 | ||
|
|
50da728abf | ||
|
|
656ce6ecad | ||
|
|
8a758dffec | ||
|
|
52bd538ed0 | ||
|
|
115c5ac890 | ||
|
|
0f7d15a4d0 | ||
|
|
5b6e07d5d3 | ||
|
|
8579ed322d | ||
|
|
44464b605d | ||
|
|
e8124dd280 | ||
|
|
0105fc2087 | ||
|
|
39e7b26128 | ||
|
|
ddbc13fc27 | ||
|
|
80660fa6cf | ||
|
|
b4a94e8da5 | ||
|
|
051c9a8c85 | ||
|
|
840b1ea4a2 | ||
|
|
ea57695a31 | ||
|
|
90778bc84c | ||
|
|
949216325f | ||
|
|
cdb521de1f | ||
|
|
e50b39c559 | ||
|
|
80afb497e0 | ||
|
|
e83a12aaee | ||
|
|
461860bb17 | ||
|
|
cff4e3e6b0 | ||
|
|
dddf0b35a2 | ||
|
|
35ec2bf215 | ||
|
|
607b60b323 | ||
|
|
bb6ad72962 | ||
|
|
4fb8420d69 | ||
|
|
74af19a9d9 | ||
|
|
737ac70e6e | ||
|
|
bfc72b735c | ||
|
|
323412f935 | ||
|
|
db34ba4995 | ||
|
|
15d7eb6d91 | ||
|
|
e2b95df2e4 | ||
|
|
1117094412 | ||
|
|
4bab076642 | ||
|
|
d602818f67 | ||
|
|
1a76321062 | ||
|
|
4b056529dd | ||
|
|
bdbf3ba5b1 | ||
|
|
aab9a650b0 | ||
|
|
f8487f07a6 | ||
|
|
e38721fa69 | ||
|
|
18e52f2f10 | ||
|
|
f1300410b8 | ||
|
|
e17059f1f7 | ||
|
|
f3e9f7cf06 | ||
|
|
63ed24d136 | ||
|
|
66008cd767 | ||
|
|
1852c1b5c4 | ||
|
|
9a4fc2fc73 | ||
|
|
6846a78833 | ||
|
|
d3d9e85a7f | ||
|
|
f867b6b2ea | ||
|
|
6b38954694 | ||
|
|
9eb350df30 | ||
|
|
639aa5e251 | ||
|
|
f089e26998 | ||
|
|
9070a6aadc | ||
|
|
c68e135c66 | ||
|
|
8693b4fe8f | ||
|
|
9390a402ff | ||
|
|
7fda2c5f88 | ||
|
|
cb394007a4 | ||
|
|
cd92910281 | ||
|
|
7f0b2e2b13 | ||
|
|
bdc44d46c8 | ||
|
|
8d8480469a | ||
|
|
a91fe6db36 | ||
|
|
20d734aa80 | ||
|
|
f053bbd544 | ||
|
|
7eba26cab1 | ||
|
|
5f77dd0adb | ||
|
|
4ef94d3c60 | ||
|
|
36006045e2 | ||
|
|
d5d025c2c9 | ||
|
|
5b7053d500 | ||
|
|
ce2e60c268 | ||
|
|
8e9b575c37 | ||
|
|
beab7d5a4f | ||
|
|
d2f5fc4d69 | ||
|
|
fb9a7f693b | ||
|
|
1d2d636270 | ||
|
|
37ec5ee442 | ||
|
|
5ed67cf5f8 | ||
|
|
76fc47d5bd | ||
|
|
aa856beee1 | ||
|
|
e6f2cc3eda | ||
|
|
02fd45587b | ||
|
|
7cef6eeb61 | ||
|
|
da919bc43b | ||
|
|
2b661d6c5b | ||
|
|
ee0ced63ef | ||
|
|
736dad5819 | ||
|
|
11f36e8a22 | ||
|
|
2cddf0b313 | ||
|
|
36a2d449b7 | ||
|
|
b6786456a2 | ||
|
|
76e8e1af6f | ||
|
|
ff55838a54 | ||
|
|
b14b6828cc | ||
|
|
be7fb67988 | ||
|
|
ae0be45d7d | ||
|
|
ba237d5dc4 | ||
|
|
bdf5cd8751 | ||
|
|
9a6d309840 | ||
|
|
9a6e92a58c | ||
|
|
1bc018918b | ||
|
|
f32f8f5cdd | ||
|
|
39585de3f0 | ||
|
|
9ce81fc68e | ||
|
|
0d56f0da98 | ||
|
|
14a3d8da12 | ||
|
|
e4fa99b865 | ||
|
|
96af2cb573 | ||
|
|
f53ec58b2f | ||
|
|
2ff30dda83 | ||
|
|
c0972f8faf | ||
|
|
9663e1aa7e | ||
|
|
d83a61b30a | ||
|
|
96d83da9b7 | ||
|
|
f1d881e0ba | ||
|
|
d1285c7e04 | ||
|
|
d4476e2d4c | ||
|
|
3124d51381 | ||
|
|
b6ae1a79d4 | ||
|
|
42d7b598bf | ||
|
|
052e828d5a | ||
|
|
55d4f8da6b | ||
|
|
1c5a4bbacc | ||
|
|
565d4bdeec | ||
|
|
3d9ef7d252 | ||
|
|
161bcbb236 | ||
|
|
c8af0ab5bc | ||
|
|
98e9c167c5 | ||
|
|
ed815c5767 | ||
|
|
f6e53ac91f | ||
|
|
3e5df50f9e | ||
|
|
1e28a93c5f | ||
|
|
717bdd3550 | ||
|
|
3bee514bb9 | ||
|
|
678d4b8db7 | ||
|
|
d76e5e7f9b | ||
|
|
9629192305 | ||
|
|
eef7debdba | ||
|
|
138d9f7f46 | ||
|
|
e4abd9ec2f | ||
|
|
8efce72e26 | ||
|
|
15ebca2d11 | ||
|
|
6583489523 | ||
|
|
5610d52813 | ||
|
|
618b61dd60 | ||
|
|
2de58f7a3b | ||
|
|
2bd94158f9 | ||
|
|
4e7ab43ac9 | ||
|
|
33529d0cfd | ||
|
|
a5b929bdf5 | ||
|
|
d10bd3358d | ||
|
|
ffe928fbe8 | ||
|
|
fd61739d96 | ||
|
|
e1602a5655 | ||
|
|
a936302fd2 | ||
|
|
7f0d4df6ca | ||
|
|
35ab0c67c5 | ||
|
|
090633140f | ||
|
|
8efe02c2ef | ||
|
|
2dbcaf029c | ||
|
|
ce758534bd | ||
|
|
15caf70170 | ||
|
|
c07c3a3a4f | ||
|
|
b9000af55e | ||
|
|
ed15ba29bb | ||
|
|
2fb8da022a | ||
|
|
ed65088cb8 | ||
|
|
f367542096 | ||
|
|
00e457542d | ||
|
|
b0c423b2dd | ||
|
|
eb5e3d637c | ||
|
|
4acd24b829 | ||
|
|
f8576834fe | ||
|
|
1e9888a8b5 | ||
|
|
d99b6643e9 | ||
|
|
0b98d98867 | ||
|
|
d040b0faf5 | ||
|
|
d53c20da56 | ||
|
|
fad035699f | ||
|
|
c7ab2b93a3 | ||
|
|
4b75144276 | ||
|
|
99edcf68c1 | ||
|
|
9b6f1ce955 | ||
|
|
b570020944 | ||
|
|
e91ba4ef79 | ||
|
|
a1fbefb13f | ||
|
|
340592d951 | ||
|
|
a1c0bf7dec | ||
|
|
a62f20469e | ||
|
|
3f1f78315b | ||
|
|
12d8bc75cd | ||
|
|
c1cf02ee9f | ||
|
|
7ac240af76 | ||
|
|
82c34a33b5 | ||
|
|
d2330337ef | ||
|
|
af38bd0383 | ||
|
|
c0a9ede377 | ||
|
|
555ba3eb73 | ||
|
|
6f0e757ad6 | ||
|
|
077b8fee96 | ||
|
|
643df47437 | ||
|
|
9e1ea4678d | ||
|
|
f3576b678b | ||
|
|
2b49bce998 | ||
|
|
896048ffff | ||
|
|
04cb14f790 | ||
|
|
bd22b0c08b | ||
|
|
95ce52bbeb | ||
|
|
6b411f5cce | ||
|
|
c15b0d178b | ||
|
|
f5ffb69675 | ||
|
|
24e59d970f | ||
|
|
4ece4b66cd | ||
|
|
7852d244bb | ||
|
|
d1c2487ba4 | ||
|
|
4ea789efcf | ||
|
|
43fc97c671 | ||
|
|
a20378d5cb | ||
|
|
7c0384c96b | ||
|
|
7d4419b300 | ||
|
|
393af9b5c5 | ||
|
|
559e423a1d | ||
|
|
a2d68e14e6 | ||
|
|
580b67d9ed | ||
|
|
080654f703 | ||
|
|
002a002749 | ||
|
|
7e888e46f9 | ||
|
|
199ca94acd | ||
|
|
67455bd47d | ||
|
|
fbb0e252c5 | ||
|
|
2566972ac7 | ||
|
|
9455294060 | ||
|
|
6870b42a1a | ||
|
|
32cd414a51 | ||
|
|
35f63b7075 | ||
|
|
f9097b11b6 | ||
|
|
dc5acdf729 | ||
|
|
e5fb25daee | ||
|
|
33b6867c02 | ||
|
|
d572973b60 | ||
|
|
3d240f0f7d | ||
|
|
3a4973d760 | ||
|
|
811c9716a2 | ||
|
|
771f6db89a | ||
|
|
97f515f573 | ||
|
|
c589dfb281 | ||
|
|
82efe5b4d1 | ||
|
|
765f593b88 | ||
|
|
21e5de25cb | ||
|
|
4333e44f6d | ||
|
|
7070fd886b | ||
|
|
89480a9018 | ||
|
|
19ce873037 | ||
|
|
977007b427 | ||
|
|
218c1c9d9a | ||
|
|
f358ac9d9c | ||
|
|
58fe2b4582 | ||
|
|
211624b1a9 | ||
|
|
6874369a48 | ||
|
|
f8c52d3577 | ||
|
|
376bf5314d | ||
|
|
2346df67a0 | ||
|
|
e63c7b43e1 | ||
|
|
578691fe8c | ||
|
|
189d8a82d5 | ||
|
|
9412d9cc28 | ||
|
|
75b2bfa14c | ||
|
|
7fcb5c8aa3 | ||
|
|
9827711111 | ||
|
|
16aecd65e6 | ||
|
|
c143ecc6ae | ||
|
|
2935f9e205 | ||
|
|
a6a33a79d4 | ||
|
|
82f9d8ddee | ||
|
|
daa6012b36 | ||
|
|
5001c82f23 | ||
|
|
59dbad9abf | ||
|
|
945c7cc7b8 | ||
|
|
3391f7646c | ||
|
|
88070aa2b2 | ||
|
|
c792296746 | ||
|
|
18a13f777d | ||
|
|
469529b324 | ||
|
|
4715a5ab9d | ||
|
|
be305162a6 | ||
|
|
7a1bc16e9d | ||
|
|
eb2c80deb8 | ||
|
|
0863b77bf0 | ||
|
|
769a698509 | ||
|
|
53870b2c81 | ||
|
|
e198a5df88 | ||
|
|
ac947f698b | ||
|
|
ecabd62b6b | ||
|
|
f350d200ac | ||
|
|
97d5a3f7ef | ||
|
|
f15f3efc3f | ||
|
|
7563b6b946 | ||
|
|
421c53e6be | ||
|
|
3db8666951 | ||
|
|
ecc6e01cf9 | ||
|
|
becf81db00 | ||
|
|
92f5b337c9 | ||
|
|
3ddf884c23 | ||
|
|
116117af55 | ||
|
|
0980bcfca5 | ||
|
|
20e2e8ded6 | ||
|
|
13af0b7b2b | ||
|
|
cbcbfdcbf1 | ||
|
|
38eb294667 | ||
|
|
71d16ff906 | ||
|
|
395058d771 | ||
|
|
d8af7c454c | ||
|
|
2f10084e7a | ||
|
|
5af387b32d | ||
|
|
4b7144f705 | ||
|
|
0fbbbb6485 | ||
|
|
f033d78785 | ||
|
|
2ea79eb57d | ||
|
|
226ee0db9d | ||
|
|
8a62f21e84 | ||
|
|
c353c39086 | ||
|
|
2b2c877ab2 | ||
|
|
016af4bfee | ||
|
|
b3d26d91de | ||
|
|
a7a7f409eb | ||
|
|
f44ccec712 | ||
|
|
1c0887733c | ||
|
|
7ee3c35785 | ||
|
|
01b725cf38 | ||
|
|
1ac6d90633 | ||
|
|
9704193237 | ||
|
|
69b150b391 | ||
|
|
7ffb3edda5 | ||
|
|
046eb68ce6 | ||
|
|
816d80a27c | ||
|
|
957037e5f4 | ||
|
|
9ca179a71f | ||
|
|
cb4d96f1ba | ||
|
|
7d57522775 | ||
|
|
902565f1b1 | ||
|
|
2f8de436af | ||
|
|
38bd035d99 | ||
|
|
88b6d1a3ca | ||
|
|
a74878e7bb | ||
|
|
2b6eba7c4d | ||
|
|
0de1b86ef5 | ||
|
|
ae0ab6471b | ||
|
|
c24cdaa8a4 | ||
|
|
df1442dd8a | ||
|
|
b17d5306db | ||
|
|
88d5294b8e | ||
|
|
8c3405d01f | ||
|
|
9f83ba700c | ||
|
|
ae147211ca | ||
|
|
01d305eba0 | ||
|
|
08c30574a9 | ||
|
|
39c4725a2f | ||
|
|
7002aeefaf | ||
|
|
f1201cc5bc | ||
|
|
0b99d4ac52 | ||
|
|
642cb701dd | ||
|
|
66d6aee115 | ||
|
|
38d8eb1108 | ||
|
|
f9941c5dff | ||
|
|
855a6f447a | ||
|
|
fa0a1f8553 | ||
|
|
0d1fee1636 | ||
|
|
ec8269332f | ||
|
|
00fe9400e6 | ||
|
|
8389b1e151 | ||
|
|
2289d10d6c | ||
|
|
b30af4f144 | ||
|
|
041322c53f | ||
|
|
548968bcfc | ||
|
|
6d405b70e7 | ||
|
|
1b4d4acc63 | ||
|
|
6f498089fb | ||
|
|
8e27cba0f6 | ||
|
|
ae48041a96 | ||
|
|
bad16a4cdc | ||
|
|
07baf769dd | ||
|
|
ab409643f6 | ||
|
|
c745a61601 | ||
|
|
c4e8e83d1e | ||
|
|
9133f3d792 | ||
|
|
b779d584a5 | ||
|
|
05bb61b3ab | ||
|
|
5d2885e662 | ||
|
|
ef645c1058 | ||
|
|
52a476fd0a | ||
|
|
7386c45f06 | ||
|
|
1a508ddedf | ||
|
|
a8675f254a | ||
|
|
0f70cd789e | ||
|
|
b8f594f42c | ||
|
|
7857527ce1 | ||
|
|
05c41a5469 | ||
|
|
f11f8afdc4 | ||
|
|
fa499aa46d | ||
|
|
e8a7cc026f | ||
|
|
433ef6a8a7 | ||
|
|
fc4b5a7bcd | ||
|
|
bd43134d58 | ||
|
|
557970ba4e | ||
|
|
d3418e0067 | ||
|
|
b8d1845d4e | ||
|
|
32e360409d | ||
|
|
c54a778af9 | ||
|
|
ce25698f87 | ||
|
|
4d95cc838a | ||
|
|
67fa0a231e | ||
|
|
3c2e8c81c4 | ||
|
|
484d46252b | ||
|
|
a2e3c67298 | ||
|
|
b2ea05d8dd | ||
|
|
1477f47962 | ||
|
|
273ce49c14 | ||
|
|
96b6790646 | ||
|
|
38227ec878 | ||
|
|
11da632972 | ||
|
|
3721b9fe22 | ||
|
|
ecb697e5fb | ||
|
|
c754772280 | ||
|
|
5f2b4ba0b3 | ||
|
|
0ab60becfc | ||
|
|
1dcfb7d6dc | ||
|
|
3c0b44b365 | ||
|
|
ec4aec50ef | ||
|
|
9c86cfe056 | ||
|
|
6bb2337276 | ||
|
|
4702ca255b | ||
|
|
ab47aa36cc | ||
|
|
4bb14c4a4e | ||
|
|
1dd75162f9 | ||
|
|
a2242e3c27 | ||
|
|
26ecf494a9 | ||
|
|
659af5d0b3 | ||
|
|
382a5ee7fc | ||
|
|
7364496844 | ||
|
|
d342316b87 | ||
|
|
b38141da88 | ||
|
|
98f80f7dae | ||
|
|
c134ec6bfe | ||
|
|
4e3f759243 | ||
|
|
a5f2e0157b | ||
|
|
fd21032e51 | ||
|
|
c4f5f9b7d3 | ||
|
|
6baf5a7068 | ||
|
|
d3460174de | ||
|
|
f9f19628ca | ||
|
|
04e48fea5d | ||
|
|
3e99e22fce | ||
|
|
0b244d5ff7 | ||
|
|
703f2ff316 | ||
|
|
34a2bbdbae | ||
|
|
cd8697c1a4 | ||
|
|
ed2dc2dd51 | ||
|
|
2dfdc1b993 | ||
|
|
6f2d7f1194 | ||
|
|
30009ef127 | ||
|
|
051a422331 | ||
|
|
fab6489e9c | ||
|
|
a448614e4a | ||
|
|
84ad874b2a | ||
|
|
19ba978291 | ||
|
|
e304469e55 | ||
|
|
7ce9e2592a | ||
|
|
681b812c7b | ||
|
|
ee1ab6785d | ||
|
|
57704b6622 | ||
|
|
7fe804e0fc | ||
|
|
a71529b641 | ||
|
|
4055173bdb | ||
|
|
3f8841a276 | ||
|
|
15c38851bc | ||
|
|
05030ae817 | ||
|
|
255fa11371 | ||
|
|
a074c0bf74 | ||
|
|
6ccd649fc4 | ||
|
|
21dbea07dd | ||
|
|
4c21d9d127 | ||
|
|
766002b079 | ||
|
|
2ce430ec41 | ||
|
|
cf2b151045 | ||
|
|
92216179df | ||
|
|
a2a95b8591 | ||
|
|
4a22dc111a | ||
|
|
5df7ecc245 | ||
|
|
d4ef520f26 | ||
|
|
e0f8737865 | ||
|
|
37b13a54a7 | ||
|
|
d9d28d31d0 | ||
|
|
66bf5da3f5 | ||
|
|
840c721afc | ||
|
|
859e705a48 | ||
|
|
7375070b21 | ||
|
|
3e2eda6a71 | ||
|
|
798d327dcb | ||
|
|
f5ca9139e6 | ||
|
|
f35e8cfa51 | ||
|
|
0f6953711b | ||
|
|
e2c5e6f9ac | ||
|
|
5ef5d6ddba | ||
|
|
5b19a5d798 | ||
|
|
bf804e8923 | ||
|
|
f47b8b5528 | ||
|
|
c353f6787a | ||
|
|
1b7d5c1a5c | ||
|
|
956456f157 | ||
|
|
49077bd798 |
No files matched your search
@@ -0,0 +1,29 @@
|
||||
name: Backport
|
||||
description: Backport to an older version of MC for modded platforms
|
||||
labels: ["Type: Backport"]
|
||||
body:
|
||||
- type: input
|
||||
attributes:
|
||||
label: Server software and version
|
||||
description: Server software and version to backport to
|
||||
placeholder: Forge 1.5.2
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Other
|
||||
description: Anything else you may want to say
|
||||
placeholder: Lots of servers want this and it's missing
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Checklist
|
||||
description: Let's make sure this request is valid
|
||||
options:
|
||||
- label: This is not a request to update to a new MC version that just came out
|
||||
required: true
|
||||
- label: This version is either not available on Modrinth, or is very outdated
|
||||
required: false
|
||||
@@ -18,6 +18,14 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Plugin list
|
||||
description: Full list of plugins (output of /plugins)
|
||||
placeholder: ...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Support
|
||||
url: https://discord.gg/YPqXt63YQj
|
||||
about: Fresh new community discord providing support with all plugins, including TAB
|
||||
@@ -0,0 +1,20 @@
|
||||
name: Problem
|
||||
description: A problem with the plugin that is not a bug
|
||||
labels: ["Type: Problem"]
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: Describe the problem
|
||||
placeholder: |
|
||||
Describe the problem here. This is not limited to the plugin jar itself. You may report issues with the wiki, plugin description on marketplaces, or anything else related to TAB.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Checklist
|
||||
description: Let's make sure this report is valid
|
||||
options:
|
||||
- label: This is not an error, bug report, compatibility issue or anything of that kind
|
||||
required: true
|
||||
@@ -0,0 +1,14 @@
|
||||
# About
|
||||
This folder contains the plugin's description as advertised on various marketplaces where each one uses a different syntax.
|
||||
(BBCode, Markdown).
|
||||
|
||||
While this is not an accurate folder to have this stored in (`.github`),
|
||||
it is the closest if we don't want to create a folder for this in the root.
|
||||
|
||||
The file structure of this folder is as following:
|
||||
|
||||
| File name | Description |
|
||||
|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| images | Folder containing all images used in the descriptions and wiki for advertising. Used not only as a backup, but for hosting them as well, so we do not need to rely on third party websites. |
|
||||
| description_markdown.md | Plugin description written in **markdown** syntax. Used by **Modrinth**. |
|
||||
| description_bbcode.txt | Plugin description written in **bbcode** syntax. Used by **SpigotMC** and **BuiltByBit**. |
|
||||
@@ -0,0 +1,34 @@
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Section_About.png[/IMG]
|
||||
TAB is an all-in-one plugin for displaying information in various places, which aims to outperform all similar plugins in terms of features, compatibility and performance.
|
||||
The compact configuration allows you to get the plugin to work the way you want regardless of how simple or complex you want it to be or how experienced you are. The default configuration already contains useful values and examples to give you a better understanding and get you started quickly with instant results. The extensive [URL='https://github.com/NEZNAMY/TAB/wiki']wiki[/URL] answers any of your questions.
|
||||
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Badge_Release.svg[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Badge_Minecraft.svg[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Badge_Java.svg[/IMG]
|
||||
[URL='https://github.com/NEZNAMY/TAB'][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Badge_SourceCode.svg[/IMG][/URL]
|
||||
[URL='https://github.com/NEZNAMY/TAB/issues'][IMG]https://img.shields.io/github/issues/neznamy/tab?label=Issues[/IMG][/URL]
|
||||
[URL='https://github.com/NEZNAMY/TAB/wiki'][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Badge_Documentation.svg[/IMG][/URL]
|
||||
[CENTER][B][SIZE=7]Discord?[/SIZE][/B][/CENTER]
|
||||
Official support by me is no longer provided to free users due to limited time and extreme inefficiency (see [URL='https://github.com/NEZNAMY/TAB?tab=readme-ov-file#provided-services']provided services[/URL] for more info).
|
||||
However, you can join this [URL='https://discord.gg/YPqXt63YQj']fresh new community discord[/URL] made by a nice person who promises to help everyone with all plugins, including TAB.
|
||||
|
||||
Before you consider requiring assistance, check out the [URL='https://github.com/NEZNAMY/TAB/wiki']wiki[/URL] first. It will answer any questions you may have and is also constantly getting improved.
|
||||
|
||||
[CENTER][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Section_Features.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_HeaderFooter.png[/IMG][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_NameTags.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_Sorting.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_TablistFormatting.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_PlayerlistObjective.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_Belowname.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_Bossbar.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_GlobalPlayerlist.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_Layout.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_Scoreboard.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_PerWorldPlayerlist.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_API.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_Placeholders.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_PlaceholderOutputReplacements.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_RGB.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_ConditionalPlaceholders.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_HighPerformance.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/refs/heads/master/.github/description/images/Generated_More.png[/IMG][/CENTER]
|
||||
@@ -0,0 +1,38 @@
|
||||

|
||||
TAB is an all-in-one plugin for displaying information in various places, which aims to outperform all similar plugins in terms of features, compatibility and performance.
|
||||
The compact configuration allows you to get the plugin to work the way you want regardless of how simple or complex you want it to be or how experienced you are.
|
||||
The default configuration already contains useful values and examples to give you a better understanding and get you started quickly with instant results.
|
||||
The extensive [wiki](https://github.com/NEZNAMY/TAB/wiki) answers any of your questions.
|
||||
|
||||

|
||||

|
||||

|
||||
[](https://github.com/NEZNAMY/TAB)
|
||||
[](https://github.com/NEZNAMY/TAB/issues)
|
||||
[](https://github.com/NEZNAMY/TAB/wiki)
|
||||
|
||||
# Discord?
|
||||
Official support by me is no longer provided to free users due to limited time and extreme inefficiency (see [provided services]([https://github.com/NEZNAMY/TAB?tab=readme-ov-file#provided-services](https://github.com/NEZNAMY/TAB?tab=readme-ov-file#provided-services)) for more info).
|
||||
However, you can join this [fresh new community discord]([https://discord.gg/YPqXt63YQj](https://discord.gg/YPqXt63YQj)) made by a nice person who promises to help everyone with all plugins, including TAB.
|
||||
|
||||
Before you consider requiring assistance, check out the [wiki](https://github.com/NEZNAMY/TAB/wiki) first. It will answer any questions you may have and is also constantly getting improved.
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="126" height="20" role="img" aria-label="Documentation: Wiki"><title>Documentation: Wiki</title><filter id="blur"><feGaussianBlur stdDeviation="16"/></filter><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="126" height="20" rx="3"/></clipPath><g clip-path="url(#r)"><rect width="93" height="20" fill="#555"/><rect x="93" width="33" height="20" fill="#d8b800"/><rect width="126" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><g transform="scale(.1)"><g aria-hidden="true" fill="#010101"><text x="475" y="150" fill-opacity=".8" filter="url(#blur)" textLength="830">Documentation</text><text x="475" y="150" fill-opacity=".3" textLength="830">Documentation</text></g><text x="475" y="140" textLength="830">Documentation</text></g><g transform="scale(.1)"><g aria-hidden="true" fill="#010101"><text x="1085" y="150" fill-opacity=".8" filter="url(#blur)" textLength="230">Wiki</text><text x="1085" y="150" fill-opacity=".3" textLength="230">Wiki</text></g><text x="1085" y="140" textLength="230">Wiki</text></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="20" role="img" aria-label="Java: 8+"><title>Java: 8+</title><filter id="blur"><feGaussianBlur stdDeviation="16"/></filter><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="60" height="20" rx="3"/></clipPath><g clip-path="url(#r)"><rect width="35" height="20" fill="#555"/><rect x="35" width="25" height="20" fill="#007ec6"/><rect width="60" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><g transform="scale(.1)"><g aria-hidden="true" fill="#010101"><text x="185" y="150" fill-opacity=".8" filter="url(#blur)" textLength="250">Java</text><text x="185" y="150" fill-opacity=".3" textLength="250">Java</text></g><text x="185" y="140" textLength="250">Java</text></g><g transform="scale(.1)"><g aria-hidden="true" fill="#010101"><text x="465" y="150" fill-opacity=".8" filter="url(#blur)" textLength="150">8+</text><text x="465" y="150" fill-opacity=".3" textLength="150">8+</text></g><text x="465" y="140" textLength="150">8+</text></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="92" height="20" role="img" aria-label="Release: 6.2.0"><title>Release: 6.2.0</title><filter id="blur"><feGaussianBlur stdDeviation="16"/></filter><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="92" height="20" rx="3"/></clipPath><g clip-path="url(#r)"><rect width="53" height="20" fill="#555"/><rect x="53" width="39" height="20" fill="#007ec6"/><rect width="92" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><g transform="scale(.1)"><g aria-hidden="true" fill="#010101"><text x="275" y="150" fill-opacity=".8" filter="url(#blur)" textLength="430">Release</text><text x="275" y="150" fill-opacity=".3" textLength="430">Release</text></g><text x="275" y="140" textLength="430">Release</text></g><g transform="scale(.1)"><g aria-hidden="true" fill="#010101"><text x="715" y="150" fill-opacity=".8" filter="url(#blur)" textLength="290">6.2.0</text><text x="715" y="150" fill-opacity=".3" textLength="290">6.2.0</text></g><text x="715" y="140" textLength="290">6.2.0</text></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="124" height="20" role="img" aria-label="GitHub: Source code"><title>GitHub: Source code</title><filter id="blur"><feGaussianBlur stdDeviation="16"/></filter><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="124" height="20" rx="3"/></clipPath><g clip-path="url(#r)"><rect width="47" height="20" fill="#555"/><rect x="47" width="77" height="20" fill="#d8b800"/><rect width="124" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><g transform="scale(.1)"><g aria-hidden="true" fill="#010101"><text x="245" y="150" fill-opacity=".8" filter="url(#blur)" textLength="370">GitHub</text><text x="245" y="150" fill-opacity=".3" textLength="370">GitHub</text></g><text x="245" y="140" textLength="370">GitHub</text></g><g transform="scale(.1)"><g aria-hidden="true" fill="#010101"><text x="845" y="150" fill-opacity=".8" filter="url(#blur)" textLength="670">Source code</text><text x="845" y="150" fill-opacity=".3" textLength="670">Source code</text></g><text x="845" y="140" textLength="670">Source code</text></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 236 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 239 KiB |
|
After Width: | Height: | Size: 36 KiB |
@@ -0,0 +1,285 @@
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
import requests
|
||||
|
||||
line_spacing = 10
|
||||
padding = 10
|
||||
|
||||
class Text:
|
||||
|
||||
def __init__(self, text, color="black", font=ImageFont.truetype("arial.ttf", 20)):
|
||||
self.text = text
|
||||
self.color = color
|
||||
self.font = font
|
||||
|
||||
class ImageGenerator:
|
||||
|
||||
def __init__(self, overlay_text, second_images, output_path, texts):
|
||||
self.overlay_text = overlay_text
|
||||
self.second_images = second_images
|
||||
self.output_path = output_path
|
||||
self.texts = texts
|
||||
|
||||
self.header_template = Image.open("Template_Small.png")
|
||||
self.example_images = [Image.open(path) for path in second_images]
|
||||
|
||||
def calculate_total_height(self):
|
||||
total_text_height = 0
|
||||
for text in self.texts:
|
||||
text_width, text_height = ImageDraw.Draw(self.header_template).textbbox((0, 0), text.text, font=text.font)[2:]
|
||||
total_text_height += text_height + line_spacing
|
||||
|
||||
total_second_images_height = sum([img.height+padding for img in self.example_images])
|
||||
return self.header_template.height + total_second_images_height + total_text_height + (3 * padding)
|
||||
|
||||
def draw_rounded_border(self, final_img, draw, radius, color, width):
|
||||
draw.rounded_rectangle([(0, 0), (final_img.width - 1, final_img.height - 1)], radius=radius, outline=color, width=width)
|
||||
|
||||
def paste_top_image(self, final_img, font):
|
||||
header_with_text = self.header_template.copy()
|
||||
draw = ImageDraw.Draw(header_with_text)
|
||||
|
||||
text_width, text_height = draw.textbbox((0, 0), self.overlay_text, font=font)[2:]
|
||||
text_x = (header_with_text.width - text_width) // 2 # Center text horizontally
|
||||
text_y = 20 # Padding from the top
|
||||
|
||||
draw.text((text_x, text_y), self.overlay_text, fill="white", font=font)
|
||||
|
||||
final_img.paste(header_with_text, (padding, padding))
|
||||
|
||||
def paste_examples(self, final_img):
|
||||
y_offset = self.header_template.height + 2 * padding
|
||||
for img2 in self.example_images:
|
||||
img2_x = (final_img.width - img2.width) // 2 # Center horizontally
|
||||
final_img.paste(img2, (img2_x, y_offset))
|
||||
y_offset += img2.height + padding
|
||||
|
||||
return y_offset
|
||||
|
||||
def paste_text(self, final_draw, y_offset):
|
||||
y_offset += padding # Extra padding before text
|
||||
for text in self.texts:
|
||||
fancy_line = f"• {text.text}" # Add bullet point
|
||||
final_draw.text((padding, y_offset), fancy_line, fill=text.color, font=text.font)
|
||||
y_offset += ImageDraw.Draw(self.header_template).textbbox((0, 0), fancy_line, font=text.font)[3] + line_spacing # Add space between lines
|
||||
|
||||
def save(self, final_img):
|
||||
final_img.save(self.output_path)
|
||||
|
||||
|
||||
def create_image(overlay_text, second_images, output_path, texts):
|
||||
generator = ImageGenerator(overlay_text, second_images, output_path, texts)
|
||||
final_img = Image.new("RGB", (generator.header_template.width + 2 * padding, generator.calculate_total_height()), "white")
|
||||
final_draw = ImageDraw.Draw(final_img)
|
||||
|
||||
# Rounded border
|
||||
generator.draw_rounded_border(final_img, final_draw, 15, (39, 0, 114), 5)
|
||||
|
||||
# Template with text
|
||||
generator.paste_top_image(final_img, ImageFont.truetype("arial.ttf", 60))
|
||||
|
||||
# Examples
|
||||
y_offset = generator.paste_examples(final_img)
|
||||
|
||||
# Text
|
||||
generator.paste_text(final_draw, y_offset)
|
||||
|
||||
# Save
|
||||
generator.save(final_img)
|
||||
|
||||
def download_image(url, save_path):
|
||||
try:
|
||||
response = requests.get(url, stream=True)
|
||||
response.raise_for_status()
|
||||
|
||||
with open(save_path, "wb") as file:
|
||||
for chunk in response.iter_content(1024):
|
||||
file.write(chunk)
|
||||
|
||||
except requests.RequestException as e:
|
||||
print(f"Error downloading image: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
create_image("Header & Footer", ["Example_HeaderFooter.png"], "Generated_HeaderFooter.png",
|
||||
[
|
||||
Text("Per-world / per-server support"),
|
||||
Text("Per-group / per-player support"),
|
||||
Text("Disable if a specified condition is met")
|
||||
]
|
||||
)
|
||||
create_image("NameTags", ["Example_NameTags.png"], "Generated_NameTags.png",
|
||||
[
|
||||
Text("Configurable prefix and suffix"),
|
||||
Text("Per-world / per-server support"),
|
||||
Text("Per-group / per-player support"),
|
||||
Text("Disable if a specified condition is met"),
|
||||
Text("Make nametags completely invisible"),
|
||||
Text("Control collision rule"),
|
||||
Text("Automatic compensation for 1.8.x client sided bug making nametags of invisible players still visible"),
|
||||
Text("Anti-override to prevent other plugins from overriding this one")
|
||||
]
|
||||
)
|
||||
create_image("Sorting", ["Example_Sorting.png"], "Generated_Sorting.png",
|
||||
[
|
||||
Text("Sorting by primary permission group"),
|
||||
Text("Sorting by permission nodes"),
|
||||
Text("Sorting by a numeric placeholder from lowest to highest or highest to lowest"),
|
||||
Text("Alphabetically by a placeholder (A-Z or Z-A)"),
|
||||
Text("Sorting by pre-defined placeholder values"),
|
||||
Text("Combination of multiple sorting types"),
|
||||
Text("Enable / disable case-sensitive sorting")
|
||||
]
|
||||
)
|
||||
create_image("Tablist Formatting", ["Example_TablistFormatting.png"], "Generated_TablistFormatting.png",
|
||||
[
|
||||
Text("Configurable prefix, name and suffix"),
|
||||
Text("Per-world / per-server support"),
|
||||
Text("Per-group / per-player support"),
|
||||
Text("Disable if a specified condition is met"),
|
||||
Text("Anti-override to prevent other plugins from overriding this one")
|
||||
]
|
||||
)
|
||||
create_image("Playerlist Objective",
|
||||
[
|
||||
"Example_PlayerlistObjectiveNumber.png",
|
||||
"Example_PlayerlistObjectiveHealth.png",
|
||||
"Example_PlayerlistObjectiveFancy.png"
|
||||
],
|
||||
"Generated_PlayerlistObjective.png",
|
||||
[
|
||||
Text("Display value of any numeric placeholder or hearts"),
|
||||
Text("Display any text on 1.20.3+"),
|
||||
Text("Disable if a specified condition is met")
|
||||
]
|
||||
)
|
||||
create_image("Belowname", ["Example_BelownameComparison.png"], "Generated_Belowname.png",
|
||||
[
|
||||
Text("Display value of any numeric placeholder (<1.20.3) or any text (1.20.3+)"),
|
||||
Text("Configurable text"),
|
||||
Text("Disable if a specified condition is met")
|
||||
]
|
||||
)
|
||||
create_image("Bossbar", ["Example_BossBar.png"], "Generated_Bossbar.png",
|
||||
[
|
||||
Text("Configurable text, progress, color and style"),
|
||||
Text("Define display condition to see a bossbar"),
|
||||
Text("Announce defined bossbar for specified amount of time"),
|
||||
Text("Configurable toggle command and message"),
|
||||
Text("Option to remember toggle choice between logins")
|
||||
]
|
||||
)
|
||||
create_image("Global Playerlist", [], "Generated_GlobalPlayerlist.png",
|
||||
[
|
||||
Text("Display players from all servers on a proxy network in tablist"),
|
||||
Text("Configurable server groups to share playerlist instead of with all servers"),
|
||||
Text("Ability to create isolated servers"),
|
||||
Text("Servers where people will see everyone"),
|
||||
Text("Compatible with vanish plugins"),
|
||||
Text("Option to display players from other servers as spectators")
|
||||
]
|
||||
)
|
||||
create_image("Layout", ["Example_Layout.png"], "Generated_Layout.png",
|
||||
[
|
||||
Text("Customize all 80 tablist slots"),
|
||||
Text("Create static slots with any text and skin"),
|
||||
Text("Create player groups based on conditions"),
|
||||
Text("Multiple layouts based on conditions")
|
||||
]
|
||||
)
|
||||
create_image("Scoreboard", ["Example_ScoreboardComparison.png"], "Generated_Scoreboard.png",
|
||||
[
|
||||
Text("Display up to 15 lines"),
|
||||
Text("Option to show 0 (or any other static number) in every line instead of 1-15"),
|
||||
Text("Fully configurable text on right side of lines on 1.20.3+"),
|
||||
Text("Displaying different scoreboards based on conditions (output of placeholder, permissions)"),
|
||||
Text("Up to 64 characters per line for <1.13, unlimited for 1.13+ clients"),
|
||||
Text("Customizable toggle command and message"),
|
||||
Text("Option to remember toggle choice between logins"),
|
||||
Text("Automatic detection of scoreboards from other plugins to hide own and show it again once other plugin hides its scoreboard")
|
||||
]
|
||||
)
|
||||
create_image("Per world Playerlist", [], "Generated_PerWorldPlayerlist.png",
|
||||
[
|
||||
Text("Only display players from current world in tablist"),
|
||||
Text("Group worlds which should share players"),
|
||||
Text("Worlds where players see everyone"),
|
||||
Text("Option to see all players in all worlds for players with permission")
|
||||
]
|
||||
)
|
||||
create_image("API", [], "Generated_API.png",
|
||||
[
|
||||
Text("Tablist formatting - Change player prefix/name/suffix"),
|
||||
Text("Header / Footer - Change values"),
|
||||
Text("Teams - Change nametag prefix / suffix, change visibility, collision rule"),
|
||||
Text("Sorting - Change sorting priority"),
|
||||
Text("Scoreboard - Create custom scoreboards, show different scoreboard, toggle scoreboard, announce scoreboard"),
|
||||
Text("Bossbar - Create custom boss bars, toggle bossbar visibility, announce/send bossbar"),
|
||||
Text("Layout - Create custom layouts, send existing layouts"),
|
||||
Text("Placeholders - Create custom placeholders")
|
||||
]
|
||||
)
|
||||
create_image("Placeholders", [], "Generated_Placeholders.png",
|
||||
[
|
||||
Text("Internal placeholders with customizable output"),
|
||||
Text("Create and use custom animations"),
|
||||
Text("All placeholders and animations are supported in all features"),
|
||||
Text("Full PlaceholderAPI support including relational placeholders"),
|
||||
Text("PlaceholderAPI support on BungeeCord / Velocity"),
|
||||
Text("Conditional placeholders")
|
||||
]
|
||||
)
|
||||
create_image("Conditional placeholders", [], "Generated_ConditionalPlaceholders.png",
|
||||
[
|
||||
Text("Conditions based on placeholder output (comparing numeric value, exact output)"),
|
||||
Text("Conditions based on permission node"),
|
||||
Text("Combine conditions with AND or OR"),
|
||||
Text("Configurable output of both cases when condition is and isn't met"),
|
||||
Text("Placeholder support in condition output")
|
||||
]
|
||||
)
|
||||
create_image("Placeholder replacements", [], "Generated_PlaceholderOutputReplacements.png",
|
||||
[
|
||||
Text("Modify output of any placeholder, including PlaceholderAPI placeholders"),
|
||||
Text("Replace exact text with another text"),
|
||||
Text("Change output if it's in a number interval"),
|
||||
Text("Set value if none of the above is met"),
|
||||
Text("Use original placeholder's output in new one"),
|
||||
Text("Support for nested placeholders"),
|
||||
Text("Can be used in other plugins as well")
|
||||
]
|
||||
)
|
||||
create_image("RGB Support", [], "Generated_RGB.png",
|
||||
[
|
||||
Text("5 supported RGB patterns"),
|
||||
Text("3 supported gradient patterns"),
|
||||
Text("Automatically display closest color to legacy clients"),
|
||||
Text("Supported in all features where possible")
|
||||
]
|
||||
)
|
||||
create_image("High Performance", [], "Generated_HighPerformance.png",
|
||||
[
|
||||
Text("Full control of CPU usage by optimizing configuration and disabling unwanted features"),
|
||||
Text("Fully asynchronous - no impact on TPS"),
|
||||
Text("Check plugin's CPU usage using /tab cpu"),
|
||||
Text("Constant improvements to reduce usage"),
|
||||
Text("Handle thousands of players")
|
||||
]
|
||||
)
|
||||
create_image("And more!", [], "Generated_More.png",
|
||||
[
|
||||
Text("RedisBungee support for multiple proxies"),
|
||||
Text("MySQL support to store groups/users"),
|
||||
Text("Potential errors logged into a file instead of spamming the console"),
|
||||
Text("Yaml error assistant for more user-friendly messages and fix suggestions"),
|
||||
Text("Many misconfiguration checks to help solve issues much faster")
|
||||
]
|
||||
)
|
||||
|
||||
release = "6.2.0"
|
||||
download_image(f"https://img.shields.io/badge/Release-{release}-blue.svg", "Badge_Release.svg")
|
||||
|
||||
java = "8+"
|
||||
download_image(f"https://img.shields.io/badge/Java-{java}-blue.svg", "Badge_Java.svg")
|
||||
|
||||
download_image(f"https://img.shields.io/badge/GitHub-Source%20code-yellow.svg", "Badge_SourceCode.svg")
|
||||
|
||||
download_image(f"https://img.shields.io/badge/Documentation-Wiki-yellow.svg", "Badge_Documentation.svg")
|
||||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
@@ -0,0 +1,11 @@
|
||||
# About
|
||||
This is a backup of the wiki in case anything happened to the repository, so the wiki will not get lost forever.
|
||||
The "Clone this wiki locally" option on GitHub wiki does not actually work (the downloaded file is malformed) and cannot be used to import data from the file (?).
|
||||
Since GitHub wiki does not support reading the wiki from source code, every change
|
||||
to the wiki must be copied here as well. The wiki is being updated on an almost daily basis for many reasons, including, but not limited to
|
||||
updating compatibility page (especially when new MC versions come out), adding more examples, improving descriptions, fixing mistakes or
|
||||
adding information that was previously missing. This synchronization will be done periodically once a month.
|
||||
|
||||
# Hyperlinks
|
||||
All hyperlinks used inside the wiki link to other wiki pages using full URLs. As a result, they will all be broken when browsing here.
|
||||
This is expected and will not be resolved.
|
||||
@@ -0,0 +1,46 @@
|
||||
## Getting started
|
||||
* [Why TAB?](https://github.com/NEZNAMY/TAB/wiki/Why-TAB%3F)
|
||||
* [Installation](https://github.com/NEZNAMY/TAB/wiki/Installation)
|
||||
* [Commands & Permissions](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions)
|
||||
* [Frequently Asked Questions](https://github.com/NEZNAMY/TAB/wiki/Frequently-Asked-Questions)
|
||||
* [Compatibility](https://github.com/NEZNAMY/TAB/wiki/Compatibility)
|
||||
* [How to assign players into groups](https://github.com/NEZNAMY/TAB/wiki/How-to-assign-players-into-groups)
|
||||
* [Known issues](https://github.com/NEZNAMY/TAB/wiki/Known-issues)
|
||||
* [TAB-Bridge plugin](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge)
|
||||
|
||||
## Core features
|
||||
* [Belowname](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Belowname)
|
||||
* [Bossbar](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Bossbar)
|
||||
* [Global playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist)
|
||||
* [Header/Footer](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Header-&-Footer)
|
||||
* [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout)
|
||||
* [Multi server support](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Multi-server-support)
|
||||
* [Nametags](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Nametags)
|
||||
* [Per world playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Per-world-playerlist)
|
||||
* [Ping spoof](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Ping-Spoof)
|
||||
* [Playerlist objective](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Playerlist-Objective)
|
||||
* [Scoreboard](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Scoreboard)
|
||||
* [Sorting in tablist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Sorting-players-in-tablist)
|
||||
* [Spectator fix](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Spectator-fix)
|
||||
* [Tablist name formatting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Tablist-name-formatting)
|
||||
|
||||
## Functions
|
||||
* [Animations](https://github.com/NEZNAMY/TAB/wiki/Animations)
|
||||
* [Component usage (RGB, fonts, sprites)](https://github.com/NEZNAMY/TAB/wiki/How-to-use-Minecraft-components)
|
||||
* [Conditional placeholders](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders)
|
||||
* [Error logging](https://github.com/NEZNAMY/TAB/wiki/Error-logging)
|
||||
* [MySQL](https://github.com/NEZNAMY/TAB/wiki/MySQL)
|
||||
* [Placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements)
|
||||
* [Placeholders](https://github.com/NEZNAMY/TAB/wiki/Placeholders)
|
||||
|
||||
## Other
|
||||
* [Additional information](https://github.com/NEZNAMY/TAB/wiki/Additional-information)
|
||||
* [Bedrock compatibility](https://github.com/NEZNAMY/TAB/wiki/Bedrock-compatibility)
|
||||
* [Client-sided mechanics](https://github.com/NEZNAMY/TAB/wiki/Client%E2%80%90sided-mechanics)
|
||||
* [Developer API](https://github.com/NEZNAMY/TAB/wiki/Developer-API)
|
||||
* [How to display name from nickname plugins](https://github.com/NEZNAMY/TAB/wiki/How-to-display-name-from-nickname-plugins)
|
||||
* [How to save config in UTF-8 encoding](https://github.com/NEZNAMY/TAB/wiki/How-to-save-the-config-in-UTF8-encoding)
|
||||
* [How to set up compatibility with glow plugins](https://github.com/NEZNAMY/TAB/wiki/How-to-make-TAB-compatible-with-glow-plugins)
|
||||
* [Mini guides collection](https://github.com/NEZNAMY/TAB/wiki/Mini-guides-collection)
|
||||
* [Optimizing plugin's CPU usage](https://github.com/NEZNAMY/TAB/wiki/Optimizing-the-plugin)
|
||||
* [Quick PlaceholderAPI startup guide](https://github.com/NEZNAMY/TAB/wiki/Quick-PlaceholderAPI-startup-guide)
|
||||
@@ -0,0 +1,105 @@
|
||||
# About
|
||||
This is a collection of random information about the plugin not necessarily limited to a single feature or function.
|
||||
|
||||
# Content
|
||||
* [Vanish detection](#vanish-detection)
|
||||
* [Async player loading](#async-player-loading)
|
||||
* [Scoreboard objective and team naming](#scoreboard-objective-and-team-naming)
|
||||
* [Per-version experience](#per-version-experience)
|
||||
* [Detection](#detection)
|
||||
* [Differences](#differences)
|
||||
* [Debug config option](#debug-config-option)
|
||||
|
||||
# Vanish detection
|
||||
TAB is not a vanish plugin and does not manage vanishing players in any way, therefore, is not responsible for removing vanished players from the tablist.
|
||||
However, it checks vanish status for features to be properly compatible.
|
||||
At the moment, vanishing detection is used for:
|
||||
* `%vanished%` placeholder (used for internal functionality, but can be used to display vanish status if one wants to)
|
||||
* `%online%`, `%serveronline%`, `%worldonline%` and `%staffonline%` will not count vanished players
|
||||
* [Global playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist) makes vanish plugins unable to remove players on other servers from tablist, vanish check will make TAB remove vanished players.
|
||||
* Hide vanished players from [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout).
|
||||
* [Unregister teams of vanished players](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Nametags#additional-note-6---vanish-hook) to players who cannot see them to prevent third party client exploits from seeing vanished players.
|
||||
|
||||
Permission `tab.seevanished` allows players to:
|
||||
* See vanished players in [Global playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist).
|
||||
* See vanished players in [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout).
|
||||
* Not have [teams of vanished players unregistered](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Nametags#additional-note-6---vanish-hook), which would make them not appear sorted properly and have no nametag prefix/suffix.
|
||||
|
||||
For a player to be detected, player has to have `vanished` metadata flag set to `true`.
|
||||
Most, (if not all) vanish plugins do this, including, but not limited to CMI,
|
||||
Essentials, SuperVanish, PremiumVanish and probably more.
|
||||
If TAB is installed on proxy,
|
||||
[Bridge](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge) must be installed on backend servers
|
||||
to forward vanish status to the proxy.
|
||||
|
||||
Additionally, if PremiumVanish is installed and vanish status of a player changes,
|
||||
it is asked if the vanished player can be seen by each player.
|
||||
Players who are marked as being able to see that vanished player by PV do not require `tab.seevaninished` permission.
|
||||
|
||||
# Async player loading
|
||||
To not slow down the server, TAB loads players asynchronously on join.
|
||||
As a casual user, this does not impact you, but there are some cases where you'll feel it:
|
||||
* Players will not be accessible in the [API](https://github.com/NEZNAMY/TAB/wiki/Developer-API) during PlayerJoinEvent
|
||||
* [TAB's PlaceholderAPI expansion](https://github.com/NEZNAMY/TAB/wiki/Placeholders#placeholderapi) will not be accessible during the join process, such as when trying to use it in plugins editing join messages (the exception is `replace_` placeholder, which doesn't directly use any TAB code).
|
||||
|
||||
# Scoreboard objective and team naming
|
||||
There's a well-known BungeeCord bug that kicks players if a duplicate team or objective is registered.
|
||||
This message also shows the name of the objective/team.
|
||||
Before reporting this, make sure it actually comes from TAB.
|
||||
|
||||
TAB's objective and team naming:
|
||||
* Objectives ("Objective ... already exists in this scoreboard")
|
||||
* `TAB-BelowName` for [Belowname](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Belowname)
|
||||
* `TAB-Scoreboard` for [Scoreboard](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Scoreboard)
|
||||
* `TAB-PlayerList` for [Playerlist objective](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Playerlist-Objective)
|
||||
* Teams ("Team ... already exists in this scoreboard")
|
||||
* For sidebar scoreboard: `TAB-Sidebar-x` where `x` is a number from 1 to 15+ (for each line)
|
||||
* For players: This is more complicated to use the 16-character limit to the max and heavily depends on configuration. If you are sorting by player names, part of player name will be there. It also often contains random non-alphanumeric symbols. The most reliable way is the team name (almost) always ending with `A` (or `B`, `C` etc. if you tried to sort several players into the same slot).
|
||||
|
||||
# Per-version experience
|
||||
Minecraft has changed over the years.
|
||||
It had some limits removed, some added, some bugs fixed, but also some bugs added.
|
||||
TAB adapts code based on player's version for the best possible experience on each Minecraft version.
|
||||
|
||||
## Detection
|
||||
When TAB is installed on a proxy, the proxy's API is used to get player's version.
|
||||
When TAB is installed on a backend server, ViaVersion's API is used to get player's version (as it's the only plugin allowing multiple versions, ProtocolSupport is abandoned).
|
||||
|
||||
You can check what version the plugin thinks player has by using any of the following:
|
||||
* `/tab parse <player> %player-version%` - Shows version name, if multiple versions share the same protocol, the newer one is returned
|
||||
* `/tab parse <player> %player-version-id%` - Returns network id of player's version
|
||||
* Set `debug: true` in config and check console messages on player join, it will send a message containing game version ViaVersion API has returned
|
||||
|
||||
Player game version detection may fail. Here are a few possible scenarios why:
|
||||
* ViaVersion is installed on proxy and TAB is on backend servers - There is no ViaVersion to hook into, therefore, there is no suspicion of player not using server's version and not having a way to verify it.
|
||||
* ViaVersion API returns `-1` - This was an issue in the past and hasn't been reported in years now.
|
||||
|
||||
When a player's game version is not detected correctly, player's experience will be very limited, see below.
|
||||
|
||||
## Differences
|
||||
To ensure the best possible experience, TAB is currently checking for player's version to alter its logic in some way.
|
||||
If a player's version is not detected correctly, a side effect might occur instead, making the situation worse.
|
||||
You will not experience all of these, only those that affect the version difference between the server and client.
|
||||
|
||||
| Change of logic | Negative side effect if version is not detected correctly |
|
||||
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Disabling [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) for 1.7 players | [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) entries being sent into the tablist of the player, breaking it as the layout is not designed support 1.7 |
|
||||
| Use alternate way of sorting [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) entries for 1.19.3 - 1.21.1 as the optimal sorting way cannot be used | [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) entries being out of order for 1.19.3 - 1.21.1 <br />Layout entries appearing in chat complete for <1.19.3 even if they don't have to |
|
||||
| Show 1.9+ bossbar on 1.8 servers for 1.9+ players using ViaVersion API | No 1.9+ bossbar for 1.9+ players on 1.8 server |
|
||||
| Disabling [Tablist name formatting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Tablist-name-formatting) for 1.7 and lower due to a 16-character limit total to take advantage of the mechanic where nametags are displayed in tablist, which extends the limit to up to 48 characters (16 prefix, 16 name, 16 suffix) | Trying to fit the entire formatting into 16 characters, resulting in massive cutting and nametag feature not working |
|
||||
| Play around <1.13 limitations of [Scoreboard](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Scoreboard) | Scoreboard lines limited to ~26 characters, even for 1.13+ clients <br />Scoreboard lines limited to 14 characters for < 1.13 clients |
|
||||
| Cutting nametag prefix/suffix to 16 characters for <1.13, but keeping it full for 1.13+ | Nametag prefix/suffix being cut to 16 characters, even for 1.13+ clients |
|
||||
|
||||
# Debug config option
|
||||
You may have noticed `debug: false` in your config.
|
||||
Enabling it will unlock extra console messages beyond the usual misconfiguration / errors.
|
||||
They give deeper information about what's going on in the plugin in case a more complex issue comes up.
|
||||
Currently, it offers the following:
|
||||
* Makes plugin print thrown errors into console as well, instead of just errors.log file. They are printed into the console even if the error log reaches the 16MB limit.
|
||||
* Sends a message saying how long each feature + total it took to process player join/quit or plugin reload. High values may suggest something is not optimized correctly. Originally added for myself when optimizing, but adding/removing it each time would be too much of a hassle, so it remains as a debug message.
|
||||
* Sends a message when plugin detects player name change by a nick plugin. Since lots of things are bound to player names, having players change their name and plugin not detecting it would result in plugin not working correctly them. Therefore, every time a player changes their nickname (or resets it), a message should pop up.
|
||||
* Sends a message whenever another plugin sends a scoreboard (such as a mini-game plugin) and TAB hides its own. Then, when that other plugin removes its scoreboard, TAB sends its own back (and sends a console message).
|
||||
* Sends a message regarding the bedrock client status of players who join in using Floodgate API. This includes a message if floodgate is not enabled correctly (API instance is null), as well as true/false bedrock status of players.
|
||||
* Shows network id of protocol version of players who join when ViaVersion is installed. It should show the version players are actually using. If not, the plugin may not work correctly for those players. This is usually caused by having ViaVersion on proxy and backend.
|
||||
* Sends a message whenever a placeholder takes more than 50 milliseconds to retrieve value. If it only happens once, it may be a random hiccup and can be ignored. In case of consistent problems, this may cause plugin overload.
|
||||
* On proxy installation, shows how long did Bridge take to answer player join plugin message. This should be below 100ms. If it's continuously significantly higher, it suggests something bad is going on, either bridge being overloaded or the server itself.
|
||||
@@ -0,0 +1,61 @@
|
||||
# Content
|
||||
* [Creating an animation](#creating-an-animation)
|
||||
* [Using an animation](#using-an-animation)
|
||||
* [Tips & Tricks](#tips--tricks)
|
||||
* [External tools](#external-tools)
|
||||
* [Additional info](#additional-info)
|
||||
* [Additional note 1 - Frame synchronization](#additional-note-1---frame-synchronization)
|
||||
|
||||
# Creating an animation
|
||||
Animations can be created in **animations.yml** file.
|
||||
To begin, you can copy an already existing animation or directly modify already existing one.
|
||||
Let's take a look at an example:
|
||||
```animations:
|
||||
Welcome: #this is name of the animation
|
||||
change-interval: 400 #this is refresh interval of the animation in milliseconds
|
||||
texts: #the frames of animation
|
||||
- "&7&lW_"
|
||||
- "&7&lW_"
|
||||
- "&7&lWe_"
|
||||
- "&7&lWel_"
|
||||
- "&7&lWelc_"
|
||||
- "&7&lWelco_"
|
||||
- "&7&lWelcom_"
|
||||
- "&7&lWelcome_"
|
||||
- "&7&lWelcome_"
|
||||
- "&7&lWelcome_"
|
||||
- "&7&lWelcome_"
|
||||
- "&7&lWelcom_"
|
||||
- "&7&lWelco_"
|
||||
- "&7&lWelc_"
|
||||
- "&7&lWel_"
|
||||
- "&7&lWe_"
|
||||
- "&7&lW_"
|
||||
- "&7&lW_"
|
||||
```
|
||||
This is an animation called `Welcome` with `change-interval` of `400` milliseconds, which is 2.5 refreshes per second. `Texts` are the actual frames of animation.
|
||||
|
||||
# Using an animation
|
||||
To use an animation, use `%animation:<name>%` format.
|
||||
In the example above it's `%animation:Welcome%`.
|
||||
Animations are supported everywhere.
|
||||
That includes header/footer, prefix/suffix, belowname, playerlist objective, bossbar and more.
|
||||
|
||||
# Tips & Tricks
|
||||
* Animations don't need to be fast. You can use them as a changing text in general.
|
||||
* Animations can also be used as a short alias to a long text. You can do this by creating an animation with one frame.
|
||||
* Adding to the previous point, animations can be used as a way to wrap a placeholder, having two different identifiers return the same value, allowing to use both original and replaced output from [Placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements).
|
||||
|
||||
# External tools
|
||||
If you want an animation too complicated to be done manually, you can check out these websites:
|
||||
* https://www.birdflop.com/resources/animtab/
|
||||
* https://starve-l.github.io/tab-animation.html
|
||||
* https://srnyx.com/gradient
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - Frame synchronization
|
||||
All animations start at the same time, which is time of plugin being (re)loaded.
|
||||
Thanks to this, all animations with the same number of frames and the same change interval will be synchronized.
|
||||
If you want to synchronize multiple animations with a different change interval and different number of frames,
|
||||
you need to make sure `(frame count)*(change interval)` is same for both animations.
|
||||
For example, one animation with 10 frames and 1000ms and second animation with 2 frames and 5000ms.
|
||||
@@ -0,0 +1,34 @@
|
||||
# Content
|
||||
* [Detection](#detection)
|
||||
* [Differences](#differences)
|
||||
* [Issues with `.` in name](#issues-with--in-name)
|
||||
|
||||
# Detection
|
||||
For TAB to properly detect player as a bedrock player, floodgate and TAB must be installed on the same server instance.
|
||||
If TAB is installed on backend and floodgate is on both proxy and backend,
|
||||
make sure [they are connected](https://geysermc.org/wiki/floodgate/setup/?platform=proxy-servers).
|
||||
|
||||
To make sure floodgate is configured correctly, you can do any of the following:
|
||||
* Set `debug: true` in TAB config and check console output on join/reload. It should say `Floodgate returned bedrock status TRUE for player <player>`.
|
||||
* Run `/tab parse <player> %bedrock%`. It should return `true`.
|
||||
* Run `/tab dump <player>`, open the link and see ` bedrockPlayer: '<true|false> (floodgate is installed: <true|false>)'`
|
||||
|
||||
If any of them say `false` for an actual bedrock player, you didn't connect floodgate correctly.
|
||||
|
||||
# Differences
|
||||
It is a job of plugin allowing bedrock clients to connect (probably Geyser) to correctly translate all packets.
|
||||
If you are experiencing an issue on bedrock but not java, it is most likely not an issue in TAB code.
|
||||
|
||||
Currently, TAB does check for bedrock clients for:
|
||||
* Disabling [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) for bedrock players.
|
||||
|
||||
This is the only known change required on the TAB's side.
|
||||
|
||||
# Issues with `.` in name
|
||||
If you configured Geyser to prefix bedrock player names with `.`, it will mess up config loading,
|
||||
because `.` is used to split a section path.
|
||||
This means that using `/tab player <playername containing .> ...` will not work.
|
||||
There are three solutions available:
|
||||
* Use player UUID if commands are executed via another plugin (`/tab player <uuid> ...`).
|
||||
* Use `playeruuid` type, which accepts player name and saves the online player's UUID (`/tab playeruuid <player name> ...`).
|
||||
* Use a different username prefix than `.`.
|
||||
@@ -0,0 +1,22 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Nametag format in tablist](#nametag-format-in-tablist)
|
||||
* [Tablist entry overlap](#tablist-entry-overlap)
|
||||
* [Tablist entry widths](#tablist-entry-widths)
|
||||
|
||||
# About
|
||||
This is a collection of mechanics related to the plugin explaining how does the Minecraft client process information from the server and what you can and what you cannot impact.
|
||||
|
||||
# Nametag format in tablist
|
||||
Tablist names can be formatted in 2 ways. The main one, designed explicitly for tablist names was added into Minecraft in version 1.8 and can be controlled by TAB's [Tablist name formatting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Tablist-name-formatting) feature.
|
||||
If the feature is disabled or not applied properly (disabled with condition, some deeper compatibility issue ...), nametag prefix/suffix will be displayed in tablist instead. This mechanic is also used for <1.8 players due to 16-character tablist name limit there. You can also do this intentionally, for example for better performance.
|
||||
If you don't want any prefixes in tablist, keep the feature enabled but don't set any prefix / suffix. Disabling this feature is only useful to allow other plugins to use the feature or to intentionally display teams in tablist.
|
||||
|
||||
# Tablist entry overlap
|
||||
When having enough online players for 3–4 columns (or using [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout)) and their name formats are too long, they might overlap. This is caused by attempting to display text wider than the monitor can handle.
|
||||
There isn't really any ideal solution for this. Here are a few tips that might help:
|
||||
* Decrease GUI scale in client options to make text smaller
|
||||
* Make tablist entries shorter, such as avoiding using bold text (&l) or using short aliases for ranks instead of their full names (such as `A` instead of `Admin`).
|
||||
|
||||
# Tablist entry widths
|
||||
All tablist entries are rendered with the same width regardless of their content to match width of the longest text. This is done globally, not on a per-column basis. Therefore, one wide entry with make them all render wide, even if the content is empty. This can be a problem when using [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) to force all 80 slots. Just like in the point above, you need to make the longest entry shorter to have the tablist smaller.
|
||||
@@ -0,0 +1,151 @@
|
||||
# About
|
||||
This page lists all the commands and permissions that are available with TAB.
|
||||
Commands have required permissions associated with them.
|
||||
|
||||
**Users who installed TAB on a proxy server:**
|
||||
* Use **/btab** instead of /tab. Permissions are the same.
|
||||
* Permission nodes are checked on the server where the plugin is installed (by default). This means that with TAB on proxy, permission nodes are checked on the proxy, and therefore you'll need a permission plugin there as well. If you wish to take permission groups and checks from backend servers instead, set `use-bukkit-permissions-manager: true` in config.
|
||||
* Giving yourself OP on the backend server does not give you permissions on the proxy. It's a completely different server. You'll need to give yourself permissions using a permission plugin installed on the proxy (unless you enabled the option above).
|
||||
* You are not able to execute proxy commands using a backend plugin (for example some menu plugin). If you want to achieve this, you'll need to find an updated plugin that allows you to send commands to the proxy.
|
||||
|
||||
# Content
|
||||
* [Configuration](#configuration-commands)
|
||||
* [/tab \<player/group/playeruuid\> \<name\> \<property\> \[value\] \[options\]](#tab-playergroupplayeruuid-name-property-value-options)
|
||||
* [/tab \<player/group/playeruuid\> \<name\> remove](#tab-playergroupplayeruuid-name-remove)
|
||||
* [/tab reload](#tab-reload)
|
||||
* [/tab dump \[player\]](#tab-dump-player)
|
||||
* [/tab group \<group\>](#tab-group-group)
|
||||
* [/tab groups](#tab-groups)
|
||||
* [Bossbar](#bossbar)
|
||||
* [/tab bossbar send \<name\> \[player\]](#tab-bossbar-show-name-player)
|
||||
* [/tab bossbar \[on/off/toggle\] \[player\] \[options\]](#tab-bossbar-onofftoggle-player-options)
|
||||
* [/tab bossbar announce \<name\> \<length\>](#tab-bossbar-announce-name-duration)
|
||||
* [Scoreboard](#scoreboard)
|
||||
* [/tab scoreboard show \<name\> \[player\]](#tab-scoreboard-show-name-player)
|
||||
* [/tab scoreboard \[on/off/toggle\] \[player\] \[options\]](#tab-scoreboard-onofftoggle-player-options)
|
||||
* [/tab scoreboard announce \<name\> \<length\>](#tab-scoreboard-announce-name-duration)
|
||||
* [Nametags / Teams](#nametags--teams)
|
||||
* [/tab nametag <show/hide/toggle> \[player\] \[viewer\] \[options\]](#tab-nametag-showhidetoggle-player-viewer-options)
|
||||
* [/tab nametag <showview/hideview/toggleview> \[viewer\] \[options\]](#tab-nametag-showviewhideviewtoggleview-viewer-options)
|
||||
* [/tab setcollision <player> <true/false>](#tab-setcollision-player-truefalse)
|
||||
* [MySQL](#mysql)
|
||||
* [/tab mysql upload](#tab-mysql-upload)
|
||||
* [/tab mysql download](#tab-mysql-download)
|
||||
* [Other](#other)
|
||||
* [/tab cpu](#tab-cpu)
|
||||
* [/tab parse \<player\> \<placeholder\>](#tab-parse-player-text)
|
||||
* [Additional permissions](#additional-permissions)
|
||||
|
||||
# Configuration commands
|
||||
## /tab \<player/group/playeruuid\> \<name\> \<property\> \[value\] \[options\]
|
||||
* **Permission:** `tab.change.<property>`
|
||||
* **Description:** Changes a property of a group/player to the given value. No value argument will result in that property being deleted.
|
||||
|
||||
#### Properties
|
||||
* For tablist: `tabprefix`, `customtabname`, and `tabsuffix`.
|
||||
* For nametag: `tagprefix` and `tagsuffix`.
|
||||
|
||||
#### Options
|
||||
* `-s <server>` - Applying value only for a specific server
|
||||
* `-w <world>` - Applying value only for a specific world
|
||||
|
||||
#### Names for each command type
|
||||
* player: Supports both player name and raw uuid. Player doesn't need to be online.
|
||||
* playeruuid: Requires name of an online player. Equal to using `player` with player's uuid.
|
||||
* group: Using group names from permission plugin. `_DEFAULT_` is used for default settings for all groups.
|
||||
|
||||
## /tab \<player/group/playeruuid\> \<name\> remove
|
||||
* **Permission:** `tab.remove`
|
||||
* **Description:** Removes all direct data from the given player/group.
|
||||
|
||||
#### Notes
|
||||
* The `playeruuid` argument requires the name of an **online player** to remove data from.
|
||||
|
||||
## /tab reload
|
||||
* **Permission:** `tab.reload`
|
||||
* **Description:** Unloads the plugin, loads configuration files including changes and loads the plugin.
|
||||
|
||||
## /tab dump \<player\>
|
||||
* **Permission:** `tab.dump`
|
||||
* **Description:** Creates a very detailed dump about the specified player to help with troubleshooting, uploads it to a paste site and shows the generated URL.
|
||||
|
||||
## /tab group \<group\>
|
||||
* **Permission:** `tab.groupinfo`
|
||||
* **Description:** Shows all settings applied to the specified group, both global and per-world / per-server. Handy when plugin is connected to MySQL, where you have no other way to effectively check group settings.
|
||||
|
||||
## /tab groups
|
||||
* **Permission:** `tab.grouplist`
|
||||
* **Description:** Shows a list of all groups that have anything assigned to them, either globally or per-world / per-server. Handy when plugin is connected to MySQL, where you have no other way to effectively check your groups.
|
||||
|
||||
# Scoreboard
|
||||
## /tab scoreboard show \<name\> \[player\]
|
||||
* **Permission:** `tab.scoreboard.show` for showing to yourself, `tab.scoreboard.show.other` for showing to others.
|
||||
* **Description:** Shows the scoreboard with the given `name`, either to yourself if no `player` was given, or to the given `player`.
|
||||
|
||||
## /tab scoreboard \[on/off/toggle\] \[player\] \[options\]
|
||||
* **Permission:** `tab.scoreboard.toggle` for toggling for yourself, `tab.scoreboard.toggle.other` for toggling for others.
|
||||
* **Description:** Shows / hides / toggles scoreboard of specified player. If no player was given, command affects the sender.
|
||||
* **Options:**
|
||||
* `-s` for silent toggling (no chat message for affected player)
|
||||
|
||||
## /tab scoreboard announce \<name\> \<duration\>
|
||||
* **Permission:** `tab.announce.scoreboard`
|
||||
* **Description:** Shows the scoreboard with the given `name` to every player on the server for the given `duration`, in seconds.
|
||||
|
||||
# Bossbar
|
||||
## /tab bossbar show \<name\> \[player\]
|
||||
* **Permission:** `tab.bossbar.show` for showing to yourself, `tab.bossbar.show.other` for showing to others.
|
||||
* **Description:** Shows the bossbar with the given `name`, either to yourself if no `player` was given, or to the given `player`.
|
||||
|
||||
## /tab bossbar \[on/off/toggle\] \[player\] \[options\]
|
||||
* **Permission:** `tab.bossbar.toggle` for toggling for yourself, `tab.bossbar.toggle.other` for toggling for others.
|
||||
* **Description:** Shows / hides / toggles bossbar of specified player. If no player was given, command affects the sender.
|
||||
* **Options:**
|
||||
* `-s` for silent toggling (no chat message for affected player)
|
||||
|
||||
## /tab bossbar announce \<name\> \<duration\>
|
||||
* **Permission:** `tab.announce.bar`
|
||||
* **Description:** Shows the bossbar with the given `name` to every player on the server for the given `duration`, in seconds.
|
||||
|
||||
# Nametags / Teams
|
||||
## /tab nametag <show/hide/toggle> \[player\] \[viewer\] \[options\]
|
||||
* **Permission:** `tab.nametag.visibility` (`tab.nametag.visibility.other` for toggling for other players)
|
||||
* **Description:** Shows / hides / toggles nametag of a specified player. If viewer is specified, view is only affected for the viewer.
|
||||
* **Options:**
|
||||
* `-s` for silent toggling (no chat message for affected player)
|
||||
|
||||
## /tab nametag <showview/hideview/toggleview> \[viewer\] \[options\]
|
||||
* **Permission:** `tab.nametag.view` (`tab.nametag.view.other` for toggling for other players)
|
||||
* **Description:** Shows / hides / toggles nametag VIEW of a specified player. When hidden, the viewer will not see anyone's nametags.
|
||||
* **Options:**
|
||||
* `-s` for silent toggling (no chat message for affected player)
|
||||
|
||||
## /tab setcollision \<player\> \<true|false\>
|
||||
* **Permission:** `tab.setcollision`
|
||||
* **Description:** Forces collision rule for specified player, overriding configuration.
|
||||
|
||||
# MySQL
|
||||
## /tab mysql upload
|
||||
* **Permission:** `tab.mysql.upload`
|
||||
* **Description:** Uploads all data from users.yml and groups.yml to MySQL. MySQL must be enabled and connected for this command to work.
|
||||
|
||||
## /tab mysql download
|
||||
* **Permission:** `tab.mysql.download`
|
||||
* **Description:** Downloads all data to users.yml and groups.yml from MySQL. MySQL must be enabled and connected for this command to work.
|
||||
|
||||
# Other
|
||||
## /tab cpu
|
||||
* **Permission:** `tab.cpu`
|
||||
* **Description:** Shows approximate CPU usage of the plugin from the last 10 seconds. There are parts that are impossible to be measured, so this shows slightly less than the real value is. The content is self-explanatory. All major ways to decrease CPU usage can be found at [Optimizing the plugin](https://github.com/NEZNAMY/TAB/wiki/Optimizing-the-plugin).
|
||||
|
||||
## /tab parse \<player\> \<text\>
|
||||
* **Permission:** `tab.parse`
|
||||
* **Description:** Replaces all placeholders (both the plugin's internal ones, and those from PlaceholderAPI if it is installed) in the given `text`. It can be used to verify if a placeholder works as expected.
|
||||
|
||||
# Additional permissions
|
||||
* `tab.admin` - Allows the player to execute all commands.
|
||||
* `tab.bypass` - If the per-world player list is enabled as well as this permission, it allows the player to see everyone on the server, regardless of what the per-world player list settings allow. For example, if your per-world player list is set up to isolate worlds A and B, players with this permission will see all players from both A and B on their player list, whereas players that don't have the permission will only see either players from world A or players from world B, depending on what world they are in.
|
||||
* `tab.staff` - Allows the player to be counted in the `%staffonline%` placeholder.
|
||||
* `tab.spectatorbypass` - If enabling bypass permission in [Spectator fix](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Spectator-fix), this is the permission.
|
||||
* `tab.tabcomplete` - Allows the player to auto-complete the `/tab` command.
|
||||
* `tab.seevanished` - Allows the player to see other vanished players on the [Global Playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist) and [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout).
|
||||
@@ -0,0 +1,110 @@
|
||||
# Content
|
||||
* [Requirements](#requirements)
|
||||
* [Java](#java)
|
||||
* [Supported server software and versions](#supported-server-software-and-versions)
|
||||
* [Supported features per platform](#supported-features-per-platform)
|
||||
* [Plugin / mod hooks](#plugin--mod-hooks)
|
||||
* [Compatibility issues](#compatibility-issues)
|
||||
|
||||
# Requirements
|
||||
TAB does not depend on any other plugins. The experience can however be enhanced by installing other plugins, see below. There is also no additional Java version requirement. If your server runs on your Java version, TAB will too.
|
||||
|
||||
# Supported server software and versions
|
||||
With the introduction of new Minecraft versions, it is becoming harder and harder to support many versions in the same jar, eventually making it impossible since Minecraft 26.1.
|
||||
**As a general rule, if you want the latest TAB version for your server, please use [Modrinth](https://modrinth.com/plugin/tab-was-taken)'s download filter, where you can select your server software and version and you'll get the latest jar.**
|
||||
|
||||
Currently, the latest Minecraft version supported by TAB is **26.3**. When new versions come out, TAB is always updated soon after to support them.
|
||||
|
||||
If your server software and version is reasonably popular and TAB hasn't been backported to that version in a very long time, you may [request a backport](https://github.com/NEZNAMY/TAB/issues/new/choose) (unless backports to that version are no longer offered, see below).
|
||||
Since TAB 6.0.0, Minecraft 1.x started taking hits with each subsequent TAB versions - Bukkit versions started disappearing and **modded platforms no longer offer backports of TAB 6.0.0+ to MC 1.x** (this is because the build scripts had to be massively changed for MC 26+).
|
||||
|
||||
The sections below provide **additional** information for each platform.
|
||||
|
||||
## Bukkit
|
||||
Since TAB 6.0.0, support for unused 1.x versions started disappearing and will continue to disappear with each subsequent Minecraft release.
|
||||
Currently, the latest release supports the following versions:
|
||||
* 1.7.10
|
||||
* 1.8.8
|
||||
* 1.12.2
|
||||
* 1.16.5
|
||||
* 1.17.1
|
||||
* 1.18.2
|
||||
* 1.19.4 - 26.3
|
||||
|
||||
If you want a jar with support for a 1.x version that is no longer supported, you can use TAB v5.5.0, which supports all MC 1.x versions. For 1.5.2 - 1.6.4, use TAB v5.2.5.
|
||||
|
||||
## BungeeCord / Velocity
|
||||
For proxies, the plugin is made to work with the latest build.
|
||||
Since breaking changes don't happen too often, it means a wide range of versions is usually supported.
|
||||
When a breaking change occurs, the plugin is updated to support the new version,
|
||||
automatically making old versions incompatible.
|
||||
Since proxies support all client versions, there is never a reason to stay outdated,
|
||||
so you can always safely update to a new build of your proxy software if the plugin requires it.
|
||||
|
||||
## Fabric
|
||||
Every TAB update only supports the latest Fabric version(s) at the time of release.
|
||||
|
||||
Minecraft 1.x - TAB 5.5.0 was backported to 1.20 - 1.21.11 and the jars were uploaded to Modrinth. TAB 5.0.7 supports all Fabric versions from 1.14 to 1.19.4. Backports to 1.x are no longer offered.
|
||||
|
||||
## Forge
|
||||
Every TAB update only supports the latest Forge version(s) at the time of release.
|
||||
|
||||
Minecraft 1.x - TAB 5.5.0 was backported to 1.20 - 1.21.11 and the jars were uploaded to Modrinth, along with a few other random versions people requested. If your version is not available, you may request a backport.
|
||||
|
||||
## NeoForge
|
||||
Every TAB update only supports the latest NeoForge version(s) at the time of release.
|
||||
|
||||
Minecraft 1.x - TAB 5.5.0 was backported to all existing NeoForge versions (1.20.2+) and the jars were uploaded to Modrinth. Backports to 1.x are no longer offered.
|
||||
|
||||
## Sponge
|
||||
This platform is no longer supported as no one is using it and it has breaking changes to the API with each Minecraft version. Sponge is supposed to be combined with Forge or NeoForge, both of which TAB supports. You can use Modrinth's download filter to see what is available.
|
||||
|
||||
# Supported features per platform
|
||||
| Feature <sup>Platform</sup> | Bukkit / Hybrid | Fabric / Forge / NeoForge | BungeeCord | Velocity |
|
||||
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------|---------------------------|------------|----------------------------------------------------------------------------|
|
||||
| [Belowname](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Belowname) | ✔ | ✔ | ✔ | ✔ (via [VSAPI](https://github.com/NEZNAMY/VelocityScoreboardAPI/releases)) |
|
||||
| [BossBar](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Bossbar) | ✔ | ✔ | ✔ | ✔ |
|
||||
| [Global Playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist) | ✔ | ✔ | ✔ | ✔ |
|
||||
| [Header/Footer](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Header-&-Footer) | ✔ | ✔ | ✔ | ✔ |
|
||||
| [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) | ✔ | ✔ | ✔ | ✔ |
|
||||
| [Nametags](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Nametags) & [Sorting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Sorting-players-in-tablist) | ✔ | ✔ | ✔ | ✔ (via [VSAPI](https://github.com/NEZNAMY/VelocityScoreboardAPI/releases)) |
|
||||
| [Per world playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Per-world-playerlist) | ✔ | ❌ | ❌ | ❌ |
|
||||
| [Playerlist objective](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Playerlist-Objective) | ✔ | ✔ | ✔ | ✔ (via [VSAPI](https://github.com/NEZNAMY/VelocityScoreboardAPI/releases)) |
|
||||
| [Scoreboard](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Scoreboard) | ✔ | ✔ | ✔ | ✔ (via [VSAPI](https://github.com/NEZNAMY/VelocityScoreboardAPI/releases)) |
|
||||
| [Spectator fix](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Spectator-fix) | ✔ | ✔ | ✔ | ✔ |
|
||||
| [Tablist names](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Tablist-name-formatting) | ✔ | ✔ | ✔ | ✔ |
|
||||
|
||||
✔ = Fully functional
|
||||
❌ = Completely missing
|
||||
|
||||
# Plugin / mod hooks
|
||||
To enhance user experience, TAB hooks into other plugins / mods for better experience.
|
||||
This set of plugins / mods is different for each platform based on their availability.
|
||||
Some are available on all platforms, some only in a few.
|
||||
|
||||
| Platform | Plugins / mods |
|
||||
|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| All platforms | [**Floodgate**](https://github.com/GeyserMC/Floodgate) - For properly detecting bedrock players to adapt features for the best possible user experience. <br /> [**LuckPerms**](https://github.com/LuckPerms/LuckPerms) - Detecting permission groups of players for per-group settings. <br /> [**ViaVersion**](https://github.com/ViaVersion/ViaVersion) - For properly detecting player's version to adapt features for the best possible user experience. |
|
||||
| Bukkit | [**LibsDisguises**](https://github.com/libraryaddict/LibsDisguises) - Detecting disguised players to disable collision to avoid endless push by colliding with own copy created by LibsDisguises. <br />[**PlaceholderAPI**](https://github.com/PlaceholderAPI/PlaceholderAPI) - Allows users to use its placeholders inside TAB. <br />[**PremiumVanish**](https://www.spigotmc.org/resources/14404) - Supporting PremiumVanish's vanishing levels instead of using a basic compatibility system. <br />[**Vault**](https://github.com/milkbowl/Vault) - Detecting permission groups of players for per-group settings. |
|
||||
| BungeeCord | [**PremiumVanish**](https://www.spigotmc.org/resources/14404) - Supporting PremiumVanish's vanishing levels instead of using a basic compatibility system. <br />[**RedisBungee**](https://github.com/ProxioDev/RedisBungee) - Communicating with other proxies to properly display visuals on players on another proxy. |
|
||||
| Fabric | [**fabric-permissions-api**](https://github.com/lucko/fabric-permissions-api) - Supporting permission nodes instead of OP levels. <br />[**placeholder-api**](https://modrinth.com/mod/placeholder-api) - Displaying placeholders from that mod and offering TAB's placeholders into it. |
|
||||
| Forge | [**LuckPerms**](https://github.com/LuckPerms/LuckPerms) - Permission checks with a string instead of using vanilla OP levels. <br /> [**ForgePlaceholderAPI**](https://github.com/EnvyWare/ForgePlaceholderAPI) - Allows users to use its placeholders inside TAB. <br /> [**Vanishmod**](https://modrinth.com/mod/vanishmod) - Getting player's vanish status. |
|
||||
| NeoForge | [**LuckPerms**](https://github.com/LuckPerms/LuckPerms) - Permission checks with a string instead of using vanilla OP levels. |
|
||||
| Velocity | [**PremiumVanish**](https://www.spigotmc.org/resources/14404) - Supporting PremiumVanish's vanishing levels instead of using a basic compatibility system. <br />[**RedisBungee**](https://github.com/ProxioDev/RedisBungee) - Communicating with other proxies to properly display visuals on players on another proxy. <br />[**VelocityScoreboardAPI**](https://github.com/NEZNAMY/VelocityScoreboardAPI) - Sending scoreboard packets (scoreboard-teams, belowname-objective, playerlist-objective, scoreboard) |
|
||||
|
||||
# Compatibility issues
|
||||
* **Glow plugins** will fail to apply glow color correctly. Check [How to make the plugin compatible with glow plugins](https://github.com/NEZNAMY/TAB/wiki/How-to-make-TAB-compatible-with-glow-plugins) for more information.
|
||||
* Some Skript addons may cause features to not work properly, such as sorting and scoreboard.
|
||||
* **Waterfall**'s `disable_tab_list_rewrite: true` **may** cause tablist to use offline UUIDs while TAB expects online UUIDs, causing various problems (most notably tablist formatting not working). Checking for this option is not an option either, because tablist rewrite might still be enabled despite being disabled (don't ask how, I have no idea). Set the option to `false` if you are experiencing issues.
|
||||
* **ViaVersion on proxy and TAB on backend** acts like a client-sided protocol hack, making it impossible for TAB to know player's real version and causing issues related to it, see [Per-version experience](https://github.com/NEZNAMY/TAB/wiki/Additional-information#per-version-experience) for more info. Avoid this combination. Either install ViaVersion on all backend servers instead or install TAB on the proxy as well.
|
||||
* **Nexo**'s `hide_scoreboard_numbers` config option (may apply to ItemsAdder and Oraxen as well) makes [Belowname](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Belowname)'s and [Playerlist objective](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Playerlist-Objective)'s `value` and `fancy-value` not visible. When using these features, you'll need to keep the option disabled.
|
||||
* **Custom clients / resource packs** - Unofficially modified Minecraft clients often tend to break things. Just Lunar client has tons of bugs that can be reproduced with TAB. Resource packs may also contain modifications you are not aware of, making things not look the way you want them to. If you are experiencing any visual issue and are using a custom client or resource pack, try it with a clean vanilla client. If it works there, it's an issue with the client / resource pack and TAB cannot do anything about it.
|
||||
For example, here are a few bugs in LunarClient / FeatherClient that you may run into when using TAB:
|
||||
* They add their icon to players in tablist, but don't widen the entries. This results in player names overlapping with latency bar. You can avoid this by configuring some spaces in tabsuffix.
|
||||
* They don't support color field in chat components, which means they don't support RGB codes and will display bossbar without colors as well.
|
||||
* Rendering belowname 3 times.
|
||||
* They don't respect nametag visibility rule, showing their own nametag using F5 even if set to invisible by the plugin.
|
||||
* When the scoreboard is set to use all 0s, lines are rendered in opposite order on 1.20.3+.
|
||||
* They don't display 1.20.3+ NumberFormat feature in scoreboard objectives.
|
||||
* **XCord** - Has additional amazing optimizations that prevent TAB from being able to read outgoing packets and modify them if needed, resulting in some features not working properly, such as [tablist name formatting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Tablist-name-formatting).
|
||||
* **Random Spigot/BungeeCord forks** - All safe patches for improving security & performance are present in well-known public open-source projects, such as Paper, Purpur or Waterfall. Using a random overpriced closed-source (and probably obfuscated) fork from BuiltByBit may not be safe, since they likely include unsafe patches that may break compatibility with plugins in an attempt to fix things that are not broken. Before spending your entire budget on such a fork, reconsider it first. Paper (and its forks) is a performance-oriented fork used by 2/3 of all MC servers worldwide, while the rest is still stuck on Spigot. It is highly unlikely your needs are so specific you need every single "improvement" anyone can come up with. If you need a feature, Purpur is a feature-oriented fork. Together with plugins you should achieve what you are looking for.
|
||||
@@ -0,0 +1,110 @@
|
||||
# Page content
|
||||
* [About](#about)
|
||||
* [Adding the dependency](#adding-the-dependency)
|
||||
* [Getting started](#getting-started)
|
||||
* [Lifespan of API calls](#lifespan-of-api-calls)
|
||||
* [Events](#Events)
|
||||
|
||||
# External Content
|
||||
* [BossBar](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Bossbar#api)
|
||||
* [Header/Footer](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Header-&-Footer#api)
|
||||
* [Nametags](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Nametags#api)
|
||||
* [Scoreboard](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Scoreboard#api)
|
||||
* [Sorting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Sorting-players-in-tablist#api)
|
||||
* [Tablist name formatting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Tablist-name-formatting#api)
|
||||
* [Placeholders](https://github.com/NEZNAMY/TAB/wiki/Placeholders#api)
|
||||
|
||||
# About
|
||||
This page explains how to import TAB's API into your project and together with other pages everything you can do with it.
|
||||
|
||||
Before starting, please seriously reconsider if you really need this and cannot already achieve it using existing features (such as registering placeholders into PlaceholderAPI instead of TAB, using display conditions for scoreboards, ...). If not, consider making a request.
|
||||
|
||||
# Adding the dependency
|
||||
|
||||
For Maven users, you can add the API dependency like this:
|
||||
|
||||
```xml
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.NEZNAMY</groupId>
|
||||
<artifactId>TAB-API</artifactId>
|
||||
<version>6.1.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
|
||||
Or, for Gradle users, here are a few examples:
|
||||
|
||||
Groovy:
|
||||
```groovy
|
||||
repositories {
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'com.github.NEZNAMY:TAB-API:6.1.2'
|
||||
}
|
||||
```
|
||||
|
||||
Kotlin:
|
||||
```kotlin
|
||||
repositories {
|
||||
maven("https://jitpack.io")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("com.github.NEZNAMY", "TAB-API", "6.1.2")
|
||||
}
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> DO NOT SHADE THE API IN TO YOUR JAR! DO NOT RELOCATE THE API FROM ITS ORIGINAL PACKAGE!**
|
||||
> If you relocate, the API that you are calling will also get relocated in your code, meaning that you will be trying to call the relocated API. If you shade the API in, your code could load that bundled API, causing class path conflicts.
|
||||
Ensure that you are using **`<scope>provided</scope>` for Maven**, or **`compileOnly` for Gradle**.
|
||||
|
||||
> [!WARNING]
|
||||
> If you are on Paper and your plugin is defined as a paper plugin (paper-plugin.yml), TAB's classes may not be visible to the class loader that loaded your plugin. To avoid this issue, do not use paper-plugin.yml in your plugin, just plugin.yml.
|
||||
|
||||
# Getting started
|
||||
First, you need to get an instance of the API.
|
||||
You can do this with `TabAPI.getInstance()`.
|
||||
The `TabAPI` class that you want to import is located in the `me.neznamy.tab.api` package.
|
||||
If you do not see this imported,
|
||||
or it is imported but the package is not `me.neznamy.tab.api`, then you have the **wrong class**.
|
||||
|
||||
Now you have the instance, you can get a `TabPlayer` with the methods `getPlayer(UUID)` and `getPlayer(String)`, to get players by UUID and name respectively.
|
||||
If no player was found with the UUID or the name that you gave, these methods will return `null`. It is important that you catch this, to avoid running in to a `NullPointerException`. You should **NOT** assume that just because a player has logged in that TAB will already have a player for them, as players are processed asynchronously. This will be especially true for join events like `PlayerJoinEvent`.
|
||||
|
||||
If you want to be 100% sure that the player you want is loaded when you want to process them, use `PlayerLoadEvent`.
|
||||
This will give you the `TabPlayer` that has been loaded, so that you can process that `TabPlayer`.
|
||||
See below for more details on how to use the event.
|
||||
|
||||
# Lifespan of API calls
|
||||
All API calls result in temporary changes to the plugin's logic.
|
||||
When the plugin is reloaded or server restarted, all previous API calls will lose effect.
|
||||
This also applies for players after they reconnect—they are reset back.
|
||||
If you want to perform long-term changes to player's prefix or suffix,
|
||||
call TAB's [commands](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions) from your plugin.
|
||||
If you want to re-apply your changes on plugin reload, listen to [events](#events) using plugin's own event system,
|
||||
specifically `TabLoadEvent`, which is called on plugin reload.
|
||||
|
||||
# Events
|
||||
TAB is using a custom platform-independent event API. As such, the same event listener code will work on all supported platforms. Usage is also different, let's take a look at an example:
|
||||
```
|
||||
TabAPI.getInstance().getEventBus().register(PlayerLoadEvent.class, event -> {
|
||||
TabPlayer tabPlayer = event.getPlayer();
|
||||
//do something
|
||||
});
|
||||
```
|
||||
TAB plugin provides the following events:
|
||||
* `TabLoadEvent` - Called when the plugin has finished its load, either on startup or plugin reload.
|
||||
* `PlayerLoadEvent` - Called when the plugin has finished loading a player (either join or plugin reload).
|
||||
* `PlaceholderRegisterEvent` - Called when the plugin is about to register a parser for used PlaceholderAPI placeholder, allowing to override it.
|
||||
@@ -0,0 +1,52 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [errors.log](#errorslog)
|
||||
* [placeholder-errors.log](#placeholder-errorslog)
|
||||
* [anti-override.log](#anti-overridelog)
|
||||
|
||||
# About
|
||||
TAB logs various events in multiple files to keep the console clean.
|
||||
All of these notifications are negative, so they should be looked at.
|
||||
|
||||
Files are only created when something is about to get logged.
|
||||
This means if you have none of these files in your folder, everything is good.
|
||||
It is safe to delete the logs any time while the server is running without needing to reload the plugin or anything.
|
||||
|
||||
All files have their sizes limited to 16 MB to avoid giant files consisting of the same error repeating over and over.
|
||||
Remember these files are **logs**; therefore, after solving the problems you must delete them.
|
||||
These files will not delete themselves.
|
||||
After deleting a file, there is no need to perform any other action.
|
||||
Every time an error is about to be logged, the file is created if it doesn't exist.
|
||||
|
||||
Java errors usually contain stack traces.
|
||||
If you got an error spamming with an error message but no stack trace,
|
||||
the most common cause is java not including it because too many errors were thrown already.
|
||||
To bypass this check, add `-XX:-OmitStackTraceInFastThrow` to your startup parameters.
|
||||
|
||||
# errors.log
|
||||
No one likes having their console spammed with errors.
|
||||
Fixing errors is the most reliable solution, however, that takes time,
|
||||
and you usually don't get an update fixing an error the second you report it.
|
||||
Because of that, all plugin errors are moved to this file instead.
|
||||
|
||||
# placeholder-errors.log
|
||||
This file is used
|
||||
to track errors thrown by PlaceholderAPI expansions when trying to retrieve the value of a placeholder.
|
||||
These should be reported to the expansion author.
|
||||
First line(s) of error should give you a good idea which expansion it is,
|
||||
as well as the actual placeholder which threw the error
|
||||
(displayed on top of the error).
|
||||
|
||||
# anti-override.log
|
||||
This file logs all attempts of other plugins to override TAB's visuals.
|
||||
This is checking for features that only a single plugin can be displaying info in at once
|
||||
(such as nametag prefix/suffix, tablist prefix/suffix).
|
||||
This means that (at least) one of your plugins is not configured correctly,
|
||||
and you didn't disable functions you don't want.
|
||||
If you want TAB to use a feature, disable it in other plugins.
|
||||
If you want a different plugin to display it, disable it in TAB (disabled features do not log this).
|
||||
|
||||
It is unfortunately not possible to easily figure out which plugin is causing it, you can only guess from the message.
|
||||
|
||||
Although this is technically unnecessary since TAB automatically blocks other plugins from overriding it,
|
||||
it's good to have your plugins configured properly.
|
||||
@@ -0,0 +1,265 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* ~Commands~
|
||||
* ~Placeholders~
|
||||
* [Limitations](#limitations)
|
||||
* [Compatibility with other plugins](#compatibility-with-other-plugins)
|
||||
* [Additional info](#additional-info)
|
||||
* [Additional note 1 - Copying nametag visibility rule](#additional-note-1---copying-nametag-visibility-rule)
|
||||
* [Additional note 2 - [1.8.x] Hidden on sneak](#additional-note-2---18x-hidden-on-sneak)
|
||||
* [Additional note 3 - [26.1.2-] Visible on NPCs](#additional-note-3---2612--visible-on-npcs)
|
||||
* [[26.1.x] Visible on all entities](#261x-visible-on-all-entities)
|
||||
* [Additional note 4 - Compatibility with modified clients](#additional-note-4---compatibility-with-modified-clients)
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
* ~API~
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Per-world values](#example-1---per-world-values)
|
||||
* [Example 2 - Hiding `title` for 1.20.3+ players](#example-2---hiding-title-for-1203-players)
|
||||
* [Example 3 - Displaying health as 0-10 or in %](#example-3---displaying-health-as-0-10-or-in-)
|
||||
* [Example 4 - Health bar using hearts](#example-4---health-bar-using-hearts)
|
||||
* [Example 5 - Conditionally hiding belowname for 26.2+ viewers](#example-5---conditionally-hiding-belowname-for-262-viewers)
|
||||
* [Tips & Tricks](#tips--tricks)
|
||||
* [Tip 1 - Heart symbol](#tip-1---heart-symbol)
|
||||
|
||||
# About
|
||||
This features gives you control over Minecraft's scoreboard objective feature with BELOW_NAME slot.
|
||||
On Minecraft 1.21.11 and below, it is visible on all player entities (including NPCs). On 26.1.x, it is visible on all player entities and all named entities (such as holograms), making this feature unusable. On 26.2 and above, it only appears on entities with a score assigned (the ideal implementation).
|
||||
It is only visible when the target player is within a 10-block range of the viewer (the value is configurable since Minecraft 26.1).
|
||||
|
||||
Example visual effect:
|
||||

|
||||
|
||||
The displayed line is not one continuous configurable text. It consists of 2 parts (score and title) joined with a space.
|
||||
The exact format is `[score]` + space + `title` (no, the space cannot be removed), where `[score]` is:
|
||||
* `value` for 1.20.2- (will show `0` on NPCs), which only supports numbers (integers)
|
||||
* `fancy-value` for 1.20.3+ (will show `fancy-value-default` on NPCs), which supports any text
|
||||
|
||||
As you can see, the feature still has limits, even on 1.20.3+. If you are below this version or still don't like the forced space before title, you are out of luck and cannot use this feature the way you would like to. If you have seen this feature seemingly limitless, it could be a feature that was a part of TAB, but removed later. This feature hid the original nametag and placed invisible armor stands instead. If you are interested in this kind of solution, you'll need to look into other plugins.
|
||||
|
||||
# Configuration
|
||||
The feature can be configured in **config.yml** under **belowname-objective** section.
|
||||
This is how the default configuration looks:
|
||||
```
|
||||
belowname-objective:
|
||||
enabled: false
|
||||
value: "%health%"
|
||||
title: "&cHealth"
|
||||
fancy-value: "&c%health%"
|
||||
fancy-value-default: "NPC"
|
||||
disable-condition: '%world%=disabledworld'
|
||||
```
|
||||
All the options are explained in the following table.
|
||||
|
||||
| Option name | Default value | Description |
|
||||
|---------------------|-----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | true | Enables / Disables the feature |
|
||||
| value | %health% | [1.20.2-] An integer from -2147483648 to 2147483647, doesn't support decimal values. The number is always white. Supports placeholders with player-specific output, such as player health. Only visible on 1.20.2 and lower. <br/> **Note**: Even if you only support 1.20.3+, you still need to configure this value to properly evaluate to a number, because the value is still sent to the client (just not displayed). You can set it to `0` for simplicity. |
|
||||
| fancy-value | &c%health% | [1.20.3+] Any text, supports placeholders with per-player output. Only visible on 1.20.3+, where it completely replaces `value`. When evaluates to an empty string, the entire belowname is hidden for viewers using MC 26.2+ (when it was made possible). |
|
||||
| fancy-value-default | NPC | [1.20.3 - 26.1.2] Default number format (`fancy-value`) for all player entities. `fancy-value` is displayed on every real player, therefore this default value will only appear on player entities which are not actual players, a.k.a. NPCs. Only visible on since 1.20.3 (the function did not exist prior) until 26.1.2 (player entities without scores no longer display any belowname since 26.2). |
|
||||
| title | Health | Shared label shown after the score for every player entity. Player sees the same text on everyone (= placeholders are parsed for the viewer). Use the `value`/`fancy-value` fields for per‑player data; use `title` only for static labels like `Health` or placeholders which are supposed to be parsed for the viewing player. |
|
||||
| disable-condition | %world%=disabledworld | A [condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) (either name of a condition or a conditional expression) that must be met for disabling the feature for players. Set to empty for not disabling the feature ever. <br/> **Note**: Disabling the feature for a player means sending objective unregister packet to them, which results in player not seeing belowname on anyone anymore. It doesn't work the other way around - you cannot disable this feature on target players, only for viewers. |
|
||||
| view-distance | 10 | [26.1+] How close (in blocks) to a player one must be to see their belowname. This value is configurable since Minecraft 26.1, so this option won't work on older versions. |
|
||||
|
||||
# Limitations
|
||||
* [1.12.2-] Title length is limited to 32 characters (including color codes).
|
||||
* [1.20.2-] `value` is limited to a white number.
|
||||
* [Bedrock] Doesn't support 1.20.3+ features (`fancy-value`), `value` will be displayed instead, just like on <1.20.3.
|
||||
* The format is a **[score] + space + shared title**. No, the space cannot be removed.
|
||||
* The title is the same on all players, therefore, it cannot be personalized (such as player's faction). Only [score] can be per-player.
|
||||
* It appears on all entities of player type. **This includes player NPCs.**
|
||||
|
||||
# Compatibility with other plugins
|
||||
TAB does not contain any sort of compatibility functionality for this feature.
|
||||
It will not try to prevent other plugins from applying the feature and neither will it detect it to re-add back once the other plugin removes it.
|
||||
Therefore, if another plugin also sends belowname objective, TAB's may not show anymore (depending on who sends it first).
|
||||
Make sure you do not have any other plugin sending it to ensure the feature works properly.
|
||||
|
||||
You can check the list of objectives registered by either commands or plugins using Bukkit API using `/scoreboard objectives list`.
|
||||
If it contains one that could be the cause, you can unregister it by running `/scoreboard objectives remove <name>`. After doing so, reload TAB, so it resends its objectives again.
|
||||
Note that if this was automatically generated by a plugin, it will probably be added back again.
|
||||
|
||||
# Additional Info
|
||||
## Additional note 1 - Copying nametag visibility rule
|
||||
The Minecraft feature is programmed to be affected by nametag visibility rule.
|
||||
This means that when the nametag is set to invisible, belowname will be invisible as well.
|
||||
|
||||
## Additional note 2 - [1.8.x] Hidden on sneak
|
||||
Belowname is not visible on 1.8.x clients when player is sneaking. This is client-sided behavior and cannot be changed by the server.
|
||||
|
||||
## Additional note 3 - [26.1.2-] Visible on NPCs
|
||||
Belowname objective is automatically attached to all entities of player type with the default value of
|
||||
`0` (<1.20.3) or value configured as `fancy-value-default` (1.20.3+).
|
||||
This includes player NPCs.
|
||||
|
||||
There is currently only one way to make them not visible on NPCs.
|
||||
From [Additional note 1 - Copying nametag visibility rule](#additional-note-1---copying-nametag-visibility-rule) we know
|
||||
that belowname is not visible if player's nametag is invisible.
|
||||
NPC plugin can take advantage of this by using teams to hide the original name and display a hologram instead.
|
||||
|
||||
This is how you can achieve it using the following popular NPC plugins:
|
||||
* **Citizens**:
|
||||
* 1 - Select the NPC (`/npc select <ID>` or `/npc select` to select the nearest NPC)
|
||||
* 2 - Hide its original nametag (which also hides belowname) using `/npc name`
|
||||
* 3 - Display your desired text using `/npc hologram add <text>` ([more info](https://wiki.citizensnpcs.co/Commands#:~:text=the%20NPC%20hitbox-,/npc%20hologram,-add%20%5Btext%5D%20%7C%20set))
|
||||
* **FancyNpcs with FancyHolograms**:
|
||||
* 1 - Create a hologram with `/hologram create text <name>`.
|
||||
* 2 - Link your newly created hologram with your NPC: `/hologram edit <hologram name> linkWithNpc <NPC name>`.
|
||||
Its original name will be hidden automatically, so you don't need to manually do it.
|
||||
* 3 - Change the NPC's name by editing your hologram's line(s): `/hologram edit hi setline 1 <text>`.
|
||||
You can also add more lines if you want. See [FancyNpcs's wiki](https://docs.fancyinnovations.com/fancyholograms/commands/hologram/#text-hologram-modification) for more commands & info.
|
||||
|
||||
### [26.1.x] Visible on all entities
|
||||
In Minecraft version 26.1, Mojang "fixed" [MC-99647](https://bugs.mojang.com/browse/MC/issues/MC-99647), which reported that belowname is not visible on non-player entities. As a result, the belowname is now visible on all entities with a custom name (this even includes invisible armor stands, holograms and more). A new bug report was made for this: [MC-307012](https://bugs.mojang.com/browse/MC/issues/MC-307012).
|
||||
|
||||
**This is a client-sided bug. You will experience it on 26.1.x regardless of the server version**.
|
||||
If your server is on 26.1.x, or you support players with this version through ViaVersion, this might be a dealbreaker for you. If that's the case, either disable this feature entirely, or set
|
||||
```
|
||||
belowname-objective:
|
||||
disable-condition: "%player-version-id%=775"
|
||||
```
|
||||
which will make 26.1.x players not see this feature on anyone (remember: disabling this feature disables it for the viewer, not target players).
|
||||
**This bug was fixed in Minecraft version 26.2.**
|
||||
|
||||
## Additional note 4 - Compatibility with modified clients
|
||||
Sadly, this feature is suffering from bugs introduced by third party clients such as Feather and Lunar. These two completely ignore `fancy-value` as if it was never added into the game, even on 1.20.3+. This is just an example, and it's not limited to these two clients and this one issue. If you experience issues with the feature and believe you configured it correctly, use vanilla client to make sure it's not caused by a broken client.
|
||||
|
||||
# Troubleshooting
|
||||
This is a collection of tips to help you figure out why the feature isn't working as you expect.
|
||||
To get started, run `/tab dump <any player>` (this feature doesn't contain per-player content in dump output) and open the generated link. Scroll down to `features` -> `BelowName` and check the content:
|
||||
* If it says `BelowName: Feature is disabled`, it means you disabled the feature. Enable it by setting
|
||||
```
|
||||
belowname-objective:
|
||||
enabled: true
|
||||
```
|
||||
* Check the `configuration` section and compare it with your config file. If it's different, you either forgot to reload TAB, or uploaded the config to the wrong server (or did not upload it at all).
|
||||
* If a player cannot see belowname on anyone, check the table of players and make sure it's not because `Disabled with condition` is `true`.
|
||||
* Check the table of players for `value`, `fancy-value` and `title` and make sure they match your expectations. Don't forget `value` only supports numbers.
|
||||
* If you want to see `fancy-value` instead of just `value`'s number:
|
||||
* Make sure your client is on 1.20.3+.
|
||||
* Make sure your server is on 1.20.3+ (using TAB on proxy counts as being latest).
|
||||
* Make sure you are not using a 3rd party client that removed this feature from 1.20.3+, such as Lunar or Feather.
|
||||
* Keep in mind `title` parses for viewer and is visible on all other players, it does not parse for each target player. Do not use placeholders with strictly per-player results in `title`.
|
||||
* If you have TAB on Velocity, install [VelocityScoreboardAPI](https://github.com/NEZNAMY/VelocityScoreboardAPI/releases) (and make sure it is not outdated).
|
||||
|
||||
# Examples
|
||||
## Example 1 - Per-world values
|
||||
This feature doesn't directly support per-world values or similar.
|
||||
However, this can be achieved with conditions.
|
||||
Let's make `fancy-value` conditional based on player's world.
|
||||
Let's make an example with 3 worlds.
|
||||
Check if player is in world `world1`, then show one text.
|
||||
If not, check if player is in world `world2`, then show another text.
|
||||
If not, show the final text.
|
||||
This can be achieved by chaining 2 conditions:
|
||||
```
|
||||
conditions:
|
||||
belowname1:
|
||||
conditions:
|
||||
- "%world%=world1"
|
||||
true: "Text to display in world world1" # Player is in world world1, display the text
|
||||
false: "%condition:belowname2%" # Player is not in world world1, check another condition
|
||||
belowname2:
|
||||
conditions:
|
||||
- "%world%=world2"
|
||||
true: "Text to display in world world2" # Player is in world world2, display the text
|
||||
false: "Text to display in other worlds" # Player is not in any of the 2 worlds
|
||||
```
|
||||
> [!WARNING]
|
||||
> DO NOT JUST RANDOMLY PASTE THIS ENTIRE "CONDITIONS" SECTION INTO YOUR CONFIG!
|
||||
> INSTEAD, EDIT YOUR EXISTING CONDITIONS SECTION TO PREVENT HAVING THE SECTION TWICE,
|
||||
> HAVING SECOND ONE COMPLETELY OVERRIDE THE FIRST ONE!
|
||||
|
||||
Finally, use this condition as value in `fancy-value`:
|
||||
```
|
||||
belowname-objective:
|
||||
fancy-value: "%condition:belowname1%"
|
||||
```
|
||||
If you are under 1.20.3 and want to make `value` and `title` conditional,
|
||||
create two condition chains, one for each value and use them.
|
||||
|
||||
> [!NOTE]
|
||||
> This is just an example, the plugin is not limited to displaying different values only per world.
|
||||
> If you want per server values on proxy, use %server% with server names.
|
||||
> This works for any placeholder offered by TAB or by PlaceholderAPI.
|
||||
|
||||
## Example 2 - Hiding `title` for 1.20.3+ players
|
||||
1.20.3 has replaced `value` field,
|
||||
which is limited to a white number with value configurable as `fancy-value`, which has no limits.
|
||||
However, `title` field is still visible on 1.20.3+.
|
||||
If you support both version ranges and want to make the best out of the new functionality,
|
||||
you might want to not show `title` to 1.20.3+ players anymore,
|
||||
since you can fully customize the text you want to display in `fancy-value`.
|
||||
|
||||
First, let's remind ourselves what `title` *actually* is.
|
||||
It is actually called scoreboard title.
|
||||
Yes, just like the one on top of sidebar, just displayed elsewhere.
|
||||
This is why it displays on all players and placeholders are parsed for the viewing player.
|
||||
With this knowledge, all we need to do is check for player's version and only show something for <1.20.3.
|
||||
For this, we will use `%player-version-id%` placeholder,
|
||||
which returns the network protocol version of player's game version, which can then be compared to.
|
||||
```
|
||||
conditions:
|
||||
version:
|
||||
- "%player-version-id%>=765" # 1.20.3 is 765
|
||||
true: "" # Show empty value for 1.20.3+
|
||||
false: "Some text to display"
|
||||
```
|
||||
> [!WARNING]
|
||||
> DO NOT JUST RANDOMLY PASTE THIS ENTIRE "CONDITIONS" SECTION INTO YOUR CONFIG!
|
||||
> INSTEAD, EDIT YOUR EXISTING CONDITIONS SECTION TO PREVENT HAVING THE SECTION TWICE,
|
||||
> HAVING SECOND ONE COMPLETELY OVERRIDE THE FIRST ONE!
|
||||
```
|
||||
belowname-objective:
|
||||
title: "%condition:version%"
|
||||
```
|
||||
Unfortunately, due to the limitations of this feature,
|
||||
there is a forced space between `value`/`fancy-value` and `title`,
|
||||
even if the `title` is empty.
|
||||
You'll either need to live with it, or put some shared text there to avoid having a space at the end.
|
||||
|
||||
## Example 3 - Displaying health as 0-10 or in %
|
||||
If you want health to display health as 0-10 instead of 0-20, you can achieve it with PlaceholderAPI:
|
||||
* `%math_0_{player_health}/2%` for 0-10
|
||||
* `%math_0_{player_health}*5%` for 0-100
|
||||
|
||||
## Example 4 - Health bar using hearts
|
||||
You can achieve this on `1.20.3+` using `healthbar` expansion from PlaceholderAPI:
|
||||
```
|
||||
belowname-objective:
|
||||
fancy-value: "%healthbar_healthbar%"
|
||||
title: ""
|
||||
```
|
||||
<img width="130" height="159" alt="image" src="https://github.com/user-attachments/assets/cef217ec-0a39-41ad-8457-f8f67a1e4b02" />
|
||||
|
||||
Sadly, there is no way to remove the forced space between `fancy-value` and `title`. You can only try to play around it by adding some static text after it, to make it look like the space is intended. Or you can just ignore the space and live with it.
|
||||
|
||||
# Tips & Tricks
|
||||
## Tip 1 - Heart symbol
|
||||
If you want to show health of players and display a heart symbol instead of text saying "Health", you can use this one: `❤`.
|
||||
```
|
||||
belowname-objective:
|
||||
title: "&4❤"
|
||||
```
|
||||
> [!IMPORTANT]
|
||||
> Make sure your config is [saved in UTF-8 encoding](https://github.com/NEZNAMY/TAB/wiki/How-to-save-the-config-in-UTF8-encoding) to properly read the heart symbol.
|
||||
|
||||
## Example 5 - Conditionally hiding belowname for 26.2+ viewers
|
||||
Since Minecraft 26.2, belowname only appears on entities with a score. This can be used to disable the belowname on players with a condition. We are trying to achieve a condition like this: "If something, hide belowname for 26.2+ viewers".
|
||||
TAB is made to reset score (= hide belowname) of target players for 26.2+ viewers (<26.2 viewers are not affected, resetting scores for them would result in `fancy-value-default` to be shown, which is undesirable) if `fancy-value` evaluated to an empty string. Therefore, we will need to make a [relational condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders#relational-conditions) that checks the viewer's version and returns empty string if some condition is met.
|
||||
Here is an example of hiding it if target player has less than 10 health (5 hearts):
|
||||
```
|
||||
conditions:
|
||||
belowname-health:
|
||||
conditions:
|
||||
- "%viewer:player-version-id%>=776" # 26.2 uses 776, check for viewer's version, not target player's
|
||||
- "%health%<10" # This should check target player's health
|
||||
type: AND
|
||||
true: "" # Viewer is on 26.2+ and target has less than 10 health, return empty string to hide it
|
||||
false: "%health%" # Display health as normal
|
||||
```
|
||||
Then, use this condition as a relational condition (because it checks both viewer and target players):
|
||||
```
|
||||
belowname-objective:
|
||||
fancy-value: "%rel_condition:belowname-health%"
|
||||
```
|
||||
@@ -0,0 +1,261 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* [Commands](#commands)
|
||||
* [Placeholders](#placeholders)
|
||||
* [Limitations](#limitations)
|
||||
* [Compatibility with other plugins](#compatibility-with-other-plugins)
|
||||
* [Additional info](#additional-info)
|
||||
* [Additional note 1 - Hiding bar itself](#additional-note-1---hiding-bar-itself)
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
* [API](#api)
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Changing text](#example-1---changing-text)
|
||||
* [Example 2 - Switching between bossbars with condition](#example-2---switching-between-bossbars-with-condition)
|
||||
* [Example 3 - Periodical appearing and disappearing](#example-3---periodical-appearing-and-disappearing)
|
||||
* [Example 4 - Dynamic progress tracking a relative placeholder value](#example-4---dynamic-progress-tracking-a-relative-placeholder-value)
|
||||
|
||||
# About
|
||||
This feature allows you to send modern bossbars to players, which appear on top of the screen.
|
||||
Only works on Minecraft 1.9 and up.
|
||||
Supporting 1.8 and lower would require an entity to be spawned (wither / dragon), which TAB no longer offers.
|
||||

|
||||
|
||||
# Configuration
|
||||
The feature can be configured in **config.yml** under **bossbar** section.
|
||||
This is how the default configuration looks:
|
||||
```
|
||||
bossbar:
|
||||
enabled: false
|
||||
toggle-command: /bossbar
|
||||
remember-toggle-choice: false
|
||||
hidden-by-default: false
|
||||
bars:
|
||||
ServerInfo:
|
||||
style: "PROGRESS" # for 1.9+: PROGRESS, NOTCHED_6, NOTCHED_10, NOTCHED_12, NOTCHED_20
|
||||
color: "%animation:barcolors%" # for 1.9+: BLUE, GREEN, PINK, PURPLE, RED, WHITE, YELLOW
|
||||
progress: "100" # in %
|
||||
text: "&fWebsite: &bwww.domain.com"
|
||||
```
|
||||
All the options are explained in the following table.
|
||||
|
||||
| Option name | Default value | Description |
|
||||
|------------------------|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | false | Enables / Disables the feature |
|
||||
| toggle-command | /bossbar | A command to toggle bossbar visibility for player running the command. This command requires `tab.bossbar.toggle` permission. <br />**Note:** Commands are not supposed to be registered / unregistered dynamically at runtime. As such, you may run into small issues when changing the toggle command and reloading. After you modify the command to your liking, reconnect to properly see it in tabcomplete. If you don't use TAB on a proxy, consider restarting the server as well for the old command to actually be unregistered. |
|
||||
| remember-toggle-choice | false | When enabled, disabling bossbar using `toggle-command` is remembered between reloads and restarts. |
|
||||
| hidden-by-default | false | When enabled, bossbar will automatically be hidden until toggle command is used. |
|
||||
| bars | *Map* | Map of defined bossbars, see below for more information. |
|
||||
|
||||
|
||||
Bossbars can be defined in `bars` section. Bossbar name can be anything, but you cannot use the same name for 2 bossbars.
|
||||
A bossbar consists of up to 6 properties:
|
||||
|
||||
| Option | Example | Description |
|
||||
|-------------------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| style | PROGRESS | Type of bossbar division. You can choose from 5 styles: **PROGRESS**, **NOTCHED_6**, **NOTCHED_10**, **NOTCHED_12** and **NOTCHED_20**. <br />  <br /> These were defined by mojang, no other options are available. Other plugins may be using different names, but it's the same result in the end. |
|
||||
| color | BLUE | Color of bossbar. You can choose from 7 colors: **BLUE**, **GREEN**, **PINK**, **PURPLE**, **RED**, **WHITE** and **YELLOW**. <br />  <br /> These were defined by mojang, no other options are available. |
|
||||
| progress | 100 | A number between 0 and 100. Accepts decimals. <br />  |
|
||||
| text | "Hi" | Text of the bossbar. Length is not limited, supports RGB codes on 1.16+. Does not support newlines. |
|
||||
| announcement-bar | false | When set to `true`, the bossbar will not appear by default, only when used in announce command. |
|
||||
| display-condition | "%world%=world" | [Condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) that must be met for player to see the bossbar. Even when using announce command on a bossbar with display condition, players must meet it to see the bossbar. When condition is not defined, bossbar has no requirement to be displayed. |
|
||||
|
||||
Here is an example using all 6 properties:
|
||||
```
|
||||
bars:
|
||||
ServerInfo:
|
||||
style: "PROGRESS"
|
||||
color: "PURPLE"
|
||||
progress: "100"
|
||||
text: "Welcome to the nether!"
|
||||
announcement-bar: false
|
||||
display-condition: "%world%=world_nether"
|
||||
```
|
||||
|
||||
# Commands
|
||||
| Command | Permission | Description |
|
||||
|-------------------------------------------------------|------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| /tab bossbar show \<name\> \[player\] | `tab.bossbar.show` (for yourself) <br /> `tab.bossbar.show.other` (for others) | Shows the bossbar with the given `name`, either to yourself if no `player` was given, or to the given `player`. |
|
||||
| /tab bossbar \[on/off/toggle\] \[player\] \[options\] | `tab.bossbar.toggle` (for yourself) <br /> `tab.bossbar.toggle.other` (for others) | Shows / hides / toggles bossbar of specified player. If no player was given, command affects the sender. You can use `-s` as option for silent toggling (no chat message for affected player) |
|
||||
| /tab bossbar announce \<name\> \<duration\> | `tab.announce.bar` | Shows the bossbar with the given `name` to every player on the server for the given `duration`, in seconds. |
|
||||
|
||||
# Placeholders
|
||||
Here are TAB's internal placeholders you can use when this feature is enabled:
|
||||
| Placeholder | Description |
|
||||
|-------------|-------------|
|
||||
| `%bossbar_announce_time_left_<bossbar>%` | Returns remaining time of the announcement of specified bossbar (in seconds). |
|
||||
| `%bossbar_announce_time_total_<bossbar>%` | Returns total time of the announcement of specified bossbar (in seconds) (the inputted number). |
|
||||
|
||||
You can further use these placeholders in progress, for example, using Math expansion from PlaceholderAPI, such as `%math_{tab_placeholder_bossbar_announce_time_left_<bossbar>}/{tab_placeholder_bossbar_announce_time_total_<bossbar>}*100%` (remember to replace `<bossbar>` with the actual name of the bossbar).
|
||||
|
||||
Here are TAB's PlaceholderAPI placeholders you can use when this feature is enabled:
|
||||
| Placeholder | Description |
|
||||
|-------------|-------------|
|
||||
| `%tab_bossbar_visible%` | "Enabled" if visible (not toggled with a command), "Disabled" if not (toggled with a command) |
|
||||
|
||||
# Limitations
|
||||
* Does not support newlines. If you want to display more lines, you'll need to create multiple bossbars.
|
||||
* The bar itself cannot be removed from the server side. However, it can be removed with a resource pack (see below for more info).
|
||||
* While there is no explicit limit to how many bossbars you can configure, the client will only display up to 9 depending on window size and GUI scale in client settings.
|
||||
|
||||
# Compatibility with other plugins
|
||||
Bossbar is a feature that can have multiple instances sent and displayed, so there is no possible conflict like in scoreboard for example. Every plugin manages its own bossbars and doesn't care about others.
|
||||
|
||||
One thing to mention is the order of bossbars. They are ordered by the order they were received. This means the final order depends on which plugin is faster (or slower), which is something you can't really control. As such, there is no feasible way to control the order of bossbars across different plugins. TAB's own bossbars are sent in the order they are defined in the configuration, so that won't be a problem.
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - Hiding bar itself
|
||||
If you want to hide the bossbar itself and only show text, this is possible, but not from the plugin's side.
|
||||
You'll need to create a custom resource pack where the bar is invisible and force your players to get the resource pack.
|
||||
Here is how to do it:
|
||||
**Minecraft 1.20+**:
|
||||
* Navigate to `assets/minecraft/textures/gui/sprites/boss_bar`. You will need to create 2 files. In this example, we will use `WHITE` Bossbar color.
|
||||
* Use GIMP or any other photo editing software and create a **1x1 px** image, that is fully transparent.
|
||||
* Name the file **white_progress.png**. Now copy-paste the same file and name it **white_background.png**.
|
||||
|
||||
**Minecraft 1.19.4-**:
|
||||
* Navigate to `assets/minecraft/textures/gui/`. You will need to download the default `bars.png` file (https://github.com/Faithful-Pack/Default-Java/blob/1.19.4/assets/minecraft/textures/gui/bars.png).
|
||||
* Use GIMP or any other Photo editing software and remove the White bars in the file. Save the file and move it to `assets/minecraft/textures/gui/`.
|
||||
|
||||
Finally, set your Bossbar color in TAB Config to `WHITE`. Now the line will be invisible!
|
||||
|
||||
# Troubleshooting
|
||||
This is a collection of tips to help you figure out why the feature isn't working as you expect.
|
||||
To get started, run `/tab dump <affected player>` and open the generated link. Scroll down to `features` -> `BossBar` and check the content:
|
||||
* If it says `BossBar: Feature is disabled`, it means you disabled the feature. Enable it by setting
|
||||
```
|
||||
bossbar:
|
||||
enabled: true
|
||||
```
|
||||
* Check the `configuration` section and compare it with your config file. If it's different, you either forgot to reload TAB, or uploaded the config to the wrong server (or did not upload it at all).
|
||||
* Check the `bossbar conditions` section and for each bossbar and analyze the `display-condition` options (the value, with placeholders parsed, whether it is met or not) if it matches what you expect. If not, you may have made a mistake in your conditions.
|
||||
* Check `bossbars visible` value to make sure user did not toggle the bossbar(s).
|
||||
* Check `currently displayed bossbars` section and compare it with your expectations, as well as the actual in-game result. If it doesn't match your expectations, you didn't configure something correctly. If the output doesn't match the in-game result, it might be a bug.
|
||||
|
||||
|
||||
# API
|
||||
*To get started with the API, see [Developer API](https://github.com/NEZNAMY/TAB/wiki/Developer-API) page.*
|
||||
|
||||
To access this feature, you'll need to obtain `BossBarManager` instance. Get it using `TabAPI.getInstance().getBossBarManager()`. If this feature is disabled, the method will return `null`.
|
||||
|
||||
A boss bar is made up of a few things:
|
||||
* A name. This is either the name given in the config, if the bar was loaded from the config, or a random UUID string when created with API.
|
||||
* A title. This is the display message of the boss bar.
|
||||
* The progress from 0 to 100.
|
||||
* The color. This determines what color the boss bar will appear when it is shown to clients.
|
||||
* The style. This determines how many segments, if any, the boss bar will be split to.
|
||||
|
||||
Let's start with methods in `BossBarManager`:
|
||||
* `BossBarManager#createBossBar(String, float, BarColor, BarStyle` - Creates new bossbar using direct values.
|
||||
* `BossBarManager#createBossBar(String, String, String, String` - Creates new bossbar. Accepts all the previous parameters as strings, to allow for placeholders, though the given placeholders must match the requirements (progress will be a number, color and style matching enum names).
|
||||
* `BossBarManager#getBossBar(String)` - Returns bossbar by name defined in config.
|
||||
* `BossBarManager#toggleBossBar(TabPlayer, boolean)` - Toggles all bossbars for specified player. The boolean flags whether toggle message defined in messages.yml should be sent to the player or not.
|
||||
* `BossBarManager#hasBossBarVisible(TabPlayer)` - Returns `true` if player has bossbars visible, `false` if disabled using toggling.
|
||||
* `BossBarManager#setBossBarVisible(TabPlayer, boolean, boolean)` - Sets bossbar visibility status for specified player to specified value (first boolean). Second boolean determines whether toggle message configured in messages.yml should be sent or not.
|
||||
* `BossBarManager#sendBossBarTemporarily(TabPlayer, String, int)` - Temporarily sends bossbar to player. String defines name of the bossbar defined in config. Int defines length in milliseconds.
|
||||
* `BossBarManager#announceBossBar(String, int)` - Sends bossbar with specified name in config to all players for `int` milliseconds.
|
||||
* `BossBarManager#getAnnouncedBossBars()` - Returns all bossbars, which are currently being announced.
|
||||
* `BossBarManager#getRegisteredBossBars()` - Returns map of all registered bossbars using configuration or the API.
|
||||
|
||||
Methods in `BossBar`:
|
||||
* `BossBar#getName()` - Returns name of the bossbar defined in config, or randomly generated UUID string when generated using API.
|
||||
* `BossBar#setTitle(String)` - Sets title. Accepts placeholders, which will be replaced and periodically updated.
|
||||
* `BossBar#setProgress(String)` - Sets progress. Accepts placeholders, which will be replaced and periodically updated.
|
||||
* `BossBar#setProgress(float)` - Sets progress.
|
||||
* `BossBar#setColor(String)` - Sets color. Accepts placeholders, which will be replaced and periodically updated.
|
||||
* `BossBar#setColor(BarColor)` - Sets color.
|
||||
* `BossBar#setStyle(String)` - Sets style. Accepts placeholders, which will be replaced and periodically updated.
|
||||
* `BossBar#setStyle(BarStyle)` - Sets style.
|
||||
* `BossBar#getTitle()` - Returns raw title.
|
||||
* `BossBar#getProgress()` - Returns raw progress as string.
|
||||
* `BossBar#getColor()` - Returns raw color as string.
|
||||
* `BossBar#getStyle()` - Returns raw style as string.
|
||||
* `BossBar#addPlayer(TabPlayer)` - Sends the bossbar to specified player.
|
||||
* `BossBar#removePlayer(TabPlayer)` - Removes the bossbar from specified player.
|
||||
* `BossBar#getPlayers()` - Returns all players that can currently see this bossbar.
|
||||
* `BossBar#containsPlayer(TabPlayer)` - Returns `true` if player can see this bossbar, `false` if not.
|
||||
* `BossBar#isAnnouncementBar()` - Returns `true` if this bossbar is defined as announcement bar in config, `false` if visible permanently.
|
||||
|
||||
# Examples
|
||||
## Example 1 - Changing text
|
||||
You can make the change text periodically using [animations](https://github.com/NEZNAMY/TAB/wiki/Animations).
|
||||
First, create an animation in **animations.yml**, such as
|
||||
```
|
||||
BossBarText:
|
||||
change-interval: 1000
|
||||
texts:
|
||||
- "Text1"
|
||||
- "Text2"
|
||||
```
|
||||
Then, use the animation in bossbar configuration
|
||||
```
|
||||
bars:
|
||||
ServerInfo:
|
||||
style: "PROGRESS"
|
||||
color: "PURPLE"
|
||||
progress: "100"
|
||||
text: "%animation:BossBarText%"
|
||||
```
|
||||
This bossbar will change text every second between `text1` and `text2`. You can make the change interval higher and add more texts to suit your needs.
|
||||
|
||||
> [!NOTE]
|
||||
> This works for style, color and progress as well, not just text. Just make sure the animation returns a valid value accepted by the field (listed enum constants for style and color, number between 0 and 100 for progress).
|
||||
|
||||
## Example 2 - Switching between bossbars with condition
|
||||
If you want the plugin to switch between bossbars based on a condition, first consider using condition for text itself
|
||||
(or some other property).
|
||||
If this is not an option (you want text, color, style and progress to be different, which would result in 4 conditions),
|
||||
create 2 bars and give them the same condition, except, negate it.
|
||||
If your original condition uses `=`, make second condition use `!=`.
|
||||
For number comparisons, negate `<` using `>=` and so on.
|
||||
**Example**:
|
||||
```
|
||||
bars:
|
||||
full:
|
||||
style: "PROGRESS"
|
||||
color: "YELLOW"
|
||||
progress: "100"
|
||||
text: "&aYour health is full"
|
||||
display-condition: "%health%=20"
|
||||
notfull:
|
||||
style: "PROGRESS"
|
||||
color: "RED"
|
||||
progress: "0"
|
||||
text: "&cYou took damage"
|
||||
display-condition: "%health%!=20"
|
||||
```
|
||||
|
||||
## Example 3 - Periodical appearing and disappearing
|
||||
This can be achieved using [animations](https://github.com/NEZNAMY/TAB/wiki/Animations) and [conditions](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders). We will create an animation with 2 frames and check if it's on the first one, then display the bossbar. Otherwise, don't display it.
|
||||
To get started, create an animation in **animations.yml**:
|
||||
```
|
||||
animations:
|
||||
bossbar-toggle:
|
||||
change-interval: 10000
|
||||
texts:
|
||||
- "ON"
|
||||
- "OFF"
|
||||
```
|
||||
Then, create a display condition that checks if the animation is on the first frame (`ON`):
|
||||
```
|
||||
bars:
|
||||
ServerInfo:
|
||||
display-condition: "%animation:bossbar-toggle%=ON" # Check for the first frame of the animation
|
||||
style: "PROGRESS"
|
||||
color: "PURPLE"
|
||||
progress: "100"
|
||||
text: "&fWebsite: &bwww.domain.com"
|
||||
```
|
||||
Now, the bossbar will appear and disappear every 10 seconds.
|
||||
|
||||
## Example 4 - Dynamic progress tracking a relative placeholder value
|
||||
If you want to show the progress of a placeholder's value relative to a maximum one, you can use the [Math Expansion](https://github.com/PlaceholderAPI/PlaceholderAPI/wiki/Placeholders#math) from PlaceholderAPI and use a placeholder like this one: `%math_{placeholder_current_value}/{placeholder_max_value}*100%` or `%math_{placeholder_current_value}/<max_value>*100%` if your max value is fixed.
|
||||
|
||||
> [!NOTE]
|
||||
> Replace the text in between the `{}` with the actual placeholder you want to use and `<max_value>` with a valid number (i.e., 20).
|
||||
|
||||
You cannot use the `%placeholder%` format inside the math placeholder.
|
||||
Example for showing a player's health:
|
||||
`progress: "%math_{player_health}/20*100%"`
|
||||
or
|
||||
`progress: "%math_{player_health}/{player_max_health}*100%"`
|
||||
@@ -0,0 +1,218 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Condition types](#condition-types)
|
||||
* [Number comparisons](#number-comparisons)
|
||||
* [Text operations](#text-operations)
|
||||
* [Permission](#permission)
|
||||
* [Usage](#usage)
|
||||
* [Conditional text](#conditional-text)
|
||||
* [Using in a field where condition is expected](#using-in-a-field-where-condition-is-expected)
|
||||
* [Using in a field where condition is expected (short format)](#using-in-a-field-where-condition-is-expected-short-format)
|
||||
* [Relational conditions](#relational-conditions)
|
||||
* [Refresh interval](#refresh-interval)
|
||||
* [Additional info](#additional-info)
|
||||
* [Additional note 1 - Choosing the correct AND / OR type](#additional-note-1---choosing-the-correct-and--or-type)
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Chaining conditional placeholders](#example-1---chaining-conditional-placeholders)
|
||||
* [Example 2 - Combining AND and OR](#example-2---combining-and-and-or)
|
||||
|
||||
# About
|
||||
Conditions / conditional placeholders allow you
|
||||
to create output which depends on the output of other placeholders or permission requirement.
|
||||
They have 2 main uses in the plugin:
|
||||
* `display-condition` which must be met to be able to see something (bossbar, scoreboard, layout) or `disable-condition` for disabling a feature (scoreboard-teams, tablist-name-formatting, ...)
|
||||
* Conditional placeholders which return defined outputs based on if the condition passes or fails
|
||||
|
||||
# Condition types
|
||||
## Number comparisons
|
||||
| Operation | Description | Example |
|
||||
|-----------|--------------------------|--------------------------------------------------------------------------------|
|
||||
| `>=` | Greater than or equal to | `%ping%>=100` will pass if the player's ping is greater than or equal to `100` |
|
||||
| `>` | Greater than | `%ping%>100` will pass if the player's ping is greater than `100` |
|
||||
| `<=` | Less than or equal to | `%ping%<=100` will pass if the player's ping is less than or equal to `100` |
|
||||
| `<` | Less than | `%ping%<100` will pass if the player's ping is less than `100` |
|
||||
|
||||
## Text operations
|
||||
| Operation | Description | Example |
|
||||
|-----------|------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
|
||||
| `=` | Equal to | `%world%=world` will pass if player is in world `world` |
|
||||
| `!=` | Not equal to | `%world%!=world` will pass if player is in any world except `world` |
|
||||
| `<-` | Contains (left side for full text, right side text to contain) | `%world%<-lobby-` will pass if player is in any world that contains `lobby-` (such as `lobby-1` etc.) |
|
||||
| `!<-` | Not Contains (left side for full text, right side text to not contain) | `%world%!<-lobby-` will pass if player is in any world that does not contain `lobby-` (such as `lobby-1` etc.) |
|
||||
| `\|-` | Starts with (left side for full text, right side text to start with) | `%world%\|-lobby-` will pass if player is in any world that starts with `lobby-` (such as `lobby-1` etc.) |
|
||||
| `!\|-` | Not Starts with (left side for full text, right side text to not start with) | `%world%!\|-lobby-` will pass if player is in any world that does not start with `lobby-` (such as `lobby-1` etc.) |
|
||||
| `-\|` | Ends with (left side for full text, right side text to end with) | `%world%-\|nether` will pass if player is in any world that ends with `nether` (such as `world_nether` etc.) |
|
||||
| `!-\|` | Not Ends with (left side for full text, right side text to not end with) | `%world%!-\|nether` will pass if player is in any world that does not end with `nether` (such as `world_nether` etc.) |
|
||||
|
||||
> [!NOTE]
|
||||
> For `=` and `!=` you can check for empty output of a placeholder using `%my_placeholder%=` and `%my_placeholder%!=`.
|
||||
|
||||
> [!NOTE]
|
||||
> For string operations, the text must match placeholder's output exactly, including color codes, as well as lower/UPPER case letters.
|
||||
If you are using [Placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements),
|
||||
condition must contain the altered output.
|
||||
To see the exact output of a placeholder including color codes, use `/tab parse <player> <placeholder>`.
|
||||
|
||||
## Permission
|
||||
> [!WARNING]
|
||||
> Giving someone OP status will automatically give them all permissions, which will make all the permission checks in conditions pass.
|
||||
|
||||
| Operation | Description | Example |
|
||||
|-----------------------|---------------------------------|----------------------------------------------------------------------------------------------|
|
||||
| `permission:<value>` | Permission requirement | `permission:my.permission` will pass if player has `my.permission` permission |
|
||||
| `!permission:<value>` | Negative permission requirement | `!permission:my.permission` will pass if player **does not have** `my.permission` permission |
|
||||
|
||||
# Usage
|
||||
There are multiple different ways you can use conditions, all of which are described below.
|
||||
|
||||
## Conditional text
|
||||
This way allows you to create conditional text that depends on other placeholders.
|
||||
|
||||
First, find the `conditions` section in your config and create a new condition like this one:
|
||||
```
|
||||
conditions:
|
||||
lobby:
|
||||
conditions:
|
||||
- '%server%=lobby'
|
||||
true: "You are in lobby"
|
||||
false: "You are not in lobby"
|
||||
```
|
||||
This condition checks if player is in server `lobby` and if yes, displays `"You are in lobby"`, otherwise displays `"Your are not in lobby"`.
|
||||
To check for more than just 1 condition, add more to the list. Additionally, you will now need to specify `type`, which is either `AND` or `OR`.
|
||||
|
||||
For example,
|
||||
```
|
||||
conditions:
|
||||
lobby:
|
||||
conditions:
|
||||
- '%server%=lobby'
|
||||
- '%server%=lobby2'
|
||||
type: OR
|
||||
true: "You are in lobby"
|
||||
false: "You are not in lobby"
|
||||
```
|
||||
will return the lobby text if player is in server `lobby` **OR** in server `lobby2`. If you want both of those conditions to be required to display text, use `type: AND`.
|
||||
It is not possible to combine both `AND` and `OR` in a single condition. To do that, create multiple conditions and use one inside another (see Example 2 below).
|
||||
|
||||
Now that the condition is created, we can use it using `%condition:lobby%`. This placeholder will return the texts configured in `true` and `false` values based on whether the condition was met or not.
|
||||
|
||||
## Using in a field where condition is expected
|
||||
A lot of the features support either `display-condition` or `disable-condition`. The value configured is expected to be a condition. Let's say we want to use it as a display condition somewhere, for example when player is in server `lobby`. First, create the condition:
|
||||
```
|
||||
conditions:
|
||||
lobby:
|
||||
conditions:
|
||||
- '%server%=lobby'
|
||||
```
|
||||
As you can see, `true` and `false` were not configured. This is because we are not trying to display any text, we are passing the condition as an object to evaluate.
|
||||
Then, use `display-condition: lobby` in the feature. This will evaluate the condition named `lobby` and either display or not display the visual based on player's server. To check for 2 servers, use
|
||||
```
|
||||
conditions:
|
||||
lobby:
|
||||
conditions:
|
||||
- '%server%=lobby'
|
||||
- '%server%=lobby2'
|
||||
type: OR
|
||||
```
|
||||
Now, the condition `lobby` will pass if player is in server `lobby` **OR** in server `lobby2`. To require both of the conditions to be met instead of at least 1, use `type: AND`.
|
||||
It is not possible to combine both `AND` and `OR` in a single condition. To do that, create multiple conditions and use one inside another (see Example 2 below).
|
||||
|
||||
## Using in a field where condition is expected (short format)
|
||||
When using condition as a `display-condition` or `disable-condition`, you don't need to specify `true` / `false` texts. In fact, you only need the list of conditions and separator (AND / OR).
|
||||
For this purpose, short format was created. Instead of having to create a condition and using it, you can specify the expression directly.
|
||||
|
||||
**Single condition example**:
|
||||
```
|
||||
display-condition: "%server%=lobby"
|
||||
```
|
||||
|
||||
**Multiple conditions, all of them must be met**:
|
||||
```
|
||||
display-condition: "%server%=lobby;%world%=world"
|
||||
```
|
||||
|
||||
**Multiple conditions, at least one of them must be met**:
|
||||
```
|
||||
display-condition: "%server%=lobby|%server%=lobby2"
|
||||
```
|
||||
It is not possible to combine both `AND` (`;`) and `OR` (`|`) in a single condition. To do that, create multiple conditions and use one inside another (see Example 2 below).
|
||||
|
||||
## Relational conditions
|
||||
> [!NOTE]
|
||||
> This section only describes differences from standard conditions. For more information about those, see sections above.
|
||||
|
||||
Relational conditions allow you to check placeholder outputs for the player who is looking instead of only the target player.
|
||||
|
||||
To make placeholder check for viewer instead of the target player, use `%viewer:<placeholder>%` instead of just `%placeholder%`.
|
||||
You can still check for target player using `%placeholder%` or `%target:<placeholder>%` (if you want to make it more clear for the reader).
|
||||
Example: `%viewer:server%=%server%` will pass if viewer is in the same server as the target player.
|
||||
|
||||
There are 2 ways to use it:
|
||||
* display-condition of layout player groups (which is currently the only feature supporting it as it would not make sense elsewhere)
|
||||
* A placeholder using `%rel_condition:<condition>%` syntax
|
||||
|
||||
Using `%viewer:...%` will upgrade the condition to a relational condition and standard version will no longer be available.
|
||||
If trying to use relational condition in `%condition:name%` syntax, it will return a warning text instead of evaluating the condition.
|
||||
Same the other way around - if trying to use standard condition in `%rel_condition:name%` syntax, it will return a warning text.
|
||||
|
||||
# Refresh interval
|
||||
Conditions are just placeholders after all, and, as such, they must be refreshed periodically.
|
||||
Refresh intervals of conditions are not directly configurable.
|
||||
They are based on placeholders used inside (subconditions, true/false values).
|
||||
Permission checks count as 1000ms.
|
||||
To configure refresh intervals of placeholders,
|
||||
check out the [Optimization guide](https://github.com/NEZNAMY/TAB/wiki/Optimizing-the-plugin#2---all-platforms-placeholder-refresh-intervals).
|
||||
|
||||
# Additional Info
|
||||
## Additional note 1 - Choosing the correct AND / OR type
|
||||
Sometimes you want to combine multiple expressions using `AND` or `OR`. When doing this, you must pick the correct one based on your needs.
|
||||
A common mistake is trying to turn spoken language directly into config, which can be wrong.
|
||||
|
||||
For example, you say you want to display scoreboard in servers `server1` **and** `server2`. As such, you may accidentally use `type: AND` or `;` in short format (`%server%=server1;%server%=server2`). This is, however, wrong, because that would mean your server must be `server1` **and** `server2` at the same time, which is obviously impossible. The correct type is `OR` here (`|`). So instead of thinking "I want to display scoreboard in `server1` **and** `server2`", you should think "I want to display scoreboard if player is in `server1` **or** `server2`.
|
||||
|
||||
# Examples
|
||||
## Example 1 - Chaining conditional placeholders
|
||||
Let's create colored ping by chaining conditions using multiple intervals for ping quality. This specific case would be easier done using [replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements), but this is just an example. Let's say we want <50 for good, <100 for medium and 100+ for bad. Let's create the first condition:
|
||||
```
|
||||
conditions:
|
||||
ping:
|
||||
conditions:
|
||||
- "%ping%<50"
|
||||
true: "&a%ping%"
|
||||
false: "%condition:ping2%"
|
||||
```
|
||||
When ping is <50, display it as green. Otherwise, use another condition. Put them together and we get
|
||||
```
|
||||
conditions:
|
||||
ping:
|
||||
conditions:
|
||||
- "%ping%<50"
|
||||
true: "&a%ping%" # Ping is < 50, display as green
|
||||
false: "%condition:ping2%" # Ping is 50+, check another condition
|
||||
ping2:
|
||||
conditions:
|
||||
- "%ping%<100"
|
||||
true: "&e%ping%" # Ping is < 100, display as yellow
|
||||
false: "&c%ping%" # Ping is 100+, display as red
|
||||
```
|
||||
Finally, we can use this ping placeholder using `%condition:ping%`.
|
||||
This example chained 2 conditions, but more can be used. There is no limit.
|
||||
|
||||
## Example 2 - Combining AND and OR
|
||||
If you want to combine both "AND" and "OR" types, create 2 conditions and use first one in the second one.
|
||||
For example, if we want to check that player is in server `lobby` **and** in worlds **either** `world1` or `world2`,
|
||||
it can be achieved in the following way:
|
||||
```
|
||||
conditions:
|
||||
world:
|
||||
conditions:
|
||||
- "%world%=world1"
|
||||
- "%world%=world2"
|
||||
type: OR
|
||||
main:
|
||||
conditions:
|
||||
- "%condition:world%=true"
|
||||
- "%server%=lobby"
|
||||
type: AND
|
||||
```
|
||||
Then, use condition `main` as the display condition (or as a placeholder - `%condition:main%`). Note that `true`/`false` values were not defined, as such, they default to `true` and `false`, respectively. Therefore, we use the placeholder from the condition and check if the result is `true`. Then, check if player is also in the specified server.
|
||||
@@ -0,0 +1,161 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* [Grouping players only from certain servers](#grouping-players-only-from-certain-servers)
|
||||
* [Pattern Matching](#pattern-matching)
|
||||
* [Configuring isolated servers](#configuring-isolated-servers)
|
||||
* [Seeing all players on the network from some server](#seeing-all-players-on-the-network-from-some-server)
|
||||
* ~Commands~
|
||||
* [Placeholders](#placeholders)
|
||||
* ~Limitations~
|
||||
* [Compatibility with other plugins](#compatibility-with-other-plugins)
|
||||
* ~Additional Info~
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
* ~API~
|
||||
* ~Examples~
|
||||
|
||||
# About
|
||||
This feature allows you to see players from different servers, instead of only seeing players on the same server. The typical use is to show players under the whole proxy network.
|
||||
If TAB is installed on a backend server, you'll need to set up [Multi server support](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Multi-server-support) to properly make the servers communicate. On proxy installation, this is not needed, unless you have multiple proxies.
|
||||
|
||||
# Configuration
|
||||
The feature can be configured in **config.yml** under **global-playerlist** section.
|
||||
This is how the default configuration looks:
|
||||
```
|
||||
global-playerlist:
|
||||
enabled: false
|
||||
display-others-as-spectators: false
|
||||
display-vanished-players-as-spectators: true
|
||||
isolate-unlisted-servers: false
|
||||
update-latency: false
|
||||
spy-servers:
|
||||
- spyserver1
|
||||
- spyserver2
|
||||
server-groups:
|
||||
lobbies:
|
||||
- lobby1
|
||||
- lobby2
|
||||
group2:
|
||||
- server1
|
||||
- server2
|
||||
```
|
||||
All of the options are explained in the following table.
|
||||
| Option name | Default value | Description |
|
||||
|----------------------------------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | false | Enables / Disables the feature |
|
||||
| display-others-as-spectators | false | When enabled, players on different servers will appear as having spectator gamemode in tablist. |
|
||||
| display-vanished-players-as-spectators | true | When enabled, vanished players will show as in spectator gamemode for those, who have permission to see vanished players (tab.seevanished) (others will obviously not see them at all). Vanished players will still see themselves in the gamemode they are actually in, since changing that would cause problems (client would think it's in spectator gamemode while it isn't). |
|
||||
| isolate-unlisted-servers | false | When enabled, servers not listed in any group will not share playerlist with any other server, instead of sharing it with other unlisted servers. |
|
||||
| update-latency | false | When **enabled**, plugin will send ping update to players on other servers, since backend servers only send ping updates of players on the same server. This is displayed as the green bar in tablist, unless altered by a mod / resource pack (?). <br /> <br />When **disabled**, ping of players on other servers will be set to `0` (). <br /> <br />Disabled by default, because it's not only not very useful, but also has a very high CPU usage to due spamming a large amount of packets (especially on large networks). |
|
||||
| spy-servers | *List* | See [Seeing all players on the network from some server](#seeing-all-players-on-the-network-from-some-server) |
|
||||
| server-groups | *Map* | See [Grouping players only from certain servers](#grouping-players-only-from-certain-servers) |
|
||||
|
||||
## Grouping players only from certain servers
|
||||
In case you want multiple servers to share playerlist,
|
||||
but not with every server, create a server group and put servers there.
|
||||
The default example
|
||||
```
|
||||
global-playerlist:
|
||||
server-groups:
|
||||
lobbies:
|
||||
- lobby1
|
||||
- lobby2
|
||||
group2:
|
||||
- server1
|
||||
- server2
|
||||
```
|
||||
Contains 2 groups, each of them consisting of 2 servers.
|
||||
Server group name can be anything (in our case, they're called "lobbies" and "group2").
|
||||
Under group name, list the actual server names defined in config.yml of the proxy server.
|
||||
|
||||
With this setup, "lobby1" and "lobby2" will share playerlist, as well as "server1" with "server2". All unlisted servers are automatically put into a hidden default group and share playerlist. This means that all other servers except these 4 will share playerlist.
|
||||
|
||||
To make all servers share the playerlist, simply clear server groups and set
|
||||
```
|
||||
server-groups: {}
|
||||
```
|
||||
|
||||
### Pattern Matching
|
||||
Server names in groups support multiple pattern types for flexible configuration:
|
||||
|
||||
**Exact Match** - Matches server name exactly:
|
||||
```yaml
|
||||
server-groups:
|
||||
lobbies:
|
||||
- lobby1
|
||||
- lobby2
|
||||
```
|
||||
|
||||
**Wildcard Patterns** - Use `*` for prefix or suffix matching:
|
||||
```yaml
|
||||
server-groups:
|
||||
lobbies:
|
||||
- "Lobby-*" # Matches: Lobby-1, Lobby-2, Lobby-Hub, etc.
|
||||
- "*-lobby" # Matches: eu-lobby, us-lobby, etc.
|
||||
```
|
||||
|
||||
**Regex Patterns** - Use `regex:` prefix for advanced pattern matching:
|
||||
```yaml
|
||||
server-groups:
|
||||
lobbies:
|
||||
- regex:Lobby-[0-9]+ # Matches: Lobby-1, Lobby-23, but not Lobby-Hub
|
||||
smp:
|
||||
- regex:SMP-(EU|US)-[0-9]+ # Matches: SMP-EU-1, SMP-US-2, etc.
|
||||
```
|
||||
|
||||
Note: Wildcard patterns are case-insensitive, while regex patterns are case-sensitive by default (use `(?i)` flag for case-insensitive regex).
|
||||
|
||||
## Configuring isolated servers
|
||||
If you want servers which are isolated (no one will see these players, and they will not see anyone on other servers),
|
||||
create a new group and only put that 1 server there.
|
||||
For example:
|
||||
```
|
||||
global-playerlist:
|
||||
server-groups:
|
||||
test1:
|
||||
- isolatedServer1
|
||||
test2:
|
||||
- isolatedServer2
|
||||
```
|
||||
|
||||
This is not needed when `isolate-unlisted-servers` is set to `true`, in which case all unlisted servers are isolated by default.
|
||||
|
||||
## Seeing all players on the network from some server
|
||||
If, despite configuring server groups,
|
||||
you want players to see everyone on the network if they're connected to specific server(s),
|
||||
you can list those servers at
|
||||
```
|
||||
global-playerlist:
|
||||
spy-servers:
|
||||
- spyserver1
|
||||
- spyserver2
|
||||
```
|
||||
Now, players connected to "spyserver1" or "spyserver2" will see everyone on the network in tablist, but no one else (unless on another spy server / in the same server group) will see them.
|
||||
|
||||
# Placeholders
|
||||
Here are TAB's internal placeholders you can use when this feature is enabled:
|
||||
| Placeholder | Description |
|
||||
|-------------|-------------|
|
||||
| %playerlist-group_\<group\>% | Amount of online players in specified global playerlist group |
|
||||
|
||||
# Compatibility with other plugins
|
||||
For compatibility with vanish plugins, vanish status must be detected correctly. See [Additional information - Vanish detection](https://github.com/NEZNAMY/TAB/wiki/Additional-information#vanish-detection) for more info.
|
||||
|
||||
# Troubleshooting
|
||||
This is a collection of tips to help you figure out why the feature isn't working as you expect.
|
||||
To get started, run `/tab dump <player looking at the tablist>` and open the generated link. Scroll down to `features` -> `GlobalPlayerList` and check the content:
|
||||
* If it says `GlobalPlayerList: Feature is disabled`, it means you did not enable the feature. Enable it by setting
|
||||
```
|
||||
global-playerlist:
|
||||
enabled: true
|
||||
```
|
||||
* Check the `configuration` section and compare it with your config file. If it's different, you either forgot to reload TAB, uploaded the config to the wrong server, or did not upload it at all.
|
||||
* Check the `player info` section and make sure everything is as expected - server name, server group and other servers in that group. If server name says `N/A`, it means you did not configure `server-name` (TODO create section and link it).
|
||||
* Check the `visibility from viewer's perspective` table. Find the target player who the viewer should see but doesn't (or vice versa) and check their server, server group and whether they should be visible or not.
|
||||
<br /> **If "visible" doesn't match the expected result, but matches what is shown in-game:**
|
||||
* See the full message for a hint why the player is or is not visible
|
||||
* Make sure server groups are configured as desired
|
||||
* If the issue involves vanishing, see [Vanish Detection](https://github.com/NEZNAMY/TAB/wiki/Additional-information#vanish-detection). In short, make sure the player has `tab.seevanished` permission to see vanished players and if the vanish plugin is PremiumVanish, its layered vanish system does not block the target player from being seen by the viewer
|
||||
|
||||
**If "visible" matches the expected result, but not in-game result:**
|
||||
* If both players are on the same server, the visibility is managed purely by the server (and plugins there), not by TAB. It means the player was hidden by another plugin or not shown by the server itself, for example when using redis to connect the servers and TAB, but the different servers acting as one do not share tablist information between them.
|
||||
@@ -0,0 +1,211 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* [Design](#design)
|
||||
* [Chaining designs](#chaining-designs)
|
||||
* ~Commands~
|
||||
* ~Placeholders~
|
||||
* ~Limitations~
|
||||
* [Compatibility with other plugins](#compatibility-with-other-plugins)
|
||||
* [Additional info](#additional-info)
|
||||
* [Additional note 1 - [1.8 - 1.20.1] Not resetting on server switch](#additional-note-1---18---1201-not-resetting-on-server-switch)
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
* [API](#api)
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Per-version header/footer](#example-1---per-version-headerfooter)
|
||||
* [Example 2 - Per-world header/footer](#example-2---per-world-headerfooter)
|
||||
* [Example 3 - Dynamic line count](#example-3---dynamic-line-count)
|
||||
|
||||
# About
|
||||
Minecraft feature **introduced in 1.8** showing text above and below playerlist. It cannot be displayed on 1.7 clients in any way.
|
||||
|
||||

|
||||
|
||||
# Configuration
|
||||
The feature can be configured in **config.yml** under **header-footer** section.
|
||||
This is how the default configuration looks:
|
||||
```
|
||||
header-footer:
|
||||
enabled: true
|
||||
designs:
|
||||
world-test:
|
||||
display-condition: "%world%=test"
|
||||
header:
|
||||
- "Test header in world 'test'"
|
||||
footer:
|
||||
- "Test footer in world 'test'"
|
||||
default:
|
||||
header:
|
||||
- "<#FFFFFF>&m </#FFFF00>"
|
||||
- "&3&lServer name"
|
||||
- "&r&7&l>> %animation:Welcome%&3 &l%player%&7&l! &7&l<<"
|
||||
- "&r&7Online players: &f%online%"
|
||||
- "&6Online staff: &e%staffonline%"
|
||||
- ""
|
||||
footer:
|
||||
- "%animation:time%"
|
||||
- "&2Ping: %ping%"
|
||||
- "&7&l Used memory: %memory-used% MB / %memory-max% MB"
|
||||
- ""
|
||||
- "&r&7Visit our webpage %animation:web%"
|
||||
- "<#FFFFFF>&m </#FFFF00>"
|
||||
```
|
||||
All the options are explained in the following table.
|
||||
|
||||
| Option name | Default value | Description |
|
||||
|-------------------|-----------------------|-------------------------------------------------------------------|
|
||||
| enabled | true | Enables / Disables the feature |
|
||||
| designs | *Map* | Designs to display based on conditions (see below for more info). |
|
||||
|
||||
## Design
|
||||
A header/footer design consists of the following options:
|
||||
| Option name | Description |
|
||||
|-------------|------------------|
|
||||
| `display-condition` (optional) | [Condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) (either condition name or a conditional expression) <br /> that must be met for the design to be displayed. <br />If not defined, design will be displayed without any required condition. <br />If player does not meet condition, another design may be displayed <br /> based on chaining (see below for more info). |
|
||||
| `header` | List of lines to display in the header. |
|
||||
| `footer` | List of lines to display in the footer. |
|
||||
|
||||
**Example**:
|
||||
```
|
||||
header-footer:
|
||||
enabled: true
|
||||
designs:
|
||||
MyDesign: # Design name
|
||||
display-condition: "%world%=world" # Delete the line for no condition requirement
|
||||
header:
|
||||
- "Header for world %world%"
|
||||
footer:
|
||||
- "Footer for world %world%"
|
||||
```
|
||||
|
||||
## Chaining designs
|
||||
When defining more than 1 design in config, the plugin will display the correct design based on conditions.
|
||||
The plugin goes through all defined designs, starting with the design on top.
|
||||
If the design's condition is met or not set, it is displayed.
|
||||
If not, the next defined design is checked and so on.
|
||||
If no suitable design is found (the last one has a condition requirement which wasn't met), none is displayed.
|
||||
**Example**:
|
||||
```
|
||||
header-footer:
|
||||
enabled: true
|
||||
designs:
|
||||
per-world:
|
||||
display-condition: "%world%=world"
|
||||
header:
|
||||
- "Header for world world"
|
||||
footer:
|
||||
- "Footer for world world"
|
||||
default: # No display condition
|
||||
header:
|
||||
- "Header for every world except world"
|
||||
footer:
|
||||
- "Footer for every world except world"
|
||||
```
|
||||
Design `per-world` is checked first. If condition is not met, `default` is displayed.
|
||||
If a chaining 3 or more and player meets 2 or more conditions for 2 (or more) different designs, the first one defined in the config will be displayed. You can swap order of designs based on your priority needs.
|
||||
|
||||
# Compatibility with other plugins
|
||||
Header/Footer is a feature that cannot be handled by multiple plugins at once.
|
||||
To make sure no other plugin sends their own Header/Footer when not disabled in the plugin's config properly, TAB will block header/footer coming from all other plugins if this feature is enabled (and not disabled for a player with a condition).
|
||||
An exception to this is Velocity installation, where this "anti-override" is not available.
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - [1.8 - 1.20.1] Not resetting on server switch
|
||||
When under a BungeeCord network and having TAB installed on backend server and switching to another server, the header/footer will not reset. This is because BungeeCord makes it look like a world switch to the client. To avoid this, you have 2 options:
|
||||
* Install TAB on BungeeCord and disable header/footer on the server.
|
||||
* Install a plugin that sends some, or even empty header/footer on join.
|
||||
|
||||
Velocity sends a reset packet on server switch, so it isn't a problem there. It is also not a problem since 1.20.2, where configuration phase was added.
|
||||
|
||||
# Troubleshooting
|
||||
This is a collection of tips to help you figure out why the feature isn't working as you expect.
|
||||
To get started, run `/tab dump <affected player>` and open the generated link. Scroll down to `features` -> `HeaderFooter` and check the content:
|
||||
* If it says `HeaderFooter: Feature is disabled`, it means you disabled the feature. Enable it by setting
|
||||
```
|
||||
header-footer:
|
||||
enabled: true
|
||||
```
|
||||
* Check the `configuration` section and compare it with your config file. If it's different, you either forgot to reload TAB, or uploaded the config to the wrong server (or did not upload it at all).
|
||||
* Check the `chain` section and for each design and analyze the `display-condition` options (the value, with placeholders parsed, whether it is met or not) if it matches what you expect. If not, you may have made a mistake in your conditions. If more display conditions for more than 1 design are met, the first design with display condition met is displayed. See [Chaining designs](#chaining-designs) for more info.
|
||||
* Check `currently displayed design` and compare it with your expectations, as well as the actual in-game result. If it doesn't match your expectations, you didn't configure something correctly.
|
||||
* Make sure you don't have another plugin sending header/footer, such as CMI. While TAB should block other plugins from applying it, this functionality is not available on Velocity installation.
|
||||
|
||||
|
||||
# API
|
||||
*To get started with the API, see [Developer API](https://github.com/NEZNAMY/TAB/wiki/Developer-API) page.*
|
||||
|
||||
To access this feature, you'll need to obtain `HeaderFooterManager` instance. Get it using `TabAPI.getInstance().getHeaderFooterManager()`. If this feature is disabled, the method will return `null`.
|
||||
|
||||
To set the header and/or footer for a player, use the following:
|
||||
* `HeaderFooterManager#setHeader(TabPlayer, String)`
|
||||
* `HeaderFooterManager#setFooter(TabPlayer, String)`
|
||||
* `HeaderFooterManager#setHeaderAndFooter(TabPlayer, String, String)`
|
||||
|
||||
To reset the header and/or footer for a player back to their original values, use `null` as argument.
|
||||
|
||||
# Examples
|
||||
## Example 1 - Per-version header/footer
|
||||
Minecraft 1.21.9 has introduced [object components](https://github.com/NEZNAMY/TAB/wiki/How-to-use-Minecraft-components#object-components-1219), but these are not available for older versions. Let's make 2 designs, one for 1.21.9+ and second one for <1.21.9.
|
||||
```
|
||||
header-footer:
|
||||
enabled: true
|
||||
designs:
|
||||
newer-client:
|
||||
display-condition: "%player-version-id%>=773" # 1.21.9 uses 773
|
||||
header:
|
||||
- "Look, it's your head! <head:name:%player%>"
|
||||
footer:
|
||||
- "Cool, isn't it?"
|
||||
older-client:
|
||||
header:
|
||||
- "Regular header for old clients"
|
||||
footer:
|
||||
- "Consider updating your game"
|
||||
```
|
||||
|
||||
## Example 2 - Per-world header/footer
|
||||
For this, we can use design chaining with conditions. There is no limit to how many worlds we can configure, but let's stick to 3 designs - one for `world`, one for `world2` and one for the rest.
|
||||
```
|
||||
header-footer:
|
||||
enabled: true
|
||||
designs:
|
||||
world:
|
||||
display-condition: "%world%=world" # Only show if player is in world "world"
|
||||
header:
|
||||
- "Header for world world"
|
||||
footer:
|
||||
- "Footer for world world"
|
||||
world2:
|
||||
display-condition: "%world%=world2" # Only show if player is in world "world2"
|
||||
header:
|
||||
- "Header for world world2"
|
||||
footer:
|
||||
- "Footer for world world2"
|
||||
default:
|
||||
header:
|
||||
- "Header for all worlds except world and world2"
|
||||
footer:
|
||||
- "Footer for all worlds except world and world2"
|
||||
```
|
||||
|
||||
## Example 3 - Dynamic line count
|
||||
The entire header is just a single character sequence that allows newline symbol (`\n`) for new lines. It is only being split into multiple lines in config for convenience to make it readable when configuring and editing. Same for footer.
|
||||
If using a placeholder that returns the newline symbol, it will create a new line. You can use this to your advantage and create a [conditional placeholder](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) or an [animation](https://github.com/NEZNAMY/TAB/wiki/Animations) that includes newline in some frames.
|
||||
**Example**:
|
||||
|
||||
**animations.yml**
|
||||
```
|
||||
MyAnimation:
|
||||
change-interval: 1000
|
||||
texts:
|
||||
- "First frame with only 1 line"
|
||||
- "Second frame\nconsisting of 2 lines"
|
||||
```
|
||||
**config.yml**
|
||||
```
|
||||
header-footer:
|
||||
designs:
|
||||
DesignName:
|
||||
header:
|
||||
- "%animation:MyAnimation%"
|
||||
```
|
||||
@@ -0,0 +1,383 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* [Layout](#layout)
|
||||
* [Fixed slots](#fixed-slots)
|
||||
* [Player groups](#player-groups)
|
||||
* [Chaining layouts](#chaining-layouts)
|
||||
* [Skins](#skins)
|
||||
* ~Commands~
|
||||
* ~Placeholders~
|
||||
* ~Limitations~
|
||||
* [Compatibility with other plugins](#compatibility-with-other-plugins)
|
||||
* [Compatibility with other features](#compatibility-with-other-features)
|
||||
* [Playerlist objective incompatibility](#playerlist-objective-incompatibility)
|
||||
* [Global playerlist incompatibility](#global-playerlist-incompatibility)
|
||||
* [Per world playerlist incompatibility](#per-world-playerlist-incompatibility)
|
||||
* [Additional info](#additional-info)
|
||||
* [Additional note 1 - [1.19.3 - 1.21.1] Entries in chat complete](#additional-note-1---1193---1211-entries-in-chat-complete)
|
||||
* [Additional note 2 - [1.8 - 1.21.3] Second layer of skin missing](#additional-note-2---18---1213-second-layer-of-skin-missing)
|
||||
* [Additional note 3 - Entry overlap](#additional-note-3---entry-overlap)
|
||||
* ~Troubleshooting~
|
||||
* [API](#api)
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Per-server columns](#example-1---per-server-columns)
|
||||
* [Example 2 - Per-world playerlist](#example-2---per-world-playerlist)
|
||||
|
||||
# About
|
||||
This feature allows you to customize all 80 tablist slots (possibly less on 1.19.3+). This feature can be enabled and configured in **config.yml** file under **layout** section.
|
||||
|
||||
This feature is only available for versions **1.8** and up due to massive tablist changes, which would make 1.7- compatibility require a complete rewrite of the functionality and could still cause all kinds of visual issues, including, but not limited to compatibility with other plugins adding/removing players from the tablist.
|
||||
|
||||
# Configuration
|
||||
The feature can be configured in **config.yml** under **layout** section.
|
||||
This is how the default configuration looks:
|
||||
```
|
||||
layout:
|
||||
enabled: false
|
||||
direction: COLUMNS
|
||||
default-skin: mineskin:37e93c8e12cd426cb28fce31969e0674
|
||||
enable-remaining-players-text: true
|
||||
remaining-players-text: '... and %s more'
|
||||
empty-slot-ping-value: 1000
|
||||
layouts:
|
||||
default:
|
||||
slot-count: 80
|
||||
fixed-slots:
|
||||
- '1|&3Website&f:'
|
||||
- '2|&bmyserver.net'
|
||||
- '3|&8&m '
|
||||
- '4|&3Name&f:'
|
||||
- '5|&b%player%'
|
||||
- '7|&3Rank&f:'
|
||||
- '8|Rank: %group%'
|
||||
- '10|&3World&f:'
|
||||
- '11|&b%world%'
|
||||
- '13|&3Time&f:'
|
||||
- '14|&b%time%'
|
||||
- '21|&3Teamspeak&f:'
|
||||
- '22|&bts.myserver.net'
|
||||
- '23|&8&m '
|
||||
- '41|&3Store&f:'
|
||||
- '42|&bshop.myserver.net'
|
||||
- '43|&8&m '
|
||||
groups:
|
||||
staff:
|
||||
display-condition: permission:tab.staff
|
||||
slots:
|
||||
- 24-40
|
||||
players:
|
||||
slots:
|
||||
- 44-80
|
||||
```
|
||||
All the options are explained in the following table.
|
||||
|
||||
| Option name | Default value | Description |
|
||||
|-------------------------------|----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | true | Enables / Disables the feature |
|
||||
| direction | COLUMNS | Defines direction of slots. Options are COLUMNS (top to bottom, left to right) and ROWS (left to right, top to bottom). This does not only change the slot numbers in configuration, but will also affect the way players are being filled into player groups. |
|
||||
| default-skin | "mineskin:383747683" | Default skin to display for fixed slots that do not define a skin, empty slots and fixed slots with invalid skin. |
|
||||
| enable-remaining-players-text | true | When enabled and there are more players in a player group than available slots, the last slot of player group will show how many more players there are, instead of using the last slot for one more player. |
|
||||
| remaining-players-text | "... and %s more" | Text to show if option above is enabled. Use `%s` variable for defining how many more players there are. |
|
||||
| empty-slot-ping-value | 1000 | Ping value to use for fixed slots and empty slots. The ping intervals for bars are client sided and are as following: <br />- Negative value: ✖ <br />- 0 - 149: 5 bars <br />- 150 - 299: 4 bars <br />- 300 - 599: 3 bars <br />- 600 - 999: 2 bars <br />- 1000+: 1 bar |
|
||||
| layouts | *Map* | Layouts to display based on conditions (see below for more info). |
|
||||
|
||||
## Layout
|
||||
A layout consists of the following options:
|
||||
| Option name | Description |
|
||||
|-------------|------------------|
|
||||
| `display-condition` (optional) | [Condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) (either condition name or a conditional expression) that must be met for the layout to be displayed. If not defined, layout will be displayed without any required condition. If player does not meet condition, another layout may be displayed based on chaining (see below for more info). |
|
||||
| `default-skin` (optional) | Overrides global `default-skin` setting for this layout. |
|
||||
| `slot-count` (optional) | Amount of slots to show in this layout. If not specified, defaults to `80`. **Only works on 1.19.3+**. |
|
||||
| `fixed-slots` | List of fixed slots, see below for more info. |
|
||||
| `player-groups` | Map of player groups, see below for more info. |
|
||||
|
||||
### Fixed slots
|
||||
These are slots with fixed position that contain configurable text and skin.
|
||||
They can be configured under `fixed-slots` option of each layout. The definition syntax is `SLOT|TEXT[|SKIN]` (skin is optional). If you don't want to define custom skin for that slot, use `SLOT|TEXT`.
|
||||
`SLOT` - The position of the fixed slot. It can be from 1 to 80. By default, the direction is set to columns, so the first column is 1-20.
|
||||
`TEXT` - the text. It supports placeholders.
|
||||
`SKIN` - layout's skin, see below for configuration.
|
||||
Example:
|
||||
```
|
||||
fixed-slots:
|
||||
- '1|&3RAM&f:'
|
||||
- '2|&b%memory-used%MB / %memory-max%MB'
|
||||
- '3|&8&m '
|
||||
- '4|&3TPS&f:'
|
||||
- '5|&b%tps%'
|
||||
```
|
||||
If you do not wish to use any fixed slots, make it an empty list (`[]`).
|
||||
Example:
|
||||
```
|
||||
layouts:
|
||||
staff:
|
||||
fixed-slots: []
|
||||
```
|
||||
|
||||
### Player groups
|
||||
These are groups of players that meet the specified condition. They consist of 2 parts - condition and slots.
|
||||
|
||||
**1. Display Condition**
|
||||
The condition players must meet to be displayed in the group.
|
||||
If a player doesn't meet condition for a group, the next group's condition is checked
|
||||
(groups are checked in the order they are defined in config).
|
||||
If player doesn't meet any condition, they are not displayed at all.
|
||||
Display condition is not required (can be used to make a "default" group with the remaining players).
|
||||
|
||||
**2. Slots**
|
||||
Slot intervals dedicated to the group. Interval `1-5` would mean all slots from 1 to 5. In case you want to define multiple intervals to exclude some slots, define another interval below the first one.
|
||||
Example:
|
||||
```
|
||||
layouts:
|
||||
myLayout:
|
||||
groups:
|
||||
staff:
|
||||
display-condition: permission:tab.staff
|
||||
slots:
|
||||
- '24-40'
|
||||
players:
|
||||
slots:
|
||||
- '44-80'
|
||||
```
|
||||
In this example, slots `24-40` will be reserved for players with `tab.staff` permission. Players without that permission will be in slots `44-80`.
|
||||
|
||||
## Chaining layouts
|
||||
When defining more than 1 layout in config, the plugin will display the correct design based on conditions.
|
||||
The plugin goes through all defined layouts, starting with the design on top.
|
||||
If the layout's condition is met or not set, it is displayed.
|
||||
If not, the next defined layout is checked and so on.
|
||||
If no suitable layout is found (the last one has a condition requirement which wasn't met), no layout is displayed (player will see the normal tablist).
|
||||
Example:
|
||||
```
|
||||
layouts:
|
||||
staff:
|
||||
display-condition: "permission:tab.staff"
|
||||
fixed-slots:
|
||||
...
|
||||
groups:
|
||||
...
|
||||
default:
|
||||
fixed-slots:
|
||||
...
|
||||
groups:
|
||||
...
|
||||
```
|
||||
In this example, players with `tab.staff` permission will see `staff` layout, others will see `default` layout.
|
||||
|
||||
## Skins
|
||||
*If you're wondering how to enable / disable heads in the tablist, see [FAQ](https://github.com/NEZNAMY/TAB/wiki/Frequently-Asked-Questions#6---how-to-make-player-heads-visible-in-tablist).*
|
||||
|
||||
For players, their skin is displayed. For fixed slots and empty slots, you can specify which skin to show using the same skin syntax.
|
||||
Currently, TAB supports these skin formats:
|
||||
| Format | Example | Description |
|
||||
|--------|---------|-------------|
|
||||
| `mineskin:<UUID>` | `mineskin:37e93c8e12cd426cb28fce31969e0674` | Takes UUID from [MineSkin](https://mineskin.org). |
|
||||
| `player:<name>` | `player:Notch` | Displays skin of specified player. |
|
||||
| `texture:<texture>` | `texture:469b3bac406b51ba0e76c2c218aa4d45fde9ea7c101c85fbd8106c92c4aa36dd` | Uses skin texture from `textures.minecraft.net`. Skin browsing websites often show this value (for example `Texture URL` on mineskin.org). |
|
||||
|
||||
# Compatibility with other plugins
|
||||
This feature does not have any compatibility issues with other plugins.
|
||||
When it comes to compatibility with vanish plugins, see [Additional information - Vanish detection](https://github.com/NEZNAMY/TAB/wiki/Additional-information#vanish-detection).
|
||||
|
||||
# Compatibility with other features
|
||||
## Playerlist objective incompatibility
|
||||
To avoid showing fake players in tab-complete, TAB uses an empty string as the fake players' names.
|
||||
Though Minecraft's scoreboard objectives (which help achieve the Playerlist objective feature) only use players' names and not players' UUIDs to define values.
|
||||
As a result, it is impossible for TAB to assign a different value for each fake player since they all have the same name, making the [Playerlist objective](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Playerlist-Objective) feature incompatible.
|
||||
|
||||
## Global playerlist incompatibility
|
||||
The way this feature works is by pushing all real players out of the tablist and showing fake players instead.
|
||||
As a result, enabling [Global playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist) feature won't make any difference, since real players aren't visible in the tablist.
|
||||
Layout feature is capable of working with all online players connected to the server where TAB is installed, meaning it can show players from all servers when installed on a proxy. Because of this, if you use layout, you can disable global playerlist to reduce resource usage.
|
||||
|
||||
## Per world playerlist incompatibility
|
||||
Layout works by adding 80 fake players into the tablist, pushing real player entries out of view.
|
||||
Because of this,
|
||||
when using [per world playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Per-world-playerlist),
|
||||
the feature will only hide the real players,
|
||||
which are outside tablist and not visible anyway and not touch the layout entries.
|
||||
However, you can replicate the same effect using layout feature itself, using conditions.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
*We are going to ignore fixed slots in the examples,
|
||||
as they don't affect anything, and you can just configure them however you want.*
|
||||
Let's create 2 layouts, one for world `world1` and one for world `world2`.
|
||||
Each layout only displays players in that world.
|
||||
```
|
||||
layouts:
|
||||
layout1:
|
||||
display-condition: "%world%=world1"
|
||||
fixed-slots: []
|
||||
groups:
|
||||
players:
|
||||
display-condition: "%world%=world1"
|
||||
slots:
|
||||
- 1-80
|
||||
layout2:
|
||||
display-condition: "%world%=world2"
|
||||
fixed-slots: []
|
||||
groups:
|
||||
players:
|
||||
display-condition: "%world%=world2"
|
||||
slots:
|
||||
- 1-80
|
||||
```
|
||||
You can also merge multiple worlds into a group.
|
||||
```
|
||||
layouts:
|
||||
layout1:
|
||||
display-condition: "%world%=world1|%world%=world2"
|
||||
fixed-slots: []
|
||||
groups:
|
||||
players:
|
||||
display-condition: "%world%=world1|%world%=world2"
|
||||
slots:
|
||||
- 1-80
|
||||
```
|
||||
You can also replicate "ignore-effect-in-worlds" by creating a layout with condition for displaying, but not for groups.
|
||||
```
|
||||
layouts:
|
||||
globalWorld:
|
||||
display-condition: "%world%=globalWorld"
|
||||
fixed-slots: []
|
||||
groups:
|
||||
players: # No condition here to show all players
|
||||
slots:
|
||||
- 1-80
|
||||
```
|
||||
</details>
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - [1.19.3 - 1.21.1] Entries in chat complete
|
||||
From 1.19.3 until 1.21.1 (inclusive), entries will also appear in chat complete.
|
||||
The mechanic used to hide them on <1.19.3 can no longer be used since 1.19.3.
|
||||
1.21.2 has added a new way of sorting players, which is being taken advantage of to restore empty chat complete.
|
||||
|
||||
## Additional note 2 - [1.8 - 1.21.3] Second layer of skin missing
|
||||
Layout works by creating 80 fake entries, pushing real players out of the tablist.
|
||||
Unfortunately, players must be spawned around the player viewing the tablist to see the second layer of their skin.
|
||||
Since those fake entries you see are not the actual players and aren't spawned,
|
||||
as a result, you won't see the second layers of skins.
|
||||
This can only be fixed by actually letting the real entries display in the tablist,
|
||||
which would require a rework of the feature, which is not planned.
|
||||
**1.21.4 has added a new tablist option called "show hats", which layout sets to true.
|
||||
They will be visible for 1.21.4+ players.**
|
||||
|
||||
## Additional note 3 - Entry overlap
|
||||
Tablist entries automatically adapt their width based on the longest entry.
|
||||
The final width is global for all columns, not just using the longest width in each respective column.
|
||||
When the requested width is higher than the game window can handle, the text in entries will start to overlap.
|
||||
This is how it looks with 1/4 screen size, which is the default window size when launching Minecraft.
|
||||
<img width="855" height="519" alt="image" src="https://github.com/user-attachments/assets/2a256b25-c672-49ea-8c8f-d670aa9efd43" />
|
||||
This can be solved by increasing window size either manually, or by pressing the expand button on the top left, next to the "X".
|
||||
If it still looks the same for you even though you have the game in full screen, your GUI scale can be messed up.
|
||||
|
||||
To fix it, go to `Esc -> Options -> Video Settings...` and set `GUI Scale: ` to a lower value.
|
||||
|
||||
If you are looking for a more systematic solution that will automatically work for all of your players and not just you, the only way is to make the entries shorter.
|
||||
Here are a few tips how to do that:
|
||||
* Avoid using suffix altogether
|
||||
* Do not use bold (`&l`) code
|
||||
* Use a shorter alternative for your prefixes, such as `A` instead of `Admin`
|
||||
* Remove unnecessary brackets from prefix
|
||||
|
||||
|
||||
# API
|
||||
*To get started with the API, see [Developer API](https://github.com/NEZNAMY/TAB/wiki/Developer-API) page.*
|
||||
|
||||
To access this feature, you'll need to obtain `LayoutManager` instance. Get it using `TabAPI.getInstance().getLayoutManager()`. If this feature is disabled, the method will return `null`.
|
||||
|
||||
The `LayoutManager` has the following methods:
|
||||
* `Layout createNewLayout(String name)` - Creates new layout with given internal name and 80 slots.
|
||||
* `Layout createNewLayout(String name, int slotCount)` - Creates new layout with given internal name and slot count (for 1.19.3+, <1.19.3 players will still see 80 slots).
|
||||
* `Layout getLayout(String name)` - Returns layout by given internal name. Works for layouts created in both configuration and through the API.
|
||||
* `sendLayout(TabPlayer player, Layout layout)` - Sends given layout to the player, overriding configuration. Sending `null` as layout will restore layout from configuration.
|
||||
|
||||
After creating a `Layout` using the API or getting it from configuration, you can use the following methods:
|
||||
* `String getName()` - Returns layout's name
|
||||
* `addFixedSlot(int slot, String text)` / `addFixedSlot(int slot, String text, String skin)` / `addFixedSlot(int slot, String text, int ping)` / `addFixedSlot(int slot, String text, String skin, int ping)` / `addFixedSlot(int slot, String text, String skin, String ping)` - Adds a fixed slot with gieven properties - slot, text, skin (optional) and ping (optional)
|
||||
* `addGroup(String condition, int[] slots)` - Adds a new player group with given condition (nullable for no condition) and slots. Condition can be either a conditional expression, or a condition created in config.
|
||||
|
||||
# Examples
|
||||
## Example 1 - Per-server columns
|
||||
```
|
||||
layout:
|
||||
enabled: true
|
||||
direction: COLUMNS
|
||||
default-skin: mineskin:383747683
|
||||
enable-remaining-players-text: true
|
||||
remaining-players-text: '... and %s more'
|
||||
empty-slot-ping-value: 1000
|
||||
layouts:
|
||||
default:
|
||||
fixed-slots:
|
||||
- "1|&2&lLobby"
|
||||
- "21|&2&lSurvival"
|
||||
- "41|&2&lCreative"
|
||||
- "61|&2&lSkyblock"
|
||||
groups:
|
||||
lobby:
|
||||
display-condition: "%server%=lobby"
|
||||
slots:
|
||||
- 2-20
|
||||
survival:
|
||||
display-condition: "%server%=survival"
|
||||
slots:
|
||||
- 22-40
|
||||
creative:
|
||||
display-condition: "%server%=creative"
|
||||
slots:
|
||||
- 42-60
|
||||
skyblock:
|
||||
display-condition: "%server%=skyblock"
|
||||
slots:
|
||||
- 62-80
|
||||
```
|
||||
You can also remove the last condition (in this case `display-condition: "%server=skyblock%"`) and the columns will be used for all other servers, instead of just a specified one.
|
||||

|
||||
|
||||
|
||||
## Example 2 - Per-world playerlist
|
||||
If you want to reproduce the per-world-playerlist feature but with layouts, you can use relational conditions to check the viewer's world (`%viewer:world%`) with the target player's world (`%world%`) like so:
|
||||
```yml
|
||||
layout:
|
||||
enabled: true
|
||||
direction: COLUMNS
|
||||
default-skin: mineskin:383747683
|
||||
enable-remaining-players-text: true
|
||||
remaining-players-text: '... and %s more'
|
||||
empty-slot-ping-value: 1000
|
||||
layouts:
|
||||
default:
|
||||
slot-count: 80
|
||||
fixed-slots:
|
||||
- '1|&3Website&f:'
|
||||
- '2|&bmyserver.net'
|
||||
- '3|&8&m '
|
||||
- '4|&3Name&f:'
|
||||
- '5|&b%player%'
|
||||
- '7|&3Rank&f:'
|
||||
- '8|Rank: %group%'
|
||||
- '10|&3World&f:'
|
||||
- '11|&b%world%'
|
||||
- '13|&3Time&f:'
|
||||
- '14|&b%time%'
|
||||
- '21|&3Teamspeak&f:'
|
||||
- '22|&bts.myserver.net'
|
||||
- '23|&8&m '
|
||||
- '41|&3Store&f:'
|
||||
- '42|&bshop.myserver.net'
|
||||
- '43|&8&m '
|
||||
groups:
|
||||
players:
|
||||
display-condition: "%viewer:world%=%world%"
|
||||
slots:
|
||||
- 24-40
|
||||
- 44-80
|
||||
```
|
||||
> [!NOTE]
|
||||
> This is just an example, relational conditions are not limited to displaying only players in your world.
|
||||
> If you want players in your server on proxy, use `%viewer:server%=%server%` in `display-condition`.
|
||||
> This works for any placeholder offered by TAB or by PlaceholderAPI.
|
||||
@@ -0,0 +1,39 @@
|
||||
# Enabling
|
||||
Find this section in your config:
|
||||
```
|
||||
proxy-support:
|
||||
enabled: true
|
||||
# Supported types: PLUGIN, REDIS, RABBITMQ
|
||||
type: PLUGIN
|
||||
plugin:
|
||||
# Compatible plugins: RedisBungee
|
||||
# If enabled and compatible plugin is found, hook is enabled to work with proxied players
|
||||
name: RedisBungee
|
||||
redis:
|
||||
url: 'redis://:password@localhost:6379/0'
|
||||
rabbitmq:
|
||||
exchange: 'plugin'
|
||||
url: 'amqp://guest:guest@localhost:5672/%2F'
|
||||
```
|
||||
Pick your desired way and configure it. I don't know anything about redis or rabbitmq, so good luck.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **BACKEND INSTALLATION ONLY**
|
||||
> You should also add this into your **config.yml** and configure it:
|
||||
> ```
|
||||
> server-name: "server"
|
||||
> ```
|
||||
> Ideally, name it the same as servers in your proxy config. This value will be used for getting player's server name. Aside from %server% placeholder, it will be used for internal logic when checking for player's server. One of them is global playerlist not adding/removing players who are on the same server in the tablist, as backend servers already do this (and duplicating actions would cause problems).
|
||||
> **As a result, not configuring this value will result in everyone's server being "N/A", therefore global playerlist will think everyone is on the same server and not add anyone into the tablist, effectively making the feature not work.**
|
||||
|
||||
Supported plugins:
|
||||
* [RedisBungee](https://github.com/ProxioDev/RedisBungee)
|
||||
|
||||
# Supported features
|
||||
* [Belowname](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Belowname)
|
||||
* [Global playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist)
|
||||
* [Nametags](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Nametags) & [Sorting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Sorting-players-in-tablist)
|
||||
* [Tablist name formatting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Tablist-name-formatting)
|
||||
* [Playerlist Objective](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Playerlist-Objective)
|
||||
|
||||
The hook does not and will never support [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout), which would require drastic changes to the feature itself and wouldn't be worth it, since the amount of visible players is usually even lower due to fixed slots and RedisBungee is used on networks with many players, so there will be enough players to work with anyway.
|
||||
@@ -0,0 +1,306 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* [config.yml](#configyml)
|
||||
* [groups.yml and users.yml](#groupsyml-and-usersyml)
|
||||
* [Global settings](#global-settings)
|
||||
* [Per-world / per-server](#per-world--per-server)
|
||||
* [Priorities](#priorities)
|
||||
* [Name color](#name-color)
|
||||
* [Commands](#commands)
|
||||
* [Placeholders](#placeholders)
|
||||
* [Limitations](#limitations)
|
||||
* [Compatibility with other plugins](#compatibility-with-other-plugins)
|
||||
* [Additional info](#additional-info)
|
||||
* [Additional note 1 - NPC (in)compatibility](#additional-note-1---npc-incompatibility)
|
||||
* [Additional note 2 - Prefix/suffix on pets](#additional-note-2---prefixsuffix-on-pets)
|
||||
* [Additional note 3 - Changing name itself](#additional-note-3---changing-name-itself)
|
||||
* [Additional note 4 - F1 view](#additional-note-4---f1-view)
|
||||
* [Additional note 5 - Transparent players](#additional-note-5---transparent-players)
|
||||
* [Additional note 6 - Vanish hook](#additional-note-6---vanish-hook)
|
||||
* ~Troubleshooting~
|
||||
* [API](#api)
|
||||
* [Changing prefix and suffix](#changing-prefix-and-suffix)
|
||||
* [Collision](#collision)
|
||||
* [Manipulating visibility](#manipulating-visibility)
|
||||
* [Disabling team handling](#disabling-team-handling)
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Taking prefix/suffix from permission plugin](#example-1---taking-prefixsuffix-from-permission-plugin)
|
||||
* [Example 2 - Making nametags invisible on a subserver](#example-2---making-nametags-invisible-on-a-subserver)
|
||||
|
||||
# About
|
||||
Nametags are controlled by a feature called scoreboard teams. They offer 6 properties:
|
||||
* Team name - used for sorting players in tablist, see [Sorting guide](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Sorting-players-in-tablist) for more info
|
||||
* Prefix - prefix displayed in nametag, it will be referred to as `tagprefix`
|
||||
* Suffix - suffix displayed in nametag, it will be referred to as `tagsuffix`
|
||||
* Nametag visibility rule
|
||||
* Collision rule
|
||||
* Team color (1.13+) - used to set name and glow color (check out [How to make TAB compatible with glow plugins](https://github.com/NEZNAMY/TAB/wiki/How-to-make-TAB-compatible-with-glow-plugins)) (on 1.12- it uses last color of prefix).
|
||||
* Options - AllowFriendlyFire and CanSeeFriendlyInvisibles
|
||||
|
||||
When enabling this feature, TAB will control all of these. It is not possible to take values from 2 different teams (plugins). Most of the compatibility problems with other plugins can be solved with placeholders. If you want sorting but not nametags, just don't configure any prefix/suffix. If you want another plugin to handle teams, configure sorting in that plugin.
|
||||
|
||||
# Configuration
|
||||
This feature is configured in 2 parts based on what you are configuring. Most settings are in the **config.yml**, but prefix/suffix is configured in **groups.yml** and **users.yml**.
|
||||
## config.yml
|
||||
The first part can be configured in **config.yml** under **scoreboard-teams** section. It controls everything except prefix and suffix.
|
||||
|
||||
This is how the default configuration looks (excluding sorting options):
|
||||
```
|
||||
scoreboard-teams:
|
||||
enabled: true
|
||||
enable-collision: true
|
||||
invisible-nametags: false
|
||||
can-see-friendly-invisibles: false
|
||||
disable-condition: '%world%=disabledworld'
|
||||
```
|
||||
All of the options are explained in the following table.
|
||||
| Option name | Default value | Description |
|
||||
|-----------------------------|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | true | Enables / Disables the feature |
|
||||
| enable-collision | true | Controls collision rule. Available values are: <br />- `true` - Collision will be enabled permanently. <br />- `false` - Collision will be disabled permanently. <br /> - *Conditional expression* - Collision will be enabled if player meets the [short format](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders#short-format) conditional expression (for example `%world%=world` will result in collision only being enabled for players in world `world`). <br /> - *Condition name* - Uses name of a [defined condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) that must be met for a player to have collision enabled. |
|
||||
| invisible-nametags | false | Controls nametags visibility rule. Available values are: <br />- `true` - Nametags will be invisible. <br />- `false` - Nametags will be visible. <br /> - *Conditional expression* - Nametags will be invisible if player meets the [short format](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders#short-format) conditional expression. <br /> - *Condition name* - Uses name of a [defined condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders). <br /> Option to hide nametags was added in Minecraft **1.8**, therefore it will not work on 1.7. |
|
||||
| can-see-friendly-invisibles | false | Controls value of the team flag. It allows you to see invisible players in the same team as transparent instead of completely invisible. Since TAB places each player into an individual team, this option will only take effect in combination with plugins that spawn a dummy clone of the player (sit or disguise plugins). |
|
||||
| disable-condition | %world%=disabledworld | A [condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) that must be met for disabling the feature for players. Set to empty for not disabling the feature ever. |
|
||||
|
||||
## groups.yml and users.yml
|
||||
This part allows you to configure prefix and suffix. They are called `tagprefix` and `tagsuffix`, where "tag" refers to name tag, to allow separation from tablist settings.
|
||||
|
||||
### Global settings
|
||||
Properties can be applied in 2 ways: groups and users. Users can be defined by both username and their UUID. Values applied to users take priority over groups.
|
||||
|
||||
**groups.yml**
|
||||
```
|
||||
admin:
|
||||
tagprefix: "&4&lAdmin &r"
|
||||
```
|
||||
Or with an in-game command `/tab group admin tagprefix "&4&lAdmin &r"`.
|
||||
|
||||
**users.yml**
|
||||
```
|
||||
_NEZNAMY_:
|
||||
tagprefix: "&6&lTAB &r"
|
||||
|
||||
# An alternate way using UUID
|
||||
237d8b55-3f97-4749-aa60-e9fe97b45062:
|
||||
tagprefix: "&6&lTAB &r"
|
||||
```
|
||||
Or with in-game commands `/tab player _NEZNAMY_ tagprefix "&6&lTAB &r"` and `/tab playeruuid _NEZNAMY_ tagprefix "&6&lTAB &r"` (the player must be online for uuid option to work).
|
||||
|
||||
Properties can also be set as "default" for everyone who does not have them defined.
|
||||
For that purpose, a group keyword `_DEFAULT_` was made.
|
||||
Example:
|
||||
**groups.yml**
|
||||
```
|
||||
admin:
|
||||
tagprefix: "&4&lAdmin &r"
|
||||
_DEFAULT_:
|
||||
tagprefix: "&7" # This will be displayed on everyone except admin
|
||||
```
|
||||
|
||||
### Per-world / per-server
|
||||
Values can also be applied per-world (and per-server on a proxy), where they can be defined per group/user. These values take priority over global settings. Example:
|
||||
**groups.yml**
|
||||
```
|
||||
per-world:
|
||||
world1:
|
||||
_DEFAULT_:
|
||||
tagprefix: "&a" # Everyone in world "world1" will have this prefix
|
||||
per-server:
|
||||
server1:
|
||||
_DEFAULT_:
|
||||
tagprefix: "&a" # Everyone in server "server1" will have this prefix
|
||||
```
|
||||
|
||||
For multiple worlds/servers to share the same settings, separate them with a`;`.
|
||||
For worlds/server starting with a specified text, use `*` after shared part. For ending with a shared part, use `*` at the beginning.
|
||||
Example:
|
||||
```
|
||||
per-world:
|
||||
world1;world2:
|
||||
_DEFAULT_:
|
||||
tagsuffix: "Shared tagsuffix in worlds world1 and world2"
|
||||
lobby-*:
|
||||
_DEFAULT_:
|
||||
tagsuffix: "Suffix in all worlds starting with lobby-"
|
||||
```
|
||||
|
||||
### Priorities
|
||||
The full list of priorities to choose correct prefix/suffix for a player looks like this:
|
||||
1. value set using the [API](#api)
|
||||
2. per-world / per-server applied to username
|
||||
3. value applied to username
|
||||
4. per-world / per-server applied to uuid
|
||||
5. value applied to uuid
|
||||
6. per-world / per-server applied to player's group
|
||||
7. per-world / per-server applied to group `_DEFAULT_`
|
||||
8. value applied to player's group
|
||||
9. value applied to group `_DEFAULT_`
|
||||
|
||||
This list is browsed through until the first match is found. If no match is found, empty value is used.
|
||||
|
||||
Values are taken independently of each other.
|
||||
This means you can set per-world tagprefix, but only keep one global tagsuffix, for example.
|
||||
|
||||
You can see the source of a value displayed on player by using `/tab dump <player>`, opening the link and checking "source"
|
||||
part of the value you are looking for (tagprefix / tagsuffix).
|
||||
|
||||
## Name color
|
||||
On versions 1.12.2 and below, name color follows the last color of prefix. This also includes magic codes. On 1.13+, this is no longer the case. Instead, a new field called "team color" was created. This is an enum constant, where we need to pick from 22 options - 16 colors, 5 magic codes and reset. **As you can see, it doesn't allow for RGB colors**. This also means name can no longer have color and magic codes simultaneously.
|
||||
|
||||
TAB does not have an option for configuring team color to avoid complexity, such as per-version configuration, or having to configure an additional field.
|
||||
For that reason, TAB detects the last used color code and uses that for team color.
|
||||
> [!CAUTION]
|
||||
> An exception is when using MiniMessage syntax / using RGB codes on server which has MiniMessage library. In this scenario, it is not possible to detect reset (`&r`) as last used "color", because in Minecraft components it is not a color, rather, it resets formatting by setting all magic codes to false / color to null. If you use `&r` (`<reset>`) and notice it not working, replace it with `&f` (`<white>`) (or add it after the reset to be safe). There seems to be no difference between setting color to `WHITE` versus `RESET`.
|
||||
|
||||
# Commands
|
||||
| Command | Permission | Description |
|
||||
|--------------------------------------------------------------------|--------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| /tab nametag <show/hide/toggle> \[player\] \[viewer\] \[options\] | `tab.nametag.visibility` (for yourself) <br /> `tab.nametag.visibility.other` (for others) | Shows / hides / toggles nametag of a specified player. If viewer is specified, view is only affected for the viewer. You can use `-s` as option for silent toggling (no chat message for affected player). |
|
||||
| /tab nametag <showview/hideview/toggleview> \[viewer\] \[options\] | `tab.nametag.view` (for yourself) <br /> `tab.nametag.view.other` (for others) | Shows / hides / toggles nametag VIEW a specified player. You can use `-s` as option for silent toggling (no chat message for affected player) |
|
||||
| /tab setcollision \<player\> \<true\|false\> | `tab.setcollision` | Forces collision rule for specified player, overriding configuration. |
|
||||
|
||||
# Placeholders
|
||||
Here are TAB's PlaceholderAPI placeholders you can use when this feature is enabled:
|
||||
| Placeholder | Description |
|
||||
|-------------|-------------|
|
||||
| `%tab_tagprefix%` | Player's current tagprefix with placeholders parsed. |
|
||||
| `%tab_tagsuffix%` | Player's current tagprefix with placeholders parsed. |
|
||||
| `%tab_tagprefix_raw%` | Player's current raw tagprefix with placeholder identifiers. |
|
||||
| `%tab_tagsuffix_raw%` | Player's current raw tagsuffix with placeholder identifiers. |
|
||||
| `%tab_nametag_visibility%` | "Enabled" if player can see nametags, "Disabled" if disabled using `/tab nametag toggleview` |
|
||||
|
||||
# Limitations
|
||||
* [1.12.2-] Prefix/suffix length is limited to 16 characters (including color codes). Any characters beyond that will be cut to prevent players getting disconnected.
|
||||
* [1.13+] Name color is controlled by a chat format enum constant. This means:
|
||||
* Name can only have one code. That is either color or magic code (such as &4 or &l), but not both.
|
||||
* Name does not support RGB codes. Any used RGB colors will be rounded to the nearest legacy code.
|
||||
* The same value manages name color and glow color, which means they cannot be different.
|
||||
* The name cannot be effectively changed and the plugin doesn't offer it.
|
||||
|
||||
If you want to avoid these at all costs, the only way is to create entities (armor stands / display) and make them ride the player (or teleport). TAB no longer offers this functionality due to a large amount of unfixable issues (full thread [here](https://gist.github.com/NEZNAMY/f4cabf2fd9251a836b5eb877720dee5c/)). You can, however, check out these 3rd party plugins (**not affiliated with me in any way, use at your own risk**):
|
||||
* [UnlimitedNameTags](https://www.spigotmc.org/resources/unlimitednametags.117526/)
|
||||
* [DisplayNameTags](https://github.com/Matt-MX/DisplayNameTags)
|
||||
* [NotJustNamePlates](https://github.com/YouHaveTrouble/NotJustNameplates)
|
||||
* [CustomNameplates](https://polymart.org/product/2543/customnameplates)
|
||||
|
||||
# Compatibility with other plugins
|
||||
Scoreboard teams is a feature that cannot be handled by multiple plugins at once.
|
||||
To make sure no other plugin sends their own teams when not disabled in the plugin's config properly, TAB will block players being added into teams coming from all other plugins (if this feature is enabled and not disabled for a player with a condition).
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - NPC (in)compatibility
|
||||
Teams are bound to player names, not UUIDs or entity ids.
|
||||
Because of that, they will affect all player entities with that name.
|
||||
This includes NPCs with the same names as online players, and prefixes/suffixes will be displayed on those as well.
|
||||
To avoid it, make their names not match any online player and use holograms to display them instead
|
||||
(Citizens plugin has an option for this).
|
||||
|
||||
## Additional note 2 - Prefix/suffix on pets
|
||||
Since Minecraft 1.9, teams affect tamed animals as well, displaying prefix/suffix on them as well and if nametags are set to be invisible, they will be completely invisible as well. If you want to avoid it, install [this plugin](https://www.spigotmc.org/resources/109466/).
|
||||
|
||||
## Additional note 3 - Changing name itself
|
||||
Teams do not allow to change the nametag name itself and TAB does not offer this functionality in any (other) way. For more information, see [How to display name from nickname plugins - Nametag](https://github.com/NEZNAMY/TAB/wiki/How-to-display-name-from-nickname-plugins#nametag).
|
||||
|
||||
## Additional note 4 - F1 view
|
||||
Using teams causes player nametags to remain visible when using F1 view.
|
||||
The plugin cannot avoid this in any way.
|
||||
The only possible solution would be to modify the client.
|
||||
|
||||
## Additional note 5 - Transparent players
|
||||
Minecraft's teams can show players in the same team transparent (partially invisible).
|
||||
This requires both players (viewer and target) to be in the same team.
|
||||
As such, this effect is impossible to achieve with TAB,
|
||||
because it puts every player into a different team
|
||||
to properly sort players and give them different prefix/suffix in nametag
|
||||
(and more, such as collision and nametag visibility).
|
||||
|
||||
If you want this effect, the only way is to use another plugin that offers this and disable TAB's teams entirely by setting
|
||||
```
|
||||
scoreboard-teams:
|
||||
enabled: false
|
||||
```
|
||||
In config.yml. Keep in mind, you'll not be able to use any team features if you do so.
|
||||
|
||||
## Additional note 6 - Vanish hook
|
||||
When a player is [vanished](https://github.com/NEZNAMY/TAB/wiki/Additional-information#vanish-detection), their team is unregistered for all other players who do **not** have `tab.seevanished` permission.
|
||||
|
||||
The purpose of this is to avoid players figuring out a staff member is still online but just vanished by "checking" registered teams and their members.
|
||||
An example of "exploiting" this is to have a 3rd party client spawn a player entity with name of a chosen player (staff member) and seeing if their name is formatted (= team is registered = player is online) or not (offline).
|
||||
|
||||
For this reason, make sure you give all of your staff members who can see vanished players the `tab.seevanished` permission, otherwise the vanished player will appear on top of the tablist (players without team are above players with team) and their nametag will not be formatted.
|
||||
|
||||
# API
|
||||
*To get started with the API, see [Developer API](https://github.com/NEZNAMY/TAB/wiki/Developer-API) page.*
|
||||
|
||||
To access this feature, you'll need to obtain `NameTagManager` instance. Get it using `TabAPI.getInstance().getNameTagManager()`. If this feature is disabled, the method will return `null`.
|
||||
|
||||
## Changing prefix and suffix
|
||||
To set the values for the respective formatting, use the following:
|
||||
* `NameTagManager#setPrefix(TabPlayer, String)`
|
||||
* `NameTagManager#setSuffix(TabPlayer, String)`
|
||||
|
||||
To reset them, set values to `null`.
|
||||
|
||||
To get custom values previously set using the API (they will return `null` if no custom value is set):
|
||||
* `NameTagManager#getCustomPrefix(TabPlayer)`
|
||||
* `NameTagManager#getCustomSuffix(TabPlayer)`
|
||||
|
||||
To get the original value set by the plugin based on configuration:
|
||||
* `NameTagManager#getOriginalRawPrefix(TabPlayer)` - Prefix with raw placeholder identifiers
|
||||
* `NameTagManager#getOriginalRawSuffix(TabPlayer)` - Suffix with raw placeholder identifiers
|
||||
* `NameTagManager#getOriginalReplacedPrefix(TabPlayer)` - Prefix with all placeholders parsed
|
||||
* `NameTagManager#getOriginalReplacedSuffix(TabPlayer)` - Suffix with all placeholders parsed
|
||||
|
||||
> [!NOTE]
|
||||
> These values are only temporary,
|
||||
> meaning they won't get saved anywhere and will get reset on player quit or plugin reload.
|
||||
> If you wish to save these values into file,
|
||||
> use [commands](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions#tab-playergroupplayeruuid-name-property-value-options).
|
||||
|
||||
## Collision
|
||||
* `NameTagManager#setCollisionRule(TabPlayer, Boolean)` - Forces collision rule to the player. Use `null` to reset value and make it follow configuration again.
|
||||
* `NameTagManager#getCollisionRule(TabPlayer)` - Returns forced collision rule using the API, `null` if no value was forced and player follows the configuration.
|
||||
|
||||
## Manipulating visibility
|
||||
* `NameTagManager#hideNametag(TabPlayer)` - Hides player's nametag from all players
|
||||
* `NameTagManager#hideNametag(TabPlayer, TabPlayer)` - Hides player's nametag from a specific player, where the first `TabPlayer` is the player whose nametag you want to hide, and the second `TabPlayer` is the player who you want to hide the first player's nametag from.
|
||||
* `NameTagManager#showNametag(TabPlayer)` - Shows player's nametag back again for everyone
|
||||
* `NameTagManager#showNametag(TabPlayer, TabPlayer)` - Shows player's nametag back. The first `TabPlayer` is the player whose nametag you want to show, and the second `TabPlayer` is the player who you want to show the first player's nametag to.
|
||||
* `NameTagManager#hasHiddenNametag(TabPlayer)` - Returns `true` if player has hidden nametag for everyone, `false` if not
|
||||
* `NameTagManager#hasHiddenNametag(TabPlayer, TabPlayer)` - Returns `true` if player has hidden nametag for specific player, `false` if not. The first `TabPlayer` is the player whose nametag you want to check is hidden, and the second `TabPlayer` is the player who you want to check if they can see the first player's nametag.
|
||||
|
||||
## Disabling team handling
|
||||
* `NameTagManager#pauseTeamHandling(TabPlayer)` - Pauses team handling for a specific player. This will unregister the player's team and disable anti-override for teams.
|
||||
* `NameTagManager#resumeTeamHandling(TabPlayer)` - Resumes team handling for a specific player. This will register the player's team and enable anti-override for teams.
|
||||
* `NameTagManager#hasTeamHandlingPaused(TabPlayer)` - Returns `true` if handling is disabled using methods above, `false` if not.
|
||||
|
||||
# Examples
|
||||
## Example 1 - Taking prefix/suffix from permission plugin
|
||||
If you want TAB to only take prefixes/suffixes from the permission plugin,
|
||||
delete all groups from **groups.yml** and only keep this:
|
||||
```
|
||||
_DEFAULT_:
|
||||
tagprefix: "%luckperms-prefix%"
|
||||
tagsuffix: "%luckperms-suffix%"
|
||||
```
|
||||
Or a PlaceholderAPI placeholder from your permission plugin if you use a different one.
|
||||
|
||||
> [!NOTE]
|
||||
> When doing this, make sure you don't delete something you didn't mean to delete, for example ta**b**prefix and ta**b**suffix from tablist name formatting feature.
|
||||
|
||||
## Example 2 - Making nametags invisible on a subserver
|
||||
The config option `invisible-nametags` takes either a [condition or a conditional expression](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders).
|
||||
We can use short format `%server%=<server name>`. If the server name is `server1`, it will look like this:
|
||||
```
|
||||
invisible-nametags: "%server%=server1"
|
||||
```
|
||||
If we want to disable it in 2 servers, we separate them with `|` (OR). Result:
|
||||
```
|
||||
invisible-nametags: "%server%=server1|%server%=server2"
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> This is just an example, the plugin is not limited to making nametags invisible only based on server.
|
||||
> If you want to disable them in a world, use %world% with world name(s).
|
||||
> This works for any placeholder offered by TAB or by PlaceholderAPI.
|
||||
@@ -0,0 +1,74 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* [Grouping playerlist from multiple worlds](#grouping-playerlist-from-multiple-worlds)
|
||||
* [Pattern Matching](#pattern-matching)
|
||||
* ~Commands~
|
||||
* ~Placeholders~
|
||||
* ~Limitations~
|
||||
* ~Compatibility with other plugins~
|
||||
* ~Additional Info~
|
||||
* ~Troubleshooting~
|
||||
* ~API~
|
||||
* ~Examples~
|
||||
|
||||
# About
|
||||
This feature allows you to limit players you see in tablist to only players in your world, or in a group of worlds.
|
||||
This feature can be configured in **config.yml** under **per-world-playerlist** section.
|
||||
To use it, you need TAB installed on Bukkit server. This feature is not available on any other platform.
|
||||
|
||||
# Configuration
|
||||
| Option name | Default value | Description |
|
||||
|--------------------------------|---------------|-------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | false | Enables / Disables the feature. |
|
||||
| allow-bypass-permission | false | If enabled, players with `tab.bypass` permission will see everyone in tablist despite this feature enabled. |
|
||||
| ignore-effect-in-worlds | *List* | List of worlds where players will see everyone in tablist, not just players in the same world / world group |
|
||||
| shared-playerlist-world-groups | *Map* | See [Grouping playerlist from multiple worlds](#grouping-playerlist-from-multiple-worlds) |
|
||||
|
||||
## Grouping playerlist from multiple worlds
|
||||
In case you want multiple worlds to share playerlist despite this option enabled, create a group and put world names there. The default example
|
||||
```
|
||||
per-world-playerlist:
|
||||
shared-playerlist-world-groups:
|
||||
lobby:
|
||||
- lobby1
|
||||
- lobby2
|
||||
minigames:
|
||||
- paintball
|
||||
- bedwars
|
||||
```
|
||||
Contains 2 groups, each of them consisting of 2 worlds.
|
||||
World group name can be anything (in our case, they're called "lobby" and "minigames").
|
||||
Under group name, list the actual world names.
|
||||
|
||||
With this setup, "lobby1" and "lobby2" will share playerlist, as well as "paintball" with "bedwars". All other worlds will have playerlist not shared with any other worlds. Creating a group for 1 world only is completely useless.
|
||||
|
||||
### Pattern Matching
|
||||
World names in groups support multiple pattern types for flexible configuration:
|
||||
|
||||
**Exact Match** - Matches server name exactly:
|
||||
```yaml
|
||||
shared-playerlist-world-groups:
|
||||
worlds:
|
||||
- world1
|
||||
- world2
|
||||
```
|
||||
|
||||
**Wildcard Patterns** - Use `*` for prefix or suffix matching:
|
||||
```yaml
|
||||
shared-playerlist-world-groups:
|
||||
worlds:
|
||||
- "World-*" # Matches: World-1, World-2, World-Hub, etc.
|
||||
- "*-world" # Matches: eu-world, us-world, etc.
|
||||
```
|
||||
|
||||
**Regex Patterns** - Use `regex:` prefix for advanced pattern matching:
|
||||
```yaml
|
||||
shared-playerlist-world-groups:
|
||||
worlds:
|
||||
- regex:World-[0-9]+ # Matches: World-1, World-23, but not World-Hub
|
||||
smp:
|
||||
- regex:SMP-(EU|US)-[0-9]+ # Matches: SMP-EU-1, SMP-US-2, etc.
|
||||
```
|
||||
|
||||
Note: Wildcard patterns are case-insensitive, while regex patterns are case-sensitive by default (use `(?i)` flag for case-insensitive regex).
|
||||
@@ -0,0 +1,26 @@
|
||||
# About
|
||||
By default, the server sends information about ping of players to everyone,
|
||||
which you can see in the tablist as the green bar.
|
||||
Some modified clients allow seeing the exact value instead of just bars.
|
||||
This feature spoofs the ping value of all players to the configured value, hiding their true ping.
|
||||
I don't know why anyone would want to do that.
|
||||
|
||||
# Configuration
|
||||
Find this section in your **config.yml**
|
||||
```
|
||||
ping-spoof:
|
||||
enabled: false
|
||||
value: 0
|
||||
```
|
||||
To enable the feature, set `enabled: true`.
|
||||
When the feature is enabled, everyone's ping value will be shown as value configured in `value` field.
|
||||
|
||||
The ping intervals for bars are client sided and are as following:
|
||||
| Ping value | Displayed icon |
|
||||
| ----------- | -------------- |
|
||||
| Negative | |
|
||||
| 0 - 149 | |
|
||||
| 150 - 299 | |
|
||||
| 300 - 599 | |
|
||||
| 600 - 999 | |
|
||||
| 1000+ | |
|
||||
@@ -0,0 +1,209 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* [Supported replacement patterns](#supported-replacement-patterns)
|
||||
* [Pattern 1: Exact text](#pattern-1-exact-text)
|
||||
* [Pattern 2: Number intervals](#pattern-2-number-intervals)
|
||||
* [Pattern 3: else](#pattern-3-else)
|
||||
* [Supported content in values](#supported-content-in-values)
|
||||
* [Using in other plugins](#using-in-other-plugins)
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Adding brackets to placeholder output if it returns non-empty value](#example-1---adding-brackets-to-placeholder-output-if-it-returns-non-empty-value)
|
||||
* [Example 2 - Replicating PlaceholderAPI's %player_colored_ping%](#example-2---replicating-placeholderapis-player_colored_ping)
|
||||
* [Example 3 - Using both original and replaced output](#example-3---using-both-original-and-replaced-output)
|
||||
* [Example 4 - Replacing identifier with custom text](#example-4---replacing-identifier-with-custom-text)
|
||||
|
||||
# About
|
||||
Most placeholders don't have fully configurable output, making you unable to customize it as you'd like.
|
||||
This is especially a problem with placeholders such as vanish or afk ones that return "yes"
|
||||
or "no" instead of some fancy text.
|
||||
It is a job of the plugins providing placeholders to allow control over outputs,
|
||||
but for plugins that don't we have a solution - now you're able to configure output of any placeholder in many ways.
|
||||
|
||||
# Configuration
|
||||
Open **config.yml** and find this section:
|
||||
```
|
||||
placeholder-output-replacements:
|
||||
<placeholder>:
|
||||
<original output>: <new output>
|
||||
```
|
||||
|
||||
## Supported replacement patterns
|
||||
|
||||
### Pattern 1: Exact text
|
||||
If the placeholder's output is exact to the text on the left side, it will return text on the right side.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
```
|
||||
placeholder-output-replacements:
|
||||
"%tps%":
|
||||
"20": "Running at perfect 20 TPS!"
|
||||
"%essentials_vanished%":
|
||||
"yes": " &7[V]"
|
||||
"no": ""
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
> [!NOTE]
|
||||
> If you want to replace empty output, use `""` or `''` on the left side.
|
||||
|
||||
> [!NOTE]
|
||||
> The text must match exactly, including color codes.
|
||||
> To check the color codes a placeholder returns use
|
||||
> [`/tab parse <player> <placeholder>`](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions#tab-parse-player-text)
|
||||
> and check "Raw colors" part.
|
||||
|
||||
### Pattern 2: Number intervals
|
||||
Output will be replaced if it's numeric and belongs in a configured interval.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
```
|
||||
placeholder-output-replacements:
|
||||
"%tps%":
|
||||
"15-20": "Solid"
|
||||
"5-15": "Bad"
|
||||
"0-5": "Terrible"
|
||||
```
|
||||
</details>
|
||||
|
||||
> [!NOTE]
|
||||
> If a number is included in more than 1 interval (just like 5 and 15 from the example above), the one higher is used.
|
||||
> In this case, 15 would give `Solid` and 5 would give `Bad`.
|
||||
|
||||
Intervals can be defined using both `-` and `~`.
|
||||
If you need support for negative values, use `~` for an interval instead of `-`.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
```
|
||||
placeholder-output-replacements:
|
||||
"%my_negative_placeholder%":
|
||||
"-100~-1": "Negative"
|
||||
"0": "Zero"
|
||||
"1-100": "Positive"
|
||||
```
|
||||
</details>
|
||||
|
||||
### Pattern 3: else
|
||||
If none of the configured outputs are used and "else" is set, that value will be used instead.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
```
|
||||
placeholder-output-replacements:
|
||||
"%tps%":
|
||||
"20": "Running at perfect 20 TPS!"
|
||||
"15-20": "Solid"
|
||||
"5-15": "Bad"
|
||||
"else": "Terrible" #0-5 in this case
|
||||
```
|
||||
</details>
|
||||
|
||||
## Supported content in values
|
||||
You can use placeholders inside outputs, including the original placeholder you are altering.
|
||||
It will return the original output of the placeholder.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
```
|
||||
placeholder-output-replacements:
|
||||
"%tps%":
|
||||
"20": "Running at perfect 20 TPS!"
|
||||
"15-20": "%tps% (Solid)"
|
||||
"5-15": "%tps% (Bad)"
|
||||
"else": "%tps% (Terrible)"
|
||||
```
|
||||
|
||||
With this example, if TPS reaches, for example 17.5, the output would be `17.5 (Solid)`.
|
||||
</details>
|
||||
|
||||
# Using in other plugins
|
||||
These replacements are only supported inside TAB. They won't work in other plugins.
|
||||
If you want to use these in other plugins, you'll need to [enable tab's PlaceholderAPI expansion](https://github.com/NEZNAMY/TAB/wiki/Placeholders#placeholderapi) and use `%tab_replace_<placeholder>%`. If you, for example, configure output for %player_health%, use `%tab_replace_player_health%`.
|
||||
|
||||
This only works for PlaceholderAPI placeholders, not TAB's internal ones. For TAB's internal ones use `%tab_placeholder_<placeholder>`, such as for %health% use `%tab_placeholder_health%`.
|
||||
|
||||
# Examples
|
||||
## Example 1 - Adding brackets to placeholder output if it returns non-empty value
|
||||
When displaying faction or clan of players, you may want to add brackets if a player is in a faction/clan,
|
||||
but not show them if they are not in one.
|
||||
To achieve this,
|
||||
we are going to use [Pattern 1: Exact text](#pattern-1-exact-text) and [Pattern 3: else](#pattern-3-else).
|
||||
If the placeholder returned nothing, show nothing.
|
||||
Otherwise, show the output with added brackets:
|
||||
```
|
||||
placeholder-output-replacements:
|
||||
"%my_placeholder%":
|
||||
"": ""
|
||||
"else": "[%my_placeholder%] "
|
||||
```
|
||||
Note that you'll need to match the placeholder output exactly. Not all clan/faction-like plugins return empty value when player doesn't have any. They may return just a color code, such as `&7`, in which case replacing empty value won't work. To see what the exact output of a placeholder is, use `/tab parse <player> <placeholder>` and check "Without colors" part. If that's the case, you'll need to change it on the left side. Example:
|
||||
```
|
||||
placeholder-output-replacements:
|
||||
"%my_placeholder%":
|
||||
"&7": ""
|
||||
"else": "[%my_placeholder%] "
|
||||
```
|
||||
**Don't forget that parse command applies replacements, so when trying to see what placeholder returns, you should disable any previously configured replacements for that placeholder to see the correct raw output**.
|
||||
## Example 2 - Replicating PlaceholderAPI's %player_colored_ping%
|
||||
> [!NOTE]
|
||||
> Please note that this is just an example to demonstrate the plugin's functionality.
|
||||
> It is not supposed to discourage anyone from using PlaceholderAPI or any of its placeholders.*
|
||||
|
||||
The placeholder allows you to configure intervals in config.yml. Default values are <50 for good, <100 for medium and 100+ for high. We can achieve this using [Pattern 2: Number intervals](#pattern-2-number-intervals) and [Pattern 3: else](#pattern-3-else). When put together, it looks as following:
|
||||
```
|
||||
placeholder-output-replacements:
|
||||
"%ping%":
|
||||
"0-50": "&a%ping%"
|
||||
"51-100": "&e%ping%"
|
||||
"else": "&c%ping%"
|
||||
```
|
||||
Keep in mind that now the placeholder will no longer return just a number,
|
||||
which can break features like [Playerlist Objective](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Playerlist-Objective),
|
||||
which require a numeric input (for versions prior to 1.20.3).
|
||||
If you want that feature and ping to be displayed there, replacements won't work for you,
|
||||
and you'll need
|
||||
to use [Conditional placeholders](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) instead
|
||||
to achieve colored ping.
|
||||
|
||||
## Example 3 - Using both original and replaced output
|
||||
Once configured, replacements are applied as the placeholder output everywhere. It is not directly possible to use original output in one place and replaced in another.
|
||||
|
||||
If you need this, you should consider [conditional placeholders](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) instead.
|
||||
If conditional placeholders are too complicated to use, there are alternate ways. The main point of the solution is to create different placeholder that eventually calls the same function and returns the same result. This can be done by "wrapping" the placeholder into another one. The easiest way using existing TAB's functions is using animations. Create an animation with a single frame that contains the placeholder and configure replacements for that placeholder instead.
|
||||
<details>
|
||||
<summary>Example for %ping%</summary>
|
||||
|
||||
**animations.yml**:
|
||||
```
|
||||
ping:
|
||||
change-interval: 50 # Actual value doesn't matter
|
||||
texts:
|
||||
- "%ping%"
|
||||
```
|
||||
Then, configure replacements for the animation in **config.yml**:
|
||||
```
|
||||
placeholder-output-replacements:
|
||||
"%animation:ping%":
|
||||
"0-50": "&a%animation:ping%" # %ping% would work too
|
||||
"51-100": "&e%animation:ping%"
|
||||
"else": "&c%animation:ping%"
|
||||
```
|
||||
Now, you can use `%ping%` for original output and `%animation:ping%` for replaced.
|
||||
|
||||
</details>
|
||||
|
||||
## Example 4 - Replacing identifier with custom text
|
||||
Sometimes a placeholder doesn't parse and instead returns the identifier itself (such as on proxy installation before Bridge responds back with placeholder values), but you want to display some default value to avoid issues (ugly text, warnings in console if used in sorting or conditions).
|
||||
|
||||
This can be achieved in the following way:
|
||||
|
||||
```
|
||||
placeholder-output-replacements:
|
||||
"%my_placeholder%":
|
||||
"%my_placeholder%": "Loading..."
|
||||
```
|
||||
If the placeholder is used in numeric sorting for example, you can make it default to `0` or anything else you need at the time.
|
||||
@@ -0,0 +1,134 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* ~Commands~
|
||||
* ~Placeholders~
|
||||
* [Limitations](#limitations)
|
||||
* [Compatibility with other plugins](#compatibility-with-other-plugins)
|
||||
* [Additional info](#additional-info)
|
||||
* [Additional note 1 - Spectator gamemode](#additional-note-1---spectator-gamemode)
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
* ~API~
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Per-world values](#example-1---per-world-values)
|
||||
* [Example 2 - Displaying hearts](#example-2---displaying-hearts)
|
||||
|
||||
# About
|
||||
This features gives you control over Minecraft's scoreboard objective feature with PLAYER_LIST slot.
|
||||
On 1.20.2- it supports 2 display types:
|
||||
* yellow number
|
||||

|
||||
* hearts
|
||||

|
||||
|
||||
Since 1.20.3, it can display any text.
|
||||

|
||||
|
||||
# Configuration
|
||||
The feature can be configured in **config.yml** under **playerlist-objective** section.
|
||||
This is how the default configuration looks:
|
||||
```
|
||||
playerlist-objective:
|
||||
enabled: true
|
||||
value: "%ping%"
|
||||
fancy-value: "&7Ping: %ping%"
|
||||
title: "TAB" # Only visible on Bedrock Edition
|
||||
render-type: INTEGER
|
||||
disable-condition: '%world%=disabledworld'
|
||||
```
|
||||
All of the options are explained in the following table.
|
||||
| Option name | Default value | Description |
|
||||
|-------------------|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | true | Enables / Disables the feature |
|
||||
| value | "%ping%" | [1.20.2-] An integer from -2147483648 to 2147483647, doesn't support decimal values. The number is always yellow. Supports placeholders with player-specific output, such as player health. Only visible on 1.20.2 and lower (unless you set `render-type` to `HEARTS`). <br/> **Note**: Even if you only support 1.20.3+, you still need to configure this value to properly evaluate to a number, because the value is still sent to the client (just not displayed). You can set it to `0` for simplicity. |
|
||||
| fancy-value | "&7Ping: %ping%" | [1.20.3+] Any text, supports placeholders with per-player output. Only visible on 1.20.3+, where it completely replaces `value`, or if `render-type` is set to `HEARTS`. |
|
||||
| title | "TAB" | Title to send. Only visible on Bedrock Edition. |
|
||||
| render-type | INTEGER | Render type of the value. Supported values are `INTEGER` and `HEARTS`. <br />When set to `HEARTS`, the `value` is used displayed even on 1.20.3+, where `fancy-value` is ignored. |
|
||||
| disable-condition | %world%=disabledworld | A [condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) (either name of a condition or a conditional expression) that must be met for disabling the feature for players. Set to empty for not disabling the feature ever. <br/> **Note**: Disabling the feature for a player means sending objective unregister packet to them, which results in player not seeing the feature on anyone anymore. It doesn't work the other way around - you cannot disable this feature on target players, only for viewers. |
|
||||
|
||||
# Limitations
|
||||
* [1.20.2-] Only 2 display types are supported - yellow number and hearts.
|
||||
* [1.20.2-] A yellow 0 will appear on all tablist entries that aren't actual players (such as NPCs and [layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) entries) and it cannot be removed.
|
||||
|
||||
# Compatibility with other plugins
|
||||
TAB does not contain any sort of compatibility functionality for this feature.
|
||||
It will not try to prevent other plugins from applying the feature and neither will it detect it to re-add back once the other plugin removes it.
|
||||
Therefore, if another plugin also sends playerlist objective, TAB's may not show anymore (depending on who sends it first).
|
||||
Make sure you do not have any other plugin sending it to ensure the feature works properly.
|
||||
|
||||
You can check the list of objectives registered by either commands or plugins using Bukkit API using `/scoreboard objectives list`.
|
||||
If it contains one that could be the cause, you can unregister it by running `/scoreboard objectives remove <name>`. After doing so, reload TAB, so it resends its objectives again.
|
||||
Note that if this was automatically generated by a plugin, it will probably be added back again.
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - Spectator gamemode
|
||||
The feature will not be visible on players with spectator gamemode. To resolve this, check out [Spectator fix](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Spectator-fix) feature.
|
||||
|
||||
# Troubleshooting
|
||||
This is a collection of tips to help you figure out why the feature isn't working as you expect.
|
||||
To get started, run `/tab dump <any player>` (this feature doesn't contain per-player content in dump output) and open the generated link. Scroll down to `features` -> `PlayerlistObjective` and check the content:
|
||||
* If it says `PlayerlistObjective: Feature is disabled`, it means you disabled the feature. Enable it by setting
|
||||
```
|
||||
playerlist-objective:
|
||||
enabled: true
|
||||
```
|
||||
* Check the `configuration` section and compare it with your config file. If it's different, you either forgot to reload TAB, or uploaded the config to the wrong server (or did not upload it at all).
|
||||
* If a player cannot see playerlist objective on anyone, check the table of players and make sure it's not because `Disabled with condition` is `true`.
|
||||
* Check the table of players for `value`, `fancy-value` and `title` and make sure they match your expectations. Don't forget `value` only supports numbers.
|
||||
* If you want to see `fancy-value` instead of just `value`'s number:
|
||||
* Make sure your client is on 1.20.3+.
|
||||
* Make sure your server is on 1.20.3+ (using TAB on proxy counts as being latest).
|
||||
* Make sure you are not using a 3rd party client that removed this feature from 1.20.3+, such as Lunar or Feather.
|
||||
* If you have TAB on Velocity, install [VelocityScoreboardAPI](https://github.com/NEZNAMY/VelocityScoreboardAPI/releases) (and make sure it is not outdated).
|
||||
|
||||
# Examples
|
||||
## Example 1 - Per-world values
|
||||
This feature doesn't directly support per-world values or similar.
|
||||
However, this can be achieved with conditions.
|
||||
Let's make `fancy-value` conditional based on player's world.
|
||||
Let's make an example with 3 worlds.
|
||||
Check if player is in world `world1`, then show one text.
|
||||
If not, check if player is in world `world2`, then show another text.
|
||||
If not, show the final text.
|
||||
This can be achieved by chaining 2 conditions:
|
||||
```
|
||||
conditions:
|
||||
playerlist1:
|
||||
conditions:
|
||||
- "%world%=world1"
|
||||
true: "Text to display in world world1" # Player is in world world1, display the text
|
||||
false: "%condition:playerlist2%" # Player is not in world world1, check another condition
|
||||
playerlist2:
|
||||
conditions:
|
||||
- "%world%=world2"
|
||||
true: "Text to display in world world2" # Player is in world world2, display the text
|
||||
false: "Text to display in other worlds" # Player is not in any of the 2 worlds
|
||||
```
|
||||
> [!WARNING]
|
||||
> DO NOT JUST RANDOMLY PASTE THIS ENTIRE "CONDITIONS" SECTION INTO YOUR CONFIG!
|
||||
> INSTEAD, EDIT YOUR EXISTING CONDITIONS SECTION TO PREVENT HAVING THE SECTION TWICE,
|
||||
> HAVING SECOND ONE COMPLETELY OVERRIDE THE FIRST ONE!
|
||||
|
||||
Finally, use this condition as value in `fancy-value`:
|
||||
```
|
||||
playerlist-objective:
|
||||
fancy-value: "%condition:playerlist1%"
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> This is just an example, the plugin is not limited to displaying different values only per world.
|
||||
> If you want per server values on proxy, use %server% with server names.
|
||||
> This works for any placeholder offered by TAB or by PlaceholderAPI.
|
||||
|
||||
## Example 2 - Displaying hearts
|
||||
In order to display the value as hearts, set `render-type` to `HEARTS`.
|
||||
Then, set `value` to a placeholder that returns player's health. If you have TAB on a backend server, use `%health%`. If you have TAB on a proxy, use PlaceholderAPI's `%player_health_rounded%`.
|
||||
Example configuration:
|
||||
|
||||
```
|
||||
value: "%health%"
|
||||
render-type: HEARTS
|
||||
```
|
||||
When using `HEARTS` render type, `fancy-value` is not displayed by the client, so it doesn't matter what it is set to.
|
||||
Final result:
|
||||

|
||||
@@ -0,0 +1,402 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* [Scoreboard](#scoreboard)
|
||||
* [Line syntax](#line-syntax)
|
||||
* [Hiding a line](#hiding-a-line)
|
||||
* [Longer lines](#longer-lines)
|
||||
* [Chaining scoreboards](#chaining-scoreboards)
|
||||
* [Commands](#commands)
|
||||
* [Placeholders](#placeholders)
|
||||
* [Limitations](#limitations)
|
||||
* [Compatibility with other plugins](#compatibility-with-other-plugins)
|
||||
* [Additional info](#additional-info)
|
||||
* [Additional note 1 - Text alignment](#additional-note-1---text-alignment)
|
||||
* [Additional note 2 - Geyser / Bedrock issues](#additional-note-2---geyser--bedrock-issues)
|
||||
* ~Troubleshooting~
|
||||
* [API](#api)
|
||||
* [Creating custom scoreboards](#creating-custom-scoreboards)
|
||||
* [Showing custom scoreboards](#showing-custom-scoreboards)
|
||||
* [Toggling scoreboard visibility](#toggling-scoreboard-visibility)
|
||||
* [Announcing a scoreboard](#announcing-a-scoreboard)
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Per-world scoreboards](#example-1---per-world-scoreboards)
|
||||
* [Example 2 - Periodical scoreboard switching](#example-2---periodical-scoreboard-switching)
|
||||
* [Example 3 - Per-version scoreboards](#example-3---per-version-scoreboards)
|
||||
* [Example 4 - Conditional lines](#example-4---conditional-lines)
|
||||
|
||||
# About
|
||||
This features gives you control over Minecraft's scoreboard objective feature with SIDEBAR slot.
|
||||
|
||||
# Configuration
|
||||
The feature can be configured in **config.yml** under **scoreboard** section.
|
||||
This is how the default configuration looks:
|
||||
```
|
||||
scoreboard:
|
||||
enabled: false
|
||||
toggle-command: /sb
|
||||
remember-toggle-choice: false
|
||||
hidden-by-default: false
|
||||
delay-on-join-milliseconds: 0
|
||||
scoreboards:
|
||||
scoreboard-1.20.3+:
|
||||
title: "<#E0B11E>MyServer</#FF0000>"
|
||||
display-condition: "%player-version-id%>=765;%bedrock%=false" # Only display it to players using 1.20.3+ AND NOT bedrock edition
|
||||
lines:
|
||||
- "&7%date%"
|
||||
- "%animation:MyAnimation1%"
|
||||
- "&6Online:"
|
||||
- "* &eOnline&7:||%online%"
|
||||
- "* &eCurrent World&7:||%worldonline%"
|
||||
- "* &eStaff&7:||%staffonline%"
|
||||
- ""
|
||||
- "&6Personal Info:"
|
||||
- "* &bRank&7:||%group%"
|
||||
- "* &bPing&7:||%ping%&8ms"
|
||||
- "* &bWorld&7:||%world%"
|
||||
- "%animation:MyAnimation1%"
|
||||
scoreboard:
|
||||
title: "<#E0B11E>MyServer</#FF0000>"
|
||||
lines:
|
||||
- "&7%date%"
|
||||
- "%animation:MyAnimation1%"
|
||||
- "&6Online:"
|
||||
- "* &eOnline&7: &f%online%"
|
||||
- "* &eCurrent World&7: &f%worldonline%"
|
||||
- "* &eStaff&7: &f%staffonline%"
|
||||
- ""
|
||||
- "&6Personal Info:"
|
||||
- "* &bRank&7: &f%group%"
|
||||
- "* &bPing&7: &f%ping%&8ms"
|
||||
- "* &bWorld&7: &f%world%"
|
||||
- "%animation:MyAnimation1%"
|
||||
```
|
||||
All of the options are explained in the following table.
|
||||
| Option name | Default value | Description |
|
||||
|----------------------------|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | false | Enables / Disables the feature |
|
||||
| toggle-command | /sb | Command that can be used to toggle scoreboard for the player running the command. Players need `tab.scoreboard.toggle` permission to use it. <br />**Note:** Commands are not supposed to be registered / unregistered dynamically at runtime. As such, you may run into small issues when changing the toggle command and reloading. After you modify the command to your liking, reconnect to properly see it in tabcomplete. If you don't use TAB on a proxy, consider restarting the server as well for the old command to actually be unregistered. |
|
||||
| remember-toggle-choice | false | When enabled, toggling decision is saved into a file to remember it even after reloads/restarts/reconnects |
|
||||
| hidden-by-default | false | If enabled, scoreboard will automatically be hidden on join until toggle command is used to show it. |
|
||||
| delay-on-join-milliseconds | 0 | Delay in milliseconds to send scoreboard after joining. |
|
||||
| scoreboards | *Map* | Scoreboards to display based on conditions (see below for more info). |
|
||||
|
||||
## Scoreboard
|
||||
A scoreboard consists of the following options:
|
||||
|
||||
| Option name | Description |
|
||||
|--------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `display-condition` (optional) | [Condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) (either condition name or a conditional expression) <br /> that must be met for the design to be displayed. <br />If not defined, design will be displayed without any required condition. <br />If player does not meet condition, another design may be displayed <br /> based on chaining (see below for more info). |
|
||||
| `title ` | Title of the scoreboard. Limited to 32 characters (including color codes) on Minecraft versions below 1.13. It is automatically centered by the client. |
|
||||
| `lines` | List of lines to display. The client will only display up to 15 lines. See below for more information about syntax. |
|
||||
|
||||
**Example**:
|
||||
```
|
||||
scoreboards:
|
||||
MyScoreboard:
|
||||
display-condition: "%world%=world" # Only display it in world "world"
|
||||
title: "Scoreboard for world %world%"
|
||||
lines:
|
||||
- "Line1||Right side 1"
|
||||
- "Line2||Right side 2"
|
||||
- "Line3||Right side 3"
|
||||
```
|
||||
|
||||
### Line syntax
|
||||
The lines are specified as a list of strings.
|
||||
|
||||
Since 1.20.3, you can also configure the value on the right side, which no longer has to be a red number.
|
||||
On <1.20.3, you can configure red numbers with either a static number, or a placeholder that evaluates to a number.
|
||||
|
||||
The final syntax is `<text>||<number format>||<score>`, where:
|
||||
* `<text>` is the main text displayed on the left side
|
||||
* `<number format>` is the new 1.20.3+ feature that replaces `score` with any text, not just a number
|
||||
* `<score>` is the value (red number), only visible on <1.20.3 and must be a number (or a placeholder evaluating to one)
|
||||
|
||||
The second and third part are optional. Example syntaxes that configure a line are:
|
||||
* `<text>`
|
||||
* `<text>||<number format>`
|
||||
* `<text>||<number format>||<score>`
|
||||
* `<text>||||<score>`
|
||||
|
||||
For example:
|
||||
```
|
||||
lines:
|
||||
- "Left 1---"
|
||||
- "||---Right 1"
|
||||
- "Left 2------"
|
||||
- "||------Right 2"
|
||||
- "Left 3---------"
|
||||
- "||---------Right 3"
|
||||
- "Left 4------------"
|
||||
- "||------------Right 4"
|
||||
- "Left 5---------------"
|
||||
- "||---------------Right 5"
|
||||
- "Left 6------------------"
|
||||
- "||------------------Right 6"
|
||||
```
|
||||
Will give you the following:
|
||||
<img width="305" height="239" alt="image" src="https://github.com/user-attachments/assets/a712b5fb-21ea-4ee4-83ec-d962bd431a07" />
|
||||
|
||||
Additionally, the following configuration:
|
||||
```
|
||||
lines:
|
||||
- "Left 1---||---Right 1"
|
||||
- "Left 2------||------Right 2"
|
||||
- "Left 3---------||---------Right 3"
|
||||
- "Left 4------------||------------Right 4"
|
||||
- "Left 5---------------||---------------Right 5"
|
||||
- "Left 6------------------||------------------Right 6"
|
||||
```
|
||||
Will give you
|
||||
<img width="583" height="131" alt="image" src="https://github.com/user-attachments/assets/15e809c6-4ecd-4234-a30e-744c2d413335" />
|
||||
|
||||
The `number format` will not be visible at 1.20.2 and lower, and `score` will be displayed instead.
|
||||
|
||||
### Hiding a line
|
||||
When a line consists only of a placeholder that returned empty output, the line will be hidden completely. This is intentional to allow dynamic scoreboard size based on placeholder output. This is not the case if empty line is configured (`""`), to allow empty lines in configuration.
|
||||
|
||||
### Longer lines
|
||||
*Since 1.13 the line length is unlimited, so you don't need to worry about this if you use 1.13+.*
|
||||
|
||||
To make sure the scoreboard never flickers, it's only using prefix/suffix components to display text.
|
||||
These can easily be changed without any visual issues.
|
||||
The player name part, however, cannot be changed.
|
||||
A line has to be completely removed and a new one added.
|
||||
There's a chance a frame is rendered between these 2 packets are sent,
|
||||
causing the scoreboard to have 1 line missing for 1 frame, causing the visual issue known as "flickering".
|
||||
|
||||
However,
|
||||
if your scoreboard only has placeholders that don't change value often
|
||||
(pretty much any placeholder except animations, really),
|
||||
you can make TAB use player name part,
|
||||
allowing you to use an additional up to 40 characters.
|
||||
To do so, add `Long|` prefix to all lines that should use this bypass.
|
||||
```
|
||||
lines:
|
||||
- "Classic line with shorter limit"
|
||||
- "Long|Long line with much higher character limit"
|
||||
```
|
||||
This bypass is automatically enabled for all lines that only use static text
|
||||
(since there's nothing to refresh and cause flickering),
|
||||
therefore doing it for such lines (like in the example above) has no effect.
|
||||
|
||||
## Chaining scoreboards
|
||||
When defining more than 1 scoreboard in config, the plugin will display the correct scoreboard based on conditions.
|
||||
The plugin goes through all defined scoreboards, starting with the scoreboard on top.
|
||||
If the scoreboard's condition is met or not set, it is displayed.
|
||||
If not, the next defined scoreboard is checked and so on.
|
||||
If no suitable scoreboard is found (the last one has a condition requirement which wasn't met), none is displayed.
|
||||
**Example**:
|
||||
```
|
||||
scoreboards:
|
||||
scoreboard1:
|
||||
display-condition: "permission:tab.scoreboard.admin"
|
||||
title: "Title 1"
|
||||
lines:
|
||||
- "Scoreboard for admins"
|
||||
scoreboard2:
|
||||
display-condition: "%world%=myWorld"
|
||||
title: "Title 2"
|
||||
lines:
|
||||
- "Scoreboard in world myWorld"
|
||||
scoreboard3:
|
||||
title: "Title 3"
|
||||
lines:
|
||||
- "Line 1"
|
||||
```
|
||||
Scoreboard `scoreboard1` is checked first. If condition is not met, `scoreboard2` is checked. If that condition is not met, `scoreboard3` is displayed.
|
||||
If a player meets both conditions (has defined permission and is in defined world), `scoreboard1` will be displayed, because it is defined first and therefore has the highest priority. You can switch scoreboards based on your priority needs.
|
||||
|
||||
# Commands
|
||||
| Command | Permission | Description |
|
||||
|------------------------------------------------------|------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `/tab scoreboard show <name> [player]` | `tab.scoreboard.show` (for yourself) <br /> `tab.scoreboard.show.other` (for others) | Shows the scoreboard with the given `name`, either to yourself if no `player` was given, or to the given `player`. |
|
||||
| `/tab scoreboard [on/off/toggle] [player] [options]` | `tab.scoreboard.toggle` (for yourself) <br /> `tab.scoreboard.toggle.other` (for others) | Shows / hides / toggles scoreboard of specified player. If no player was given, command affects the sender. You can use `-s` as option for silent toggling (no chat message for affected player) |
|
||||
| `/tab scoreboard announce <name> <duration>` | `tab.announce.scoreboard` | Shows the scoreboard with the given `name` to every player on the server for the given `duration`, in seconds. |
|
||||
|
||||
# Placeholders
|
||||
Here are TAB's PlaceholderAPI placeholders you can use when this feature is enabled:
|
||||
| Placeholder | Description |
|
||||
|-------------|-------------|
|
||||
| `%tab_scoreboard_name%` | Returns name of player's currently displayed scoreboard or empty string if none is displayed due to no display condition being met. |
|
||||
| `%tab_scoreboard_visible%` | "Enabled" if visible, "Disabled" if not (toggled with a command) |
|
||||
|
||||
# Limitations
|
||||
* [1.12.2-] The title is limited to 32 characters (including color codes).
|
||||
* [1.12.2-] Line length is limited to 28 characters (including color codes) (64 on lines with static text / [Longer lines](#longer-lines)).
|
||||
* [1.20.2-] The red numbers on the right really cannot be removed from the plugin side (a client modification / resource pack is necessary).
|
||||
* [Bedrock] Scoreboard lines may be cut off and show `...`, this can be bypassed by using [GeyserOptionalPack](https://github.com/GeyserMC/GeyserOptionalPack)
|
||||
* The client only displays up to 15 lines. If a plugin sends more, only the top 15 scores will be displayed. Changing this would require a client modification (on versions below 1.8 the scoreboard won't appear at all if more than 15 lines are sent).
|
||||
|
||||
# Compatibility with other plugins
|
||||
TAB automatically detects scoreboard coming from other plugins, and when one is sent, TAB hides its own scoreboard.
|
||||
Later, when the other plugin hides its scoreboard, TAB will send its scoreboard back to the player.
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - Text alignment
|
||||
**Title**:
|
||||
The title is always centered by the client. You cannot disable this. You can only pad it with spaces to move it towards your desired direction.
|
||||
|
||||
**Lines**:
|
||||
The left side of the text is automatically aligned to the left,
|
||||
while the right side is automatically aligned to the right.
|
||||
This is done by the client and is out of plugin's control.
|
||||
If you want to center a line, you'll need to do it manually.
|
||||
If dynamic placeholder output length is preventing your from doing it,
|
||||
you can try to bypass it by adding spaces before and after it to artificially increase and force the scoreboard width,
|
||||
such as
|
||||
`- " Centered text "`.
|
||||
|
||||
## Additional note 2 - Geyser / Bedrock issues
|
||||
Currently, there is a great suspicion that there is a geyser bug causing scoreboard to not appear for Bedrock players ([Geyser #5304](https://github.com/GeyserMC/Geyser/issues/5304) and more). This affects other scoreboard plugins as well, not just TAB. If you are experiencing this issue, make sure it is not caused by TAB configuration (for example using %bedrock%=false as display condition). If that wasn't the case, consider making a high quality bug report on Geyser with steps to reproduce.
|
||||
|
||||
# API
|
||||
*To get started with the API, see [Developer API](https://github.com/NEZNAMY/TAB/wiki/Developer-API) page.*
|
||||
|
||||
To access this feature, you'll need to obtain `ScoreboardManager` instance. Get it using `TabAPI.getInstance().getScoreboardManager()`. If this feature is disabled, the method will return `null`.
|
||||
|
||||
## Creating custom scoreboards
|
||||
You can create and register new scoreboards using `ScoreboardManager#createScoreboard(String, String, List<String>)`, where the first `String` is the name, the second `String` is the title that will be displayed, and the `List<String>` is the list of lines that the scoreboard will display.
|
||||
|
||||
## Showing custom scoreboards
|
||||
To show your new scoreboard to a player, you can use `ScoreboardManager#showScoreboard(TabPlayer, Scoreboard)`, where the `TabPlayer` is the player you want to show the scoreboard to, and the `Scoreboard` is the scoreboard you want to show. Doing this will also disable automatic scoreboard updating for the player, so that your scoreboard does not get overridden until you unregister it.
|
||||
To reset the scoreboard that a player is using to the default scoreboard that they should be seeing as determined by the config, use `ScoreboardManager#resetScoreboard(TabPlayer)`.
|
||||
To determine whether a player has a custom scoreboard set (one that was shown through the API), use `ScoreboardManager#hasCustomScoreboard(TabPlayer)`.
|
||||
|
||||
## Toggling scoreboard visibility
|
||||
To change whether a player can see scoreboards, use `ScoreboardManager#setScoreboardVisible(TabPlayer, boolean, boolean)`, and to determine whether a player can see scoreboards, use `ScoreboardManager#hasScoreboardVisible(TabPlayer)`.
|
||||
To toggle whether a player can see scoreboards, use `ScoreboardManager#toggleScoreboard(TabPlayer, boolean)`. This will either make scoreboards visible if they are not already, or make them hidden if they are currently visible.
|
||||
|
||||
## Announcing a scoreboard
|
||||
To announce a scoreboard to all players on the server for a given number of milliseconds,
|
||||
use `ScoreboardManager#announceScoreboard(String, int)`,
|
||||
which will look up a scoreboard with the given `String` name,
|
||||
and if one is found, send it to all players for the given `int` milliseconds.
|
||||
|
||||
# Examples
|
||||
## Example 1 - Per-world scoreboards
|
||||
We will be using a condition of "equals" (=) type and check for output of `%world%` placeholder.
|
||||
If condition is met, it means player is in that world and the scoreboard is displayed.
|
||||
If not, check for the next scoreboard's condition.
|
||||
If none of the conditions are met, display the default scoreboard.
|
||||
```
|
||||
scoreboards:
|
||||
# start
|
||||
scoreboard1:
|
||||
display-condition: "%world%=world1"
|
||||
title: 'Scoreboard 1'
|
||||
lines:
|
||||
- 'You are in world world1'
|
||||
# first condition didn't pass, try next
|
||||
scoreboard2:
|
||||
display-condition: "%world%=world2"
|
||||
title: 'Scoreboard 2'
|
||||
lines:
|
||||
- 'You are in world world2'
|
||||
# first two conditions didn't pass, try next
|
||||
scoreboard3:
|
||||
display-condition: "%world%=world3"
|
||||
title: 'Scoreboard 3'
|
||||
lines:
|
||||
- 'You are in world world3'
|
||||
# none of the conditions above passed, display default scoreboard
|
||||
default:
|
||||
title: 'Default scoreboard'
|
||||
lines:
|
||||
- 'You are not in any of the worlds listed above'
|
||||
```
|
||||
> [!NOTE]
|
||||
> This is just an example, the plugin is not limited to displaying scoreboard only per world.
|
||||
> If you want per server scoreboards on proxy, use %server% with server names.
|
||||
> This works for any placeholder offered by TAB or by PlaceholderAPI.
|
||||
|
||||
## Example 2 - Periodical scoreboard switching
|
||||
We can use [animations](https://github.com/NEZNAMY/TAB/wiki/Animations) to make the plugin switch between scoreboards using display condition. Let's say we want to switch between 2 scoreboards. First, we create an animation:
|
||||
**animations.yml**
|
||||
```
|
||||
switchingScoreboard:
|
||||
change-interval: 10000
|
||||
texts:
|
||||
- "1"
|
||||
- "2"
|
||||
```
|
||||
This animation will switch frames every 10 seconds.
|
||||
Then, we will use the output of this animation as a display condition.
|
||||
If animation is on the first frame, display the first scoreboard.
|
||||
Otherwise, display the second scoreboard.
|
||||
Result:
|
||||
**config.yml**
|
||||
```
|
||||
scoreboards:
|
||||
scoreboard1:
|
||||
display-condition: "%animation:switchingScoreboard%=1" # If animation is on the first frame
|
||||
title: "Scoreboard 1"
|
||||
lines:
|
||||
- 'Text'
|
||||
# Animation is on the second frame
|
||||
scoreboard2:
|
||||
title: "Scoreboard 2"
|
||||
lines:
|
||||
- 'Text'
|
||||
```
|
||||
We don't need to define display condition for the second scoreboard,
|
||||
since if animation is not on the first frame, it has to be on the second one.
|
||||
If using more than 2, you will need to define display condition for all of them (except the last one).
|
||||
|
||||
## Example 3 - Per-version scoreboards
|
||||
1.20.3 has added new features to scoreboards, which are not visible to older clients. If you want to use new features for new players while still displaying things properly for older players, you'll need to create 2 different scoreboards.
|
||||
You'll find 2 placeholders useful for this:
|
||||
* `%player-version-id%` - Returns network ID of player's protocol version. Unlike with version names, you can perform numerical comparisons with these. You can find all version IDs [here](https://github.com/NEZNAMY/TAB/blob/master/shared/src/main/java/me/neznamy/tab/shared/ProtocolVersion.java). For example, 1.20.3 is 765.
|
||||
* `%bedrock%` - Returns `true` if player is using the bedrock edition, which does not support new functions either.
|
||||
|
||||
We only want the first scoreboard for players with version 765 or greater and not bedrock players. This can be achieved with the following condition: `display-condition: "%player-version-id%>=765;%bedrock%=false"`.
|
||||
|
||||
Let's go ahead and set it up (with proper spacing):
|
||||
```
|
||||
scoreboards:
|
||||
scoreboard-1.20.3+:
|
||||
title: "Scoreboard for 1.20.3+ and not bedrock"
|
||||
display-condition: "%player-version-id%>=765;%bedrock%=false" # Only display it to players using 1.20.3+ AND NOT bedrock edition
|
||||
lines:
|
||||
- "* &eOnline&7:||%online%"
|
||||
- "* &eCurrent World&7:||%worldonline%"
|
||||
- "* &eStaff&7:||%staffonline%"
|
||||
- "* &bRank&7:||%group%"
|
||||
- "* &bPing&7:||%ping%&8ms"
|
||||
- "* &bWorld&7:||%world%"
|
||||
scoreboard:
|
||||
title: "Scoreboard for <1.20.3 and bedrock"
|
||||
lines:
|
||||
- "* &eOnline&7: &f%online%"
|
||||
- "* &eCurrent World&7: &f%worldonline%"
|
||||
- "* &eStaff&7: &f%staffonline%"
|
||||
- "* &bRank&7: &f%group%"
|
||||
- "* &bPing&7: &f%ping%&8ms"
|
||||
- "* &bWorld&7: &f%world%"
|
||||
```
|
||||
|
||||
## Example 4 - Conditional lines
|
||||
Sometimes you may want a dynamic line that only shows sometimes. TAB is already made to hide lines if they only consist of a placeholder that returned empty value. However, you may want to add more text around it, such as
|
||||
```
|
||||
- "Faction: %factionsuuid_faction_name%"
|
||||
```
|
||||
Now, even if the placeholder returns empty string, text `Faction: ` will remain, and as such, the line will stay. In order to avoid this, create a [conditional placeholder](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders). If the placeholder returned empty value, show empty value. Otherwise, show result of the placeholder with the static text:
|
||||
```
|
||||
conditions:
|
||||
faction:
|
||||
conditions:
|
||||
- '%factionsuuid_faction_name%='
|
||||
true: "" # No faction, return empty string to hide the line
|
||||
false: "Faction: %factionsuuid_faction_name%" # Player has a faction, show the static text before it as well
|
||||
```
|
||||
> [!WARNING]
|
||||
> DO NOT JUST RANDOMLY PASTE THIS ENTIRE "CONDITIONS" SECTION INTO YOUR CONFIG!
|
||||
> INSTEAD, EDIT YOUR EXISTING CONDITIONS SECTION TO PREVENT HAVING THE SECTION TWICE,
|
||||
> HAVING SECOND ONE COMPLETELY OVERRIDE THE FIRST ONE!
|
||||
|
||||
Now, configure your scoreboard line as:
|
||||
```
|
||||
- "%condition:faction%"
|
||||
```
|
||||
and it will only display if the placeholder returned non-empty value.
|
||||
@@ -0,0 +1,244 @@
|
||||
# Content
|
||||
* ~About~
|
||||
* [Enabling](#enabling)
|
||||
* [Methods of sorting](#methods-of-sorting)
|
||||
* [GROUPS](#groups)
|
||||
* [PERMISSIONS](#permissions)
|
||||
* [PLACEHOLDER](#placeholder)
|
||||
* [PLACEHOLDER_A_TO_Z](#placeholder_a_to_z)
|
||||
* [PLACEHOLDER_Z_TO_A](#placeholder_z_to_a)
|
||||
* [PLACEHOLDER_LOW_TO_HIGH](#placeholder_low_to_high)
|
||||
* [PLACEHOLDER_HIGH_TO_LOW](#placeholder_high_to_low)
|
||||
* [Multiple elements with the same priority](#multiple-elements-with-the-same-priority)
|
||||
* [Combining multiple sorting types](#combining-multiple-sorting-types)
|
||||
* [Additional settings](#additional-settings)
|
||||
* ~Commands~
|
||||
* ~Placeholders~
|
||||
* ~Limitations~
|
||||
* ~Compatibility with other plugins~
|
||||
* [Additional info](#additional-info)
|
||||
* [Additional note 1 - Limitations](#additional-note-1---limitations)
|
||||
* [Additional note 2 - per-world sorting](#additional-note-2---per-world-sorting)
|
||||
* [Additional note 3 - Compatibility issues with other plugins](#additional-note-3---compatibility-issues-with-other-plugins)
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
* [API](#api)
|
||||
* ~Examples~
|
||||
|
||||
# Enabling
|
||||
To enable sorting, you must have either [Nametags](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Nametags) or [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) (or both) enabled.
|
||||
|
||||
# Methods of sorting
|
||||
Below are all the different methods that you can use to sort players.
|
||||
|
||||
## GROUPS
|
||||
This is the default and recommended method. Players will be sorted by their primary permission group, according to the configured group list.
|
||||
|
||||
First, put your players into groups in your permission plugin.
|
||||
All the ways to do it can be found
|
||||
at [How to assign players into groups](https://github.com/NEZNAMY/TAB/wiki/How-to-assign-players-into-groups).
|
||||
|
||||
Second, place all of your groups in to a comma separated list **in order of priority** into `sorting-types`. Example:
|
||||
```yaml
|
||||
scoreboard-teams:
|
||||
sorting-types:
|
||||
- "GROUPS:owner,admin,mod,default"
|
||||
```
|
||||
|
||||
## PERMISSIONS
|
||||
> [!CAUTION]
|
||||
> This method is not recommended,
|
||||
> as many low quality servers give OP to every staff member and don't know how to negate permissions,
|
||||
> making this option not function as intended.
|
||||
> If you think you can pull it off, and sorting by primary group is not an option, you can give this a try.
|
||||
This method is, however, handy when trying to sort specific players without assigning them into a group.
|
||||
|
||||
This method will sort players based on permission nodes they have.
|
||||
Place all of your permissions in to a comma separated list **in order of priority**.
|
||||
For example, if you have the permissions `my.permission.1`, `my.permission.2`, `my.permission.3`, and want to have players sorted in that order, you would end up with a configuration like `PERMISSIONS:my.permission.1,my.permission.2,my.permission.3`.
|
||||
Example:
|
||||
```yaml
|
||||
scoreboard-teams:
|
||||
sorting-types:
|
||||
- "PERMISSIONS:my.permission.1,my.permission.2,my.permission.3"
|
||||
```
|
||||
|
||||
## PLACEHOLDER
|
||||
This method sorts players using the output of a placeholder and comparing that to pre-defined values.
|
||||
To configure this sorting type, write the placeholder that you want to use, followed by a colon (`:`), followed by a comma separated list of outputs to check against.
|
||||
For example, if you want to sort players using the output of the `%essentials_afk%` placeholder, depending on whether it is `yes` or `no`, you would do that using a configuration such as `PLACEHOLDER:%essentials_afk%:no,yes`, where players who the placeholder outputs `no` for will be sorted above players who the placeholder outputs `yes` for in this case, putting AFK players on the bottom.
|
||||
Example:
|
||||
```yaml
|
||||
scoreboard-teams:
|
||||
sorting-types:
|
||||
- "PLACEHOLDER:%essentials_afk%:no,yes"
|
||||
```
|
||||
|
||||
## PLACEHOLDER_A_TO_Z
|
||||
This method sorts players alphabetically, according to the output of a placeholder.
|
||||
To configure this sorting type, write the placeholder that you want to use. That's it.
|
||||
For example, if you want to sort players by their name alphabetically, you would do that using a configuration such as `PLACEHOLDER_A_TO_Z:%player%`.
|
||||
Example:
|
||||
```yaml
|
||||
scoreboard-teams:
|
||||
sorting-types:
|
||||
- "PLACEHOLDER_A_TO_Z:%player%"
|
||||
```
|
||||
|
||||
## PLACEHOLDER_Z_TO_A
|
||||
This method sorts players reverse alphabetically, according to the output of a placeholder.
|
||||
This is identical to the above A to Z sorting, except that the alphabet is backwards, so Z comes first, and A comes last.
|
||||
To configure this sorting type, write the placeholder that you want to use. That's it.
|
||||
For example, if you want to sort players by their name reverse alphabetically, you would do that using a configuration such as `PLACEHOLDER_Z_TO_A:%player%`.
|
||||
Example:
|
||||
```yaml
|
||||
scoreboard-teams:
|
||||
sorting-types:
|
||||
- "PLACEHOLDER_Z_TO_A:%player%"
|
||||
```
|
||||
|
||||
## PLACEHOLDER_LOW_TO_HIGH
|
||||
This method sorts players numerically depending on the output of a **numeric** placeholder from the lowest value to the highest value.
|
||||
**Only placeholders that output number values will work with this sorting type!**
|
||||
Supported number interval is from -1,000,000,000 to 1,000,000,000 and 5 decimal places.
|
||||
To configure this sorting type, write the placeholder that you want to use. That's it.
|
||||
For example, if you want to sort players using the output of the `%health%` placeholder from the lowest health to highest, you would do that using a configuration such as `PLACEHOLDER_LOW_TO_HIGH:%health%`.
|
||||
Example:
|
||||
```yaml
|
||||
scoreboard-teams:
|
||||
sorting-types:
|
||||
- "PLACEHOLDER_LOW_TO_HIGH:%health%"
|
||||
```
|
||||
|
||||
## PLACEHOLDER_HIGH_TO_LOW
|
||||
This method sorts players numerically depending on the output of a **numeric** placeholder from the highest value to the lowest value.
|
||||
**Only placeholders that output number values will work with this sorting type!**
|
||||
Supported number interval is from -1,000,000,000 to 1,000,000,000 and 5 decimal places.
|
||||
To configure this sorting type, write the placeholder that you want to use. That's it.
|
||||
For example, if you want to sort players using LuckPerms weights, you would do that using a configuration such as `PLACEHOLDER_HIGH_TO_LOW:%luckperms_highest_group_weight%`.
|
||||
Example:
|
||||
```yaml
|
||||
scoreboard-teams:
|
||||
sorting-types:
|
||||
- "PLACEHOLDER_HIGH_TO_LOW:%luckperms_highest_group_weight%"
|
||||
```
|
||||
|
||||
# Multiple elements with the same priority
|
||||
If using a sorting type that uses pre-defined values ([GROUPS](#groups), [PERMISSIONS](#permissions) or [PLACEHOLDER](#placeholder)), you can sort multiple elements with the same priority by separating them with `|` symbol. Example using group sorting:
|
||||
```
|
||||
scoreboard-teams:
|
||||
sorting-types:
|
||||
- "GROUPS:owner,admin,vip1|vip2,default"
|
||||
```
|
||||
Where `vip1` and `vip2` will be sorted with the same priority (3rd).
|
||||
This works for permissions and pre-defined placeholder values as well.
|
||||
|
||||
# Combining multiple sorting types
|
||||
Since `sorting-types` is a list, you are able to use more than one sorting type. Sorting type priorities go in the same order as defined in the config. Let's take a look at the default config:
|
||||
```
|
||||
sorting-types:
|
||||
- "GROUPS:owner,admin,mod,helper,builder,vip,default"
|
||||
- "PLACEHOLDER_A_TO_Z:%player%"
|
||||
```
|
||||
Here, players are sorted by their group first.
|
||||
Owner goes above admin etc. However,
|
||||
if 2 people have the same group (such as admin), the next sorting type decides the final order.
|
||||
In this case, admin with alphabetically lower username will be higher in the tablist.
|
||||
|
||||
A common request is putting AFK players on the bottom of tablist. This can be achieved with the following configuration:
|
||||
```
|
||||
sorting-types:
|
||||
- "PLACEHOLDER:%essentials_afk%:no,yes"
|
||||
- "GROUPS:owner,admin,mod,helper,builder,vip,default"
|
||||
- "PLACEHOLDER_A_TO_Z:%player%"
|
||||
```
|
||||
With AFK status taking the highest priority, AFK players will always be sorted below players which are not AFK.
|
||||
Both player groups (afk and non-afk) then follow the rest of the logic explained above to define the final order.
|
||||
If trying to copy-paste this example, keep
|
||||
in mind [Placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements) work here as well,
|
||||
so if you are using a fancier output for %essentials_afk%,
|
||||
you will need to use outputs respectively when defining sorting as well.
|
||||
|
||||
Although you can theoretically use as many sorting types as you want, there are still strict limits set by mojang. See more about these limits and how to avoid them as much as possible at [Additional note 1 - Limitations](#additional-note-1---limitations).
|
||||
|
||||
# Additional settings
|
||||
| Option name | Default value | Description |
|
||||
|------------------------|---------------|------------------------------------------------------------------------|
|
||||
| case-sensitive-sorting | true | When enabled, players will be sorted as A-Z a-z. When disabled, Aa-Zz. |
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - Limitations
|
||||
All sorting elements must together build a team name up to 16 characters long. Because of that, cuts in placeholder outputs may be required. TAB is already using the shortest possible values for all sorting types:
|
||||
* `GROUPS`, `PERMISSIONS` and `PLACEHOLDER` - 1 character
|
||||
* `PLACEHOLDER_LOW_TO_HIGH` and `PLACEHOLDER_HIGH_TO_LOW` - 3 characters
|
||||
* `PLACEHOLDER_A_TO_Z` and `PLACEHOLDER_Z_TO_A` - as many as used
|
||||
|
||||
All your sorting types must be within a 15-character limit.
|
||||
Any characters above that will be cut off (TAB reserves 1 character to ensure each player is in a unique team).
|
||||
To get the most out of it, use the 1-character sorting types where possible.
|
||||
|
||||
You can bypass this limit by using [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) feature.
|
||||
Player ordering is fully plugin-sided and therefore is not artificially limited.
|
||||
|
||||
## Additional note 2 - per-world sorting
|
||||
Defining a per-world sorting type is not supported.
|
||||
However,
|
||||
this can be achieved with [Conditional placeholders](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders).
|
||||
Check for %world% and return one placeholder if it matches, another one if not.
|
||||
This will work with anything, not just worlds (server, regions, etc.).
|
||||
|
||||
## Additional note 3 - Compatibility issues with other plugins
|
||||
As you already know by now, sorting is managed by scoreboard teams (their names to be exact).
|
||||
Player can only be a member of one team.
|
||||
In other words, only one plugin can handle teams at a time.
|
||||
Having multiple plugins handling teams is supposed to end in a disaster.
|
||||
|
||||
Fortunately, TAB contains a function that prevents other plugins from assigning players into teams.
|
||||
When a plugin tries to override TAB's teams, this action is logged into `anti-override.log` file.
|
||||
If your file is empty / does not exist, it means you have no conflicting plugins / settings.
|
||||
If the file exists, most of the time you can guess where the teams come from by their name.
|
||||
Here are a few common teams and their sources (`xxxx` means any, usually random character sequence):
|
||||
* `collideRule_xxxx` - this comes from Paper. Not going to explain why as that would be quite long, but the way you can avoid is by setting `enable-player-collisions: true` in paper config and `enable-collision: false` in TAB config (yes, collisions will be disabled).
|
||||
* `CMINPxx` - CMI, set `DisableTeamManagement: true` in `plugins/CMI/config.yml` (though CMI won't allow you to change glow color if you do, so keep that in mind).
|
||||
* `CIT-xxxxxxxxxxxx` - Citizens NPC with the same name as some online player. Make NPC names not match real players and use holograms to display your desired text (/npc name or something).
|
||||
* `PVP-xxxxxxxxxxxx` - Team coming from [PvPManager](https://www.spigotmc.org/resources/pvpmanager-lite.845/) plugin.
|
||||
|
||||
This detection, however, is not 100%.
|
||||
Because of that, you may still be experiencing a compatibility issue even with anti-override enabled.
|
||||
To identify such an issue, check if /tab reload fixes your sorting issue.
|
||||
If it does, it's a compatibility issue of some sort.
|
||||
If not, it is most likely a misconfiguration issue.
|
||||
|
||||
# Troubleshooting
|
||||
There are many possible reasons why sorting may not work as desired, let's name them all.
|
||||
To get started, run `/tab dump <some player>` and open the generated link. Scroll down to `features` -> `Sorting`.
|
||||
If it says `Sorting: Feature is disabled`, it means you disabled sorting. See [Enabling](#enabling).
|
||||
Check the table of players in the `Sorting` section. The players are listed in the order they should appear in the tablist. Does it match the in-game result?
|
||||
**Option 1 - Players are listed in the same order they appear in game** - This means you did not configure sorting correctly. Check the table of all values for all players and see what is different than you expected:
|
||||
* Your group is wrong (shown in the table as well as on top of the dump):
|
||||
* You did not configure weights in LuckPerms.
|
||||
* You accidentally enabled `use-bukkit-permission-manager` option when on a proxy without knowing what it does.
|
||||
* You installed TAB on a proxy without having any permission plugin on the proxy.
|
||||
* You enabled `assign-groups-by-permissions` without giving those permissions (or the opposite - giving away OP to users, resulting in the highest group being taken).
|
||||
* You mistook `primary-group-finding-list` for the sorting list and did not configure the actual group sorting list.
|
||||
* You combined multiple sorting types, but listed them in the wrong order. See [Combining multiple sorting types](#combining-multiple-sorting-types) (sorting element priorities go from top to bottom, in the table they appear from left to right).
|
||||
|
||||
**Option 2 - Players are listed in a different order than in-game** - This means teams were not applied properly. Possible reasons include:
|
||||
* Teams are disabled for the player (`disable-condition` was met or teams were disabled via API).
|
||||
* You have TAB on Velocity and forgot to install [VelocityScoreboardAPI](https://github.com/NEZNAMY/VelocityScoreboardAPI/releases) (or it's outdated and doesn't support your Velocity / game version).
|
||||
* You are using a plugin that causes TAB to fail to apply teams (such as Tablisknu). This includes installing TAB plugin on both backend and proxy, causing the installations to conflict (typically proxy taking over and backend not working).
|
||||
|
||||
# API
|
||||
*To get started with the API, see [Developer API](https://github.com/NEZNAMY/TAB/wiki/Developer-API) page.*
|
||||
|
||||
To access this feature, you'll need to obtain `SortingManager` instance. Get it using `TabAPI.getInstance().getSortingManager()`. If sorting is disabled, the method will return `null`.
|
||||
|
||||
You can change player's team name using the following methods:
|
||||
* `SortingManager#forceTeamName(TabPlayer, String)` - Sets player's team name to specified value (and performs team unregister & register with new name).
|
||||
* `SortingManager#getForcedTeamName(TabPlayer)` - Returns player's forced team name using the method above. Will return `null` if no value is set.
|
||||
|
||||
Unfortunately, there is no simple way of just changing one's position while still accounting for other players.
|
||||
This is because the plugin supports a lot of sorting options, not just groups,
|
||||
so doing amateur stuff like "priority 1, 2" doesn't make sense.
|
||||
If you are really only interested in sorting by groups and changing group which player is sorted as,
|
||||
you can use `TabPlayer#setTemporaryGroup(String)`.
|
||||
To reset the group back to normal, call the function with `null` argument.
|
||||
@@ -0,0 +1,31 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Enabling](#enabling)
|
||||
* [Permissions](#permissions)
|
||||
* [Additional info](#additional-info)
|
||||
* [Additional note 1 - Seeing yourself still as spectator](#additional-note-1---seeing-yourself-still-as-spectator)
|
||||
|
||||
# About
|
||||
With the introduction of spectator gamemode in 1.8,
|
||||
players having it automatically appear on the bottom of tablist with transparent name and missing [Playerlist Objective](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Playerlist-Objective).
|
||||
This feature cancels gamemode change packets to spectator gamemode, cancelling this Minecraft feature.
|
||||
|
||||
# Enabling
|
||||
To enable this feature, open **config.yml** and set
|
||||
```
|
||||
prevent-spectator-effect:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
# Permissions
|
||||
| Permission | Description |
|
||||
|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `tab.spectatorbypass` | Players with this permission will see spectators the usual way despite this feature being enabled. If you don't want players (or even staff members) to bypass this feature, don't give them that permission. |
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - Seeing yourself still as spectator
|
||||
Receiving information about going spectator gamemode allows players to clip through walls.
|
||||
Cancelling this on self would result in inability to go through walls.
|
||||
To avoid this, the information will be canceled for every player except the one going spectator gamemode.
|
||||
Therefore, if you change gamemode to spectator, you will still see yourself on the bottom,
|
||||
but no one else will (unless someone has the bypass permission).
|
||||
@@ -0,0 +1,196 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* [config.yml](#configyml)
|
||||
* [groups.yml and users.yml](#groupsyml-and-usersyml)
|
||||
* [Format structure](#format-structure)
|
||||
* [Global settings](#global-settings)
|
||||
* [Per-world / per-server](#per-world--per-server)
|
||||
* [Priorities](#priorities)
|
||||
* ~Commands~
|
||||
* [Placeholders](#placeholders)
|
||||
* ~Limitations~
|
||||
* [Compatibility with other plugins](#compatibility-with-other-plugins)
|
||||
* ~Additional info~
|
||||
* ~Troubleshooting~
|
||||
* [API](#api)
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Taking prefix/suffix from permission plugin](#example-1---taking-prefixsuffix-from-permission-plugin)
|
||||
|
||||
# About
|
||||
This feature allows you to configure player name formats in the tablist.
|
||||
It was added to Minecraft in version 1.8.
|
||||
Versions 1.7 and lower only allow up to 16 characters including name,
|
||||
which is too limiting and not supported by this plugin.
|
||||
If you wish to have prefix/suffix for 1.7 and lower,
|
||||
take advantage of [this client-sided mechanic](https://github.com/NEZNAMY/TAB/wiki/Client%E2%80%90sided-mechanics#nametag-format-in-tablist) and configure tagprefix/tagsuffix,
|
||||
which will appear in the tablist.
|
||||

|
||||
|
||||
# Configuration
|
||||
This feature is configured in 2 parts based on what you are configuring. Some settings are in the **config.yml**, but prefix/suffix is configured in **groups.yml** and **users.yml**.
|
||||
## config.yml
|
||||
The first part can be configured in **config.yml** under **tablist-name-formatting** section. It controls everything except prefix and suffix.
|
||||
|
||||
This is how the default configuration looks:
|
||||
```
|
||||
tablist-name-formatting:
|
||||
enabled: true
|
||||
disable-condition: '%world%=disabledworld'
|
||||
```
|
||||
All of the options are explained in the following table.
|
||||
| Option name | Default value | Description |
|
||||
|-----------------------------|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | true | Enables / Disables the feature |
|
||||
| disable-condition | %world%=disabledworld | A [condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) that must be met for disabling the feature for players. Set to empty for not disabling the feature ever. |
|
||||
|
||||
## groups.yml and users.yml
|
||||
### Format structure
|
||||
The display name is split into 3 parts for convenience:
|
||||
`tabprefix` - first part of the text, this is where prefix is usually configured
|
||||
`customtabname` - second part of the text, it will be used as player name. If customtabname is not defined at all (not just setting empty value!), player's original name will be used instead
|
||||
`tabsuffix` - last part of the text, this is where suffix is usually configured
|
||||
|
||||
These values are then merged and displayed in the tablist.
|
||||

|
||||
|
||||
You are free to use the 3 properties in any way you want since they are only split for convenience.
|
||||
However, it is still a good idea to use them for their designed purpose to not get lost in a poor configuration.
|
||||
This means that the text which should appear before player's name should be put into `tabprefix`,
|
||||
any placeholder that is supposed to display player's name (such as from a nickname plugin)
|
||||
should go into `customtabname` and any text that should appear after player's name should be put into `tabsuffix`.
|
||||
|
||||
### Global settings
|
||||
Properties can be applied in 2 ways: groups and users. Users can be defined by both username and their UUID. Values applied to users take priority over groups.
|
||||
|
||||
**groups.yml**
|
||||
```
|
||||
admin:
|
||||
tabprefix: "&4&lAdmin &r"
|
||||
```
|
||||
Or with an in-game command `/tab group admin tabprefix "&4&lAdmin &r"`.
|
||||
|
||||
**users.yml**
|
||||
```
|
||||
_NEZNAMY_:
|
||||
tabprefix: "&6&lTAB &r"
|
||||
|
||||
# An alternate way using UUID
|
||||
237d8b55-3f97-4749-aa60-e9fe97b45062:
|
||||
tabprefix: "&6&lTAB &r"
|
||||
```
|
||||
Or with in-game commands `/tab player _NEZNAMY_ tabprefix "&6&lTAB &r"` and `/tab playeruuid _NEZNAMY_ tabprefix "&6&lTAB &r"` (the player must be online for uuid option to work).
|
||||
|
||||
Properties can also be set as "default" for everyone who does not have them defined.
|
||||
For that purpose, a group keyword `_DEFAULT_` was made.
|
||||
Example:
|
||||
**groups.yml**
|
||||
```
|
||||
admin:
|
||||
tabprefix: "&4&lAdmin &r"
|
||||
_DEFAULT_:
|
||||
tabprefix: "&7" # This will be displayed on everyone except admin
|
||||
```
|
||||
|
||||
### Per-world / per-server
|
||||
Values can also be applied per-world (and per-server on a proxy), where they can be defined per group/user. These values take priority over global settings. Example:
|
||||
**groups.yml**
|
||||
```
|
||||
per-world:
|
||||
world1:
|
||||
_DEFAULT_:
|
||||
tabprefix: "&a" # Everyone in world "world1" will have this prefix
|
||||
per-server:
|
||||
server1:
|
||||
_DEFAULT_:
|
||||
tabprefix: "&a" # Everyone in server "server1" will have this prefix
|
||||
```
|
||||
|
||||
For multiple worlds/servers to share the same settings, separate them with a`;`.
|
||||
For worlds/server starting with a specified text, use `*` after shared part. For ending with a shared part, use `*` at the beginning.
|
||||
Example:
|
||||
```
|
||||
per-world:
|
||||
world1;world2:
|
||||
_DEFAULT_:
|
||||
tabsuffix: "Shared tagsuffix in worlds world1 and world2"
|
||||
lobby-*:
|
||||
_DEFAULT_:
|
||||
tabsuffix: "Suffix in all worlds starting with lobby-"
|
||||
```
|
||||
|
||||
### Priorities
|
||||
The full list of priorities to choose correct prefix/name/suffix for a player looks like this:
|
||||
1. value set using the [API](#api)
|
||||
2. per-world / per-server applied to username
|
||||
3. value applied to username
|
||||
4. per-world / per-server applied to uuid
|
||||
5. value applied to uuid
|
||||
6. per-world / per-server applied to player's group
|
||||
7. per-world / per-server applied to group `_DEFAULT_`
|
||||
8. value applied to player's group
|
||||
9. value applied to group `_DEFAULT_`
|
||||
|
||||
This list is browsed through until the first match is found. If no match is found, empty value is used.
|
||||
|
||||
Values are taken independently of each other.
|
||||
This means you can set per-world tabprefix, but only keep one global tabsuffix, for example.
|
||||
|
||||
You can see the source of a value displayed on player by using `/tab dump <player>`, opening the link and checking "source"
|
||||
part of the value you are looking for (tabprefix / customtabname / tabsuffix).
|
||||
|
||||
# Placeholders
|
||||
Here are TAB's PlaceholderAPI placeholders you can use when this feature is enabled:
|
||||
| Placeholder | Description |
|
||||
|-------------|-------------|
|
||||
| `%tab_tabprefix%` | Player's current tabprefix with placeholders parsed. |
|
||||
| `%tab_customtabname%` | Player's current customtabname with placeholders parsed. |
|
||||
| `%tab_tabsuffix%` | Player's current tabprefix with placeholders parsed. |
|
||||
| `%tab_tabprefix_raw%` | Player's current raw tabprefix with placeholder identifiers. |
|
||||
| `%tab_customtabname_raw%` | Player's current raw customtabname with placeholder identifiers. |
|
||||
| `%tab_tabsuffix_raw%` | Player's current raw tabsuffix with placeholder identifiers. |
|
||||
|
||||
# Compatibility with other plugins
|
||||
Tablist formatting is a feature that cannot be effectively handled by multiple plugins at once.
|
||||
To make sure no other plugin sets tablist display names when not disabled in the plugin's config properly, TAB will block attempts to modify tablist display names coming from all other plugins (if this feature is enabled and not disabled for a player with a condition).
|
||||
|
||||
# API
|
||||
*To get started with the API, see [Developer API](https://github.com/NEZNAMY/TAB/wiki/Developer-API) page.*
|
||||
|
||||
To access this feature, you'll need to obtain `TabListFormatManager` instance. Get it using `TabAPI.getInstance().getTabListFormatManager()`. If this feature is disabled, the method will return `null`.
|
||||
|
||||
To set the values for the respective formatting, use the following:
|
||||
* `TabListFormatManager#setPrefix(TabPlayer, String)`
|
||||
* `TabListFormatManager#setName(TabPlayer, String)`
|
||||
* `TabListFormatManager#setSuffix(TabPlayer, String)`
|
||||
|
||||
To reset the values, set them to `null`.
|
||||
|
||||
To get custom values previously set using the API (they will return `null` if no custom value is set):
|
||||
* `TabListFormatManager#getCustomPrefix(TabPlayer)`
|
||||
* `TabListFormatManager#getCustomName(TabPlayer)`
|
||||
* `TabListFormatManager#getCustomSuffix(TabPlayer)`
|
||||
|
||||
To get the original value set by the plugin based on configuration:
|
||||
* `TabListFormatManager#getOriginalRawPrefix(TabPlayer)` - Prefix with raw placeholder identifiers
|
||||
* `TabListFormatManager#getOriginalRawName(TabPlayer)` - Name with raw placeholder identifiers
|
||||
* `TabListFormatManager#getOriginalRawSuffix(TabPlayer)` - Suffix with raw placeholder identifiers
|
||||
* `TabListFormatManager#getOriginalReplacedPrefix(TabPlayer)` - Prefix with all placeholders parsed
|
||||
* `TabListFormatManager#getOriginalReplacedName(TabPlayer)` - Name with all placeholders parsed
|
||||
* `TabListFormatManager#getOriginalReplacedSuffix(TabPlayer)` - Suffix with all placeholders parsed
|
||||
|
||||
**Note**: These values are only temporary, meaning they won't get saved anywhere and will get reset on player quit or plugin reload. If you wish to save these values into file, use [commands](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions#tab-playergroupplayeruuid-name-property-value-options).
|
||||
|
||||
# Examples
|
||||
## Example 1 - Taking prefix/suffix from permission plugin
|
||||
If you want TAB to only take prefixes/suffixes from the permission plugin,
|
||||
delete all groups from **groups.yml** and only keep this:
|
||||
```
|
||||
_DEFAULT_:
|
||||
tabprefix: "%luckperms-prefix%"
|
||||
tabsuffix: "%luckperms-suffix%"
|
||||
```
|
||||
Or a PlaceholderAPI placeholder from your permission plugin if you use a different one.
|
||||
|
||||
> [!NOTE]
|
||||
> When doing this, make sure you don't delete something you didn't mean to delete, for example ta**g**prefix and ta**g**suffix from nametag feature.
|
||||
@@ -0,0 +1,4 @@
|
||||
# About
|
||||
A collection of things people have requested that I might look into implementing when I get extremely bored sometime next decade.
|
||||
* Relational placeholder support in sorting
|
||||
* 1.21.2+ sorting support
|
||||
@@ -0,0 +1,165 @@
|
||||
# Content
|
||||
* [#1 - Why are NPCs showing up in the tablist?](#1---why-are-npcs-showing-up-in-the-tablist)
|
||||
* [#2 - How to make TAB work with LuckPerms?](#2---how-to-make-tab-work-with-luckperms)
|
||||
* [#3 - I enabled MySQL, and my prefix is now gone!](#3---i-enabled-mysql-and-my-prefix-is-now-gone)
|
||||
* [#4 - Why is player sorting not working?](#4---why-is-player-sorting-not-working)
|
||||
* [#5 - How to add players to %staffonline% placeholder?](#5---how-to-add-players-to-the-staffonline-placeholder)
|
||||
* [#6 - How to make player heads visible in tablist?](#6---how-to-make-player-heads-visible-in-tablist)
|
||||
* [#7 - Where can I find current default config files?](#7---where-can-i-find-current-default-config-files)
|
||||
* [#8 - How can I split players into multiple columns?](#8---how-can-i-split-players-into-multiple-columns)
|
||||
* [#9 - How to use space in prefix/suffix command?](#9---how-to-use-spaces-in-prefixsuffix-command)
|
||||
* [#10 - Can I change/remove the green connection bar in tablist?](#10---can-i-changeremove-the-green-connection-bar-in-tablist)
|
||||
* [#11 - Placeholder is not working](#11---placeholder-is-not-working)
|
||||
* [#12 - How can I display images from resource pack plugin?](#12---how-can-i-display-images-from-resource-pack-plugin)
|
||||
* [#13 - How can I use UTF characters in configuration?](#13---how-can-i-use-utf-characters-in-configuration)
|
||||
* [#14 - Is there a way to remove all players from tablist?](#14---is-there-a-way-to-remove-all-players-from-tablist)
|
||||
* [#15 - How to add images to tablist?](#15---how-to-add-images-to-tablist)
|
||||
* [#16 - Is MiniMessage supported?](#16---is-minimessage-supported)
|
||||
* [#17 - Is it possible to show the number of players in a specific group, similar to staffonline placeholder?](#17---is-it-possible-to-show-the-number-of-players-in-a-specific-group-similar-to-staffonline-placeholder)
|
||||
* [#18 - Why is the plugin flagged as a virus by Windows defender?](#18---why-is-the-plugin-flagged-as-a-virus-by-windows-defender)
|
||||
* [#19 - How can I show amount of online players on the entire network?](#19---how-can-i-show-amount-of-online-players-on-the-entire-network)
|
||||
* [#20 - Why is LuckPerms prefix/suffix not updating on a network?](#20---why-is-luckperms-prefixsuffix-not-updating-on-a-network)
|
||||
|
||||
## #1 - Why are NPCs showing up in the tablist?
|
||||
See [Citizens FAQ](https://wiki.citizensnpcs.co/Frequently_Asked_Questions#Why_are_NPCs_showing_up_in_the_tablist.3F).
|
||||
|
||||
## #2 - How to make TAB work with LuckPerms?
|
||||
* If you want to take prefixes/suffixes, check [this guide](https://github.com/NEZNAMY/TAB/wiki/Mini-guides-collection#taking-prefixessuffixes-from-permission-plugin) and use `%luckperms-prefix%` & `%luckperms-suffix%`.
|
||||
* Sorting:
|
||||
First, configure weights correctly in LuckPerms. Then, you have 2 options:
|
||||
* Configure [sorting by groups](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Sorting-players-in-tablist#groups) (recommended).
|
||||
* Sorting by weights directly: `PLACEHOLDER_HIGH_TO_LOW:%luckperms_highest_group_weight%`.
|
||||
|
||||
## #3 - I enabled MySQL, and my prefix is now gone!
|
||||
When enabling [MySQL](https://github.com/NEZNAMY/TAB/wiki/MySQL), it will be used as a data storage and groups.yml / users.yml files will no longer be used.
|
||||
If you want to upload your configuration to MySQL (or download it back to files), use [MySQL conversion commands](https://github.com/NEZNAMY/TAB/wiki/MySQL#data-conversion) - [`/tab mysql upload`](https://github.com/NEZNAMY/TAB/wiki/MySQL#uploading-from-files-to-mysql) and [`/tab mysql download`](https://github.com/NEZNAMY/TAB/wiki/MySQL#downloading-from-mysql-to-files), respectively.
|
||||
After you are done, run `/tab reload` for the changes to take effect.
|
||||
|
||||
## #4 - Why is player sorting not working?
|
||||
See [Common mistakes section on sorting page](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Sorting-players-in-tablist#common-mistakes).
|
||||
|
||||
## #5 - How to add players to the %staffonline% placeholder?
|
||||
Give them the `tab.staff` permission.
|
||||
|
||||
## #6 - How to make player heads visible in tablist?
|
||||
Players who did not buy the game will never be able to see heads.
|
||||
The client displays Player heads when connection to the server is an online connection authenticated through Mojang.
|
||||
It cannot be directly controlled by plugins.
|
||||
The intended way to reach this is by setting `online-mode=true` in `server.properties`.
|
||||
If you want to allow pirates on your server,
|
||||
you can still display heads for players who bought the game by changing their connections to online connections.
|
||||
Most commonly used plugins for this are [FastLogin](https://www.spigotmc.org/resources/14153/) and [JPremium](https://www.spigotmc.org/resources/27766/),
|
||||
which change connections of premium players who enabled it to online connections.
|
||||
The same goes for disabling heads - you cannot disable them if you have online mode enabled.
|
||||
|
||||
Minecraft 1.21.9 has added [object components](https://github.com/NEZNAMY/TAB/wiki/How-to-use-Minecraft-components#object-components-1219), which allow you to display player heads. You can put for example `<head:%player%>` at the beginning of tabprefix to simulate this (you will need a plugin like SkinsRestorer for the players to properly be able to recognize skins by player name).
|
||||
|
||||
## #7 - Where can I find current default config files?
|
||||
You can do any of the following:
|
||||
* Check the [source code](https://github.com/NEZNAMY/TAB/tree/master/shared/src/main/resources/config).
|
||||
* Delete or rename a file, and the plugin will regenerate it.
|
||||
* Open the plugin jar as a zip file and take files from there.
|
||||
|
||||
## #8 - How can I split players into multiple columns?
|
||||
The client puts players into columns, it is not managed by the server.
|
||||
The only way is to get more players.
|
||||
They automatically split into more columns at 21, 41 and 61 players (due to limit of 20 entries per column).
|
||||
If you don't mind getting all 80 slots filled with fake player slots,
|
||||
check out the [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) feature.
|
||||
|
||||
## #9 - How to use spaces in prefix/suffix command?
|
||||
Use "", for example `/tab group owner tabprefix "&2&lOwner&r "`
|
||||
|
||||
## #10 - Can I change/remove the green connection bar in tablist?
|
||||
The connection bar is client sided and cannot be re-textured or removed by TAB.
|
||||
You will need a custom Minecraft client or a resource pack.
|
||||
|
||||
## #11 - Placeholder is not working
|
||||
Most common reasons for a placeholder to not work include:
|
||||
* Using % symbol by itself, which breaks placeholder starts and ends and therefore breaks all placeholders after it (use %% to display the symbol)
|
||||
* Trying to use a PlaceholderAPI placeholder without downloading its expansion or not having PlaceholderAPI installed at all
|
||||
* Trying to use [TAB's internal backend-only placeholders](https://github.com/NEZNAMY/TAB/wiki/Placeholders#backend-only) on a proxy
|
||||
* Trying to use PlaceholderAPI placeholders on proxy without installing [bridge plugin](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge)
|
||||
|
||||
The full list of reasons can be found on the [Placeholders](https://github.com/NEZNAMY/TAB/wiki/Placeholders#placeholder-is-not-working) page.
|
||||
|
||||
## #12 - How can I display images from resource pack plugin?
|
||||
Images work by mapping a chosen character to an image in a resource pack.
|
||||
When the game receives this character, it displays the image instead of the character.
|
||||
What you need to do is send this character to the client.
|
||||
Although resource pack plugins are not all the same, they all have things in common.
|
||||
The first main functionality is offering placeholders.
|
||||
You can use their PlaceholderAPI placeholders in TAB, and they will return the symbol, which then the client displays as an image.
|
||||
The second main functionality is creating internal placeholders, which are different per plugin.
|
||||
The plugin then listens to outgoing packets and replaces the internal placeholder with the symbol.
|
||||
This can, however, fail.
|
||||
Here are possible reasons why:
|
||||
* You have TAB on proxy, so backend plugin cannot modify packets sent by the proxy
|
||||
* TAB also listens to packets and modifies them to make sure no other plugin is overriding it. This mostly applies to [Tablist name formatting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Tablist-name-formatting). TAB then ends up having the last shot, overriding the resource pack plugin.
|
||||
|
||||
In order to make sure images display properly, use PlaceholderAPI placeholders instead of internal placeholders of your resource pack plugins.
|
||||
Here is some extra information for each resource pack plugin you might find useful:
|
||||
* ItemsAdder:
|
||||
* The PlaceholderAPI placeholders are formatted as `%img_<name>%`, internal placeholders (`:something:`) may not always work (see above).
|
||||
* If you are unable to change the placeholder references from internal placeholders to PlaceholderAPI placeholders (for example, because they are defined in permission plugin and used elsewhere as well, where PlaceholderAPI isn't supported), you can use [PlaceholderAPI](https://github.com/NEZNAMY/TAB/wiki/Quick-PlaceholderAPI-startup-guide)'s `imgfix` expansion that replaces format of given placeholders into the correct format.
|
||||
Example: `%luckperms_prefix%` -> `%imgfix_{luckperms_prefix}%`
|
||||
* Nexo:
|
||||
* Here is a collection of tips from Nexo discord: <br /><img width="476" height="238" alt="image" src="https://github.com/user-attachments/assets/0eca8e9b-a73f-4e66-9c76-11a230e823b4" />
|
||||
|
||||
|
||||
## #13 - How can I use UTF characters in configuration?
|
||||
**Option 1**: [Save the file in UTF-8 encoding](https://github.com/NEZNAMY/TAB/wiki/How-to-save-the-config-in-UTF8-encoding) and use your desired symbol directly.
|
||||
|
||||
**Option 2**: Find hex code of your symbol (4 hexadecimal numbers) and use `\uxxxx` format,
|
||||
where `xxxx` is hex code of the symbol.
|
||||
Make sure to also wrap the text into `""` for the text to properly take `\` as an escape symbol.
|
||||
Using `''` will result in the text being display literally, not as a code.
|
||||
|
||||
**Note:** Minecraft does not support every single UTF symbol and displays unsupported symbols as a box. You can try sending your symbol into chat and see if it works or not. If not, it's not supported by MC.
|
||||
|
||||
## #14 - Is there a way to remove all players from tablist?
|
||||
Here are various ways to achieve this goal:
|
||||
|
||||
* **Option 1: Hide players entirely** - In Minecraft, for a player to be visible in-game, they also need to added into the tablist. If you don't mind hiding players from game as well, there are plugins that offer this (TAB is, however, not one of them).
|
||||
In 1.19.3, the player info packet received a new field that allows us to explicitly hide players from tablist while all the necessary data is still sent to players.
|
||||
|
||||
* **Option 2: Layout with 0 slots** - Since Minecraft 1.19.3, the limitation explained above has been lifted — it's now possible to have entities in the game without showing them in the tablist. TAB does not have an explicit feature for doing this. However, since 1.19.3, the [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) feature uses this mechanic to allow less than 80 slots. This feature can be "abused" by enabling the feature, removing fixed-slots and adding `slot-count: 0` to the displayed layout. The final effect will be a playerless tablist.
|
||||
|
||||
* **Option 3: Pushing players out of the screen with header** - You can add a ton of empty lines into the header. As a result, players will be pushed down out of the screen and effectively not visible.
|
||||
|
||||
## #15 - How to add images to tablist?
|
||||
You can check out [this Reddit post](https://www.reddit.com/r/admincraft/comments/llrgty/comment/gnswdcz/?utm_source=share&utm_medium=web2x&context=3).
|
||||
When using the symbol in configuration using \u format, remember to use `""` in config instead of `''`.
|
||||
|
||||
## #16 - Is MiniMessage supported?
|
||||
Yes, however, it must be included in your server software (it is only in Paper / Velocity). Read more about MiniMessage hook [here](https://github.com/NEZNAMY/TAB/wiki/How-to-use-Minecraft-components#minimessage).
|
||||
|
||||
## #17 - Is it possible to show the number of players in a specific group, similar to staffonline placeholder?
|
||||
The plugin's internal placeholders are limited, and this kind of functionality is not included.
|
||||
However,
|
||||
you can achieve this using PlaceholderAPI's `PlayerList` expansion
|
||||
and following [this example](https://github.com/Tanguygab/PlayerList-PlaceholderAPI-Expansion/wiki#list-of-players-in-group).
|
||||
|
||||
## #18 - Why is the plugin flagged as a virus by Windows defender?
|
||||
First, this is a false positive.
|
||||
[Here](https://www.spigotmc.org/threads/windows-defender-false-positives.639507/)'s a spigot thread confirming it.
|
||||
|
||||
After experimenting with VirusTotal,
|
||||
it turns out the antivirus software available on the website used flags [bStats](https://github.com/Bastian/bStats) library as malicious.
|
||||
Its purpose is to collect anonymous data about servers and submitting it to [bStats.org](https://bstats.org/),
|
||||
where plugin authors can see how many servers use their plugins (if they don't disable it).
|
||||
It also checks for CPU and OS types, which could be the reason for the false positive.
|
||||
[Here](https://bstats.org/plugin/bukkit/TAB%20Reborn/5304) is one of TAB's pages as an example.
|
||||
|
||||
Windows defender could be flagging it for the same reason.
|
||||
|
||||
## #19 - How can I show amount of online players on the entire network?
|
||||
If you have TAB installed on the proxy, use `%online%` placeholder.
|
||||
If you have TAB installed on the backend servers, use `%bungee_total%` from [PlaceholderAPI](https://github.com/NEZNAMY/TAB/wiki/Quick-PlaceholderAPI-startup-guide). This placeholder has an internal cooldown, which can be configured in `plugins/PlaceholderAPI/config.yml` under `expansions` -> `bungee` -> `check_interval`, default value is 30 (seconds).
|
||||
|
||||
## #20 - Why is LuckPerms prefix/suffix not updating on a network?
|
||||
In order for LuckPerms instances to pick up the changes to player data in real time, it needs to communicate the changes between proxy ↔ backend.
|
||||
If you notice changes not taking effect in TAB, try running `/lpb user <player> info` (or `/lpv` on velocity). If running the command updates it in TAB, that's the problem - LuckPerms instances not communicating in real time.
|
||||
|
||||
This is controlled by a LuckPerms setting called [messaging-service](https://luckperms.net/wiki/Syncing-data-between-servers#messaging-services). Set it to `pluginmsg` to make changes update immediately.
|
||||
Additionally, make sure `auto-push-updates` is still `true` (it is by default already).
|
||||
@@ -0,0 +1,45 @@
|
||||
# About the wiki
|
||||
The wiki explains the functionality of the plugin as of version **6.2.0**.
|
||||
If your config looks different or is missing some features, you are using an old version of the plugin.
|
||||
To get the latest version, check [releases](https://github.com/NEZNAMY/TAB/releases/).
|
||||
Wiki for older plugin versions is not available.
|
||||
|
||||
If you plan to run your server for longer than 1 week,
|
||||
it's a good idea to read this wiki as it explains everything about the plugin.
|
||||
This will give you knowledge to do things you had no idea were possible, giving you an advantage over everyone else.
|
||||
|
||||
A lot of examples on the wiki use PlaceholderAPI placeholders without explaining its installation step by step. If you are going to use the examples and aren't familiar with the plugin, check out [Quick PlaceholderAPI startup guide](https://github.com/NEZNAMY/TAB/wiki/Quick-PlaceholderAPI-startup-guide).
|
||||
|
||||
# Terminology
|
||||
On order to not have to explain something every time it is mentioned, it will be explained here once.
|
||||
| Name | Description |
|
||||
|----------------|-----------------------|
|
||||
| proxy server | Server running BungeeCord or Velocity software, which are used to connect multiple servers, allowing easy transfer between them. |
|
||||
| modded server | Fabric, Forge and NeoForge. |
|
||||
| backend server | Minecraft server that is actually being played on, not a proxy. This includes Bukkit (and its forks) and modded servers |
|
||||
|
||||
# Limitations of plugins
|
||||
TAB is a plugin (even on modded platforms, it is only a server-sided mod).
|
||||
It only modifies the server behavior to your liking.
|
||||
It does not add anything into the game.
|
||||
Because of that, you'll need
|
||||
to carefully read the limitations of each feature to know what they are capable of and what they are not capable of.
|
||||
Some of the undesired behavior can be altered using a resource pack and some using a modified client.
|
||||
Both of these are out of scope of TAB as a plugin; therefore, no advanced information regarding this is provided.
|
||||
|
||||
# Public plugin
|
||||
TAB is a public plugin designed to satisfy the needs of a majority of servers.
|
||||
|
||||
This means it has functions not everyone will need. All you need to do is disable functions you don't want. Disabled features do not consume the CPU at all.
|
||||
|
||||
On the other hand, it cannot contain everything everyone can think of.
|
||||
There must be a balance
|
||||
between providing as much as possible while making the configuration as short and readable as possible.
|
||||
This is not an easy task.
|
||||
The majority of things that are not supported directly can be achieved in different ways.
|
||||
Adding direct way for everything everyone asks for would not only take a lot of time,
|
||||
but make the plugin harder to configure for everyone, as well as introduce a lot of duplicate ways to achieve things,
|
||||
making the plugin overcomplicated.
|
||||
If your need is very specific and not available in the plugin in any way,
|
||||
you should look into private plugin development.
|
||||
You will end up with a plugin made just for you with everything you want and nothing else.
|
||||
@@ -0,0 +1,58 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Option 1: Primary group from permission plugin](#option-1-primary-group-from-permission-plugin)
|
||||
* [Option 2: Permission nodes](#option-2-permission-nodes)
|
||||
* [Taking groups from backend servers when TAB is on proxy](#taking-groups-from-backend-servers-when-tab-is-on-proxy)
|
||||
|
||||
## About
|
||||
TAB uses groups to assign properties (such as tabprefix) and sort players in tablist (if sorting by groups). You have 2 ways of configuring primary groups of players in TAB.
|
||||
|
||||
First option hooks into your permission plugin and takes groups from it. Therefore, your permission plugin must be supported.
|
||||
**Supported permission plugins**: **LuckPerms** everywhere, on Bukkit any plugin supporting **Vault**.
|
||||
If your permission plugin is not supported, you can use [Option 2](#option-2-permission-nodes).
|
||||
|
||||
## Option 1: Primary group from permission plugin
|
||||
This is the default method and recommended.
|
||||
TAB will ask your permission plugin for player's primary group.
|
||||
There are 2 simple steps to this:
|
||||
* Keep `assign-groups-by-permissions: false` in your config
|
||||
* Put players into groups in your permission plugin
|
||||
> [!CAUTION]
|
||||
> If assigning players into multiple groups, make sure their weights are correct
|
||||
> (for luckperms /lp group \<group\> setweight \<number\>).
|
||||
|
||||
> [!TIP]
|
||||
> Verify player's group using `/tab dump <player>`, opening the link and check "permissionGroup" in player info.
|
||||
|
||||
## Option 2: Permission nodes
|
||||
Instead of taking whole groups, TAB will check for permission nodes and assign groups based on the highest permission.
|
||||
1. Go to config.yml and set `assign-groups-by-permissions: true`.
|
||||
2. Give `tab.group.<group name>` permission to the user/permission group.
|
||||
3. Put all possible groups into `primary-group-finding-list`.
|
||||
This is necessary because:
|
||||
#1 - there's no way to get the list of permissions, only checking for a permission.
|
||||
The list will be used for a list of permissions to check for.
|
||||
#2 - if a player has permission for more than one group, the list will be used to pick the correct one
|
||||
(the one higher in the list).
|
||||
|
||||
> [!WARNING]
|
||||
> Remember that OP = all permissions!
|
||||
> That's the whole point of OP function.
|
||||
> To grant all permissions.
|
||||
> In that case,
|
||||
> you need to negate permissions in your permission plugin for other groups which are higher than player's wanted group.
|
||||
|
||||
# Taking groups from backend servers when TAB is on proxy
|
||||
By default, TAB takes groups from the permission plugin installed on the same server instance.
|
||||
In the case of proxy installation, groups are by default taken from the proxy.
|
||||
To see how is your proxy permission plugin configured, use its respective command
|
||||
(for LuckPerms it's `/lpb user <player> info` on BungeeCord and `/lpv user <player> info` on Velocity).
|
||||
|
||||
If you don't have your permission plugin synced using MySQL for sharing groups and don't wish to, and want groups to be taken from backend servers instead, enable the config option:
|
||||
```
|
||||
use-bukkit-permissions-manager: true
|
||||
```
|
||||
When enabling it, all group **and** permission requests will be done through [Bridge plugin](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge) to take data from backend servers. Your groups will now match data from backend server a player is connected to (in case of LuckPerms `/lp user <player> info`).
|
||||
|
||||
When assigning by permissions instead of taking the primary group directly from permission plugin,
|
||||
the permission nodes (`tab.group.<name>`) will be taken from backend servers instead.
|
||||
@@ -0,0 +1,113 @@
|
||||
# Content
|
||||
* [Tablist](#tablist)
|
||||
* [Nametag](#nametag)
|
||||
* [Proper compatibility with plugins that change profile name](#proper-compatibility-with-plugins-that-change-profile-name)
|
||||
* [Tips & Tricks](#tips--tricks)
|
||||
* [Tip 1 - Nickname prefix](#tip-1---nickname-prefix)
|
||||
* [Tip 2 - Sorting nicked players with the lowest priority](#tip-2---sorting-nicked-players-with-the-lowest-priority)
|
||||
|
||||
# Tablist
|
||||
This one is straightforward.
|
||||
The tablist format of players is one text split into 3 parts in the plugin for convenience
|
||||
(tabprefix, customtabname, tabsuffix).
|
||||
Using `customtabname` you can configure name part into any placeholder you want,
|
||||
including one from your nickname plugin.
|
||||
All you need is a working PlaceholderAPI placeholder from your nickname plugin.
|
||||
Example:
|
||||
**groups.yml**
|
||||
```
|
||||
_DEFAULT_:
|
||||
customtabname: '%essentials_nickname%'
|
||||
```
|
||||
or using in-game command `/tab group _DEFAULT_ customtabname %essentials_nickname%`.
|
||||
|
||||
This example uses `%essentials_nickname%` placeholder from Essentials. Giving it to `_DEFAULT_` group keyword makes it a default value for all groups that do not override this property.
|
||||
|
||||
> [!CAUTION]
|
||||
> Do NOT put nickname placeholder into tabprefix!
|
||||
> You will end up with double names!
|
||||
> Put the nickname placeholder into customtabname instead.
|
||||
|
||||
# Nametag
|
||||
**TLDR: TAB does not offer this functionality**.
|
||||
|
||||
With that out of the way, let's learn more about this issue.
|
||||
Unlike with tablist name formatting, which is a single component containing everything (and therefore fully customizable), nametags are different.
|
||||
They consist of prefix and suffix components (coming from scoreboard teams) and name itself.
|
||||
This name is contained in player info packet (coincidentally the same one that controls tablist format), along with player's skin and other things.
|
||||
This name is limited to 16 characters (since Minecraft doesn't allow longer names) and since it's not a component, naturally it does not support RGB colors.
|
||||
Strangely enough, legacy codes using `§` work, but they further limit the length of the rest of the name.
|
||||
|
||||
There are really only 2 ways to achieve this solution:
|
||||
* **Change the profile name** - This requires sending player info packet that removes the old player and adds a new one with the same name. Then respawn the player. Additionally, it requires a lot of packets to be sent to the affected player, since you cannot just remove & add self, as well as a lot of other packets to restore previously sent data. These packets have been changing a lot with various MC versions. A lot of them cannot even be sent from a proxy server. As such, TAB does not offer this functionality, since it would be very limited anyway (see above) and require a lot of adapting for proper functionality.
|
||||
If you decide to use a plugin with this functionality, keep in mind it breaks all name-bound features, such as scoreboard teams, belowname or playerlist objective. See below for compatibility information.
|
||||
Example third party plugins that offer this: None?
|
||||
* **Use an armor stand / text display to show any text** - TAB no longer offers this functionality ([here's why](https://gist.github.com/NEZNAMY/f4cabf2fd9251a836b5eb877720dee5c)), so you will need to look into other plugins.
|
||||
If you decide to use a plugin with this functionality, just remember to make the vanilla nametag invisible, so you don't see both vanilla nametag and the entity (`invisible-nametags: true`).
|
||||
Example third party plugins that offer this: [UnlimitedNameTags](https://www.spigotmc.org/resources/unlimitednametags.117526/), [DisplayNameTags](https://github.com/Matt-MX/DisplayNameTags), [NotJustNamePlates](https://github.com/YouHaveTrouble/NotJustNameplates), [CustomNameplates](https://polymart.org/product/2543/customnameplates)
|
||||
|
||||
# Proper compatibility with plugins that change profile name
|
||||
If using a nickname plugin that changes player's profile name to change it in the name tag,
|
||||
this has lots of side effects.
|
||||
Most notably, it breaks all name-bound features,
|
||||
especially [nametags](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Nametags) and [sorting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Sorting-players-in-tablist).
|
||||
For that reason, TAB must detect name change.
|
||||
|
||||
> [!WARNING]
|
||||
> If you have TAB installed on backend server and a proxy plugin changes nickname, TAB is not able to detect this change, since the modified packets never actually go through the backend server where TAB is installed.
|
||||
|
||||
> [!TIP]
|
||||
> If automatic detection is not working for you (you use proxy plugin for changing names while TAB is on backend), you can use [this API method](https://github.com/NEZNAMY/TAB/blob/master/api/src/main/java/me/neznamy/tab/api/TabPlayer.java#L88) to let TAB know player's name changed.
|
||||
|
||||
In order for TAB to properly detect name change, player UUID must remain the same,
|
||||
otherwise it's a random entry with a random uuid and random name, which TAB isn't able to match with actual players.
|
||||
Make sure your nickname plugin is not changing UUID of players.
|
||||
If UUID changes, the plugin won't be able to properly format names even in the tablist,
|
||||
since entries there are bound to UUIDs and by changing it, it will break.
|
||||
Identifying whether name change detection is working properly or not can be checked
|
||||
by setting `debug: true` in config and checking console on name change.
|
||||
It should say `Processing name change of player <player name> to <new nickname>`.
|
||||
If it doesn't, something went wrong, most likely UUID not matching.
|
||||
|
||||
# Tips & Tricks
|
||||
## Tip 1 - Nickname prefix
|
||||
By default, Essentials prefixes nicknames of players in chat using `~` symbol for nicked players. We can very easily replicate that with [Conditional placeholders](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders). First, create a new condition:
|
||||
```
|
||||
conditions:
|
||||
nick:
|
||||
conditions:
|
||||
- '%essentials_nickname%=%player%'
|
||||
true: "%player%" # If nickname = player name -> player is not nicked
|
||||
false: "~%essentials_nickname%" # If nickname != player name -> player is nicked
|
||||
```
|
||||
Then, use `%condition:nick%` in your `customtabname` instead of the placeholder directly.
|
||||
|
||||
## Tip 2 - Sorting nicked players with the lowest priority
|
||||
Let's say your sorting list looks like this:
|
||||
```
|
||||
sorting-types:
|
||||
- "GROUPS:owner,admin,mod,helper,builder,vip,default"
|
||||
- "PLACEHOLDER_A_TO_Z:%player%"
|
||||
```
|
||||
Let's also assume that you want every nicked player to be sorted as `default`. This can be achieved using [sorting by placeholder](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Sorting-players-in-tablist#placeholder) and creating a [condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) that will return output based on nick status. First, let's create the condition:
|
||||
```
|
||||
conditions:
|
||||
group:
|
||||
conditions:
|
||||
- '%haonick_isNicked%=true'
|
||||
true: "default"
|
||||
false: "%group%"
|
||||
```
|
||||
When the condition is met, meaning player is nicked, it will return the group we want nicked players to be sorted as, in this case `default`. Otherwise, return player's actual group.
|
||||
The condition check may differ with different nickname plugins. You will need to check documentation of your nickname plugin to see what kind of placeholders it offers and what they return (you can also use `/tab parse` to see what exactly did a placeholder return).
|
||||
In this case, we are using placeholder `%haonick_isNicked%`, which returns `true` for nicked players.
|
||||
If using Essentials, the line would look like this: `%essentials_nickname%!=%player%`, because Essentials is made to return player's actual name when not nicked, meaning when it's not equal, player is nicked.
|
||||
|
||||
Finally, use the conditional placeholder in sorting:
|
||||
```
|
||||
sorting-types:
|
||||
- PLACEHOLDER:%condition:group%:owner,admin,mod,helper,builder,vip,default"
|
||||
- PLACEHOLDER_A_TO_Z:%player%
|
||||
```
|
||||
This will result in nicked players being sorted as `default`.
|
||||
If you want to achieve something more complicated, such as not only sorted as default, but another rank, you will need to dig deeper into your problem, analyzing available placeholders and functions that will help you achieve your result.
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
This guide will explain how to solve the incompatibility with glow plugins.
|
||||
|
||||
# Content
|
||||
* [Reason for compatibility issue](#reason-for-compatibility-issue)
|
||||
* [Solution](#Solution)
|
||||
* [Examples of glow plugins](#examples-of-glow-plugins)
|
||||
|
||||
## Reason for compatibility issue
|
||||
Glow color is managed by scoreboard teams, which also handle nametag formatting and player sorting in tablist. Only one plugin can handle teams at a time. Because of that, TAB will prevent glow plugins from assigning players into teams.
|
||||
|
||||
## Solution
|
||||
The solution to get around this issue is to use the glow plugin's placeholder (if it has any).
|
||||
This placeholder has to be at the end of the player's `tagprefix` as it has to be the last color in the prefix.
|
||||
> [!WARNING]
|
||||
> For Minecraft versions below 1.13 the prefix can't be longer than 14 characters due to [16-character limit](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Nametags#limitations) total
|
||||
(glow placeholder adds 2 characters - `&` and the color code)
|
||||
|
||||
**Example:**
|
||||
This example uses the placeholder of the [eGlow](https://www.spigotmc.org/resources/63295/) plugin.
|
||||
|
||||
**groups.yml**
|
||||
```
|
||||
_DEFAULT_:
|
||||
tagprefix: '%vault-prefix%%eglow_glowcolor%'
|
||||
```
|
||||
|
||||
## Examples of glow plugins
|
||||
- [eGlow](https://www.spigotmc.org/resources/63295/) (%eglow_glowcolor%) (Paid)
|
||||
- [CMI](https://www.spigotmc.org/resources/3742/) (%cmi_user_glow_code%) (Paid)
|
||||
- ... more?
|
||||
@@ -0,0 +1,34 @@
|
||||
# Programs
|
||||
* [Notepad](#notepad)
|
||||
* [Notepad++](#notepad-1)
|
||||
* [Sublime Text 3](#sublime-text-3)
|
||||
* [WinSCP](#winscp)
|
||||
* [VSCode](#vscode)
|
||||
***
|
||||
|
||||
# Notepad
|
||||
Open the file > Click file > Save as... > Set encoding to UTF-8 > Click save
|
||||

|
||||
|
||||
***
|
||||
|
||||
# Notepad++
|
||||
Open the file > Click encoding > Click UTF-8 (if that didn't work, use Convert to UTF-8)
|
||||

|
||||
|
||||
***
|
||||
|
||||
# Sublime Text 3
|
||||

|
||||
|
||||
***
|
||||
|
||||
# WinSCP
|
||||
Open the file in WinSCP and check if it is in UTF-8 encoding already (1). If it is not, click on ENCODING at the top (2), select UTF-8 (3) and then save the file. You can now edit the file as you like and paste in characters.
|
||||

|
||||

|
||||
|
||||
# VSCode
|
||||
At the bottom right of VSCode, you can change the current file's encoding. It'll open a pop-up where you can select UTF-8
|
||||

|
||||

|
||||
@@ -0,0 +1,195 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [RGB Colors (1.16+)](#rgb-colors-116)
|
||||
* [Usage](#usage)
|
||||
* [Magic codes](#magic-codes)
|
||||
* [Invalid code handling](#invalid-code-handling)
|
||||
* [Compatibility with <1.16](#compatibility-with-116)
|
||||
* [Fonts (1.16+)](#fonts-116)
|
||||
* [Usage](#usage-1)
|
||||
* [Compatibility with RGB and gradients](#compatibility-with-rgb-and-gradients)
|
||||
* [Shadow color (1.21.4+)](#shadow-color-1214)
|
||||
* [Object components (1.21.9+)](#object-components-1219)
|
||||
* [Atlas sprite](#atlas-sprite)
|
||||
* [Player sprite](#player-sprite)
|
||||
* [Compatibility with <1.21.9](#compatibility-with-1219)
|
||||
* [MiniMessage](#minimessage)
|
||||
* [Config options](#config-options)
|
||||
* [Tips & Tricks](#tips--tricks)
|
||||
* [Tip 1 - Manually defining legacy color](#tip-1---manually-defining-legacy-color)
|
||||
|
||||
# About
|
||||
In Minecraft 1.7, new feature called components was introduced. This is an upgrade from using legacy colors (using § symbol) into creating a JSON object where text, color, and magic codes (boolean values) are separated.
|
||||
Additionally, it received new features called hover event and click event. The only place this affects is chat, which TAB does not handle, so these functions are not implemented by TAB at all.
|
||||
|
||||
Components have been receiving a lot of new functions since then, which are explained below.
|
||||
|
||||
There are also a few config options for components. You can find them in your **config.yml** under `components` section. They are explained [below](#config-options).
|
||||
|
||||
# RGB colors (1.16+)
|
||||
As of 1.16, mojang introduced RGB color support.
|
||||
This allows us to use 16,777,216 different colors instead of the original 16 ones.
|
||||
This is not supported on <1.16 in any way.
|
||||
|
||||
## Usage
|
||||
Supported RGB formats:
|
||||
* `#RRGGBB`
|
||||
* `&#RRGGBB`
|
||||
* `{#RRGGBB}`
|
||||
* `#<RRGGBB>`
|
||||
* `&x&R&R&G&G&B&B`
|
||||
|
||||
Gradients:
|
||||
* `<#RRGGBB>Text</#RRGGBB>`
|
||||
* `{#RRGGBB>}Text{#RRGGBB<}`
|
||||
* `<$#RRGGBB>Text<$#RRGGBB>`
|
||||
|
||||
TAB uses the first by default, but is able to accept the other types as well without leaving any characters (such as `{}`) behind.
|
||||
**Gradients only support 2 colors, using more will result in an invalid syntax and won't work.**
|
||||
> [!CAUTION]
|
||||
> Remember to replace `RRGGBB` with actual hexadecimal numbers (0-9, a-f)!
|
||||
|
||||
You can use a tool like [this one](https://htmlcolorcodes.com/) to easily find suitable colors.
|
||||
|
||||
## Magic codes
|
||||
Just like with legacy colors, use color first, then magic codes (in any order). For example with **bold**: `#00FFFF&lText`.
|
||||
|
||||
For gradients, put the magic codes inside the text. Example: `<#00FF00>&lBold gradient text</#FF00FF>`.
|
||||
|
||||
## Invalid code handling
|
||||
In case you accidentally use invalid hex color code, the plugin will simply ignore it and keep it in raw format.
|
||||
|
||||
## Compatibility with <1.16
|
||||
Since <1.16 clients do not understand these color codes, something else must be displayed instead.
|
||||
TAB, server software or viaversion (depending on your setup)
|
||||
will find the closest legacy color to the desired RGB combination and will use that color instead.
|
||||
|
||||
# Fonts (1.16+)
|
||||
The plugin offers usage of the font feature introduced in Minecraft 1.16.
|
||||
> [!IMPORTANT]
|
||||
> This does NOT refer to different character sets!
|
||||
> This refers to different fonts defined in resource packs or MC itself.
|
||||
|
||||
## Usage
|
||||
The syntax is `<font:FONT_NAME>Text</font>` where `FONT_NAME` is name of your desired font.
|
||||
|
||||
**Example**
|
||||
`<font:minecraft:alt>This is a text written in minecraft enchantment table language which no one understands</font>`
|
||||
|
||||
**Result**
|
||||

|
||||
|
||||
|
||||
## Compatibility with RGB and gradients
|
||||
When trying to use both font and RGB or gradients, font must be outside and RGB/gradients inside.
|
||||
|
||||
**Example**
|
||||
`<font:minecraft:alt><#00FF00>This is a colorful text written in minecraft enchantment table language which no one understands, but it looks pretty</#FF0000></font>`
|
||||
|
||||
**Result**
|
||||

|
||||
|
||||
# Shadow color (1.21.4+)
|
||||
TAB (currently?) does not have any built-in way to convert text input into shadow color field. However, you can use [MiniMessage](#minimessage) for that. TAB will properly read this value from adventure components and convert it further into Minecraft components.
|
||||
|
||||
# Object components (1.21.9+)
|
||||
A new component of "object" type was added into the game in 1.21.9. It currently has 2 implementations described below.
|
||||
|
||||
## Atlas sprite
|
||||
This type allows you to display any item or block. The syntax is
|
||||
```
|
||||
<sprite:ATLAS:SPRITE>
|
||||
```
|
||||
where `ATLAS` is the atlas and `SPRITE` is the sprite. Note that atlas can contain the `:` symbol. In order to make TAB recognize it properly, wrap at least the first value into quotes.
|
||||
Example:
|
||||
```
|
||||
header:
|
||||
- '&bDiamond helmet: <sprite:"minecraft:items":"minecraft:item/diamond_helmet">'
|
||||
- 'Diamond chestplate: <sprite:"minecraft:items":"minecraft:item/diamond_chestplate">'
|
||||
- 'Diamond leggings: <sprite:"minecraft:items":"minecraft:item/diamond_leggings">'
|
||||
- 'Diamond boots: <sprite:"minecraft:items":"minecraft:item/diamond_boots">'
|
||||
```
|
||||
<img width="386" height="101" alt="image" src="https://github.com/user-attachments/assets/e9a66305-2ae4-44f4-9d8e-a227fb7591e4" />
|
||||
|
||||
|
||||
> [!IMPORTANT]
|
||||
> These values change over MC versions (for example items were in `minecraft:blocks` atlas in 1.21.9 - 1.21.10, but got moved to `minecraft:items` in 1.21.11), so make sure you are using the correct values for your MC version. For proxy installations, you may need to use conditional placeholders and check for player's version. On backend, ViaVersion may or may not automatically translate these.
|
||||
|
||||
> [!TIP]
|
||||
> For full list of available sprites you can check out https://www.gamergeeks.net/apps/minecraft/list-of-atlas-sprites. However, it doesn't contain any information regarding different Minecraft versions.
|
||||
|
||||
|
||||
|
||||
## Player sprite
|
||||
|
||||
This type allows you to display Minecraft heads. There are 3 ways to define a head:
|
||||
| Type | Functionality |
|
||||
|--------------------------|---------------------------------------------------------------------------|
|
||||
| Player name | The client checks recently received profiles (players on current server) and shows skin of player with that name. If no such player was found, connects to Mojang and gets skin of player with specified name. <br />**Note**: This means using a plugin for changing skins will result in the skin being changed here too (the client has a cache, so it won't be visible immediately (restarting the client resets the cache)). If using offline mode and no skin plugin, head won't display correct skin even if such player is registered at Mojang. |
|
||||
| Player UUID | The client checks recently received profiles (players on current server) and shows skin of player with that UUID. If no such player was found, connects to Mojang and gets skin of player with specified UUID. <br />**Note**: This means using a plugin for changing skins will result in the skin being changed here too (the client has a cache, so it won't be visible immediately (restarting the client resets the cache)). |
|
||||
| Skin value and signature | The client displays skin from given value and signature |
|
||||
|
||||
Here are all the ways you can display player skins using TAB and their implementation (using `ALL CAPS` for "placeholder" text instead of `<>` to avoid confusion as `<>` is actual part of the syntax):
|
||||
| Syntax | Explanation | Implementation |
|
||||
|-----|-------------|------------|
|
||||
| `<head:NAME>` | Shows head defined by player name | name |
|
||||
| `<head:UUID>` | Shows head defined by player UUID | uuid |
|
||||
| `<mineskin:ID>` | Connects to Mineskin and retrieves value and signature of specified upload ID | value and signature |
|
||||
| `<head_texture:TEXTURE>` | Gets the texture from `http://textures.minecraft.net/texture/TEXTURE` | value and signature |
|
||||
|
||||
All these syntaxes are identical to MiniMessage syntax for convenience. MiniMessage only supports the first two types by default, but TAB adds tag resolvers for `mineskin` and `head_texture` as well.
|
||||
|
||||
Here is an example for all types:
|
||||
```
|
||||
footer:
|
||||
- 'Head by id: <head:%uuid%>' # This will obviously not work in offline mode
|
||||
- 'Head by name: <head:%player%>' # May or may not work in offline mode (see above for full explanation)
|
||||
- 'Head by mineskin: <mineskin:37e93c8e12cd426cb28fce31969e0674>'
|
||||
- 'Head by texture: <head_texture:ff9bb9e56125c8227b94bbda9f6e0f862931c229255ba8f1205d13c44c1bb561>'
|
||||
```
|
||||
|
||||
<img width="331" height="111" alt="image" src="https://github.com/user-attachments/assets/5912975a-a892-42c3-b9ab-7eab33ee42b6" />
|
||||
|
||||
## Compatibility with <1.21.9
|
||||
You may be wondering what happens when you try to use these and the client is below 1.21.9.
|
||||
See table below for behavior based on your setup.
|
||||
|
||||
| Setup | Legacy text decider | Displayed text for <1.21.9 players |
|
||||
|-----------------|---------------------|-----------------------------------------------------------------------|
|
||||
| Backend <1.21.9 | TAB | `<Object components were added in 1.21.9>` (even for 1.21.9+ players) |
|
||||
| Backend 1.21.9+ | ViaVersion | (empty text) |
|
||||
| BungeeCord | TAB | `<Object components were added in 1.21.9>` |
|
||||
| Velocity | (no one) | Client disconnects with a packet decoding error |
|
||||
|
||||
# MiniMessage
|
||||
TAB has [MiniMessage](https://docs.advntr.dev/minimessage/format.html) hook, however, it does not include this library on its own. Including it would cause conflicts, so it has to be included in the server software.
|
||||
* It **is** included in **Paper 1.18.2+** and **Velocity**.
|
||||
* It **is not** included in **Spigot**, any server software for **1.18.1-**, **BungeeCord**, **Fabric**, **Forge** and **NeoForge**. However, you can install [adventure-platform-mod](https://modrinth.com/mod/adventure-platform-mod) on Fabric / NeoForge.
|
||||
|
||||
When MiniMessage is detected on your server, it is automatically used unless support is disabled. All codes are translated to MiniMessage syntax and then parsed by MiniMessage.
|
||||
|
||||
TAB creates a modified MiniMessage parser that also accepts `<head_texture:TEXTURE>` and `<mineskin:ID>` head syntaxes just like TAB's own component parser.
|
||||
|
||||
# Config options
|
||||
| Option name | Default value | Description |
|
||||
|--------------------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| minimessage-support | true | Enables / Disables MiniMessage support (if it's available). |
|
||||
| disable-shadow-for-heads | true | Automatically disables shadows for head object components (1.21.9+) to match the appearance of online-mode heads, which don't use shadows. |
|
||||
|
||||
# Tips & Tricks
|
||||
## Tip 1 - Manually defining legacy color
|
||||
For features that don't depend on any other players (header/footer, bossbar, scoreboard), you can easily specify legacy color instead of automatic rounding for <1.16 players. This can be done using [conditional placeholders](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders).
|
||||
|
||||
Check for `%player-version-id%`, which returns network protocol id of the version, which can be easily compared to. 1.16's version is `735`. Final condition may look like this:
|
||||
|
||||
```
|
||||
conditions:
|
||||
rgb:
|
||||
conditions:
|
||||
- '%player-version-id%>=735'
|
||||
true: "#00FF00 RGB text"
|
||||
false: "&a Legacy text"
|
||||
```
|
||||
Then, use this condition with `%condition:rgb%`.
|
||||
|
||||
This will not work in nametags and tablist formatting, because this would parse the condition for target player, not the viewer. To achieve this, you'll need a custom-made [relational placeholder](https://github.com/NEZNAMY/TAB/wiki/Placeholders#relational-placeholders) that checks for viewer's version.
|
||||
@@ -0,0 +1,65 @@
|
||||
# Content
|
||||
* [Backend](#backend)
|
||||
* [Proxy](#proxy)
|
||||
* [Proxy installation](#proxy-installation)
|
||||
* [Backend installation](#backend-installation)
|
||||
* [Mixed installation](#mixed-installation)
|
||||
* [Updating the plugin](#updating-the-plugin)
|
||||
|
||||
# Backend
|
||||
Installation on backend servers is as simple as it can be.
|
||||
Put the plugin into the plugins folder and restart the server.
|
||||
|
||||
# Proxy
|
||||
When running a network, you have 3 options:
|
||||
* Installing TAB only on the proxy (recommended)
|
||||
* Installing TAB on all backend servers instead
|
||||
* Installing TAB everywhere and disabling features, so they don't conflict (not recommended)
|
||||
|
||||
See below for more information regarding each way.
|
||||
|
||||
## Proxy installation
|
||||
This is the recommended setup.
|
||||
Put the plugin into the plugins folder of the proxy server and restart it.
|
||||
**Recommended**:
|
||||
Install [TAB-Bridge](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge) on your **backend servers** for PlaceholderAPI support and more.
|
||||
**Recommended**:
|
||||
If you are using **Velocity**,
|
||||
install [VelocityScoreboardAPI](https://github.com/NEZNAMY/VelocityScoreboardAPI/) plugin **on the proxy** for scoreboard-related features to work.
|
||||
|
||||
> [!NOTE]
|
||||
> With proxy installation, use **/btab** command instead of **/tab**.
|
||||
|
||||
Advantages of proxy installation compared to installing on all backend servers instead:
|
||||
* Can use the [Global player list](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist) without requiring Redis set up
|
||||
* [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) can work with all players connected to the proxy
|
||||
* Avoid [header/footer](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Header-&-Footer#additional-note-1---not-resetting-on-server-switch) and [bossbar](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Bossbar#additional-note-2---not-hiding-on-server-switch) not disappearing on server switch
|
||||
* Configuration files in a single place for easier editing / no need to use MySQL for syncing data
|
||||
* Can use new features for new players even if backend is using an older version (RGB, 1.20.3+ NumberFormat and more).
|
||||
|
||||
|
||||
Disadvantages compared to installing on all backend servers instead:
|
||||
* No [per-world player list](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Per-world-playerlist) (can be achieved by installing the plugin on backend servers and disabling all features except the per-world player list)
|
||||
|
||||
## Backend installation
|
||||
Just like when not running a network, install the plugin on all servers where you want the plugin. However, this setup is not as good (see advantages of proxy installation).
|
||||
|
||||
## Mixed installation
|
||||
Mixed installation is absolutely not supported and should be avoided.
|
||||
|
||||
There is no sort of communication between backend and proxy TAB installations (this is only done by TAB-Bridge, which doesn't do anything on its own). Having TAB on both proxy and backend is effectively installing 2 plugins to do the same thing, which will naturally cause issues (although TAB's anti-override for key features should help with this).
|
||||
|
||||
If you really wish to proceed (for example having feature X handled by proxy and feature Y on backend), make sure to properly disable features (`enabled: false`) to avoid problems. However, the only case where this makes any sense is per world playerlist feature, which is not available on proxies. Everything else can be done from proxy side.
|
||||
|
||||
|
||||
# Updating the plugin
|
||||
Updating the plugin is always as simple as replacing old jar with the new one.
|
||||
|
||||
You do not need to reset your configuration files or make any manual changes to them.
|
||||
If any changes to configuration are made (changed / removed / added),
|
||||
TAB will automatically convert your existing configuration files to the latest format
|
||||
(most notably 2.9.2 → 3.0.0, but any other changes as well).
|
||||
|
||||
Downgrading is completely unsupported, as an old plugin version cannot know what the future config format is / will be.
|
||||
Just like Minecraft itself, although TAB won't fail with an error message like Minecraft does, but you will get warnings and / or features not working correctly.
|
||||
There is no reason for downgrading anyway, since in general, every version is typically superior to older versions released before it.
|
||||
@@ -0,0 +1,15 @@
|
||||
# About
|
||||
This is collection if Minecraft issues/bugs you may experience when using TAB, which are not TAB bugs and cannot be fixed with a plugin.
|
||||
|
||||
# 1.5.x - 1.12.x - Unwanted space
|
||||
You may see unwanted space at the end of a line of text even if you didn't configure any.
|
||||
This is a client sided bug.
|
||||
To avoid it, add `&r` after ending bold segment (for example, prefix `&4&lAdmin&r&6`).
|
||||
|
||||
# 1.15.x - Strikethrough and underline
|
||||
Using &m (strikethrough) and &n (underline) does not work in header,
|
||||
last line of the scoreboard and possibly other places
|
||||
([MC-180110](https://bugs.mojang.com/browse/MC-180110)).
|
||||
|
||||
# 1.20 - 1.20.4 - Chat over tablist
|
||||
Visual bug rendering chat over the tablist ([MC-263256](https://bugs.mojang.com/browse/MC-263256)).
|
||||
@@ -0,0 +1,234 @@
|
||||
# Content
|
||||
Combine the knowledge gathered by reading the wiki to get interesting results, most frequently asked ones listed here.
|
||||
* [Displaying kill / death counter in tablist](#displaying-kill--death-counter-in-tablist)
|
||||
* [Taking prefixes/suffixes from permission plugin](#taking-prefixessuffixes-from-permission-plugin)
|
||||
* [Showing player's version in tablist](#showing-players-version-in-tablist)
|
||||
* [Replicating Purpur's TPSBar](#replicating-purpurs-tpsbar)
|
||||
* [BedWars1058 compatibility](#bedwars1058-compatibility)
|
||||
* [Displaying AFK status in tablist](#displaying-afk-status-in-tablist)
|
||||
* [Showing combined online player count from multiple servers](#showing-combined-online-player-count-from-multiple-servers)
|
||||
* [Option 1 - Using global playerlist](#option-1---using-global-playerlist)
|
||||
* [Option 2 - Using PlaceholderAPI](#option-2---using-placeholderapi)
|
||||
* [Showing head components only to 1.21.9+ players](#showing-head-components-only-to-1219-players)
|
||||
|
||||
# Displaying kill / death counter in tablist
|
||||
This example uses PlaceholderAPI placeholders.
|
||||
Kills:
|
||||
```
|
||||
playerlist-objective:
|
||||
enabled: true
|
||||
value: "%statistic_player_kills%"
|
||||
```
|
||||
Deaths:
|
||||
```
|
||||
playerlist-objective:
|
||||
enabled: true
|
||||
value: "%statistic_deaths%"
|
||||
```
|
||||
**Note:** These values are taken from server stats. You can modify / reset them for each player in `<main world>/stats/<player uuid>.json` file.
|
||||
|
||||
# Taking prefixes/suffixes from permission plugin
|
||||
Delete all groups from **groups.yml** and only keep this:
|
||||
```
|
||||
_DEFAULT_:
|
||||
tabprefix: "%vault_prefix%"
|
||||
tagprefix: "%vault_prefix%"
|
||||
tabsuffix: "%vault_suffix%"
|
||||
tagsuffix: "%vault_suffix%"
|
||||
```
|
||||
This requires Vault and a permission plugin to work.
|
||||
If you have luckperms installed on the same server instance, you can use TAB's internal `%luckperms-prefix%` (and suffix) placeholders instead.
|
||||
**Note:** If TAB is on a proxy, and you want prefixes to be taken from backend servers, use `%vault_prefix%` (or `%luckperms_prefix%`) with [PlaceholderAPI support on proxy](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge).
|
||||
|
||||
# Showing player's version in tablist
|
||||
Run `/tab group _DEFAULT_ tabsuffix " &8[&3%player-version%&8]"` or any other color combination you want. You can also include other placeholders with it. You can also modify it directly in **groups.yml** file instead. With the provided example command, you'll get the following result:
|
||||

|
||||
|
||||
# Replicating Purpur's TPSBar
|
||||
*This guide was made purely for demonstration of TAB's functionality to show you can even do things like this with conditions. It is not meant to be used as a replacement for Purpur or any of its functions or discouraging users from using Purpur.*
|
||||
|
||||
By default, Purpur's TPSBar shows server's TPS, MSPT and player ping.
|
||||
These change colors from green to red based on value.
|
||||
The easier way
|
||||
to achieve this is with [Placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements-(premium-only)),
|
||||
however, it alters placeholders everywhere inside TAB,
|
||||
which would result in features like [Playerlist objective](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Playerlist-Objective)
|
||||
to stop working correctly when %ping% is used,
|
||||
since it would contain color codes now.
|
||||
For that reason,
|
||||
we will use [Conditions](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) instead.
|
||||
|
||||
When TPS is above 19, it displays as `<#55FF55>value</#00AA00>`. When above 15, `<#FFFF55>value</#FFAA00>`, otherwise `<#FF5555>value</#AA0000>`. This can be achieved with 2 conditions:
|
||||
```
|
||||
conditions:
|
||||
tps:
|
||||
conditions:
|
||||
- "%tps%>=19"
|
||||
true: "<#55FF55>%tps%</#00AA00>"
|
||||
false: "%condition:tps2%"
|
||||
tps2:
|
||||
conditions:
|
||||
- "%tps%>=15"
|
||||
true: "<#FFFF55>%tps%</#FFAA00>"
|
||||
false: "<#FF5555>%tps%</#AA0000>"
|
||||
```
|
||||
To use this, we will use `%condition:tps%`.
|
||||
Now, repeat for mspt and ping. For mspt, purpur's intervals are <40, <50, 50+. For ping, it's <100, <200, 200+.
|
||||
|
||||
Conditions for mspt and ping may look something like this:
|
||||
```
|
||||
conditions:
|
||||
mspt:
|
||||
conditions:
|
||||
- "%mspt%<40"
|
||||
true: "<#55FF55>%mspt%</#00AA00>"
|
||||
false: "%condition:mspt2%"
|
||||
mspt2:
|
||||
conditions:
|
||||
- "%mspt%<50"
|
||||
true: "<#FFFF55>%mspt%</#FFAA00>"
|
||||
false: "<#FF5555>%mspt%</#AA0000>"
|
||||
ping:
|
||||
conditions:
|
||||
- "%ping%<100"
|
||||
true: "<#55FF55>%ping%</#00AA00>"
|
||||
false: "%condition:ping2%"
|
||||
ping2:
|
||||
conditions:
|
||||
- "%ping%<200"
|
||||
true: "<#FFFF55>%ping%</#FFAA00>"
|
||||
false: "<#FF5555>%ping%</#AA0000>"
|
||||
```
|
||||
To use them, we will use `%condition:mspt%` and `%condition:ping%`. Purpur's TPSBar is using mspt as bossbar progress with range from 0 to 50. This can be achieved with PlaceholderAPI's math expansion: `%math_0_{tab_placeholder_mspt}*2%`. It always uses `GREEN` color and `NOTCHED_20` style. Let's put all of this together:
|
||||
```
|
||||
bars:
|
||||
tpsbar:
|
||||
style: NOTCHED_20
|
||||
color: GREEN
|
||||
progress: "%math_0_{tab_placeholder_mspt}*2%"
|
||||
text: "&7TPS&e: %condition:tps% &7MSPT&e: %condition:mspt% &7Ping&e: %condition:ping%&7ms"
|
||||
```
|
||||
|
||||
The last step is to configure when should this bossbar be displayed. One way is to use bossbar announce/send command. Another is to use display conditions. An example can look like `display-condition: "permission:tab.tpsbar`. Now, only players with the permission will see the bossbar.
|
||||
|
||||
# BedWars1058 compatibility
|
||||
## Sorting
|
||||
To sort teams through TAB, add the PLACEHOLDER_A_TO_Z sorting type with the %bw1058_player_team% placeholder. Example:
|
||||
```yml
|
||||
sorting-types:
|
||||
- "PLACEHOLDER_A_TO_Z:%bw1058_player_team%"
|
||||
- "GROUPS:admin,mod,default"
|
||||
- "PLACEHOLDER_A_TO_Z:%player%"
|
||||
```
|
||||
## Team name in tablist/nametag
|
||||
To display the team name in the tablist, use this command: `/tab group _DEFAULT_ tabprefix %bw1058_player_team%`
|
||||
The same goes for the nametag, but with tagprefix instead: `/tab group _DEFAULT_ tagprefix %bw1058_player_team%`
|
||||
|
||||
To display only the first letter of the team, download this PlaceholderAPI expansion: https://api.extendedclip.com/expansions/bw1058plus/
|
||||
and use `%bw1058plus_team_letter%` instead, if you want the color as well, put `%bw1058plus_team_color%` right before.
|
||||
|
||||
## Rank in lobby & Team name in game
|
||||
If you want to display the rank of the player while he's in the lobby or waiting lobby,
|
||||
BUT show the team name while in the game, then don't worry, there's a way.
|
||||
You can create a condition which checks if the player's current team = nothing (which means the player isn't playing),
|
||||
and return either the rank or the team name depending on that condition.
|
||||
Example:
|
||||
```yml
|
||||
conditions:
|
||||
rankOrTeam:
|
||||
conditions:
|
||||
- "%bw1058_player_team%="
|
||||
true: "%luckperms-prefix%"
|
||||
false: "%bw1058_player_team%"
|
||||
```
|
||||
And then do `/tab group _DEFAULT_ tabprefix %condition:rankOrTeam%` and `/tab group _DEFAULT_ tagprefix %condition:rankOrTeam%` so it shows in your nametag and in your tablist name.
|
||||
|
||||
# Displaying AFK status in tablist
|
||||
First, you'll need to get an AFK plugin. TAB does not track player AFK status. Then, find a PlaceholderAPI placeholder for your AFK plugin in their documentation, such as
|
||||
* `%essentials_afk%` for Essentials
|
||||
* `%cmi_user_afk_symbol%` for CMI
|
||||
* `%purpur_player_afk%` for Purpur (server software)
|
||||
|
||||
Remember to install PlaceholderAPI and the respective expansion of your afk plugin.
|
||||
|
||||
Then, use the placeholder in configuration wherever you want it.
|
||||
Assuming you want it for all players,
|
||||
use `_DEFAULT_` group keyword in **groups.yml** for default settings for all groups.
|
||||
Combined with other settings, it may look like this for tabsuffix:
|
||||
```
|
||||
_DEFAULT_:
|
||||
tabsuffix: "%luckperms-suffix%%essentials_afk%"
|
||||
```
|
||||
Or running an in-game command: `/tab group _DEFAULT_ tabsuffix %luckperms-suffix%%essentials_afk%`.
|
||||
This is not limited to displaying AFK status in suffix, you can also use it in tabprefix instead (or nametags).
|
||||
|
||||
|
||||
Finally, you will most likely need to set up [placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements) for the placeholder, as lots of them, including the %essentials_afk% placeholder used as an example, return `yes` and `no` values, which you most likely want to customize.
|
||||
As mentioned, by default, Essentials' afk placeholder returns `yes` / `no` (unless modified in PlaceholderAPI's config.yml). Other placeholders may return different values. To find out what a placeholder returned, use `/tab parse <player> <placeholder>`. Remember to include color codes as well.
|
||||
An example customization may look like this:
|
||||
```
|
||||
placeholder-output-replacements:
|
||||
"%essentials_afk%":
|
||||
"yes": " &4&lAFK"
|
||||
"no": "" # display nothing if not afk
|
||||
```
|
||||
Keep in mind that some placeholders don't need this.
|
||||
For example, CMI has 2 placeholders - %cmi_user_afk% that returns true/false,
|
||||
and %cmi_user_afk_symbol% that returns AFK text configured in CMI configuration.
|
||||
Therefore, if you decide to use the latter one, you don't need to set up replacements.
|
||||
|
||||
# Showing combined online player count from multiple servers
|
||||
## Option 1 - Using global playerlist
|
||||
The first way is to install TAB on the proxy
|
||||
and enable [global playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist).
|
||||
It allows you to create groups of servers that share playerlist.
|
||||
These groups can then be used to show player count on those servers using a placeholder.
|
||||
Using the following example:
|
||||
```
|
||||
global-playerlist:
|
||||
enabled: true
|
||||
server-groups:
|
||||
lobbies:
|
||||
- lobby1
|
||||
- lobby2
|
||||
```
|
||||
Servers `lobby1` and `lobby2` will share playerlist. You will also be able to use placeholder formula `%playerlist-group_<group>%`, in this case `%playerlist-group_lobbies%`. It will show amount of players on `lobby1` and `lobby2` combined.
|
||||
|
||||
Advantage of this is the natural compatibility with global playerlist's settings,
|
||||
which is also its disadvantage, since global playerlist has to be configured that way.
|
||||
When using [layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) feature,
|
||||
global playerlist is redundant and having it enabled only for the placeholder is inefficient.
|
||||
|
||||
## Option 2 - Using PlaceholderAPI
|
||||
Unlike the first option, this one offers much more freedom, but also requires another plugin. You'll need to [download PlaceholderAPI and its expansions called math and bungee](https://github.com/NEZNAMY/TAB/wiki/Quick-PlaceholderAPI-startup-guide) (`/papi ecloud download bungee`, `/papi ecloud download math`, `/papi reload`).
|
||||
First, you need placeholders for online count on specific servers. Bungee expansion does exactly that. The format is `%bungee_<server>%`. To merge the online counts, use math expansion. The syntax will be `%math_0_<expression>%`, where `expression` uses online counts from specific servers from bungee expansion. Finally, you'll end up with a placeholder like `%math_0_{bungee_lobby1}+{bungee_lobby2}%`. This placeholder will merge online counts from `lobby1` and `lobby2`.
|
||||
Please note that by default, bungee expansion updates values only every 30 seconds. This can be changed in PlaceholderAPI's config. If the numbers still don't show correct value, check if the placeholder works correctly using `/papi parse me <placeholder>`. If not, this is not a TAB issue.
|
||||
|
||||
Advantage of this is no requirement for a specific TAB feature to be enabled, which also includes no need to have TAB installed on the proxy. The downside is relying on 3rd party software. If TAB is on proxy, you'll also need [bridge plugin](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge).
|
||||
|
||||
# Showing head components only to 1.21.9+ players
|
||||
Object components were added in 1.21.9, which means they cannot be shown to 1.21.8- players. [If you try to do so, you'll either get an ugly text (BungeeCord / backend), or disconnect with a packet decode error (on Velocity)](https://github.com/NEZNAMY/TAB/wiki/How-to-use-Minecraft-components#compatibility-with--1219).
|
||||
|
||||
To achieve this goal, we will use [relational conditions](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders#relational-conditions) and check if viewer is 1.21.9+:
|
||||
```
|
||||
conditions:
|
||||
head:
|
||||
conditions:
|
||||
- "%viewer:player-version-id%>=773"
|
||||
true: "<head:name:%player%> "
|
||||
false: "" # Show nothing
|
||||
```
|
||||
The `773` is the protocol version of 1.21.9, so we can use a simple math operation instead of comparing strings. You can check [TAB's source code](https://github.com/NEZNAMY/TAB/blob/master/shared/src/main/java/me/neznamy/tab/shared/ProtocolVersion.java) for the full list. This condition will return head component of the **target** player if the **viewer** is 1.21.9+, empty value otherwise.
|
||||
[If you want to use this head syntax, you'll need to disable MiniMessage support](https://github.com/NEZNAMY/TAB/wiki/How-to-use-Minecraft-components#player-sprite), or use a syntax supported by MiniMessage (which is currently extremely limited).
|
||||
Use this condition with `%rel_condition:head%`. The rel is important, so TAB knows the placeholder is a relational placeholder. If you forget to, the condition will return a warning message instead of configured value.
|
||||
To showcase it, I have this in **groups.yml** (to show player versions as well):
|
||||
```
|
||||
_DEFAULT_:
|
||||
tabprefix: "%rel_condition:head%"
|
||||
tabsuffix: " %player-version% (%player-version-id%)"
|
||||
```
|
||||
1.21.11 player's view:
|
||||
<img width="634" height="103" alt="image" src="https://github.com/user-attachments/assets/4c762fae-3166-4247-865f-c87d1916afd7" />
|
||||
|
||||
1.21.8 player's view:
|
||||
<img width="581" height="106" alt="image" src="https://github.com/user-attachments/assets/cb7ab93d-0db5-4968-bcfe-60004125ddf1" />
|
||||
@@ -0,0 +1,63 @@
|
||||
* [About](#about)
|
||||
* [Enabling](#enabling)
|
||||
* [Configuration changes](#configuration-changes)
|
||||
* [Data conversion](#data-conversion)
|
||||
* [Downloading from MySQL to files](#downloading-from-mysql-to-files)
|
||||
* [Uploading from files to MySQL](#uploading-from-files-to-mysql)
|
||||
* [Synchronization frequency](#synchronization-frequency)
|
||||
|
||||
# About
|
||||
By default, groups and users are stored in separate files (groups.yml and users.yml).
|
||||
Enabling MySQL will use it as storage of groups and users instead of the files.
|
||||
|
||||
`playerdata.yml` file (for toggling scoreboard/bossbar and remembering the decision)
|
||||
is not affected and will still be used instead of MySQL.
|
||||
It may be added in the future.
|
||||
|
||||
All tables from TAB are prefixed with `tab_`, currently `tab_groups` for groups and `tab_users` for users.
|
||||
|
||||
# Enabling
|
||||
Find this section in **config.yml**:
|
||||
```
|
||||
mysql:
|
||||
enabled: false
|
||||
host: 127.0.0.1
|
||||
port: 3306
|
||||
database: tab
|
||||
username: user
|
||||
password: password
|
||||
useSSL: true
|
||||
```
|
||||
Enabling it will enable MySQL. The other settings are pretty straight forward.
|
||||
|
||||
# Configuration changes
|
||||
Once enabled, configured values in groups.yml and users.yml will not be visible anymore,
|
||||
which is expected because your database is empty when created.
|
||||
This is not a bug.
|
||||
All you need to do is [upload your data to the database](#uploading-from-files-to-mysql).
|
||||
|
||||
Since groups.yml and users.yml files will no longer be used, making any changes to them will take no effect. If you wish to perform any changes, you have 2 options:
|
||||
* Use in-game commands, which will upload changes to the database
|
||||
* Upload the file to the database after every change (will not work for removing though) (useful when enabling for the first time).
|
||||
|
||||
# Data conversion
|
||||
## Downloading from MySQL to files
|
||||
This can be done using `/tab mysql download` command (permission is `tab.mysql.download`). It will download all data from the MySQL and save into groups.yml / users.yml.
|
||||
This command requires the MySQL function enabled.
|
||||
Existing data in files will not intentionally be deleted, but may get overwritten.
|
||||
|
||||
## Uploading from files to MySQL
|
||||
This can be done using `/tab mysql upload` command (permission is `tab.mysql.upload`). It will upload all content from groups.yml and users.yml into MySQL.
|
||||
This command requires the MySQL function enabled.
|
||||
Existing data in the database will not intentionally be deleted, but may get overwritten.
|
||||
|
||||
# Synchronization frequency
|
||||
When using files to store data, it's simple -
|
||||
groups.yml and users.yml files are loaded into memory and read from when needed.
|
||||
When a command is run to update something, it is updated in memory and saved into files as well.
|
||||
|
||||
When using MySQL, the plugin has to keep data up to date with other servers, but at the same time not kill the server with requests all the time.
|
||||
For writing, both groups and users, whenever a command is used to update something, the update is sent to the database immediately.
|
||||
For reading, data is updated as following:
|
||||
* Groups - All data from groups table is loaded into memory on a load (server start, plugin reload). When a player joins in or any other action, values from memory are checked. Therefore, if a change is made on another server, it will not be visible until the plugin is reloaded.
|
||||
* Users - Nothing is loaded on a plugin load. Whenever a player joins, all data of that player is requested from the database. Therefore, if a player's data changes on another server, it is visible immediately when a player joins this one, without the need to reload the plugin.
|
||||
@@ -0,0 +1,155 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Ways of optimizing](#ways-of-optimizing)
|
||||
* [#1 - [All platforms] Static text instead of placeholders](#1---all-platforms-static-text-instead-of-placeholders)
|
||||
* [#2 - [All platforms] Placeholder refresh intervals](#2---all-platforms-placeholder-refresh-intervals)
|
||||
* [#3 - [All platforms] Don't use RGB](#3---all-platforms-dont-use-rgb)
|
||||
* [#4 - [All platforms] Don't use animations](#4---all-platforms-dont-use-animations)
|
||||
* [#5 - [All platforms] Disable tablist name formatting](#5---all-platforms-disable-tablist-name-formatting)
|
||||
* [#6 - [All platforms] Increase permission refresh interval](#6---all-platforms-increase-permission-refresh-interval)
|
||||
* [#7 - [Proxies] Disable TAB expansion](#7---proxies-disable-tab-expansion)
|
||||
* [#8 - [Proxies] Disable update-latency option in global playerlist](#8---proxies-disable-update-latency-option-in-global-playerlist)
|
||||
* [Netty false positive in spark reports](#netty-false-positive-in-spark-reports)
|
||||
* [Why there is a false positive](#why-there-is-a-false-positive)
|
||||
* [How to read the real value](#how-to-read-the-real-value)
|
||||
* [Packet listening usage](#packet-listening-usage)
|
||||
* [Sending packets](#sending-packets)
|
||||
|
||||
# About
|
||||
This guide will explain all primary ways you can reduce plugin's CPU usage besides the obvious things like "don't spam animations" or "disable features you don't want".
|
||||
The usage can be checked at any time using [**/tab cpu**](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions#tab-cpu) command. If the numbers appear to be higher than they should be, check this guide for various ways to optimize the plugin. Most of these apply for all platforms, but some of them are only specific for some platforms.
|
||||
|
||||
# Ways of optimizing
|
||||
## #1 - [All platforms] Static text instead of placeholders
|
||||
Static text doesn't need to be refreshed periodically, resulting in better performance.
|
||||
Some placeholders can be replaced with static text, such as placeholder for max player counts,
|
||||
since that value doesn't change at runtime.
|
||||
Another option is to configure prefixes per-group in config
|
||||
instead of using placeholders to take those values from your permission plugin.
|
||||
|
||||
## #2 - [All platforms] Placeholder refresh intervals
|
||||
Some placeholders take a long time to process and result in high cpu usage. However, this can be optimized by configuring refresh interval of placeholders.
|
||||
|
||||
Internal placeholders use a value hardcoded into the plugin by default. PlaceholderAPI placeholders use `default-refresh-interval`.
|
||||
|
||||
To begin, find this part in your config
|
||||
```yml
|
||||
placeholder-refresh-intervals:
|
||||
default-refresh-interval: 500
|
||||
"%server_uptime%": 1000
|
||||
"%server_tps_1_colored%": 1000
|
||||
"%player_health%": 200
|
||||
"%player_ping%": 1000
|
||||
"%vault_prefix%": 1000
|
||||
"%rel_factionsuuid_relation_color%": 500
|
||||
```
|
||||
Refresh interval is in milliseconds. It must be divisible by 50.
|
||||
|
||||
`default-refresh-interval` is refresh interval for all unlisted PlaceholderAPI placeholders.
|
||||
|
||||
Keep in mind that CPU measurement is reset every 10 seconds.
|
||||
This means that if you configure a higher refresh interval than 10000,
|
||||
there will be intervals when placeholder didn't refresh at all,
|
||||
making it look like the CPU is perfect, while on the next refresh it may be high.
|
||||
For this reason, if you want to cleanly track usage, keep the interval at 10000 at most.
|
||||
Using a higher interval will help if needed, but may lead to misleading info in cpu output.
|
||||
|
||||
## #3 - [All platforms] Don't use RGB
|
||||
Though RGB colors look good, they require the text to be split into several components with `color` field used instead of the whole text pasted into the `text` field. This is a complicated process that takes quite some time. Sticking to legacy colors results in better performance.
|
||||
|
||||
## #4 - [All platforms] Don't use animations
|
||||
While animations look cool, they also have a high resource usage.
|
||||
This is because they work by spamming updates every time an animation switches to a new frame.
|
||||
When animations are not used, no updates need to be sent (unless another placeholder changes value),
|
||||
not causing extra CPU usage.
|
||||
|
||||
## #5 - [All platforms] Disable tablist name formatting
|
||||
As we already know from [Client-sided mechanics](https://github.com/NEZNAMY/TAB/wiki/Client%E2%80%90sided-mechanics#nametag-format-in-tablist) page,
|
||||
the nametag format appears in tablist if tablist name is not defined.
|
||||
You can take advantage of this to effectively disable one entire feature and its cpu usage,
|
||||
while not losing on anything.
|
||||
However, you can only do this if:
|
||||
* You are fine with nametag and tablist formats being identical, which also means all [nametag limitations](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Nametags#limitations) will transfer to tablist as well
|
||||
* You don't have any plugin formatting the tablist names
|
||||
|
||||
Whether you have another plugin attempting to handle them or not may not be easy to identify with a lot of plugins and not enough time spent configuring them. In that case, your best choice is to try it and see. If tablist names break, it means you have another plugin and cannot take advantage of this optimization option.
|
||||
|
||||
## #6 - [All platforms] Increase permission refresh interval
|
||||
Plugin needs to constantly check permissions for:
|
||||
* Permission checks in conditions
|
||||
* Permission checks if sorting by permissions
|
||||
* Group retrieving from permission plugin (for sorting / per-group properties)
|
||||
|
||||
default value
|
||||
```
|
||||
permission-refresh-interval: 1000
|
||||
```
|
||||
Refreshes them every second.
|
||||
If you don't need any permission/group changes to take effect within a second,
|
||||
you can increase this value for better performance.
|
||||
|
||||
## #7 - [Proxies] Disable TAB expansion
|
||||
To maximize the performance of TAB's response to PlaceholderAPI request,
|
||||
values are tracked in advance and then quickly returned.
|
||||
This process takes resources and is especially heavy on proxy installation,
|
||||
where values must be constantly sent to bridge using plugin messages.
|
||||
Disabling TAB's PlaceholderAPI expansion if you don't use it improves performance.
|
||||
**config.yml**:
|
||||
```
|
||||
placeholders:
|
||||
register-tab-expansion: false
|
||||
```
|
||||
## #8 - [Proxies] Disable update-latency option in global playerlist
|
||||
When [Global playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist) is enabled, you can enable / disable [update-latency](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist#:~:text=other%20unlisted%20servers.-,update%2Dlatency,-false) option (open the link for detailed description of the option). Disabling this option massively improves performance.
|
||||
|
||||
# Netty false positive in spark reports
|
||||
When taking a spark report with all threads monitored instead of just the server thread using `--thread *` argument (or on a proxy where this is enabled by default since there is no main thread to monitor by default), you may notice high usage (both CPU and RAM) in netty thread when grouping threads by plugin. **Vast majority of that usage is false positive.** Let's go over why this is the case and how to read the real value.
|
||||
|
||||
## Why there is a false positive
|
||||
When listening to an event, the server fires the events in a loop, where each event is the end point. As such, measuring every event handler individually is accurate. Here is how the hierarchy looks with example numbers:
|
||||
```
|
||||
Event processing in loop (6ms total)
|
||||
↳ Plugin 1 (1ms)
|
||||
↳ Plugin 2 (2ms)
|
||||
↳ Plugin 3 (3ms)
|
||||
End of loop
|
||||
```
|
||||
As such, the measured values are accurate and spark is able to separate each event handler based on plugin. Command executions and repeating tasks are even simpler.
|
||||
|
||||
The issue is with netty injection. The purpose is to listen to outgoing packets, react to them and possibly modify them. Unlike with events, these are not processed in parallel, but every handler forwards the packet to the next one (or doesn't if it should be cancelled). As such, the hierarchy looks like this (simplified version):
|
||||
```
|
||||
Beginning (12ms total)
|
||||
↳ Plugin 1 (1ms self, 12ms total)
|
||||
↳ Plugin 2 (1ms self, 11ms total)
|
||||
↳ Plugin 3 (1ms self, 10ms total)
|
||||
↳ Minecraft encoder (10ms self)
|
||||
```
|
||||
As such, spark will show 12ms total for Plugin 1, even though its own usage is only 1ms. This is due to a limitation of the design of Spark in combination with how netty handlers work. This is only the case for plugins with their own netty injection, it does not apply to plugins that use ProtocolLib, because that one offers event-like functionality explained above. In this case, the usage shown in spark report is 100% accurate.
|
||||
|
||||
## How to read the real value
|
||||
An actual usage of the netty threads can be split into 2 parts:
|
||||
* Listening to outgoing packets
|
||||
* Sending packets, which causes it to go though the pipeline and then encode
|
||||
|
||||
### Packet listening usage
|
||||
This one is simple and accurate. Take the shown number, expand the call stack and subtract `io.netty.channel.ChannelDuplexHandler.write()` usage, which is forwarding the packet to the next handler and would be there even if that plugin wasn't injected.
|
||||
Let's take a look at a practical example:
|
||||
<img width="1091" height="266" alt="image" src="https://github.com/user-attachments/assets/6d9e8c25-8375-413b-ab9b-31b52ff9262c" />
|
||||
|
||||
Here, spark reports `31.71%` usage by TAB. However, `30.87%` of it is forwarding it to the next handler (`io.netty.channel.ChannelDuplexHandler.write()`), which forwards it to the next one, until eventually the server encodes the packet. Therefore, TAB's real usage by listening to outgoing packets in this report is `31.71%` - `30.87%` = `0.84%`. Much less than what you originally see.
|
||||
|
||||
### Sending packets
|
||||
Sadly, this one is impossible to calculate directly. When a packet is scheduled for sending, it is only added to a queue, then consumed by a netty thread, not the caller thread. At that point we are losing information about where a packet comes from.
|
||||
There is some good news though.
|
||||
|
||||
First, vast majority of plugins barely send any packets. For example PlaceholderAPI is just an interface between plugins, chat plugins only modify chat message packets that would be sent anyway, ViaVersion same thing, and so on...
|
||||
|
||||
|
||||
Second, plugins that send a lot of packets usually send the kind that the server either doesn't send at all, or not much. Expanding the data from the previously shown report gives us this:
|
||||
<img width="1083" height="496" alt="image" src="https://github.com/user-attachments/assets/c6157e78-ef6a-4d9c-b4b7-7c7b32dd14f8" />
|
||||
|
||||
Here we can see that encoding team packets took 0.99%. Since TAB is the only team plugin you need for managing players, it is safe to assume most, if not all of it comes from TAB.
|
||||
Same here - 0.13% from header and footer.
|
||||
<img width="1085" height="93" alt="image" src="https://github.com/user-attachments/assets/559dce56-83d3-49b2-9f4b-29b6124f944c" />
|
||||
|
||||
Sadly there are other operations needed than just encoding packets, such as allocating buffers and other, so this part is not that simple anymore.
|
||||
@@ -0,0 +1,271 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Internal placeholders](#internal-placeholders)
|
||||
* [Universal](#universal)
|
||||
* [Backend only](#backend-only)
|
||||
* [Proxy only](#proxy-only)
|
||||
* [PlaceholderAPI](#placeholderapi)
|
||||
* [MiniPlaceholders](#miniplaceholders)
|
||||
* [Relational placeholders](#relational-placeholders)
|
||||
* [About](#about-1)
|
||||
* [Usage](#usage)
|
||||
* [Refreshing](#refreshing)
|
||||
* [Refresh intervals](#refresh-intervals)
|
||||
* [Sync refreshing](#sync-refreshing)
|
||||
* [Placeholder is not working](#placeholder-is-not-working)
|
||||
* [Internal placeholder is not working](#internal-placeholder-is-not-working)
|
||||
* [PlaceholderAPI placeholder is not working](#placeholderapi-placeholder-is-not-working)
|
||||
* [API](#api)
|
||||
* [Server placeholders](#server-placeholders)
|
||||
* [Player placeholders](#player-placeholders)
|
||||
* [Relational placeholders](#relational-placeholders-1)
|
||||
|
||||
# About
|
||||
TAB offers various placeholders to display the most common information. It also supports [PlaceholderAPI placeholders](https://github.com/PlaceholderAPI/PlaceholderAPI/wiki/Placeholders).
|
||||
|
||||
# Internal placeholders
|
||||
|
||||
Basic placeholders provided by the plugin. Most of these placeholders were added because they were requested by people who don't want to install another plugin just to show username. Some of them have configurable output in config.yml in `Placeholders` section. Unused placeholders do not affect performance in any way.
|
||||
|
||||
Placeholders must be refreshed.
|
||||
All internal placeholders have a manually defined refresh interval,
|
||||
which I found the most optimal. You can [override the refresh intervals](https://github.com/NEZNAMY/TAB/wiki/Optimizing-the-plugin#2---all-platforms-placeholder-refresh-intervals) if you want to.
|
||||
Time is in milliseconds.
|
||||
`-1` is used for placeholders which are in fact constants (such as %player%),
|
||||
or fire an event each time they change, which can be listened to (such as %world%) and value updated.
|
||||
Refresh interval for conditions is set to be equal to the fastest refreshing placeholder used inside each condition.
|
||||
|
||||
## Universal
|
||||
These placeholders are available on all platforms.
|
||||
|
||||
| Identifier | Refresh interval | Description |
|
||||
|-------------------------------------------|------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| %online% | 1000 | Total online player count on server where plugin is installed (excluding [vanished players](https://github.com/NEZNAMY/TAB/wiki/Additional-information#vanish-detection)). If the plugin is installed on a proxy, it will show total player count on the whole network. |
|
||||
| %world% | -1 | Name of world where player is |
|
||||
| %worldonline% | 1000 | Amount of players in the same world (excluding [vanished players](https://github.com/NEZNAMY/TAB/wiki/Additional-information#vanish-detection)) as the player |
|
||||
| %ping% | 500 | Player's ping to the server where TAB is installed. <br />**Note**: This value is measured by the server and TAB is only retrieving that value. If it's wrong, it's not a TAB issue. |
|
||||
| %player% | -1 | Player's name |
|
||||
| %uuid% | -1 | Player's UUID |
|
||||
| %time% | 500 | Current real time, output is configurable in **config.yml** in `time-format` option |
|
||||
| %date% | 60000 | Current date, output is configurable in **config.yml** in `date-format` option |
|
||||
| %staffonline% | 2000 | Amount of online players with `tab.staff` permission |
|
||||
| %nonstaffonline% | 2000 | Amount of online players without `tab.staff` permission |
|
||||
| %memory-used% | 200 | Used RAM of server in MB |
|
||||
| %memory-max% | -1 | Total RAM of server in MB |
|
||||
| %memory-used-gb% | 200 | Used RAM of server in GB |
|
||||
| %memory-max-gb% | -1 | Total RAM of server in GB |
|
||||
| %player-version% | -1 | User-friendly version of player, such as `1.14.4`. For versions that share the same protocol version number, the higher one is returned (for example 1.20 & 1.20.1 -> 1.20.1 is returned) |
|
||||
| %player-version-id% | -1 | Network ID of player's version. You can see the full version list in [TAB's source code](https://github.com/NEZNAMY/TAB/blob/master/shared/src/main/java/me/neznamy/tab/shared/ProtocolVersion.java). Useful for conditions to create per-version results using numeric operations since version names cannot be effectively compared. |
|
||||
| %luckperms-prefix% | 1000 | Prefix from LuckPerms from the server where TAB is installed |
|
||||
| %luckperms-suffix% | 1000 | Suffix from LuckPerms from the server where TAB is installed |
|
||||
| %luckperms-prefixes% | 1000 | All prefixes combined from LuckPerms from the server where TAB is installed |
|
||||
| %luckperms-suffixes% | 1000 | All suffixes combined from LuckPerms from the server where TAB is installed |
|
||||
| %displayname% | 500 | Display name variable set by permission plugin, typically prefix + name + suffix |
|
||||
| %group% | 1000 | Returns player's primary group name. Created for internal functionality, but can be used as a display placeholder as well. |
|
||||
| %vanished% | 1000 | Returns `true`/`false` based on player's vanish status. Created for internal functionality, but can be used as a display placeholder as well. |
|
||||
| %bedrock% | -1 | Returns `true`/`false` based on whether player is using Bedrock edition or not (Java) |
|
||||
| %bossbar_announce_time_total_\<bossbar\>% | -1 | Total time (inputted value) of an announced bossbar. |
|
||||
| %bossbar_announce_time_left_\<bossbar\>% | 100 | Remaining time of an announced bossbar. |
|
||||
| %online_\<server name\>% | 1000 | Amount of online players on specified server (excluding vanished players) |
|
||||
| %% | -1 | Returns the `%` symbol. Useful to display `%` symbol without breaking all placeholders after it |
|
||||
|
||||
## Backend only
|
||||
These placeholders only work when TAB is installed on a backend server, they don't work when TAB is on a proxy. If you have TAB installed on proxy and wish to use these, use their [PlaceholderAPI](https://github.com/NEZNAMY/TAB/wiki/Quick-PlaceholderAPI-startup-guide) alternative with [Bridge plugin](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge) installed for PlaceholderAPI support on proxy.
|
||||
| Identifier | Refresh interval | Description | PlaceholderAPI alternative |
|
||||
|---------------|---------------| ------------- | ------------- |
|
||||
| %health% | 100 | Player's health, rounded up to match Minecraft's heart display. | %player_health_rounded% |
|
||||
| %displayname% | 500 | Player's display name value set by permission plugin. | %player_displayname% |
|
||||
| %tps% | 1000 | TPS of server from the last minute. Measured by the server. Not directly available on modded platforms - primitive approximation using MSPT (TPS = 1000/MSPT, max 20) is used there. | %server_tps_1% |
|
||||
| %mspt% | 1000 | Server's current milliseconds per tick (not available on Spigot) | - |
|
||||
| %deaths% | 1000 | Player's death count | %statistic_deaths% |
|
||||
|
||||
## Proxy only
|
||||
| Identifier | Refresh interval | Description |
|
||||
|------------------------------|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| %server% | -1 | Name of server where player is, defined in proxy's config. |
|
||||
| %serveronline% | 1000 | Amount of online players on server where the player is (excluding vanished players) |
|
||||
| %playerlist-group_\<group\>% | 1000 | Amount of online players in specified [global playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist) group (therefore the feature must be enabled) |
|
||||
|
||||
# PlaceholderAPI
|
||||
PlaceholderAPI is supported and relational placeholders are supported too.
|
||||
When parsing relational placeholders,
|
||||
TAB puts viewer as the first player argument and target player as the second argument.
|
||||
|
||||
You can find most of the placeholders
|
||||
that PlaceholderAPI offers on [PlaceholderAPI wiki](https://github.com/PlaceholderAPI/PlaceholderAPI/wiki/Placeholders).
|
||||
Some plugins are not listed there, for those you'll need to check their own wiki for placeholders.
|
||||
|
||||
TAB also offers its own placeholders into PlaceholderAPI. To enable TAB's expansion, set
|
||||
```
|
||||
placeholders:
|
||||
register-tab-expansion: true
|
||||
```
|
||||
in **config.yml**.
|
||||
Full list of placeholders (general + feature specific):
|
||||
|
||||
**General**:
|
||||
|
||||
| Identifier | Description |
|
||||
|-----------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `%tab_replace_<placeholder>%` | Applies [Placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements) to a PlaceholderAPI placeholder (for example `%tab_replace_essentials_vanished%`) |
|
||||
| `%tab_placeholder_<placeholder>%` | Returns value of tab's internal placeholder (this also applies [Placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements) to them if configured). <br />Example: `%tab_placeholder_animation:name%` for `%animation:name%` |
|
||||
| `%rel_tab_replace_<rel_placeholder>%` | Applies [Placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements) to a **relationnal** PlaceholderAPI placeholder |
|
||||
| `%rel_tab_placeholder_<rel_placeholder>%` | Returns value of tab's internal **relational** placeholder (this also applies [Placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements) to them if configured). It may look strange that the `rel` is twice in there, but there's no other way. The first one tells PlaceholderAPI that this is a relational placeholder, the second one is part of the TAB's identifier, which also uses it to mark the placeholder as relational. <br />Example: `%rel_tab_placeholder_rel_condition:name%` for `%rel_condition:name%` |
|
||||
|
||||
**BossBar**:
|
||||
|
||||
| Identifier | Description |
|
||||
|-------------------------|-----------------------------------------|
|
||||
| `%tab_bossbar_visible%` | "Enabled" if visible, "Disabled" if not |
|
||||
|
||||
**NameTags**:
|
||||
|
||||
| Identifier | Description |
|
||||
|----------------------------|----------------------------------------------------------------------------------------------|
|
||||
| `%tab_tagprefix%` | Player's current tagprefix with placeholders parsed. |
|
||||
| `%tab_tagsuffix%` | Player's current tagprefix with placeholders parsed. |
|
||||
| `%tab_tagprefix_raw%` | Player's current raw tagprefix with placeholder identifiers. |
|
||||
| `%tab_tagsuffix_raw%` | Player's current raw tagsuffix with placeholder identifiers. |
|
||||
| `%tab_nametag_visibility%` | "Enabled" if player can see nametags, "Disabled" if disabled using `/tab nametag toggleview` |
|
||||
|
||||
**Scoreboard**:
|
||||
|
||||
| Identifier | Description |
|
||||
|----------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `%tab_scoreboard_name%` | Returns name of player's currently displayed scoreboard or empty string if none is displayed due to no display condition being met. |
|
||||
| `%tab_scoreboard_visible%` | "Enabled" if visible, "Disabled" if not (toggled with a command) |
|
||||
|
||||
**Tablist name formatting**:
|
||||
|
||||
| Identifier | Description |
|
||||
|---------------------------|------------------------------------------------------------------|
|
||||
| `%tab_tabprefix%` | Player's current tabprefix with placeholders parsed. |
|
||||
| `%tab_customtabname%` | Player's current customtabname with placeholders parsed. |
|
||||
| `%tab_tabsuffix%` | Player's current tabprefix with placeholders parsed. |
|
||||
| `%tab_tabprefix_raw%` | Player's current raw tabprefix with placeholder identifiers. |
|
||||
| `%tab_customtabname_raw%` | Player's current raw customtabname with placeholder identifiers. |
|
||||
| `%tab_tabsuffix_raw%` | Player's current raw tabsuffix with placeholder identifiers. |
|
||||
|
||||
# MiniPlaceholders
|
||||
On **Velocity**, TAB integrates with [MiniPlaceholders](https://github.com/MiniPlaceholders/MiniPlaceholders) when the plugin is installed. TAB automatically detects and resolves MiniPlaceholders placeholders in config text, including global, per-player, and relational ones. Placeholders use angle brackets, with the expansion and name separated by an underscore (for example `<luckperms_prefix>`), and arguments added after a colon (for example `<luckperms_meta:key>`). See the [MiniPlaceholders placeholder list](https://miniplaceholders.github.io/docs/user-guide/Placeholders) for all available placeholders. TAB also registers its own expansion, offering placeholders such as `<tab_tabprefix>` and `<tab_placeholder:name>`. The `%placeholder%` syntax remains reserved for [PlaceholderAPI](https://github.com/PlaceholderAPI/PlaceholderAPI) (via TAB Bridge on Velocity).
|
||||
|
||||
> [!WARNING]
|
||||
> TAB's gradient syntax (`<#RRGGBB>Text</#RRGGBB>`) is a compatibility layer that TAB rewrites before parsing, it is more fragile than native [MiniMessage](https://docs.advntr.dev/minimessage/format.html) gradients (`<gradient:#RRGGBB:#RRGGBB>Text</gradient>`). On **Velocity**, this is especially problematic because [MiniPlaceholders](https://github.com/MiniPlaceholders/MiniPlaceholders) parses MiniMessage *before* TAB can rewrite its gradient syntax. For example, placeholder output like `<#E0B11E>MyServer</#FF0000>` is interpreted by MiniPlaceholders as a hex color tag (`<#E0B11E>`), but `</#FF0000>` is not recognized as a gradient closing tag, so the formatting breaks. Prefer native MiniMessage syntax in placeholder output (e.g. `<gradient:#E0B11E:#FF0000>MyServer</gradient>`). See [How to use Minecraft components - MiniMessage](https://github.com/NEZNAMY/TAB/wiki/How-to-use-Minecraft-components#minimessage) for more information.
|
||||
|
||||
# Relational placeholders
|
||||
## About
|
||||
Unlike classic placeholders which take either 0
|
||||
(placeholders with the same output for all players) or 1 (per-player placeholders) players,
|
||||
relational placeholders take in 2 players.
|
||||
The first usage was to display relation between two players, specifically enemies / allies (red / green) for factions,
|
||||
allowing players to see faction names of other players colored based on relation.
|
||||
While the usage is not limited to this, the name of the 2-player placeholder type has been established as "relational"
|
||||
and will be called that everywhere.
|
||||
|
||||
## Usage
|
||||
TAB does not offer any internal relational placeholders. However, it has full support for PlaceholderAPI placeholders. You can also register your own relational placeholders using the [API](#relational-placeholders-1). In PlaceholderAPI, all relational placeholder identifiers must start with `%rel_`. This rule is adopted and used in TAB as well (including those registered via API).
|
||||
|
||||
When passing players into the function, first player is the player viewing the text, second player is the one text is being displayed on.
|
||||
Code wise, the PlaceholderAPI request function becomes
|
||||
```
|
||||
public String onPlaceholderRequest(Player viewer, Player target, String identifier)
|
||||
```
|
||||
where `viewer` is the player looking and `target` is the player the value is being displayed on.
|
||||
|
||||
When trying to use placeholders from other plugins, you will need to check their documentation and search for relational placeholders. If your plugin does not appear to offer any, you ran out of luck and TAB cannot do anything about it.
|
||||
To properly distinguish viewer/target (if needed), your relational placeholder expansion must follow the same order as TAB does. Since PlaceholderAPI never created any convention regarding this, and instead it calls the players `one` and `two`, I had to decide and this is the decision.
|
||||
|
||||
# Refreshing
|
||||
## Refresh intervals
|
||||
TAB is refreshing placeholders in intervals. For internal placeholders it's using values I found the most optimal and set directly in the plugin. Refresh intervals for PlaceholderAPI placeholders can be [configured](https://github.com/NEZNAMY/TAB/wiki/Optimizing-the-plugin#2---all-platforms-placeholder-refresh-intervals).
|
||||
|
||||
## Sync refreshing
|
||||
By default, all placeholders are refreshed asynchronously,
|
||||
so they don't slow down the server, since reading should be a thread-safe operation.
|
||||
Some placeholders, however, require to be refreshed in the main thread,
|
||||
causing problems or throwing errors when refreshed asynchronously.
|
||||
For these, replace them with `%sync:<original placeholder>%` and they will be refreshed in the main thread,
|
||||
for example `%server_total_entities%` -> `%sync:server_total_entities%`.
|
||||
Keep in mind that now you should configure a reasonable refresh interval for these placeholders to not cause TPS drops
|
||||
(with async placeholders it doesn't really matter).
|
||||
Configured refresh intervals and CPU usage of placeholders can be checked using `/tab cpu`.
|
||||
|
||||
# Placeholder is not working
|
||||
When using a placeholder, you should know if it's a [TAB's internal placeholder](#internal-placeholders) or a [PlaceholderAPI placeholder](https://github.com/PlaceholderAPI/PlaceholderAPI/wiki/Placeholders). If you don't, that's the problem.
|
||||
|
||||
> [!CAUTION]
|
||||
> Remember that using `%` symbol will mess up placeholder starts and ends, breaking all placeholders after it.
|
||||
> To make the symbol display correctly without messing up placeholders, use `%%` to display the symbol.
|
||||
> **Example:** `Sale 100% OFF! %some_placeholder%` -> `Sale 100%% OFF! %some_placeholder%`.
|
||||
|
||||
## Internal placeholder is not working
|
||||
Here are few possible reasons:
|
||||
* You attempted to use a proxy-only placeholder on backend, or backend-only placeholder on proxy
|
||||
* You used the `%` symbol before the placeholder, breaking placeholder starts and ends (see above).
|
||||
|
||||
## PlaceholderAPI placeholder is not working
|
||||
Here are few possible reasons:
|
||||
* The placeholder is not working in PlaceholderAPI. You can check this using `/papi parse me <placeholder>`. If it isn't working there, it's not a TAB issue. If the placeholder you used is advertised somewhere, make sure you have the adequate expansion downloaded.
|
||||
* If you have TAB installed on a proxy, make sure [TAB-Bridge](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge) is installed on backend servers to forward support to the proxy.
|
||||
* You used the `%` symbol before the placeholder, breaking placeholder starts and ends (see above).
|
||||
|
||||
# API
|
||||
*To get started with the API, see [Developer API](https://github.com/NEZNAMY/TAB/wiki/Developer-API) page.*
|
||||
|
||||
For working with placeholders, you will need the `PlaceholderManager`. Get it using `TabAPI.getInstance().getPlaceholderManager()`.
|
||||
|
||||
Placeholders have two attributes:
|
||||
* An identifier, which is used to uniquely identify the placeholder. This is also what's usually used for replacement. For example, in `%uptime%`, the identifier is `%uptime%`.
|
||||
* A refresh rate in milliseconds, which is how often the placeholder's refresh function will be called, to get a new value to display. Use `-1` to make the placeholder never refresh periodically. This can be used for either constants or placeholders that update on events, and you wish to update their value manually using functions in the respective placeholder interface.
|
||||
|
||||
## Server placeholders
|
||||
Server placeholders are global to the entire plugin. Their values are not dependent on player.
|
||||
Examples of server placeholders would be uptime and TPS placeholders.
|
||||
|
||||
To register a new server placeholder, use `PlaceholderManager#registerServerPlaceholder(String, int, Supplier<Object>)`. The first two parameters are explained above, and the last parameter is a function that will be called to refresh the value of the placeholder.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
```
|
||||
TabAPI.getInstance().getPlaceholderManager().registerServerPlaceholder("%system-time%", 50, () -> System.currentTimeMillis());
|
||||
```
|
||||
|
||||
This placeholder will show current system time and update every 50 milliseconds.
|
||||
</details>
|
||||
|
||||
## Player placeholders
|
||||
Player placeholders are calculated on a per-player basis. These depend on the player that we want to get the value for.
|
||||
Examples of player placeholders would be username and prefix.
|
||||
|
||||
To register a new player placeholder, use `PlaceholderManager#registerPlayerPlaceholder(String, int, Function<TabPlayer, Object>)`. The first two parameters are explained above, and the last parameter is a function that will be called to refresh the value of the placeholder.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
```
|
||||
TabAPI.getInstance().getPlaceholderManager().registerPlayerPlaceholder("%player-uuid%", -1, player -> player.getUniqueId());
|
||||
```
|
||||
|
||||
This placeholder will show player's UUID and never refreshes, since UUID doesn't change at runtime.
|
||||
</details>
|
||||
|
||||
## Relational placeholders
|
||||
Relational placeholders are calculated using a pair of players, instead of a single one. These depend on the player pair that we want to get the value for. Their identifier must start with `rel_`.
|
||||
|
||||
To register a new relational placeholder, use `PlaceholderManager#registerRelationalPlaceholder(String, int, BiFunction<TabPlayer, TabPlayer, Object>)`. The first two parameters are explained above, and the last parameter is a function that will be called to refresh the value of the placeholder.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
```
|
||||
TabAPI.getInstance().getPlaceholderManager().registerRelationalPlaceholder("%rel_staff_version%", 1000, (viewer, target) -> {
|
||||
if (viewer.hasPermission("tab.staff")) {
|
||||
return target.getVersion().getFriendlyName();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
This placeholder will show the version of players, but only to those, who have `tab.staff` permission.
|
||||
The first player in the method is viewer, the second player is target.
|
||||
The same order is applied when hooking into PlaceholderAPI as well.
|
||||
</details>
|
||||
@@ -0,0 +1,29 @@
|
||||
# About
|
||||
This is a quick guide for [PlaceholderAPI](https://www.spigotmc.org/resources/placeholderapi.6245/) plugin, which is often referred to on the wiki, and we also get many assistance requests with TAB which turn out to be asking for help with PlaceholderAPI. Whether its documentation is not clear enough, missing information or users just don't read it isn't the topic here to judge, instead, a quick guide with everything needed is provided.
|
||||
|
||||
# Installation
|
||||
PlaceholderAPI is a standalone Bukkit plugin that can be installed just like any other plugin.
|
||||
It does not support proxies.
|
||||
If you have TAB on a proxy server and wish to use PlaceholderAPI placeholders,
|
||||
you'll need to install [Bridge](https://www.spigotmc.org/resources/83966) plugin on backend servers.
|
||||
Alongside other features, it forwards PlaceholderAPI support to the proxy.
|
||||
|
||||
# Expansions
|
||||
To effectively scale and allow the level of modification it does,
|
||||
PlaceholderAPI is using placeholder packages called expansions.
|
||||
They are loaded into the plugin on startup.
|
||||
Each expansion can be created and modified independently of the main plugin's update frequency.
|
||||
Each expansion has a name, which is used to identify its placeholders.
|
||||
The syntax is `%<expansion>_<placeholder>%`, where `<expansion>` is name of the expansion,
|
||||
for example `player` and `<placeholder>` is placeholder of the expansion, for example `health`,
|
||||
which returns player's health.
|
||||
The full placeholder syntax will then be `%player_health%`.
|
||||
|
||||
Some plugins offer their own expansions,
|
||||
which are either integrated into the plugin itself or external on PlaceholderAPI cloud.
|
||||
Integrated expansions are not downloaded; instead, plugins register them automatically.
|
||||
|
||||
You can download / update external expansions using `/papi ecloud download <expansion>`. After downloading it, run `/papi reload` to enable it.
|
||||
|
||||
# Checking if placeholder is working
|
||||
To check if a placeholder is working, run `/papi parse <player> <placeholder>`. You can also use `me` as player, which parses placeholder for the player who ran the command. If the command outputs the identifier you entered and not the actual output, it means you either entered and invalid placeholder or you are missing an expansion (or you have an outdated version of the expansion), see above.
|
||||
@@ -0,0 +1,28 @@
|
||||
# About
|
||||
When TAB is installed on a proxy, the plugin has very limited access to information. It is unable to retrieve internal server data, as well as hook into backend plugins, because it's a different server.
|
||||
Bridge is a backend plugin that sends this data to the proxy, allowing TAB to work better when installed on a proxy.
|
||||
You can download it from [GitHub](https://github.com/NEZNAMY/TAB-Bridge/releases), [Spigot](https://www.spigotmc.org/resources/83966) or [Modrinth](https://modrinth.com/plugin/tab-bridge).
|
||||
|
||||
# Installation
|
||||
Installation is as simple as it can be.
|
||||
Put it into the plugins folder of your backend servers.
|
||||
Bridge is NOT a proxy plugin!
|
||||
Bridge itself has no config file, as everything is configured in the main plugin.
|
||||
|
||||
# Features
|
||||
* Forwarding PlaceholderAPI support to the proxy
|
||||
* Allow detection if player is invisible to make their nametag invisible (compensation for 1.8.x client sided bug)
|
||||
* Allow detection if a player is disguised to disable collision to prevent endless push
|
||||
* Forwarding permission groups of players if no permission plugin is installed on the proxy
|
||||
* Forwarding vanish status for compatibility with global playerlist / layout features
|
||||
* Forward player's world for %world% and per-world settings
|
||||
* Allow TAB's PlaceholderAPI expansion with TAB on proxy
|
||||
* Forward player's gamemode for spectator fix feature to work
|
||||
|
||||
# Compatibility
|
||||
Just like with Minecraft, when there is a change in the communication protocol between TAB ↔ TAB-Bridge,
|
||||
older software will not be compatible with the new one.
|
||||
You should always be running the latest versions of both TAB and Bridge.
|
||||
|
||||
# Confirming it works
|
||||
You have many ways to verify TAB and Bridge are properly connected. Besides checking if the features above work, the easiest one is to run `/btab dump <player>` and check if bridge connection says connected. If not, it means Bridge is either not installed or versions are not compatible. Update both to the latest version.
|
||||
@@ -0,0 +1,42 @@
|
||||
## Easy to install
|
||||
Support for all possible Minecraft versions containing features the plugin is able to take advantage of.
|
||||
Support for multiple platforms (Bukkit, BungeeCord, Fabric, Forge, NeoForge, Velocity),
|
||||
with everything contained in a single jar which you can download directly.
|
||||
No need to browse version history, ask what plugin version you need for your server version,
|
||||
visit random websites looking for the download button, or anything similar.
|
||||
The same jar supports all versions & platforms, and the latest plugin version will always work for you.
|
||||
|
||||
## It works
|
||||
The plugin doesn't spam your console with errors, doesn't have compatibility issues with half of the plugins,
|
||||
and doesn't just decide to randomly stop working for no reason.
|
||||
It just works.
|
||||
Bug reports are fixed with the highest priority and preferred over adding new features.
|
||||
It's not unusual for a plugin of this size to have a 3-digit open issue count on GitHub.
|
||||
Meanwhile, TAB is always at 1-digit count.
|
||||
|
||||
## Feature packed
|
||||
All the most requested features in a single plugin.
|
||||
No need to install many plugins, disable features, so they don't conflict with each other,
|
||||
or be forced to run your server on a version that all the plugins support in common.
|
||||
All features, all server versions in a single plugin.
|
||||
|
||||
## Up to date
|
||||
The plugin is not abandoned.
|
||||
It is constantly getting updated to fix reported bugs,
|
||||
add support for new MC versions as they come out and get new optimizations.
|
||||
All that can help it run as smoothly as possible, whilst still working the way you want it to.
|
||||
|
||||
## High performance
|
||||
Unlike with other plugins where "high performance"
|
||||
often means your CPU usage will be high, TAB has a very low CPU footprint.
|
||||
There is a [command](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions#tab-cpu) available
|
||||
that shows the entire plugin's CPU usage.
|
||||
Here you can see which part of TAB is occupying the most of your CPU.
|
||||
There are [many ways to optimize TAB](https://github.com/NEZNAMY/TAB/wiki/Optimizing-the-plugin)
|
||||
to get the most out of it.
|
||||
Performance is also actively monitored on large servers, and observations show that it performs very well,
|
||||
meaning it will almost certainly perform even better on smaller servers.
|
||||
|
||||
## Simple yet powerful configuration
|
||||
Compared to other plugins, each feature is easier to configure and actually offers more.
|
||||
Want a simple result with simple configuration? No problem. Want a complicated result? No problem.
|
||||
@@ -3,43 +3,43 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- v4
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0 #https://github.com/actions/checkout/releases
|
||||
- uses: actions/checkout@v6 # https://github.com/actions/checkout/releases
|
||||
with:
|
||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3.9.0 #https://github.com/actions/setup-java/releases
|
||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||
- name: Set up JDK 25
|
||||
uses: actions/setup-java@v5 # https://github.com/actions/setup-java/releases
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
- name: Cache SonarCloud packages
|
||||
uses: actions/cache@v3.2.3 #https://github.com/actions/cache/releases
|
||||
with:
|
||||
path: ~/.sonar/cache
|
||||
key: ${{ runner.os }}-sonar
|
||||
restore-keys: ${{ runner.os }}-sonar
|
||||
java-version: 25
|
||||
- name: Cache Gradle
|
||||
uses: actions/cache@v3.2.3 #https://github.com/actions/cache/releases
|
||||
uses: actions/cache@v6 # https://github.com/actions/cache/releases
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: "${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}"
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Build and analyze
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
|
||||
run: ./gradlew clean build
|
||||
- name: Rename JAR with Build Number
|
||||
run: |
|
||||
find jar/build/libs -type f -name "TAB v*.jar" -print0 | while IFS= read -r -d '' original; do
|
||||
dir=$(dirname "$original")
|
||||
base=$(basename "$original")
|
||||
new_base="${base%.jar}+${{ github.run_number }}.jar"
|
||||
new_path="$dir/$new_base"
|
||||
mv "$original" "$new_path"
|
||||
done
|
||||
- name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v3.1.2 #https://github.com/actions/upload-artifact/releases
|
||||
uses: actions/upload-artifact@v7 # https://github.com/actions/upload-artifact/releases
|
||||
with:
|
||||
name: Jar
|
||||
path: jar/build/libs/TAB-**.jar
|
||||
name: Click here to download
|
||||
path: "jar/build/libs/TAB v*+${{ github.run_number }}.jar"
|
||||
@@ -6,4 +6,7 @@ is in quality of the report (typically providing correct steps to reproduce that
|
||||
* Test **experimental builds**, which can be found in [GitHub Actions](https://github.com/NEZNAMY/TAB/actions) for problems of any kind including bugs.
|
||||
This way you will help make the actual releases more stable / help get stable releases sooner.
|
||||
* Help improve the wiki by opening a [Wiki change issue](https://github.com/NEZNAMY/TAB/issues/new?assignees=&labels=Wiki&template=wiki_change.yml),
|
||||
where you can improve existing descriptions, add information you found missing, fix typos / grammar mistakes or add more examples.
|
||||
where you can improve existing descriptions, add information you found missing, fix typos / grammar mistakes or add more examples.
|
||||
* Create spark reports and then send them to me. I will analyze them and try to find optimizations to make the plugin run faster. Commands:
|
||||
* `/spark profiler start --timeout 300 --thread * --interval 0.1`
|
||||
* `/spark profiler start --timeout 300 --thread * --interval 0.1 --alloc`
|
||||
@@ -3,8 +3,19 @@ TAB aims to be a superior all-in-one minecraft plugin for displaying information
|
||||
similar plugins in terms of features, performance and compatibility.
|
||||
More information can be found at [Why TAB?](https://github.com/NEZNAMY/TAB/wiki/Why-TAB%3F) wiki page.
|
||||
|
||||
# Download
|
||||
### Releases
|
||||
You can download full releases from [GitHub releases](https://github.com/NEZNAMY/TAB/releases),
|
||||
[SpigotMC](https://www.spigotmc.org/resources/57806/), [Modrinth](https://modrinth.com/plugin/tab-was-taken), [BuiltByBit](https://builtbybit.com/resources/20631) or [CurseForge](https://www.curseforge.com/minecraft/mc-mods/tab).
|
||||
|
||||
### Dev builds
|
||||
Plugin's development is continuous and contains lots of small changes/fixes not worthy of being called a full
|
||||
update, therefore development builds are being created and eventually a full update is released when enough changes are made.
|
||||
If you want to benefit from a recent change in the code before official release, you can download development builds
|
||||
from [GitHub actions](https://github.com/NEZNAMY/TAB/actions) (you must be logged into GitHub to be able to download it).
|
||||
|
||||
# Compiling
|
||||
Compilation requires JDK 17 and up.
|
||||
Compilation requires JDK 25 and up.
|
||||
To compile the plugin, run `./gradlew build` from the terminal.
|
||||
Once the plugin compiles, grab the jar from `/jar/build/libs/` folder.
|
||||
The universal jar contains all modules for all supported platforms.
|
||||
@@ -21,3 +32,24 @@ is in quality of the report. Bug reports where steps to reproduce are "idk" have
|
||||
|
||||
# Contributing
|
||||
See [CONTRIBUTING.md](https://github.com/NEZNAMY/TAB/blob/master/CONTRIBUTING.md)
|
||||
|
||||
# Provided services
|
||||
The plugin is being used by a large amount of servers, which also means the demand for my attention is high. Unfortunately,
|
||||
I am no longer able to keep up with the demand since I don't want to dedicate my whole existence to a free plugin.
|
||||
In order to provide the best quality of all provided services, the amount of services provided may vary over time.
|
||||
Here is the full list of potential services and their status:
|
||||
|
||||
| Service type | Availability |
|
||||
|-------------------------------|--------------|
|
||||
| Updates for new MC versions | ✔ |
|
||||
| Bug fixes | ✔ |
|
||||
| Wiki improvements | ✔ |
|
||||
| Performance optimizations | ✔ |
|
||||
| Feature requests | ❌ |
|
||||
| Customer support<sup>1</sup> | ✔ |
|
||||
| Free user support<sup>2</sup> | ❌* |
|
||||
|
||||
<sup>1</sup> - Unrestricted assistance with the plugin for those, who bought a copy of the plugin when it was purchasable.
|
||||
<sup>2</sup> - Unlimited access to my free time for everyone in the world.
|
||||
|
||||
*Instead, you can use [this fresh new community discord](https://discord.gg/YPqXt63YQj) made by a nice person who will provide this service.
|
||||
@@ -1,5 +1,5 @@
|
||||
dependencies {
|
||||
compileOnlyApi("org.jetbrains:annotations:24.0.1")
|
||||
compileOnlyApi("org.jetbrains:annotations:26.0.2")
|
||||
}
|
||||
|
||||
tasks.javadoc {
|
||||
|
||||
@@ -4,9 +4,11 @@ import java.util.UUID;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
import me.neznamy.tab.api.belowname.BelowNameManager;
|
||||
import me.neznamy.tab.api.bossbar.BossBarManager;
|
||||
import me.neznamy.tab.api.event.EventBus;
|
||||
import me.neznamy.tab.api.placeholder.PlaceholderManager;
|
||||
import me.neznamy.tab.api.playerlistobjective.PlayerListObjectiveManager;
|
||||
import me.neznamy.tab.api.scoreboard.ScoreboardManager;
|
||||
import me.neznamy.tab.api.tablist.SortingManager;
|
||||
import me.neznamy.tab.api.tablist.HeaderFooterManager;
|
||||
@@ -83,6 +85,22 @@ public abstract class TabAPI {
|
||||
*/
|
||||
public abstract @Nullable ScoreboardManager getScoreboardManager();
|
||||
|
||||
/**
|
||||
* Returns belowname manager instance. Unlike other features, this one is returned even if
|
||||
* it is disabled in config, which allows enabling it for specific players using the API.
|
||||
*
|
||||
* @return belowname manager
|
||||
*/
|
||||
public abstract @Nullable BelowNameManager getBelowNameManager();
|
||||
|
||||
/**
|
||||
* Returns playerlist objective manager instance. Unlike other features, this one is returned
|
||||
* even if it is disabled in config, which allows enabling it for specific players using the API.
|
||||
*
|
||||
* @return playerlist objective manager
|
||||
*/
|
||||
public abstract @Nullable PlayerListObjectiveManager getPlayerListObjectiveManager();
|
||||
|
||||
/**
|
||||
* Returns team manager instance if the feature is enabled. If not, returns {@code null}.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package me.neznamy.tab.api;
|
||||
|
||||
import lombok.NonNull;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -8,6 +9,7 @@ import java.util.UUID;
|
||||
/**
|
||||
* An interface representing a player
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public interface TabPlayer {
|
||||
|
||||
/**
|
||||
@@ -15,21 +17,24 @@ public interface TabPlayer {
|
||||
*
|
||||
* @return Player's name
|
||||
*/
|
||||
@NotNull String getName();
|
||||
@NotNull
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Returns player's UUID
|
||||
*
|
||||
* @return Player's UUID
|
||||
*/
|
||||
@NotNull UUID getUniqueId();
|
||||
@NotNull
|
||||
UUID getUniqueId();
|
||||
|
||||
/**
|
||||
* Returns platform-specific entity
|
||||
*
|
||||
* @return an instance of bukkit/bungee player depending on platform
|
||||
* @return platform's player object
|
||||
*/
|
||||
@NotNull Object getPlayer();
|
||||
@NotNull
|
||||
Object getPlayer();
|
||||
|
||||
/**
|
||||
* Returns true once the player is successfully loaded (onJoin method ran through all methods)
|
||||
@@ -45,7 +50,8 @@ public interface TabPlayer {
|
||||
*
|
||||
* @return player's primary permission group
|
||||
*/
|
||||
@NotNull String getGroup();
|
||||
@NotNull
|
||||
String getGroup();
|
||||
|
||||
/**
|
||||
* Temporarily overrides player's group and applies all changes coming from new group.
|
||||
@@ -66,4 +72,54 @@ public interface TabPlayer {
|
||||
* @see #setTemporaryGroup(String)
|
||||
*/
|
||||
boolean hasTemporaryGroup();
|
||||
|
||||
/**
|
||||
* Changes expected profile name of the player. This adapts all name-bound features
|
||||
* to use this new profile name if another plugin changed profile name of the player. <p>
|
||||
* Automatic profile name change detection is available on Bukkit, BungeeCord and Fabric,
|
||||
* therefore using this is redundant there. This function is only needed on Velocity,
|
||||
* where the detection is not available. <p>
|
||||
* Warning: This function does NOT change player's profile name, it only updates the tracked
|
||||
* name inside the plugin.
|
||||
*
|
||||
* @param profileName
|
||||
* New expected profile name
|
||||
*/
|
||||
void setExpectedProfileName(@NonNull String profileName);
|
||||
|
||||
/**
|
||||
* Returns player's expected profile name. This defaults to player's username, but may
|
||||
* get changed by other plugins and then detected by TAB.
|
||||
*
|
||||
* @return Player's expected profile name
|
||||
*/
|
||||
@NotNull
|
||||
String getExpectedProfileName();
|
||||
|
||||
/**
|
||||
* Returns name of the server the player is connected to.
|
||||
* This requires TAB on proxy.
|
||||
* On backend installation, this method returns {@code "N/A"}.
|
||||
*
|
||||
* @return Player's server on proxy or {@code "N/A"} on backend installation
|
||||
*/
|
||||
@NotNull
|
||||
String getServer();
|
||||
|
||||
/**
|
||||
* Returns name of the world the player is in.
|
||||
* On proxy installation, TAB-Bridge must be installed to forward this info to the proxy.
|
||||
* Otherwise, it will return {@code "N/A"}.
|
||||
*
|
||||
* @return Player's world or {@code "N/A"} on proxy installation without TAB-Bridge installed
|
||||
*/
|
||||
@NotNull
|
||||
String getWorld();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this player is a bedrock player, {@code false} if not.
|
||||
*
|
||||
* @return {@code true} if this player is a bedrock player, {@code false} if not
|
||||
*/
|
||||
boolean isBedrockPlayer();
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package me.neznamy.tab.api.belowname;
|
||||
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Interface for manipulating the belowname objective of individual players.
|
||||
* <p>
|
||||
* Instance can be obtained using {@link TabAPI#getBelowNameManager()}.
|
||||
* Unlike other features, this one is available even if it is disabled in config,
|
||||
* which allows enabling it for specific players using {@link #setEnabled(TabPlayer, Boolean)}.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public interface BelowNameManager {
|
||||
|
||||
/**
|
||||
* Forces the objective to be visible or hidden for specified player, overriding
|
||||
* both the config option and the disable condition. This only affects what the
|
||||
* player sees, not how the player is displayed to others. Use {@code null} to
|
||||
* give the control back to configuration.
|
||||
*
|
||||
* @param player
|
||||
* Player to set visibility for
|
||||
* @param enabled
|
||||
* Forced visibility or {@code null} to reset back to configuration
|
||||
* @see #getCustomEnabled(TabPlayer)
|
||||
*/
|
||||
void setEnabled(@NonNull TabPlayer player, @Nullable Boolean enabled);
|
||||
|
||||
/**
|
||||
* Returns forced visibility assigned using {@link #setEnabled(TabPlayer, Boolean)}.
|
||||
* If no visibility is forced, returns {@code null}.
|
||||
*
|
||||
* @param player
|
||||
* Player to get forced visibility of
|
||||
* @return Forced visibility or {@code null} if not forced
|
||||
* @see #setEnabled(TabPlayer, Boolean)
|
||||
*/
|
||||
@Nullable Boolean getCustomEnabled(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Changes score value of specified player to provided value. Supports placeholders,
|
||||
* however, the value must evaluate to a number. Only 1.20.2 and lower clients display
|
||||
* this value, newer clients display the number format instead. Use {@code null} to
|
||||
* reset value back to the configured one.
|
||||
*
|
||||
* @param player
|
||||
* Player to change score value of
|
||||
* @param value
|
||||
* New score value or {@code null} to reset back to configuration
|
||||
* @see #getCustomValue(TabPlayer)
|
||||
* @see #setFancyValue(TabPlayer, String)
|
||||
*/
|
||||
void setValue(@NonNull TabPlayer player, @Nullable String value);
|
||||
|
||||
/**
|
||||
* Returns score value assigned using {@link #setValue(TabPlayer, String)}.
|
||||
* If no value is assigned, returns {@code null}.
|
||||
*
|
||||
* @param player
|
||||
* Player to get custom score value of
|
||||
* @return Custom score value assigned using the API
|
||||
* @see #setValue(TabPlayer, String)
|
||||
*/
|
||||
@Nullable String getCustomValue(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Changes number format of specified player to provided value. Supports placeholders,
|
||||
* as well as any supported RGB formats. Only 1.20.3+ clients display the number format,
|
||||
* older clients display the score value instead. If it evaluates to an empty string, the
|
||||
* score is not displayed at all. Use {@code null} to reset value back to the configured one.
|
||||
*
|
||||
* @param player
|
||||
* Player to change number format of
|
||||
* @param fancyValue
|
||||
* New number format or {@code null} to reset back to configuration
|
||||
* @see #getCustomFancyValue(TabPlayer)
|
||||
* @see #setValue(TabPlayer, String)
|
||||
*/
|
||||
void setFancyValue(@NonNull TabPlayer player, @Nullable String fancyValue);
|
||||
|
||||
/**
|
||||
* Returns number format assigned using {@link #setFancyValue(TabPlayer, String)}.
|
||||
* If no number format is assigned, returns {@code null}.
|
||||
*
|
||||
* @param player
|
||||
* Player to get custom number format of
|
||||
* @return Custom number format assigned using the API
|
||||
* @see #setFancyValue(TabPlayer, String)
|
||||
*/
|
||||
@Nullable String getCustomFancyValue(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Changes objective title of specified player to provided value. Supports placeholders,
|
||||
* as well as any supported RGB formats. Use {@code null} to reset value back to the
|
||||
* configured one.
|
||||
*
|
||||
* @param player
|
||||
* Player to change objective title of
|
||||
* @param title
|
||||
* New objective title or {@code null} to reset back to configuration
|
||||
* @see #getCustomTitle(TabPlayer)
|
||||
*/
|
||||
void setTitle(@NonNull TabPlayer player, @Nullable String title);
|
||||
|
||||
/**
|
||||
* Returns objective title assigned using {@link #setTitle(TabPlayer, String)}.
|
||||
* If no title is assigned, returns {@code null}.
|
||||
*
|
||||
* @param player
|
||||
* Player to get custom objective title of
|
||||
* @return Custom objective title assigned using the API
|
||||
* @see #setTitle(TabPlayer, String)
|
||||
*/
|
||||
@Nullable String getCustomTitle(@NonNull TabPlayer player);
|
||||
}
|
||||
@@ -4,13 +4,27 @@ package me.neznamy.tab.api.bossbar;
|
||||
* An enum representing all available BossBar colors.
|
||||
* Calling ordinal() will return color's network ID.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public enum BarColor {
|
||||
|
||||
/** Pink color */
|
||||
PINK,
|
||||
|
||||
/** Blue color */
|
||||
BLUE,
|
||||
|
||||
/** Red color */
|
||||
RED,
|
||||
|
||||
/** Green color */
|
||||
GREEN,
|
||||
|
||||
/** Yellow color */
|
||||
YELLOW,
|
||||
|
||||
/** Purple color */
|
||||
PURPLE,
|
||||
|
||||
/** White color */
|
||||
WHITE
|
||||
}
|
||||
@@ -4,11 +4,21 @@ package me.neznamy.tab.api.bossbar;
|
||||
* An enum representing all available BossBar styles.
|
||||
* Calling ordinal() will return style's network ID.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public enum BarStyle {
|
||||
|
||||
/** Fully solid line */
|
||||
PROGRESS,
|
||||
|
||||
/** Line segmented into 6 parts */
|
||||
NOTCHED_6,
|
||||
|
||||
/** Line segmented into 10 parts */
|
||||
NOTCHED_10,
|
||||
|
||||
/** Line segmented into 12 parts */
|
||||
NOTCHED_12,
|
||||
|
||||
/** Line segmented into 20 parts */
|
||||
NOTCHED_20
|
||||
}
|
||||
@@ -10,11 +10,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* An interface representing a BossBar line.
|
||||
* <p>
|
||||
* For clients 1.8 and lower it uses wither, which only allows 1 bar
|
||||
* to be displayed at a time. Entity packets are not available on BungeeCord,
|
||||
* where nothing will be displayed for these players.
|
||||
* <p>
|
||||
* For 1.9+ it uses the new BossBar feature, allowing configurable styles
|
||||
* It uses 1.9+ BossBar feature, allowing configurable styles
|
||||
* and colors, as well as display several bars at once. Limit of maximum
|
||||
* displayed BossBars depends on client resolution and GUI scale, up to
|
||||
* 9 concurrent BossBars displayed at once.
|
||||
@@ -205,7 +201,7 @@ public interface BossBar {
|
||||
* Player to check
|
||||
* @return {@code true} if player is allowed to see this Boss Bar, {@code false} if not.
|
||||
*/
|
||||
boolean containsPlayer(TabPlayer player);
|
||||
boolean containsPlayer(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this boss bar is configured as announcement-only bar,
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package me.neznamy.tab.api.bossbar;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An interface allowing work with BossBars such as creating, sending
|
||||
* and toggling.
|
||||
@@ -17,6 +17,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
* This requires the BossBar feature to be enabled in config, otherwise the method will
|
||||
* return {@code null}.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public interface BossBarManager {
|
||||
|
||||
/**
|
||||
@@ -77,6 +78,28 @@ public interface BossBarManager {
|
||||
*/
|
||||
@NotNull Map<String, BossBar> getRegisteredBossBars();
|
||||
|
||||
/**
|
||||
* Removes BossBar with specified name from the manager, making it no longer available.
|
||||
* If BossBar was displayed to any players, it is removed.
|
||||
*
|
||||
* @param name
|
||||
* Name of registered BossBar to remove
|
||||
* @throws IllegalArgumentException
|
||||
* if no BossBar with specified name exists
|
||||
*/
|
||||
void removeBossBar(@NonNull String name);
|
||||
|
||||
/**
|
||||
* Removes BossBar from the manager, making it no longer available.
|
||||
* If BossBar was displayed to any players, it is removed.
|
||||
*
|
||||
* @param bossBar
|
||||
* BossBar to remove
|
||||
* @throws IllegalArgumentException
|
||||
* if specified BossBar is not registered
|
||||
*/
|
||||
void removeBossBar(@NonNull BossBar bossBar);
|
||||
|
||||
/**
|
||||
* Toggles BossBar for this player and sends toggle message if {@code sendToggleMessage} is true.
|
||||
*
|
||||
@@ -116,14 +139,14 @@ public interface BossBarManager {
|
||||
void setBossBarVisible(@NonNull TabPlayer player, boolean visible, boolean sendToggleMessage);
|
||||
|
||||
/**
|
||||
* Temporarily displays registered BossBar to player for specified amount of time in milliseconds.
|
||||
* Temporarily displays registered BossBar to player for specified amount of time in seconds.
|
||||
*
|
||||
* @param player
|
||||
* Player to show BossBar to
|
||||
* @param bossBar
|
||||
* Name of registered BossBar to show
|
||||
* @param duration
|
||||
* In milliseconds for how long should BossBar be displayed
|
||||
* In seconds for how long should BossBar be displayed
|
||||
* @throws IllegalArgumentException
|
||||
* if no BossBar with specified name exists
|
||||
* @see #announceBossBar(String, int)
|
||||
@@ -132,12 +155,12 @@ public interface BossBarManager {
|
||||
void sendBossBarTemporarily(@NonNull TabPlayer player, @NonNull String bossBar, int duration);
|
||||
|
||||
/**
|
||||
* Temporarily displays registered BossBar to all players for specified amount of time in milliseconds.
|
||||
* Temporarily displays registered BossBar to all players for specified amount of time in seconds.
|
||||
*
|
||||
* @param bossBar
|
||||
* Name of registered BossBar to show
|
||||
* @param duration
|
||||
* In milliseconds for how long should BossBar be displayed
|
||||
* In seconds for how long should BossBar be displayed
|
||||
* @throws IllegalArgumentException
|
||||
* if no BossBar with specified name exists
|
||||
* @see #sendBossBarTemporarily(TabPlayer, String, int)
|
||||
|
||||