Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
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
|
||||
@@ -1,5 +1,5 @@
|
||||
# About
|
||||
This folder contains the plugin's description as advertised on various marketplaces which use various syntaxes
|
||||
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`),
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
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://img.shields.io/badge/Release-5.0.5-blue.svg[/IMG]
|
||||
[IMG]https://img.shields.io/badge/Minecraft-1.5%20--%201.21.4-blue.svg[/IMG]
|
||||
[IMG]https://img.shields.io/badge/Java-8+-blue.svg[/IMG]
|
||||
[URL='https://github.com/NEZNAMY/TAB'][IMG]https://img.shields.io/badge/GitHub-Source%20code-yellow.svg[/IMG][/URL]
|
||||
[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://img.shields.io/badge/Documentation-Wiki-yellow.svg[/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.
|
||||
@@ -15,164 +15,20 @@ However, you can join this [URL='https://discord.gg/YPqXt63YQj']fresh new commun
|
||||
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/master/.github/description/images/Section_HeaderFooter.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Example_HeaderFooter.png[/IMG][/CENTER]
|
||||
[LIST]
|
||||
[*]Per-world / per-server support
|
||||
[*]Per-group / per-player support
|
||||
[*]Disable if a specified condition is met
|
||||
[/LIST]
|
||||
[CENTER][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Section_NameTags.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Example_NameTags.png[/IMG][/CENTER]
|
||||
[LIST]
|
||||
[*]Configurable prefix and suffix
|
||||
[*]Per-world / per-server support
|
||||
[*]Per-group / per-player support
|
||||
[*]Disable if a specified condition is met
|
||||
[*]Make nametags completely invisible
|
||||
[*]Control collision rule
|
||||
[*]Automatic compensation for 1.8.x client sided bug making nametags of invisible players still visible
|
||||
[*]Anti-override to prevent other plugins from overriding this one
|
||||
[/LIST]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Section_Sorting.png[/IMG]
|
||||
[CENTER][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Example_Sorting.png[/IMG][/CENTER]
|
||||
[LIST]
|
||||
[*]Sorting by primary permission group
|
||||
[*]Sorting by permission nodes
|
||||
[*]Sorting by a numeric placeholder from lowest to highest or highest to lowest
|
||||
[*]Alphabetically by a placeholder (A-Z or Z-A)
|
||||
[*]Sorting by pre-defined placeholder values
|
||||
[*]Combination of multiple sorting types
|
||||
[*]Enable / disable case-sensitive sorting
|
||||
[/LIST]
|
||||
[CENTER][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Section_TablistFormatting.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Example_TablistFormatting.png[/IMG][/CENTER]
|
||||
[LIST]
|
||||
[*]Configurable prefix, name and suffix
|
||||
[*]Per-world / per-server support
|
||||
[*]Per-group / per-player support
|
||||
[*]Disable if a specified condition is met
|
||||
[*]Anti-override to prevent other plugins from overriding this one
|
||||
[/LIST]
|
||||
[CENTER][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Section_PlayerlistObjective.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Example_PlayerlistObjectiveNumber.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Example_PlayerlistObjectiveHealth.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Example_PlayerlistObjectiveFancy.png[/IMG][/CENTER]
|
||||
[LIST]
|
||||
[*]Display value of any numeric placeholder or hearts
|
||||
[*]Display any text on 1.20.3+
|
||||
[*]Disable if a specified condition is met
|
||||
[/LIST]
|
||||
[CENTER][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Section_Belowname.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Example_BelownameComparison.png[/IMG][/CENTER]
|
||||
[LIST]
|
||||
[*]Display value of any numeric placeholder (<1.20.3) or any text (1.20.3+)
|
||||
[*]Configurable text
|
||||
[*]Disable if a specified condition is met
|
||||
[/LIST]
|
||||
[CENTER][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Section_Bossbar.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Example_BossBar.png[/IMG][/CENTER]
|
||||
[LIST]
|
||||
[*]Configurable text, progress, color and style
|
||||
[*]Define display condition to see a bossbar
|
||||
[*]Announce defined bossbar for specified amount of time
|
||||
[*]Configurable toggle command and message
|
||||
[*]Option to remember toggle choice between logins
|
||||
[/LIST]
|
||||
[CENTER][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Section_GlobalPlayerlist.png[/IMG][/CENTER]
|
||||
[LIST]
|
||||
[*]Display players from all servers on a proxy network in tablist
|
||||
[*]Configurable server groups to share playerlist instead of with all servers
|
||||
[*]Ability to create isolated servers
|
||||
[*]Servers where people will see everyone
|
||||
[*]Compatible with vanish plugins
|
||||
[*]Option to display players from other servers as spectators
|
||||
[/LIST]
|
||||
[CENTER][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Section_Layout.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Example_Layout.png[/IMG][/CENTER]
|
||||
[LIST]
|
||||
[*]Customize all 80 tablist slots
|
||||
[*]Create static slots with any text and skin
|
||||
[*]Create player groups based on conditions
|
||||
[*]Multiple layouts based on conditions
|
||||
[/LIST]
|
||||
[CENTER][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Section_Scoreboard.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Example_ScoreboardComparison.png[/IMG][/CENTER]
|
||||
[LIST]
|
||||
[*]Display up to 15 lines
|
||||
[*]Option to show 0 (or any other static number) in every line instead of 1-15
|
||||
[*]Fully configurable text on right side of lines on 1.20.3+
|
||||
[*]Displaying different scoreboards based on conditions (output of placeholder, permissions)
|
||||
[*]Up to 64 characters per line for <1.13, unlimited for 1.13+ clients
|
||||
[*]Customizable toggle command and message
|
||||
[*]Option to remember toggle choice between logins
|
||||
[*]Automatic detection of scoreboards from other plugins to hide own and show it again once other plugin hides its scoreboard
|
||||
[/LIST]
|
||||
[CENTER][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Section_PerWorldPlayerlist.png[/IMG][/CENTER]
|
||||
[LIST]
|
||||
[*]Only display players from current world in tablist
|
||||
[*]Group worlds which should share players
|
||||
[*]Worlds where players see everyone
|
||||
[*]Option to see all players in all worlds for players with permission
|
||||
[/LIST]
|
||||
[CENTER][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Section_API.png[/IMG][/CENTER]
|
||||
[LIST]
|
||||
[*]Change player prefix/name/suffix in tablist
|
||||
[*]Change header/footer
|
||||
[*]Change nametag prefix / suffix
|
||||
[*]Change player collision rule and nametag visibility
|
||||
[*]Change sorting priority
|
||||
[*]Create custom scoreboards, show different scoreboard, toggle scoreboard
|
||||
[*]Create custom placeholders
|
||||
[*]Create custom boss bars, toggle bossbar visibility, announce bossbar
|
||||
[*]... and more!
|
||||
[/LIST]
|
||||
[LIST]
|
||||
[*]Placeholder support
|
||||
[LIST]
|
||||
[*]Internal placeholders with customizable output
|
||||
[*]Create and use custom animations
|
||||
[*]All placeholders and animations are supported in all features
|
||||
[*]Full PlaceholderAPI support including relational placeholders
|
||||
[*]PlaceholderAPI support on BungeeCord
|
||||
[/LIST]
|
||||
[*]Placeholder output replacements
|
||||
[LIST]
|
||||
[*]Modify output of any placeholder, including PlaceholderAPI placeholders
|
||||
[*]Replace exact text with another text
|
||||
[*]Change output if it's in a number interval
|
||||
[*]Set value if none of the above is met
|
||||
[*]Use original placeholder's output in new one
|
||||
[*]Support for nested placeholders
|
||||
[*]Can be used in other plugins as well
|
||||
[/LIST]
|
||||
[*]RGB Support
|
||||
[LIST]
|
||||
[*]5 supported RGB patterns
|
||||
[*]4 supported gradient patterns
|
||||
[*]Automatically display closest color to legacy clients
|
||||
[*]Configurable color for legacy clients
|
||||
[*]Supported in all features [B]where possible[/B]
|
||||
[/LIST]
|
||||
[*]Conditional placeholders
|
||||
[LIST]
|
||||
[*]Conditions based on placeholder output (comparing numeric value, exact output)
|
||||
[*]Conditions based on permission node
|
||||
[*]Combine conditions with AND or OR
|
||||
[*]Configurable output of both cases when condition is and isn't met
|
||||
[*]Placeholder support in condition output
|
||||
[/LIST]
|
||||
[*]High performance
|
||||
[LIST]
|
||||
[*]Full control of CPU usage by optimizing configuration and disabling unwanted features
|
||||
[*]Fully asynchronous - no impact on TPS
|
||||
[*]Check plugin's CPU usage using /tab cpu
|
||||
[/LIST]
|
||||
[*]RedisBungee support
|
||||
[*]MySQL support
|
||||
[*]Fully client-sided, server-side stays unaffected (scoreboards with their teams and objectives, bossbar entities, armor stands)
|
||||
[*]Disable vanilla feature making players in spectator gamemode appear on the bottom of tablist
|
||||
[*]Possible errors moved into a separate file to not spam your console
|
||||
[*]Yaml error assistant for more user-friendly messages and fix suggestions
|
||||
[*]Many misconfiguration checks to help solve issues much faster
|
||||
[/LIST]
|
||||
[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]
|
||||
@@ -4,12 +4,12 @@ The compact configuration allows you to get the plugin to work the way you want
|
||||
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)
|
||||

|
||||

|
||||

|
||||
[](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).
|
||||
@@ -18,148 +18,21 @@ However, you can join this [fresh new community discord]([https://discord.gg/YPq
|
||||
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.
|
||||
|
||||

|
||||

|
||||

|
||||
* Per-world / per-server support
|
||||
* Per-group / per-player support
|
||||
* Disable if a specified condition is met
|
||||
|
||||

|
||||

|
||||
* Configurable prefix and suffix
|
||||
* Per-world / per-server support
|
||||
* Per-group / per-player support
|
||||
* Disable if a specified condition is met
|
||||
* Make nametags completely invisible
|
||||
* Control collision rule
|
||||
* Automatic compensation for 1.8.x client sided bug making nametags of invisible players still visible
|
||||
* Anti-override to prevent other plugins from overriding this one
|
||||
|
||||

|
||||

|
||||
* Sorting by primary permission group
|
||||
* Sorting by permission nodes
|
||||
* Sorting by a numeric placeholder from lowest to highest or highest to lowest
|
||||
* Alphabetically by a placeholder (A-Z or Z-A)
|
||||
* Sorting by pre-defined placeholder values
|
||||
* Combination of multiple sorting types
|
||||
* Enable / disable case-sensitive sorting
|
||||
|
||||

|
||||

|
||||
* Configurable prefix, name and suffix
|
||||
* Per-world / per-server support
|
||||
* Per-group / per-player support
|
||||
* Disable if a specified condition is met
|
||||
* Anti-override to prevent other plugins from overriding this one
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
* Display value of any numeric placeholder or hearts
|
||||
* Display any text on 1.20.3+
|
||||
* Disable if a specified condition is met
|
||||
|
||||

|
||||

|
||||
* Display value of any numeric placeholder (<1.20.3) or any text (1.20.3+)
|
||||
* Configurable text
|
||||
* Disable if a specified condition is met
|
||||
|
||||

|
||||

|
||||
* Configurable text, progress, color and style
|
||||
* Define display condition to see a bossbar
|
||||
* Announce defined bossbar for specified amount of time
|
||||
* Configurable toggle command and message
|
||||
* Option to remember toggle choice between logins
|
||||
|
||||

|
||||
* Display players from all servers on a proxy network in tablist
|
||||
* Configurable server groups to share playerlist instead of with all servers
|
||||
* Ability to create isolated servers
|
||||
* Servers where people will see everyone
|
||||
* Compatible with vanish plugins
|
||||
* Option to display players from other servers as spectators
|
||||
|
||||

|
||||

|
||||
* Customize all 80 tablist slots
|
||||
* Create static slots with any text and skin
|
||||
* Create player groups based on conditions
|
||||
* Multiple layouts based on conditions
|
||||
|
||||

|
||||

|
||||
* Display up to 15 lines
|
||||
* Option to show 0 (or any other static number) in every line instead of 1-15
|
||||
* Fully configurable text on the right side of lines on 1.20.3+
|
||||
* Displaying different scoreboards based on conditions (output of placeholder, permissions)
|
||||
* Up to 64 characters per line for <1.13, unlimited for 1.13+ clients
|
||||
* Customizable toggle command and message
|
||||
* Option to remember toggle choice between logins
|
||||
* Automatic detection of scoreboards from other plugins to hide own and show it again once the other plugin hides its scoreboard
|
||||
|
||||

|
||||
* Only display players from the same world in tablist
|
||||
* Group worlds which should share players
|
||||
* Worlds where players see everyone
|
||||
* Option to see all players in all worlds for players with permission
|
||||
|
||||

|
||||
* Change player prefix/name/suffix in tablist
|
||||
* Change header/footer
|
||||
* Change nametag prefix / suffix
|
||||
* Change player collision rule and nametag visibility
|
||||
* Change sorting priority
|
||||
* Create custom scoreboards, show different scoreboard, toggle scoreboard
|
||||
* Create custom placeholders
|
||||
* Create custom boss bars, toggle bossbar visibility, announce bossbar
|
||||
* ... and more!
|
||||
|
||||
.
|
||||
.
|
||||
.
|
||||
.
|
||||
.
|
||||
Placeholder support
|
||||
* Internal placeholders with customizable output
|
||||
* Create and use custom animations
|
||||
* All placeholders and animations are supported in all features
|
||||
* Full [PlaceholderAPI]('https://www.spigotmc.org/resources/placeholderapi.6245/') support including [relational placeholders]('https://www.spigotmc.org/resources/placeholderapi.6245/update?update=167267')
|
||||
* PlaceholderAPI support on BungeeCord / Velocity
|
||||
|
||||
Placeholder output replacements
|
||||
* Modify output of any placeholder, including PlaceholderAPI placeholders
|
||||
* Replace exact text with another text
|
||||
* Change output if it's in a number interval
|
||||
* Set value if none of the above is met
|
||||
* Use original placeholder's output in new one
|
||||
* Support for nested placeholders
|
||||
* Can be used in other plugins as well
|
||||
|
||||
RGB Support
|
||||
* 5 supported RGB patterns
|
||||
* 3 supported gradient patterns
|
||||
* Supported in all features **where possible**
|
||||
|
||||
Conditional placeholders
|
||||
* Conditions based on placeholder output (comparing numeric value, exact output)
|
||||
* Conditions based on permission node
|
||||
* Combine conditions with `AND` or `OR`
|
||||
* Configurable output of both cases when condition is and isn't met
|
||||
* Placeholder support in conditions
|
||||
|
||||
High performance
|
||||
* Full control of CPU usage by optimizing configuration and disabling unwanted features
|
||||
* Fully asynchronous - no impact on TPS
|
||||
* Check plugin's CPU usage using /tab cpu
|
||||
|
||||
RedisBungee support
|
||||
MySQL support
|
||||
Fully client-sided, server-side stays unaffected
|
||||
Disable vanilla feature making players in spectator gamemode appear on the bottom of tablist
|
||||
Possible errors moved into a separate file to not spam your console
|
||||
Yaml error assistant for more user-friendly messages and fix suggestions
|
||||
Many misconfiguration checks to help solve issues much faster
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
@@ -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><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" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="93" height="20" fill="#555"/><rect x="93" width="33" height="20" fill="#dfb317"/><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"><text aria-hidden="true" x="475" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="830">Documentation</text><text x="475" y="140" transform="scale(.1)" fill="#fff" textLength="830">Documentation</text><text aria-hidden="true" x="1085" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="230">Wiki</text><text x="1085" y="140" transform="scale(.1)" fill="#fff" textLength="230">Wiki</text></g></svg>
|
||||
|
After Width: | Height: | Size: 1.1 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><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" fill="#fff"/></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"><text aria-hidden="true" x="185" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="250">Java</text><text x="185" y="140" transform="scale(.1)" fill="#fff" textLength="250">Java</text><text aria-hidden="true" x="465" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="150">8+</text><text x="465" y="140" transform="scale(.1)" fill="#fff" textLength="150">8+</text></g></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="156" height="20" role="img" aria-label="Minecraft: 1.7.x - 1.21.10"><title>Minecraft: 1.7.x - 1.21.10</title><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="156" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="61" height="20" fill="#555"/><rect x="61" width="95" height="20" fill="#007ec6"/><rect width="156" 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"><text aria-hidden="true" x="315" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="510">Minecraft</text><text x="315" y="140" transform="scale(.1)" fill="#fff" textLength="510">Minecraft</text><text aria-hidden="true" x="1075" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="850">1.7.x - 1.21.10</text><text x="1075" y="140" transform="scale(.1)" fill="#fff" textLength="850">1.7.x - 1.21.10</text></g></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="92" height="20" role="img" aria-label="Release: 5.3.2"><title>Release: 5.3.2</title><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" fill="#fff"/></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"><text aria-hidden="true" x="275" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">Release</text><text x="275" y="140" transform="scale(.1)" fill="#fff" textLength="430">Release</text><text aria-hidden="true" x="715" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="290">5.3.2</text><text x="715" y="140" transform="scale(.1)" fill="#fff" textLength="290">5.3.2</text></g></svg>
|
||||
|
After Width: | Height: | Size: 1.1 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><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" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="47" height="20" fill="#555"/><rect x="47" width="77" height="20" fill="#dfb317"/><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"><text aria-hidden="true" x="245" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">GitHub</text><text x="245" y="140" transform="scale(.1)" fill="#fff" textLength="370">GitHub</text><text aria-hidden="true" x="845" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="670">Source code</text><text x="845" y="140" transform="scale(.1)" fill="#fff" textLength="670">Source code</text></g></svg>
|
||||
|
After Width: | Height: | Size: 1.1 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,288 @@
|
||||
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 = "5.3.2"
|
||||
download_image(f"https://img.shields.io/badge/Release-{release}-blue.svg", "Badge_Release.svg")
|
||||
|
||||
minecraft = "1.7.x - 1.21.10".replace(" ", "%20").replace("-", "--")
|
||||
download_image(f"https://img.shields.io/badge/Minecraft-{minecraft}-blue.svg", "Badge_Minecraft.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")
|
||||
|
Before Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
@@ -14,11 +14,11 @@
|
||||
* [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)
|
||||
* [RedisBungee support](https://github.com/NEZNAMY/TAB/wiki/Feature-info:-RedisBungee-support)
|
||||
* [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)
|
||||
|
||||
@@ -11,24 +11,24 @@ This is a collection of random information about the plugin not necessarily limi
|
||||
* [Debug config option](#debug-config-option)
|
||||
|
||||
# Vanish detection
|
||||
Although TAB does not manage vanishing players in any way,
|
||||
it checks vanish status for features to be properly compatible.
|
||||
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 to players who cannot see them to prevent third party client exploits from seeing vanished players.
|
||||
* [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, which would make them not appear sorted properly and have no nametag prefix/suffix.
|
||||
* 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 BungeeCord,
|
||||
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.
|
||||
|
||||
@@ -71,10 +71,8 @@ You can check what version the plugin thinks player has by using any of the foll
|
||||
* 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 BungeeCord
|
||||
* And TAB on BungeeCord as well - ViaVersion makes BungeeCord API return version of the backend server player is connected to instead of player's actual version
|
||||
* 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` - There is currently no known cause when or why this happens. However, when this happens, TAB prints a console warn notifying this has happened. Plugin will assume player is using the same version as the server in such cases.
|
||||
* 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.
|
||||
|
||||
@@ -86,7 +84,7 @@ You will not experience all of these, only those that affect the version differe
|
||||
| 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 |
|
||||
| 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 |
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
# 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 bukkit and floodgate is on both bungeecord and bukkit,
|
||||
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 have two options:
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
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
|
||||
When disabling [Tablist name formatting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Tablist-name-formatting), nametag prefix/suffix will be displayed in tablist instead. If you don't want any prefixes in tablist, keep the feature enabled but don't set any prefixes. Disabling this option is only useful to allow other plugins to use the feature or to intentionally display teams 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.
|
||||
|
||||
@@ -2,39 +2,42 @@
|
||||
This page lists all the commands and permissions that are available with TAB.
|
||||
Commands have required permissions associated with them.
|
||||
|
||||
**BungeeCord / Velocity users:**
|
||||
* If you have TAB installed **on the proxy**, 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 BungeeCord, permission nodes are checked on BungeeCord, 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.
|
||||
**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 debug [player]](#tab-debug-player)
|
||||
* [/tab group \<group\>](#tab-group-group)
|
||||
* [/tab groups](#tab-groups)
|
||||
* [/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 debug \[player\]](#tab-debug-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)
|
||||
* [/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)
|
||||
* [/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 toggle](#tab-nametag-toggle)
|
||||
* [/tab setcollision <player> <true/false>](#tab-setcollision-player-truefalse)
|
||||
* [/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)
|
||||
* [/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)
|
||||
* [/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]
|
||||
## /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.
|
||||
|
||||
@@ -65,10 +68,10 @@ Commands have required permissions associated with them.
|
||||
## /tab debug [player]
|
||||
* **Permission:** `tab.debug`
|
||||
* **Description:** Shows the server version, plugin version, permission group choice logic, and sorting type. If player argument is filled, shows info about that player:
|
||||
* On BungeeCord, shows whether player is connected to the backend server with [Bridge](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge) plugin or not.
|
||||
* Sorting value & explanation, useful to see what went wrong if players are not sorted correctly.
|
||||
* Primary group set using [How to assign players into groups](https://github.com/NEZNAMY/TAB/wiki/How-to-assign-players-into-groups)
|
||||
* List of all configured properties, their values and source.
|
||||
* On proxy, shows whether player is connected to the backend server with [Bridge](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge) plugin or not.
|
||||
* Sorting value & explanation, useful to see what went wrong if players are not sorted correctly.
|
||||
* Primary group set using [How to assign players into groups](https://github.com/NEZNAMY/TAB/wiki/How-to-assign-players-into-groups)
|
||||
* List of all configured properties, their values and source.
|
||||
|
||||
## /tab group \<group\>
|
||||
* **Permission:** `tab.groupinfo`
|
||||
@@ -83,11 +86,11 @@ Commands have required permissions associated with them.
|
||||
* **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]
|
||||
## /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)
|
||||
* `-s` for silent toggling (no chat message for affected player)
|
||||
|
||||
## /tab scoreboard announce \<name\> \<duration\>
|
||||
* **Permission:** `tab.announce.scoreboard`
|
||||
@@ -98,20 +101,28 @@ Commands have required permissions associated with them.
|
||||
* **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]
|
||||
## /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)
|
||||
* `-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 toggle
|
||||
* **Permission:** `tab.nametag.toggle`
|
||||
* **Description:** Toggles nametag visibility on all players for player who ran the command. Running the command again will make nametags visible again.
|
||||
## /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 a specified player.
|
||||
* **Options:**
|
||||
* `-s` for silent toggling (no chat message for affected player)
|
||||
|
||||
## /tab setcollision \<player\> \<true|false\>
|
||||
* **Permission:** `tab.setcollision`
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
# Content
|
||||
* [Requirements](#requirements)
|
||||
* [Java](#java)
|
||||
* [Supported server software and versions](#supported-server-software-and-versions)
|
||||
* [Supported features per platform](#supported-features-per-platform)
|
||||
* [Plugin hooks](#plugin-hooks)
|
||||
* [All platforms](#all-platforms)
|
||||
* [Bukkit](#bukkit)
|
||||
* [BungeeCord](#bungeecord)
|
||||
* [Fabric](#fabric)
|
||||
* [Sponge](#sponge)
|
||||
* [Velocity](#velocity)
|
||||
* [All platforms](#all-platforms)
|
||||
* [Bukkit](#bukkit)
|
||||
* [BungeeCord](#bungeecord)
|
||||
* [Fabric](#fabric)
|
||||
* [Forge / NeoForge](#forge--neoforge)
|
||||
* [Sponge](#sponge)
|
||||
* [Velocity](#velocity)
|
||||
* [Compatibility issues](#compatibility-issues)
|
||||
|
||||
# Requirements
|
||||
TAB does not depend on any other plugins.
|
||||
It is compiled with Java 8 and therefore supports any version of 8 and above.
|
||||
TAB does not depend on any other plugins. The experience can however be enhanced by installing other plugins, see below.
|
||||
|
||||
## Java
|
||||
TAB's shared module is compiled with Java 8. For the platforms themselves, TAB does have a higher requirement, however, it does not require a Java version higher than the server software itself does. Specifically:
|
||||
* Sponge, Fabric, Forge and NeoForge require Java 21
|
||||
* Velocity requires Java 17
|
||||
* Bukkit and BungeeCord are ok with Java 8
|
||||
|
||||
# Supported server software and versions
|
||||
<table>
|
||||
@@ -28,40 +35,42 @@ It is compiled with Java 8 and therefore supports any version of 8 and above.
|
||||
<tr>
|
||||
<td rowspan=2>Vanilla</td>
|
||||
<td rowspan=1><a href="https://getbukkit.org/">Bukkit</a> (+forge hybrids)</td>
|
||||
<td>✔ (1.5 - 1.21.4)</td>
|
||||
<td>✔ (1.7.x - 1.21.10)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=1><a href="https://www.spongepowered.org/">Sponge</a></td>
|
||||
<td>✔ (1.9<sup>1</sup> - 1.21.4)</td>
|
||||
<td>✔ (1.20.6 - 1.21.10)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td rowspan=2>Modded</td>
|
||||
<td rowspan=3>Modded</td>
|
||||
<td rowspan=1><a href="https://fabricmc.net">Fabric</a></td>
|
||||
<td>✔ (1.14 - 1.21.4)</td>
|
||||
<td>✔ (1.21.9 - 1.21.10)<sup>1</sup></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=1><a href="https://minecraftforge.net">Forge</a></td>
|
||||
<td>❌</td>
|
||||
<td>✔ (1.21.9 - 1.21.10)<sup>1</sup></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=1><a href="https://neoforged.net/">NeoForge</a></td>
|
||||
<td>✔ (1.21.9 - 1.21.10)<sup>1</sup></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td rowspan=2>Proxies</td>
|
||||
<td rowspan=1><a href="https://ci.md-5.net/job/BungeeCord/">BungeeCord</a></td>
|
||||
<td>✔ (latest only<sup>2</sup>)</td>
|
||||
<td>✔ (latest only)<sup>2</sup></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=1><a href="https://www.velocitypowered.com/">Velocity</a></td>
|
||||
<td>✔ (latest only<sup>2</sup>)</td>
|
||||
<td>✔ (latest only)<sup>2</sup></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<sup>1</sup> Due to a bug in Sponge 7, it cannot coexist in the same jar with classes compiled with Java higher than 8, which is required by some other platforms. To get the plugin to run on Sponge 7, you will need to do one of the following:
|
||||
|
||||
* Compile the plugin yourself and use the jar from `sponge7/build/libs`, which only contains sponge support instead of the universal jar from `jar/build/libs`.
|
||||
* Unzip the plugin jar, go to `me/neznamy/tab/platforms/` and delete everything except `sponge7`.
|
||||
<sup>1</sup> Modded platforms only support the latest MC version(s). For older MC versions try [modrinth](https://modrinth.com/plugin/tab-was-taken)'s version download filter. If TAB is not available for your desired Minecraft version or is very outdated, you may [request a backport](https://github.com/NEZNAMY/TAB/issues/new?template=backport.yml).
|
||||
|
||||
<sup>2</sup> Latest only doesn't mean only the latest build will work,
|
||||
it means the plugin was made to be compatible with the latest version/build.
|
||||
@@ -72,19 +81,19 @@ Since proxies support all client versions, there is never a reason to stay outda
|
||||
so you can always safely update to new version/build of your proxy software if the plugin requires it.
|
||||
|
||||
# Supported features per platform
|
||||
| Feature \ Platform | Bukkit / Hybrid | Sponge | Fabric | 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) | ✔ | ✔ | ✔ | ✔ | ✔ |
|
||||
| Feature \ Platform | Bukkit / Hybrid | Sponge | 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
|
||||
❗ = NameTags: Anti-override missing, Scoreboard: [compatibility with other plugins](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Scoreboard#compatibility-with-other-plugins) missing.
|
||||
@@ -112,7 +121,11 @@ Supporting PremiumVanish's vanishing levels instead of using a basic compatibili
|
||||
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.
|
||||
[**fabric-permissions-api**](https://github.com/lucko/fabric-permissions-api) - Supporting permission nodes instead of OP levels.
|
||||
[**placeholder-api**](https://modrinth.com/mod/placeholder-api) - Displaying placeholders from that mod and offering TAB's placeholders into it.
|
||||
|
||||
## Forge / NeoForge
|
||||
[**LuckPerms**](https://github.com/LuckPerms/LuckPerms) - Permission checks with a string instead of using vanilla OP levels.
|
||||
|
||||
## Sponge
|
||||
*None*
|
||||
@@ -127,18 +140,17 @@ Sending scoreboard packets (scoreboard-teams, belowname-objective, playerlist-ob
|
||||
|
||||
# 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.
|
||||
* **[Tablisknu](https://forums.skunity.com/resources/tablisknu.727/)** (skript addon) prevents TAB from assigning teams (sorting & nametags).
|
||||
* **SkBee** (skript addon) sends empty scoreboard, causing TAB's to not show sometimes.
|
||||
* 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 BungeeCord 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 BungeeCord instead.
|
||||
* **ViaVersion**'s `hide-scoreboard-numbers` config option makes [Belowname](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Belowname)'s `value` and [Playerlist objective](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Playerlist-Objective)'s `value` not visible for 1.20.3+ clients on <1.20.3 server when enabled. When using this setup, you'll need to keep the option disabled (sadly scoreboard numbers will not be hidden, solving this would require an implementation on ViaVersion's side).
|
||||
* **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.
|
||||
* **LimboAuth** may prevent TAB from applying tablist formatting in a way that is not detectable using Velocity API, resulting in the feature not working properly on join.
|
||||
* **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.
|
||||
* Bossbar is not visible on 1.8.
|
||||
* 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.
|
||||
* 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.
|
||||
* **Random Spigot/BungeeCord forks** - All safe patches for improving security & performance are present in well-known public opensource 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.
|
||||
@@ -1,4 +1,5 @@
|
||||
# Page content
|
||||
* [About](#about)
|
||||
* [Adding the dependency](#adding-the-dependency)
|
||||
* [Getting started](#getting-started)
|
||||
* [Lifespan of API calls](#lifespan-of-api-calls)
|
||||
@@ -13,22 +14,31 @@
|
||||
* [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
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.NEZNAMY</groupId>
|
||||
<artifactId>TAB-API</artifactId>
|
||||
<version>5.0.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.NEZNAMY</groupId>
|
||||
<artifactId>TAB-API</artifactId>
|
||||
<version>5.3.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
|
||||
Or, for Gradle users, here are a few examples:
|
||||
@@ -40,7 +50,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'com.github.NEZNAMY:TAB-API:5.0.5'
|
||||
compileOnly 'com.github.NEZNAMY:TAB-API:5.3.2'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -51,15 +61,18 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("com.github.NEZNAMY", "TAB-API", "5.0.5")
|
||||
compileOnly("com.github.NEZNAMY", "TAB-API", "5.3.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.
|
||||
> [!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()`.
|
||||
|
||||
@@ -2,40 +2,56 @@
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* [Additional info](#additional-info)
|
||||
* [Additional note 1 - Copying nametag visibility rule](#additional-note-1---copying-nametag-visibility-rule)
|
||||
* [Additional note 2 - Hidden on sneak on 1.8](#additional-note-2---hidden-on-sneak-on-18)
|
||||
* [Additional note 3 - Visible on NPCs](#additional-note-3---visible-on-npcs)
|
||||
* [Tips & Tricks](#tips--tricks)
|
||||
* [Tip 1 - Heart symbol](#tip-1---heart-symbol)
|
||||
* [Tip 2 - Displaying health as 0-10 or in %](#tip-2---displaying-health-as-0-10-or-in-)
|
||||
* [Additional note 1 - Copying nametag visibility rule](#additional-note-1---copying-nametag-visibility-rule)
|
||||
* [Additional note 2 - Hidden on sneak on 1.8](#additional-note-2---hidden-on-sneak-on-18)
|
||||
* [Additional note 3 - Visible on NPCs](#additional-note-3---visible-on-npcs)
|
||||
* [Additional note 4 - Compatibility with modified clients](#additional-note-4---compatibility-with-modified-clients)
|
||||
* [Compatibility with other plugins](#compatibility-with-other-plugins)
|
||||
* [Limitations](#limitations)
|
||||
* [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 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)
|
||||
* [Tips & Tricks](#tips--tricks)
|
||||
* [Tip 1 - Heart symbol](#tip-1---heart-symbol)
|
||||
|
||||
# About
|
||||
The scoreboard objective with BELOW_NAME display slot that adds another line of text below nametag of players.
|
||||
It is only visible on players within 8-block range.
|
||||
This value is client sided and cannot be changed by the plugin.
|
||||
This features gives you control over Minecraft's scoreboard objective feature with BELOW_NAME slot.
|
||||
This line is displayed below the nametags of all player entities in game. It is not possible to explicitly disable this feature for NPCs, however, this goal can be achieved (see below for more info).
|
||||
It is only visible when within an 8-block range of the player (the range is hardcoded in the client and cannot be changed with a plugin).
|
||||
|
||||
Example visual effect:
|
||||

|
||||
|
||||
This line automatically appears on all player entities when enabled. **Therefore, it is not possible to only display it on some players or not display it on NPCs**.
|
||||
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'
|
||||
```
|
||||
|
||||
The feature can be configured in **config.yml** under **belowname-objective** section.
|
||||
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
|
||||
* `fancy-value` for 1.20.3+ (will show `fancy-value-default` on NPCs), which supports any text
|
||||
|
||||
The feature's properties are displayed as `[score]` + space + `title` (no, the space cannot be removed), where `[score]` is:
|
||||
* `value` for 1.20.2- (will show `0` on NPCs)
|
||||
* `fancy-value` for 1.20.3+ (will show `fancy-value-default` on NPCs)
|
||||
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, 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
|
||||
| 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+. |
|
||||
| fancy-value-default | NPC | [1.20.3+] Default display for all player entities. Plugin uses the value above for 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 1.20.3+. |
|
||||
| title | Health | Text displayed after `value`. It is formally called scoreboard title, which is displayed on all player entities and value is shared on all players and therefore not bound to specific players, which makes it unable to display the value per-player. It should only contain static text or placeholders which return same value for all players. All inserted placeholders are parsed for the player viewing the text. This is intentional to allow advanced configuration with conditions for per-world values for example. |
|
||||
| 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. |
|
||||
| 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`. |
|
||||
| fancy-value-default | NPC | [1.20.3+] Default display for all player entities. Plugin uses the value above for 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 1.20.3+. |
|
||||
| title | Health | Shared label shown after the score for every player entity. Everyone sees the same text (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) that must be met for disabling the feature for players. Set to empty for not disabling the feature ever. |
|
||||
|
||||
# Additional Info
|
||||
## Additional note 1 - Copying nametag visibility rule
|
||||
@@ -57,28 +73,29 @@ NPC plugin can take advantage of this by using teams to hide the original name a
|
||||
|
||||
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))
|
||||
* 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.
|
||||
|
||||
# Tips & Tricks
|
||||
## Tip 1 - Heart symbol
|
||||
If you want to show health of players and display a heart symbol as text, you can use this one: `❤`.
|
||||
```
|
||||
belowname-objective:
|
||||
title: "&4❤"
|
||||
```
|
||||
> [!IMPORTANT]
|
||||
> Make sure your config is saved in UTF-8 encoding to properly read the heart symbol.
|
||||
# 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.
|
||||
|
||||
## Tip 2 - 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
|
||||
# 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.
|
||||
|
||||
# Limitations
|
||||
* [1.5 - 1.12.2] Title length is limited to 32 characters (including color codes).
|
||||
* [1.5 - 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.**
|
||||
@@ -121,7 +138,7 @@ 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 BungeeCord, use %server% with server names.
|
||||
> If you want per server values on proxy, use %server% with server names.
|
||||
> If you want WorldGuard regions, use %worldguard_region_name% with region names.
|
||||
> This works for any placeholder offered by the plugin or by PlaceholderAPI.
|
||||
|
||||
@@ -158,4 +175,30 @@ belowname-objective:
|
||||
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.
|
||||
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
|
||||
In order to use these placeholders, make sure PlaceholderAPI is installed and its `math` and `player` expansions are downloaded.
|
||||
|
||||
# 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 4 - Health bar using hearts
|
||||
You can achieve this on `1.20.3+` using `healthbar` expansion from PlaceholderAPI:
|
||||
```
|
||||
belowname-objective:
|
||||
fancy-value: "%healthbar_healthbar%"
|
||||
```
|
||||
<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.
|
||||
@@ -15,9 +15,10 @@
|
||||
* [Additional note 1 - Hiding bar itself](#additional-note-1---hiding-bar-itself)
|
||||
* [Additional note 2 - Not hiding on server switch](#additional-note-2---not-hiding-on-server-switch)
|
||||
* [API](#api)
|
||||
* [Tips & Tricks](#tips--tricks)
|
||||
* [Tip 1 - Animated bossbar color](#tip-1---animated-bossbar-color)
|
||||
* [Tip 2 - Switching between bossbars with condition](#tip-2---switching-between-bossbars-with-condition)
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Animated bossbar color](#example-1---animated-bossbar-color)
|
||||
* [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)
|
||||
|
||||
# About
|
||||

|
||||
@@ -101,10 +102,12 @@ bossbar:
|
||||
`/tab bossbar announce <name> <time>`
|
||||
`name` is name of bossbar defined in config.yml under **bossbar** section, `time` is length of display time in seconds.
|
||||
|
||||
When using a bossbar announcement, you have a new placeholder available:
|
||||
`%countdown%` that shows remaining time of the announcement in seconds.
|
||||
You can further use this placeholder in progress, for example,
|
||||
using Math expansion from PlaceholderAPI, such as `%math_{tab_placeholder_countdown}/<total time>*100%`.
|
||||
When using a bossbar announcement, you have new placeholders available:
|
||||
* `%bossbar_announce_time_left_<bossbar>%` - Returns remaining time of the announcement in seconds.
|
||||
* `%bossbar_announce_time_total_<bossbar>%` - Returns total time of the announcement 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%`.
|
||||
|
||||
## Additional settings
|
||||
| Option name | Default value | Description |
|
||||
@@ -127,8 +130,8 @@ Then, you need to force your players to get the resource pack.
|
||||
## Additional note 2 - Not hiding on server switch
|
||||
When under a proxy network and having TAB installed on backend server and switching to another server,
|
||||
the bossbar will not hide.
|
||||
This is because BungeeCord makes it look like a world switch to the client.
|
||||
To avoid this, the only way is to install TAB on BungeeCord and disable bossbar on that server.
|
||||
This is because proxies makes it look like a world switch to the client.
|
||||
To avoid this, the only way is to install TAB on the proxy and disable bossbar on that server.
|
||||
|
||||
# API
|
||||
*To get started with the API, see [Developer API](https://github.com/NEZNAMY/TAB/wiki/Developer-API) page.*
|
||||
@@ -173,8 +176,8 @@ Methods in `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.
|
||||
|
||||
# Tips & Tricks
|
||||
## Tip 1 - Animated bossbar color
|
||||
# Examples
|
||||
## Example 1 - Animated bossbar color
|
||||
You can animate the color of a bossbar using [animations](https://github.com/NEZNAMY/TAB/wiki/Animations).
|
||||
First, create an animation in **animations.yml**, such as
|
||||
```
|
||||
@@ -196,7 +199,7 @@ Then, use the animation in bossbar configuration
|
||||
This bossbar will change color every second between blue and yellow colors.
|
||||
You can do the same with progress, style and text as well.
|
||||
|
||||
## Tip 2 - Switching between bossbars with condition
|
||||
## 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),
|
||||
@@ -218,4 +221,27 @@ For number comparisons, negate `<` using `>=` and so on.
|
||||
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: "%animation:barcolors%"
|
||||
progress: "100" # in %
|
||||
text: "&fWebsite: &bwww.domain.com"
|
||||
```
|
||||
Now, the bossbar will appear and disappear every 10 seconds.
|
||||
@@ -1,20 +1,21 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Condition types](#condition-types)
|
||||
* [Number comparations](#number-comparations)
|
||||
* [Text operations](#text-operations)
|
||||
* [Permission](#permission)
|
||||
* [Number comparisons](#number-comparisons)
|
||||
* [Text operations](#text-operations)
|
||||
* [Permission](#permission)
|
||||
* [Multiple condition requirements](#multiple-condition-requirements)
|
||||
* [Condition output](#condition-output)
|
||||
* [Configuration](#configuration)
|
||||
* [Usage](#usage)
|
||||
* [Displaying text](#displaying-text)
|
||||
* [Display condition of a feature](#display-condition-of-a-feature)
|
||||
* [Short format](#short-format)
|
||||
* [Displaying text](#displaying-text)
|
||||
* [Display condition of a feature](#display-condition-of-a-feature)
|
||||
* [Short format](#short-format)
|
||||
* [Refresh interval](#refresh-interval)
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Chaining conditional placeholders](#example-1---chaining-conditional-placeholders)
|
||||
* [Example 2 - Conditions in conditions](#example-2---conditions-in-conditions)
|
||||
* [Example 1 - Chaining conditional placeholders](#example-1---chaining-conditional-placeholders)
|
||||
* [Example 2 - Combining AND and OR](#example-2---combining-and-and-or)
|
||||
* [Example 3 - Negating expressions](#example-3---negating-expressions)
|
||||
|
||||
# About
|
||||
Conditions / conditional placeholders allow you
|
||||
@@ -24,45 +25,40 @@ They have 2 main uses in the plugin:
|
||||
* Conditional placeholders which return defined outputs in both cases if the condition passes or fails
|
||||
|
||||
# Condition types
|
||||
## Number comparations
|
||||
`>=`: greater than or equal to
|
||||
Example: `%ping%>=100` will pass if the player's ping is greater than or equal to `100`.
|
||||
|
||||
`>`: greater than
|
||||
Example: `%ping%>100` will pass if the player's ping is greater than `100`.
|
||||
|
||||
`<=`: less than or equal to
|
||||
Example: `%ping%<=100` will pass if the player's ping is less than or equal to `100`.
|
||||
|
||||
`<`: less than
|
||||
Example: `%ping%<100` will pass if the player's ping is less than `100`.
|
||||
## 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
|
||||
`=`: equal to (must match exactly)
|
||||
Example: `%world%=world` will pass if player is in world `world`.
|
||||
| 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.) |
|
||||
|
||||
`!=`: not equal to (opposite of the above)
|
||||
Example: `%world%!=world` will pass if player is in any world except `world`.
|
||||
> [!NOTE]
|
||||
> For `=` and `!=` you can check for empty output of a placeholder using `%my_placeholder%=` and `%my_placeholder%!=`.
|
||||
|
||||
**Note 1**: For `=` and `!=` you can check for empty output of a placeholder using `%my_placeholder%=` and `%my_placeholder%!=`.
|
||||
|
||||
`<-`: contains (left side for full text, right side text to contain)
|
||||
Example: `%world%<-lobby-` will pass if player is in any world that contains `lobby-` (such as `lobby-1` etc.).
|
||||
|
||||
`|-`: starts with (left side for full text, right side text to start with)
|
||||
Example: `%world%|-lobby-` will pass if player is in any world that starts with `lobby-` (such as `lobby-1` etc.).
|
||||
|
||||
`-|`: ends with (left side for full text, right side text to end with)
|
||||
Example: `%world%-|nether` will pass if player is in any world that ends with `nether` (such as `world_nether` etc.).
|
||||
|
||||
**Note 2**: For string operators, the text must match placeholder's output exactly, including color codes.
|
||||
> [!NOTE]
|
||||
> For string operations, the text must match placeholder's output exactly, including color codes.
|
||||
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
|
||||
`permission:<value>`: permission requirement
|
||||
Example: `permission:my.permission` will pass if player has `my.permission` permission.
|
||||
| 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 |
|
||||
|
||||
# Multiple condition requirements
|
||||
Each condition has a `conditions` parameter, which a list of conditions. If you define more than 1 condition, you must specify the condition type.
|
||||
@@ -73,7 +69,7 @@ This value can be found under `type` field. Types are:
|
||||
If you only defined one subcondition, you don't need to define the type at all, since it's not used for anything.
|
||||
|
||||
# Condition output
|
||||
If using condition as a placeholder, you can specify output in both cases using `yes` and `no` values. `yes` is used when condition passes, `no` if not. If using condition only as a view requirement, you can leave these values empty / not specify them at all.
|
||||
If using condition as a placeholder, you can specify output in both cases using `true` and `false` values. `true` is used when condition passes, `false` if not. If using condition only as a view requirement, you can leave these values empty / not specify them at all.
|
||||
|
||||
# Configuration
|
||||
Open **config.yml** and find this section:
|
||||
@@ -84,21 +80,21 @@ conditions:
|
||||
- '%health%<21'
|
||||
- '%health%>15'
|
||||
type: AND
|
||||
yes: Healthy!
|
||||
no: Damaged!
|
||||
true: Healthy!
|
||||
false: Damaged!
|
||||
```
|
||||
`health` is name of our condition in this case.
|
||||
`conditions` is a list of subconditions that must be met for this condition to pass.
|
||||
`type` defines whether all subconditions must be met or at least one.
|
||||
`yes` & `no` define output in both cases.
|
||||
`true` & `false` define output in both cases.
|
||||
|
||||
# Usage
|
||||
You have 2 ways to use conditions.
|
||||
|
||||
## Displaying text
|
||||
The first way is to use conditions to display text.
|
||||
Configure outputs in `yes` and `no` values and then use `%condition:<name>%`,
|
||||
which will output text defined in `yes` or `no` depending on if condition is met or not.
|
||||
Configure outputs in `true` and `false` values and then use `%condition:<name>%`,
|
||||
which will output text defined in `true` or `false` depending on if condition is met or not.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
@@ -107,8 +103,8 @@ conditions:
|
||||
serverName:
|
||||
conditions:
|
||||
- "%server%=lobby"
|
||||
yes: "You are in the lobby"
|
||||
no: "You are not in lobby"
|
||||
true: "You are in the lobby"
|
||||
false: "You are not in lobby"
|
||||
```
|
||||
|
||||
Use with `%condition:serverName%`
|
||||
@@ -117,7 +113,7 @@ Use with `%condition:serverName%`
|
||||
## Display condition of a feature
|
||||
The second way is to use condition's name in places where a condition is accepted.
|
||||
This includes display conditions for bossbar, scoreboard and layout.
|
||||
In these cases, yes/no texts are unused; therefore, they do not need to be defined.
|
||||
In these cases, true/false texts are unused; therefore, they do not need to be defined.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
@@ -137,36 +133,31 @@ In this example, scoreboard will only be displayed to players with `tab.admin` p
|
||||
</details>
|
||||
|
||||
### Short format
|
||||
If trying to use a condition on place where it's available (bossbar display condition, scoreboard display condition) where you don't need the yes/no values, you can use a short format instead.
|
||||
If trying to use a condition on place where it's available (bossbar display condition, scoreboard display condition) where you don't need the true/false values, you can use a short format instead.
|
||||
|
||||
This can be used by simply creating all subconditions and separating them with `;` for `AND` condition type. For `OR` type, use `|`.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
Single condition:
|
||||
This can be used by simply creating all subconditions and separating them with `;` for `AND` condition type. For `OR` type, use `|`.
|
||||
**Single condition example**:
|
||||
```
|
||||
display-condition: "%server%=lobby"
|
||||
```
|
||||
|
||||
Multiple conditions, all of them must be met:
|
||||
**Multiple conditions, all of them must be met**:
|
||||
```
|
||||
display-condition: "%server%=lobby;%world%=world"
|
||||
```
|
||||
|
||||
Multiple conditions, at least one of them must be met:
|
||||
**Multiple conditions, at least one of them must be met**:
|
||||
```
|
||||
display-condition: "%server%=lobby|%server%=lobby2"
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
# 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, yes/no values).
|
||||
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---placeholder-refresh-intervals).
|
||||
check out the [Optimization guide](https://github.com/NEZNAMY/TAB/wiki/Optimizing-the-plugin#2---all-platforms-placeholder-refresh-intervals).
|
||||
|
||||
# Examples
|
||||
## Example 1 - Chaining conditional placeholders
|
||||
@@ -196,9 +187,8 @@ conditions:
|
||||
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 - Conditions in conditions
|
||||
If you want to use a condition in another one,
|
||||
for example, to use both "AND" and "OR" types, create 2 conditions and use one in the other one.
|
||||
## 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:
|
||||
```
|
||||
@@ -214,4 +204,33 @@ conditions:
|
||||
- "%server%=lobby"
|
||||
type: AND
|
||||
```
|
||||
Then, use condition `main` as the display condition. Note that `yes`/`no` 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.
|
||||
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.
|
||||
|
||||
## Example 3 - Negating expressions
|
||||
Most condition types contain their opposites, such as:
|
||||
* `=` -> `!=`
|
||||
* `permission:` -> `!permission:`
|
||||
* `>=` -> `<`
|
||||
* `>` -> `<=`
|
||||
* `|-` -> `!|-`
|
||||
* `-|` -> `!-|`
|
||||
* `<-` -> `!<-`
|
||||
|
||||
You can achieve this by creating a full condition and check if it returned false.
|
||||
**Example:**
|
||||
Original:
|
||||
```
|
||||
display-condition: "%server%|-lobby"
|
||||
```
|
||||
Negated:
|
||||
```
|
||||
conditions:
|
||||
lobby:
|
||||
conditions:
|
||||
- "%server%|-lobby"
|
||||
```
|
||||
...
|
||||
```
|
||||
display-condition: "%condition:lobby%=false"
|
||||
```
|
||||
This way, the display condition will pass if the nested condition returned `false` (player is not in any lobby).
|
||||
@@ -1,25 +1,25 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* [Grouping players only from certain servers](#grouping-players-only-from-certain-servers)
|
||||
* [Configuring isolated servers](#configuring-isolated-servers)
|
||||
* [Seeing all players on the network from some server](#seeing-all-players-on-the-network-from-some-server)
|
||||
* [Grouping players only from certain servers](#grouping-players-only-from-certain-servers)
|
||||
* [Configuring isolated servers](#configuring-isolated-servers)
|
||||
* [Seeing all players on the network from some server](#seeing-all-players-on-the-network-from-some-server)
|
||||
* [Compatibility with vanish plugins](#compatibility-with-vanish-plugins)
|
||||
|
||||
# About
|
||||
This feature allows you to see players from other servers under a bungeecord network, instead of only seeing players on the same server.
|
||||
To use this feature, you need [TAB installed on bungeecord](https://github.com/NEZNAMY/TAB/wiki/Installation#bungeecord). This option is not available on bukkit and will not be added.
|
||||
This feature allows you to see players from other servers, instead of only seeing players on the same server.
|
||||
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) for proper linking of servers. On proxy installation, this is not required.
|
||||
|
||||
# Configuration
|
||||
| Option name | Default value | Description |
|
||||
|----------------------------------------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | false | Enables / Disables the feature |
|
||||
| server-groups | *Map* | See [Grouping players only from certain servers](#grouping-players-only-from-certain-servers) |
|
||||
| spy-servers | *List* | See [Seeing all players on the network from some server](#seeing-all-players-on-the-network-from-some-server) |
|
||||
| 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 (5 bars). <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). |
|
||||
| Option name | Default value | Description |
|
||||
|----------------------------------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | false | Enables / Disables the feature |
|
||||
| server-groups | *Map* | See [Grouping players only from certain servers](#grouping-players-only-from-certain-servers) |
|
||||
| spy-servers | *List* | See [Seeing all players on the network from some server](#seeing-all-players-on-the-network-from-some-server) |
|
||||
| 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). |
|
||||
|
||||
## Grouping players only from certain servers
|
||||
In case you want multiple servers to share playerlist,
|
||||
@@ -37,7 +37,7 @@ global-playerlist:
|
||||
```
|
||||
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 bungeecord.
|
||||
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.
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* [Global settings](#global-settings)
|
||||
* [Per-world / per-server](#per-world--per-server)
|
||||
* [Per-group / per-player](#per-group--per-player)
|
||||
* [Designs](#designs)
|
||||
* [Chaining designs](#chaining-designs)
|
||||
* [Additional info](#additional-info)
|
||||
* [Additional note 1 - Not resetting on server switch](#additional-note-1---not-resetting-on-server-switch)
|
||||
* [Additional note 1 - [1.8 - 1.20.1] Not resetting on server switch](#additional-note-1---18---1201-not-resetting-on-server-switch)
|
||||
* [Tips & Tricks](#tips--tricks)
|
||||
* [Tip 1 - Dynamic line count](#tip-1---dynamic-line-count)
|
||||
* [Tip 1 - Dynamic line count](#tip-1---dynamic-line-count)
|
||||
* [API](#api)
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Per-version header/footer](#example-1---per-version-headerfooter)
|
||||
|
||||
# About
|
||||
Minecraft feature **introduced in 1.8** showing text above and below playerlist. It cannot be displayed on 1.7 clients in any way.
|
||||
@@ -16,81 +17,64 @@ Minecraft feature **introduced in 1.8** showing text above and below playerlist.
|
||||

|
||||
|
||||
# Configuration
|
||||
| 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. |
|
||||
| Option name | Default value | Description |
|
||||
|-------------------|-----------------------|-------------------------------------------------------------------|
|
||||
| enabled | true | Enables / Disables the feature |
|
||||
| designs | *Map* | Designs to display based on conditions (see below for more info). |
|
||||
|
||||
## Global settings
|
||||
The example above is using this configuration:
|
||||
# Designs
|
||||
A header/footer design has 3 options:
|
||||
* `display-condition` (optional) - [Condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) that must be met for the design to be displayed. If not defined, design will be displayed without any required condition. If player does not meet condition, another design may be displayed 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:
|
||||
header:
|
||||
- "This is the first line of header"
|
||||
- "2nd line of header"
|
||||
footer:
|
||||
- "This is the first line of footer"
|
||||
- "2nd line of footer"
|
||||
```
|
||||
It is the default header/footer for everyone, unless overridden in some way.
|
||||
|
||||
## Per-world / per-server
|
||||
```
|
||||
header-footer:
|
||||
per-world:
|
||||
<your world>:
|
||||
enabled: true
|
||||
designs:
|
||||
MyDesign: # Design name
|
||||
display-condition: "%world%=world" # Delete the line for no condition requirement
|
||||
header:
|
||||
- "Header in specified world"
|
||||
- "Header for world %world%"
|
||||
footer:
|
||||
- "Footer in specified world"
|
||||
per-server:
|
||||
<your server>:
|
||||
header:
|
||||
- "Header in specified server"
|
||||
footer:
|
||||
- "Footer in specified server"
|
||||
- "Footer for world %world%"
|
||||
```
|
||||
|
||||
For multiple worlds/servers to share the same settings, separate them with `;`.
|
||||
For worlds/servers starting with a specified text, use `*` after the shared part. For ending with a shared part, use `*` at the beginning.
|
||||
# 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:
|
||||
per-world:
|
||||
world1;world2:
|
||||
enabled: true
|
||||
designs:
|
||||
per-world:
|
||||
display-condition: "%world%=world"
|
||||
header:
|
||||
- "Shared header in worlds world1 and world2"
|
||||
lobby-*:
|
||||
- "Header for world %world%"
|
||||
footer:
|
||||
- "Footer for world %world%"
|
||||
default: # No display condition
|
||||
header:
|
||||
- "Header in all worlds starting with lobby-"
|
||||
- "Header for every world except %world%"
|
||||
footer:
|
||||
- "Footer for every world except %world%"
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> To make per-world work on proxy installation,
|
||||
> install the [TAB-Bridge](https://www.mc-market.org/resources/21641) plugin on your backend servers.
|
||||
|
||||
## Per-group / per-player
|
||||
**groups.yml**
|
||||
```
|
||||
MyGroup:
|
||||
header:
|
||||
- "This is a header for MyGroup group"
|
||||
footer:
|
||||
- "This is a footer for MyGroup group"
|
||||
per-world:
|
||||
MyWorld:
|
||||
TestGroup:
|
||||
header:
|
||||
- "Header for group TestGroup in world MyWorld"
|
||||
```
|
||||
Same for users, which can be configured in **users.yml**.
|
||||
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.
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - Not resetting on server switch
|
||||
## 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 reset packet, so it isn't a problem there.
|
||||
|
||||
# Tips & Tricks
|
||||
## Tip 1 - 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.
|
||||
@@ -109,8 +93,10 @@ MyAnimation:
|
||||
**config.yml**
|
||||
```
|
||||
header-footer:
|
||||
header:
|
||||
- "%animation:MyAnimation%"
|
||||
designs:
|
||||
DesignName:
|
||||
header:
|
||||
- "%animation:MyAnimation%"
|
||||
```
|
||||
</details>
|
||||
|
||||
@@ -124,4 +110,24 @@ To set the header and/or footer for a player, use the following:
|
||||
* `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.
|
||||
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"
|
||||
```
|
||||
@@ -1,29 +1,36 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Creating a layout](#creating-a-layout)
|
||||
* [Display condition](#display-condition)
|
||||
* [Fixed slots](#fixed-slots)
|
||||
* [Player groups](#player-groups)
|
||||
* [Display condition](#display-condition)
|
||||
* [default-skin](#default-skin)
|
||||
* [Fixed slots](#fixed-slots)
|
||||
* [Player groups](#player-groups)
|
||||
* [Managing multiple layouts with conditions](#managing-multiple-layouts-with-conditions)
|
||||
* [Skins](#skins)
|
||||
* [Format](#format)
|
||||
* [Format](#format)
|
||||
* [Additional settings](#additional-settings)
|
||||
* [Compatibility](#compatibility)
|
||||
* [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 - Playerlist objective incompatibility](#additional-note-1---playerlist-objective-incompatibility)
|
||||
* [Additional note 2 - Global playerlist incompatibility](#additional-note-2---global-playerlist-incompatibility)
|
||||
* [Additional note 3 - [1.19.3 - 1.21.1] Entries in chat complete](#additional-note-3---1193---1211-entries-in-chat-complete)
|
||||
* [Additional note 4 - Per world playerlist incompatibility](#additional-note-4---per-world-playerlist-incompatibility)
|
||||
* [Additional note 5 - [1.8 - 1.21.3] Second layer of skin missing](#additional-note-5---18---1213-second-layer-of-skin-missing)
|
||||
* [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](https://github.com/NEZNAMY/TAB/wiki/Feature-guide%3A-Layout/_edit#additional-note-3---entry-overlap)
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Per-server columns](#example-1---per-server-columns)
|
||||
* [Example 1 - Per-server columns](#example-1---per-server-columns)
|
||||
|
||||
# About
|
||||
This feature allows you to customize all 80 tablist slots. Displaying less than 4 columns is currently not supported. This feature can be enabled and configured in **config.yml** file under **layout** section.
|
||||
This feature allows you to customize all 80 tablist slots. Displaying less than 4 columns is currently not supported ([here's why](https://gist.github.com/NEZNAMY/3dfcbf7d44283735d3c18266a2851651)). 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.
|
||||
|
||||
# Creating a layout
|
||||
Layouts can be creating in config under `layout.layouts` section. Each layout contains 3 settings: Fixed slots, player groups and display condition (optional).
|
||||
Layouts can be creating in config under `layout.layouts` section. A layout has 4 settings:
|
||||
* [Display condition](#display-condition) (optional)
|
||||
* [default-skin](#default-skin) (optional)
|
||||
* [Fixed slots](#fixed-slots)
|
||||
* [Player groups](#player-groups)
|
||||
|
||||
## Display condition
|
||||
Condition that must be met for player to see the layout.
|
||||
@@ -39,6 +46,27 @@ layouts:
|
||||
```
|
||||
This layout will only be visible to players with `tab.staff` permission.
|
||||
|
||||
## default-skin
|
||||
When configured, layout will override `default-skin` value and use that one for empty slots and fixed slots without skin definition. When not set, global `default-skin` will be displayed.
|
||||
**Example**:
|
||||
```
|
||||
layout:
|
||||
enabled: true
|
||||
direction: COLUMNS
|
||||
default-skin: mineskin:37e93c8e12cd426cb28fce31969e0674 # Global default skin for all layouts
|
||||
enable-remaining-players-text: true
|
||||
remaining-players-text: '... and %s more'
|
||||
empty-slot-ping-value: 1000
|
||||
layouts:
|
||||
test:
|
||||
default-skin: player:Notch # All empty slots will use skin of player "Notch" in this layout
|
||||
fixed-slots: []
|
||||
groups:
|
||||
players:
|
||||
slots:
|
||||
- 1-80
|
||||
```
|
||||
|
||||
## 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`. If you don't want to define custom skin for that slot, use `SLOT|TEXT`.
|
||||
@@ -56,6 +84,13 @@ layouts:
|
||||
- '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.
|
||||
@@ -108,41 +143,17 @@ layouts:
|
||||
In this example, players with `tab.staff` permission will see `staff` layout, others will see `default` layout.
|
||||
|
||||
# Skins
|
||||
In slots where players are, their skin is displayed. For fixed slots, if their skin is defined, it is used, otherwise `default-skin` is used. It is also used if invalid skin is specified anywhere.
|
||||
*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).*
|
||||
In slots which display a connected player, their skin is displayed.
|
||||
For fixed slots, if their skin is defined, it is used, otherwise `default-skin` is used. It is also used if invalid skin is specified.
|
||||
|
||||
## Format
|
||||
Currently, TAB supports 3 skin formats:
|
||||
* `mineskin:<ID>` - takes UUID from [MineSkin](https://mineskin.org). You can find some pre-uploaded skins at the bottom of this page.
|
||||
* `player:<name>` - displays skin of player `name`
|
||||
* `mineskin:<UUID>` - takes UUID from [MineSkin](https://mineskin.org). You can find some pre-uploaded skins at the bottom of this page.
|
||||
* `player:<name>` - displays skin of player with the `name`
|
||||
* `texture:<texture>` - uses literal skin texture. This lets you use heads from [Minecraft-Heads](https://minecraft-heads.com/custom-heads) by taking the texture in the `Minecraft-URL` field.
|
||||

|
||||
|
||||
Some pre-uploaded Mineskin skins:
|
||||
```yml
|
||||
BTLP's balance.png: 510604280
|
||||
BTLP's clock.png: 2053951237
|
||||
BTLP's server.png: 604037953
|
||||
BTLP's ping.png: 796704708
|
||||
BTLP's players.png: 1160612233
|
||||
BTLP's rank.png: 527763880
|
||||
Aqua: 1749359849
|
||||
Black: 1551047136
|
||||
Blue: 1870064311
|
||||
Dark Aqua: 1893783461
|
||||
Dark Blue: 899643609
|
||||
Dark Gray: 383747683
|
||||
Dark Green: 588254656
|
||||
Dark Purple: 2061328517
|
||||
Dark Red: 924139093
|
||||
Gold: 1074335506
|
||||
Gray: 745109047
|
||||
Green: 224445819
|
||||
Pink: 1818936290
|
||||
Red: 1160568696
|
||||
White: 1105851698
|
||||
Yellow: 1307755006
|
||||
```
|
||||
|
||||
# Additional settings
|
||||
| Option name | Default value | Description |
|
||||
|-------------------------------|----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
@@ -155,27 +166,18 @@ Yellow: 1307755006
|
||||

|
||||

|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - Playerlist objective incompatibility
|
||||
# Compatibility
|
||||
## 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.
|
||||
|
||||
## Additional note 2 - Global playerlist incompatibility
|
||||
## 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 BungeeCord. Because of this, if you use layout, you can disable global playerlist to reduce resource usage.
|
||||
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.
|
||||
|
||||
## Additional note 3 - [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.
|
||||
> [!NOTE]
|
||||
> To hide entries from chat complete on 1.21.2+,
|
||||
the server also has to be 1.21.2+ so TAB can send the new content to the players
|
||||
(having TAB installed on proxy counts as using the latest version).
|
||||
|
||||
## Additional note 4 - Per world playerlist incompatibility
|
||||
## 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),
|
||||
@@ -233,7 +235,13 @@ You can also replicate "ignore-effect-in-worlds" by creating a layout with condi
|
||||
```
|
||||
</details>
|
||||
|
||||
## Additional note 5 - [1.8 - 1.21.3] Second layer of skin missing
|
||||
# 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,
|
||||
@@ -241,7 +249,26 @@ 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 on 1.21.4+ servers (using a proxy counts as being latest).**
|
||||
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
|
||||
|
||||
|
||||
# Examples
|
||||
## Example 1 - Per-server columns
|
||||
|
||||
@@ -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.
|
||||
@@ -1,24 +1,26 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* [Groups and users](#groups-and-users)
|
||||
* [Per-world / per-server](#per-world--per-server)
|
||||
* [Priority system](#priority-system)
|
||||
* [Placeholder support](#placeholder-support)
|
||||
* [Additional settings](#additional-settings)
|
||||
* [Groups and users](#groups-and-users)
|
||||
* [Per-world / per-server](#per-world--per-server)
|
||||
* [Priority system](#priority-system)
|
||||
* [Name color](#name-color)
|
||||
* [Placeholder support](#placeholder-support)
|
||||
* [Additional settings](#additional-settings)
|
||||
* [Tips & Tricks](#tips--tricks)
|
||||
* [Limitations](#limitations)
|
||||
* [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 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)
|
||||
* [API](#api)
|
||||
* [Changing prefix and suffix](#changing-prefix-and-suffix)
|
||||
* [Collision](#collision)
|
||||
* [Manipulating visibility](#manipulating-visibility)
|
||||
* [Disabling team handling](#disabling-team-handling)
|
||||
* [Changing prefix and suffix](#changing-prefix-and-suffix)
|
||||
* [Collision](#collision)
|
||||
* [Manipulating visibility](#manipulating-visibility)
|
||||
* [Disabling team handling](#disabling-team-handling)
|
||||
|
||||
# About
|
||||
Nametags are controlled by a feature called scoreboard teams. They offer 6 properties:
|
||||
@@ -57,8 +59,8 @@ _NEZNAMY_:
|
||||
This can also be achieved with commands, in this case `/tab player _NEZNAMY_ tagprefix "&4&lAdmin &r"` or `/tab playeruuid _NEZNAMY_ tagprefix "&4&lAdmin &r"`.
|
||||
|
||||
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:
|
||||
For that purpose, a group keyword `_DEFAULT_` was made.
|
||||
Example:
|
||||
**groups.yml**
|
||||
```
|
||||
admin:
|
||||
@@ -68,7 +70,7 @@ _DEFAULT_:
|
||||
```
|
||||
|
||||
## Per-world / per-server
|
||||
Values can also be applied per-world (and per-server on bungeecord), where they can be defined per group/user. These values take priority over global settings. Example:
|
||||
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:
|
||||
@@ -114,19 +116,25 @@ This means you can set per-world tagprefix, but only keep one global tagsuffix,
|
||||
You can see the source of a value displayed on player by using `/tab debug <player>` and checking "source"
|
||||
part of the value you are looking for.
|
||||
|
||||
## 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, while people are used to putting some color code at the end of prefix and expect the name to take it. 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`.
|
||||
|
||||
## Placeholder support
|
||||
All values fully support [TAB's internal placeholders](https://github.com/NEZNAMY/TAB/wiki/Placeholders#internal-placeholders) and [PlaceholderAPI placeholders](https://github.com/PlaceholderAPI/PlaceholderAPI/wiki/Placeholders) including relational placeholders.
|
||||
The number of placeholders is not limited, and they can be used in combination with static text as well.
|
||||
|
||||
## Additional settings
|
||||
| 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 condition (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 | When enabled, everyone will have invisible nametag all the time. Option to hide nametags was added in minecraft **1.8**, therefore it will not work on 1.7 and lower. |
|
||||
| anti-override | true | While enabled, prevents other plugins from assigning online players into teams and making TAB not work correctly. They should be configured to not use teams, however many users fail to disable features in other plugins that they don't want, making this option required. Some plugins don't even say they use teams to achieve their goals. Did you know even Paper uses teams? |
|
||||
| can-see-friendly-invisibles | false | Controlling 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. |
|
||||
| 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 | When evaluates to `true`, makes player's nametag invisible. 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). <br /> Option to hide nametags was added in minecraft **1.8**, therefore it will not work on 1.7 and lower. |
|
||||
| can-see-friendly-invisibles | false | Controlling 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. |
|
||||
|
||||
# Tips & Tricks
|
||||
If you want TAB to only take prefixes/suffixes from the permission plugin,
|
||||
@@ -138,11 +146,18 @@ _DEFAULT_:
|
||||
```
|
||||
|
||||
# Limitations
|
||||
* [1.5 - 1.12.2] Prefix/suffix length is limited to 16 characters (including color codes).
|
||||
* [1.13+] The name can only have one code. That is either color or magic code (such as &4 or &l), but not both.
|
||||
* The name cannot be effectively changed and the plugin doesn't offer it.
|
||||
* Name does not support RGB codes. Any used RGB colors will be rounded to the nearest legacy code.
|
||||
* [1.5 - 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)
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - NPC (in)compatibility
|
||||
@@ -153,15 +168,12 @@ To avoid it, make their names not match any online player and use holograms to d
|
||||
(Citizens plugin has an option for this).
|
||||
|
||||
## Additional note 2 - Prefix/suffix on pets
|
||||
Since 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/).
|
||||
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.
|
||||
Changing name is a complicated process which is slightly out of scope of the plugin as well,
|
||||
this is what nick plugins are about.
|
||||
On top of that, it's a pain
|
||||
requiring a ton of different packets which change their structure every version and with how many versions the plugin supports,
|
||||
it doesn't sound like fun doing.
|
||||
Teams do not allow to change the nametag name itself. The only way to achieve this goal is to send & modify packets to replace the player's actual profile name with a fake one. This is very complicated and can have a lot of side effects. This is out of scope of TAB and is in fact something nick plugins are trying to achieve. As such, **TAB does not offer this**.
|
||||
|
||||
Once you find a nick plugin that supports this, you will need to [make sure TAB properly detects this](https://github.com/NEZNAMY/TAB/wiki/How-to-display-name-from-nickname-plugins#proper-compatibility-with-plugins-that-change-profile-name) to make name-bound features (such as nametags) work properly for nicked players.
|
||||
|
||||
## Additional note 4 - F1 view
|
||||
Using teams causes player nametags to remain visible when using F1 view.
|
||||
@@ -183,6 +195,13 @@ scoreboard-teams:
|
||||
```
|
||||
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. The easiest way 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.*
|
||||
|
||||
@@ -192,15 +211,18 @@ To access this feature, you'll need to obtain `NameTagManager` instance. Get it
|
||||
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 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#getOriginalPrefix(TabPlayer)`
|
||||
* `NameTagManager#getOriginalSuffix(TabPlayer)`
|
||||
* `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,
|
||||
@@ -209,8 +231,8 @@ To get the original value set by the plugin based on configuration:
|
||||
> use [commands](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions#tab-playergroupplayeruuid-name-property-value-options).
|
||||
|
||||
## Collision
|
||||
* `NameTagManager#getCollisionRule(TabPlayer)` - Returns forced collision rule using the API, `null` if no value was forced and player follows the configuration.
|
||||
* `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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* [Grouping playerlist from multiple worlds](#grouping-playerlist-from-multiple-worlds)
|
||||
* [Grouping playerlist from multiple worlds](#grouping-playerlist-from-multiple-worlds)
|
||||
|
||||
# About
|
||||
This feature allows you to limit players you see in tablist to only players in your world, or in a group of worlds.
|
||||
|
||||
@@ -51,8 +51,8 @@ placeholder-output-replacements:
|
||||
> [!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-text)
|
||||
> and check "Without colors" part.
|
||||
> [`/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.
|
||||
@@ -168,7 +168,7 @@ 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
|
||||
## 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.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* [Configuration](#configuration)
|
||||
* [Limitations](#limitations)
|
||||
* [Additional info](#additional-info)
|
||||
* [Additional note 1 - Spectator gamemode](#additional-note-1---spectator-gamemode)
|
||||
* [Additional note 1 - Spectator gamemode](#additional-note-1---spectator-gamemode)
|
||||
|
||||
# About
|
||||
The scoreboard objective with PLAYER_LIST display slot. On 1.20.2- it supports 2 display types:
|
||||
@@ -18,12 +18,14 @@ Since 1.20.3, it can display any text.
|
||||
This feature can be configured in **config.yml** under **playerlist-objective** section.
|
||||
|
||||
# Configuration
|
||||
| Option name | Default value | Description |
|
||||
|-------------------|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | true | Enables / Disables the feature |
|
||||
| value | "%ping%" | [1.20.2-] Defines value displayed. You can set this to any placeholder that outputs a number. Setting value to `%health%`, `%player_health%` or `%player_health_rounded%` will result in the display type being changed to hearts instead of number. If you want to display health but as a number and not hearts, set value to `0%health%` for example. 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 | "&7Ping: %ping%" | [1.20.3+] Value to display for 1.20.3+ clients. Supports any text. |
|
||||
| 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. |
|
||||
| Option name | Default value | Description |
|
||||
|-------------------|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | true | Enables / Disables the feature |
|
||||
| value | "%ping%" | [1.20.2-] Defines value displayed. You can set this to any placeholder that outputs a number. 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 | "&7Ping: %ping%" | [1.20.3+] Value to display for 1.20.3+ clients. Supports any text. |
|
||||
| title | "TAB" | Title to send. Only visible on Bedrock Edition. |
|
||||
| render-type | INTEGER | Render type of the value. Supported values are `INTEGER` and `HEARTS` |
|
||||
| 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. |
|
||||
|
||||
# Limitations
|
||||
* [1.5 - 1.20.2] Only 2 display types are supported - yellow number and hearts.
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Creating a scoreboard](#creating-a-scoreboard)
|
||||
* [title](#title)
|
||||
* [lines](#lines)
|
||||
* [Alignment](#alignment)
|
||||
* [Empty placeholder output](#empty-placeholder-output)
|
||||
* [display-condition](#display-condition)
|
||||
* [title](#title)
|
||||
* [lines](#lines)
|
||||
* [Alignment](#alignment)
|
||||
* [Empty placeholder output](#empty-placeholder-output)
|
||||
* [display-condition](#display-condition)
|
||||
* [Chaining scoreboards](#chaining-scoreboards)
|
||||
* [Announce command](#announce-command)
|
||||
* [Additional settings](#additional-settings)
|
||||
* [Limitations](#limitations)
|
||||
* [Longer lines](#longer-lines)
|
||||
* [Compatibility with other plugins](#compatibility-with-other-plugins)
|
||||
* [Geyser / Bedrock issues](#geyser--bedrock-issues)
|
||||
* [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)
|
||||
* [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 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
|
||||
Scoreboard objective with SIDEBAR display slot.
|
||||
@@ -43,18 +45,37 @@ Up to 15 lines of text. You can define more, but the client won't display them.
|
||||
Since 1.20.3, you can also configure the value on the right side, which no longer has to be a red number. To set it, use `||` sequence and put right-side text after it. Example:
|
||||
```
|
||||
lines:
|
||||
- "Left side text 1||Right side text 1"
|
||||
- "Left side text 2....||Right side text 2...."
|
||||
- "Left side text 3.......||Right side text 3......."
|
||||
- "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 right side text will not be visible at 1.20.2 and lower, and numbers will be displayed instead.
|
||||
To properly see the right side, not only the client has to be 1.20.3+, but the server as well,
|
||||
since the plugin cannot send a packet that does not exist (on older versions).
|
||||
Proxies always include new content and therefore count as the latest version.
|
||||
This can be used to send new content to new players while having an outdated server version.
|
||||
|
||||
### Alignment
|
||||
The left side of the text is automatically aligned to the left,
|
||||
@@ -102,7 +123,7 @@ If a player meets both conditions (has defined permission and is in defined worl
|
||||
# Announce command
|
||||
This takes priority over the current scoreboard.
|
||||
Once the announcement is over, the previous scoreboard is restored.
|
||||
`/tab announce scoreboard <name> <time>`
|
||||
`/tab scoreboard announce <name> <time>`
|
||||
name - name of scoreboard to be displayed
|
||||
time - number of seconds to display the scoreboard for
|
||||
|
||||
@@ -113,15 +134,16 @@ time - number of seconds to display the scoreboard for
|
||||
| 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:** This command will not appear in command auto-complete, because it's not a real registered command. Registered commands must be defined in plugin jar directly and cannot be dynamic. If you want to solve this, you can try getting a dummy private plugin made which registers that command. |
|
||||
| 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. |
|
||||
| use-numbers | false | If enabled, numbers 1-15 will be used in the scoreboard. If disabled, `static-number` is shown everywhere. |
|
||||
| use-numbers | false | If enabled, numbers 1-15 will be used in the scoreboard. If disabled, `static-number` is shown everywhere. Will not be visible for 1.20.3+ players, instead, you can configure any text to show using `\|\|text` in the lines (scroll up for more info). |
|
||||
| static-number | 0 | If `use-numbers` is disabled, this is number to be in all lines. |
|
||||
| delay-on-join-milliseconds | 0 | Delay in milliseconds to send scoreboard after joining. |
|
||||
|
||||
# Limitations
|
||||
* [1.5 - 1.12.2] The title is limited to 32 characters (including color codes).
|
||||
* [1.5 - 1.12.2] Line length is limited to 28 characters (including color codes) (68 on lines with static text / [Longer lines](#longer-lines)).
|
||||
* [1.5 - 1.12.2] Line length is limited to 28 characters (including color codes) (64 on lines with static text / [Longer lines](#longer-lines)).
|
||||
* [1.5 - 1.20.2] The red numbers on the right really cannot be removed from the plugin side (a client modification / resource pack is necessary).
|
||||
* 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.
|
||||
* 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 displayed).
|
||||
* [Bedrock] Scoreboard lines may be cut off and show `...`, this can be bypassed by using [GeyserOptionalPack](https://github.com/GeyserMC/GeyserOptionalPack)
|
||||
|
||||
# Longer lines
|
||||
To make sure the scoreboard never flickers, it's only using prefix/suffix components to display text.
|
||||
@@ -191,6 +213,9 @@ so if you configured a fancy output for that placeholder, you'll need to use it
|
||||
To see what exactly has placeholder returned, use `/tab parse <player> <placeholder>`.
|
||||
</details>
|
||||
|
||||
# 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.*
|
||||
|
||||
@@ -285,7 +310,7 @@ 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
|
||||
## 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.
|
||||
@@ -315,4 +340,29 @@ Let's go ahead and set it up (with proper spacing):
|
||||
- "* &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.
|
||||
@@ -1,20 +1,20 @@
|
||||
# Content
|
||||
* [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)
|
||||
* [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)
|
||||
* [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)
|
||||
* [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)
|
||||
* [Common mistakes](#common-mistakes)
|
||||
* [API](#api)
|
||||
|
||||
@@ -205,15 +205,12 @@ 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.
|
||||
This can be enabled/disabled by toggling `anti-override` setting under `scoreboard-teams`.
|
||||
This is, however, highly recommended to keep enabled, unless all of your plugins are configured correctly.
|
||||
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 and can disable this option,
|
||||
slightly boosting performance.
|
||||
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`.
|
||||
* `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.
|
||||
|
||||
@@ -229,16 +226,16 @@ For that reason, let's call it list of mistakes made when following this page.
|
||||
|
||||
The most common mistakes include:
|
||||
* Disabling both teams and layout, not realizing it disables sorting as well.
|
||||
* Disabling anti-override without disabling teams in other plugins.
|
||||
* Mistaking `primary-group-finding-list` for the sorting list, despite that list having nothing to do with sorting and by default even having a comment above it saying it has nothing to do with sorting.
|
||||
* Not configuring primary groups correctly. This can have multiple reasons, such as
|
||||
* Not configuring group weights in LuckPerms.
|
||||
* Accidentally enabling `use-bukkit-permission-manager` option when on BungeeCord without knowing what it does.
|
||||
* Installing TAB on BungeeCord without having any permission plugin on BungeeCord.
|
||||
* Enabling `assign-groups-by-permissions` without giving those permissions (or the opposite - giving away OP to users, resulting in the highest group being taken).
|
||||
* Not configuring group weights in LuckPerms.
|
||||
* Accidentally enabling `use-bukkit-permission-manager` option when on a proxy without knowing what it does.
|
||||
* Installing TAB on a proxy without having any permission plugin on the proxy.
|
||||
* Enabling `assign-groups-by-permissions` without giving those permissions (or the opposite - giving away OP to users, resulting in the highest group being taken).
|
||||
|
||||
[Debug command](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions#tab-debug-player) will help you identify if this is your case.
|
||||
* Using a plugin that causes TAB to fail to apply teams (such as Tablisknu). This includes installing TAB plugin on both bukkit and bungeecord, causing the installations to conflict.
|
||||
* 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.
|
||||
* Using TAB on Velocity without installing [VelocityScoreboardAPI](https://github.com/NEZNAMY/VelocityScoreboardAPI/releases)
|
||||
|
||||
# API
|
||||
*To get started with the API, see [Developer API](https://github.com/NEZNAMY/TAB/wiki/Developer-API) page.*
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* [Enabling](#enabling)
|
||||
* [Permissions](#permissions)
|
||||
* [Additional info](#additional-info)
|
||||
* [Additional note 1 - Seeing yourself still as spectator](#additional-note-1---seeing-yourself-still-as-spectator)
|
||||
* [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,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Configuration](#configuration)
|
||||
* [Introduction](#introduction)
|
||||
* [Groups and users](#groups-and-users)
|
||||
* [Per-world / per-server](#per-world--per-server)
|
||||
* [Priority system](#priority-system)
|
||||
* [Placeholder support](#placeholder-support)
|
||||
* [Additional settings](#additional-settings)
|
||||
* [Introduction](#introduction)
|
||||
* [Groups and users](#groups-and-users)
|
||||
* [Per-world / per-server](#per-world--per-server)
|
||||
* [Priority system](#priority-system)
|
||||
* [Placeholder support](#placeholder-support)
|
||||
* [Additional settings](#additional-settings)
|
||||
* [Tips & Tricks](#tips--tricks)
|
||||
* [API](#api)
|
||||
|
||||
@@ -73,7 +73,7 @@ _DEFAULT_:
|
||||
```
|
||||
|
||||
## Per-world / per-server
|
||||
Values can also be applied per-world (and per-server on bungeecord), where they can be defined per group/user. These values take priority over global settings. Example:
|
||||
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:
|
||||
@@ -126,7 +126,6 @@ The number of placeholders is not limited, and they can be used in combination w
|
||||
| Option name | Default value | Description |
|
||||
|-------------------|-----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | true | Enables / Disables the feature |
|
||||
| anti-override | true | When enabled, prevents other plugins from overriding TAB. This results in slightly higher CPU usage, but will make sure the function works as expected. <br />Unlike with teams, attempts to override TAB are not logged into anti-override.log file. This is due to high amount of false positives from TAB's own features, as well as bungeecord server switch, higher CPU usage and more. Whether you need this or not depends on how properly your plugins are configured. Some of them attempt to format tablist even if you'd not expect it from such plugin. Keep this enabled to stay safe. |
|
||||
| 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. |
|
||||
|
||||
# Tips & Tricks
|
||||
@@ -156,8 +155,11 @@ To get custom values previously set using the API (they will return `null` if no
|
||||
* `TabListFormatManager#getCustomSuffix(TabPlayer)`
|
||||
|
||||
To get the original value set by the plugin based on configuration:
|
||||
* `TabListFormatManager#getOriginalPrefix(TabPlayer)`
|
||||
* `TabListFormatManager#getOriginalName(TabPlayer)`
|
||||
* `TabListFormatManager#getOriginalSuffix(TabPlayer)`
|
||||
* `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).
|
||||
@@ -1,13 +0,0 @@
|
||||
When a plugin for linking proxies is detected, TAB automatically enables its hook to add support for it.
|
||||
No configuration is necessary.
|
||||
Supported redis 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,8 @@
|
||||
# About
|
||||
A collection of things people have requested that I might look into implementing when I get extremely bored sometime next decade.
|
||||
* Less than 4 columns in Layout
|
||||
* Relational placeholder support in sorting
|
||||
* Relational conditions for layout player groups
|
||||
* 1.21.2+ sorting support
|
||||
* disable-condition support in multi-server-support
|
||||
* Custom relational placeholders
|
||||
@@ -17,6 +17,7 @@
|
||||
* [#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)
|
||||
|
||||
## #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).
|
||||
@@ -24,9 +25,9 @@ See [Citizens FAQ](https://wiki.citizensnpcs.co/Frequently_Asked_Questions#Why_a
|
||||
## #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](https://github.com/NEZNAMY/TAB/wiki/How-to-setup-weights-priorities#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%`.
|
||||
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.
|
||||
@@ -50,6 +51,8 @@ Most commonly used plugins for this are [FastLogin](https://www.spigotmc.org/res
|
||||
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:name:%player%>` at the beginning of tabprefix to simulate this.
|
||||
|
||||
## #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).
|
||||
@@ -74,8 +77,8 @@ You will need a custom minecraft client or a resource pack.
|
||||
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 bukkit-only placeholders](https://github.com/NEZNAMY/TAB/wiki/Placeholders#bukkit-only) on BungeeCord
|
||||
* Trying to use [PlaceholderAPI placeholders on BungeeCord](https://github.com/NEZNAMY/TAB/wiki/How-to-set-up-PlaceholderAPI-support-on-bungeecord) without installing [bridge plugin](https://www.mc-market.org/resources/20631/)
|
||||
* 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.
|
||||
|
||||
@@ -99,10 +102,15 @@ 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?
|
||||
For a player to be visible in game, they must be in the tablist as well.
|
||||
Remember the NPC in tablist issue?
|
||||
If you don't mind players not appearing in the game, get a plugin that hides all players.
|
||||
If you want to see them in the game, however, your only choice is to put a lot of empty lines into header,
|
||||
In Minecraft, for a player to be visible in-game, they also need to appear in the tablist.
|
||||
Remember the issue with NPCs showing up in the tablist? It's the same underlying mechanic.
|
||||
|
||||
If you're okay with players not being visible in the world, you can use a plugin that hides all players completely.
|
||||
|
||||
Since Minecraft 1.19.3, this limitation has been lifted — it's now possible to have entities in the game without showing them in the tablist.
|
||||
However, the TAB plugin does **not** support removing all players from the tablist in any version of Minecraft.
|
||||
|
||||
An alternative solution using TAB is putting a lot of empty lines into header,
|
||||
which will push all players out of the screen.
|
||||
|
||||
## #15 - How to add images to tablist?
|
||||
@@ -110,14 +118,7 @@ You can check out [this reddit post](https://www.reddit.com/r/admincraft/comment
|
||||
When using the symbol in configuration using \u format, remember to use `""` in config instead of `''`.
|
||||
|
||||
## #16 - Is MiniMessage supported?
|
||||
Kind of.
|
||||
MiniMessage support **is** included; however, this doesn't mean it is guaranteed to work.
|
||||
MiniMessage library must be included in your server software.
|
||||
TAB does not include this library.
|
||||
* It **is** included in **Paper 1.18.2** and higher, **Velocity** and **Sponge 8**.
|
||||
* It **is not** included in **Spigot**, any server software for 1.18.1 and lower, **BungeeCord**, **Sponge 7** and **Fabric**.
|
||||
|
||||
If you believe MiniMessage should be supported on your server but doesn't work, open a bug report.
|
||||
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.
|
||||
@@ -136,4 +137,8 @@ where plugin authors can see how many servers use their plugins (if they don't d
|
||||
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.
|
||||
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).
|
||||
@@ -1,5 +1,5 @@
|
||||
# About the wiki
|
||||
The wiki explains the functionality of the plugin as of version **5.0.5**.
|
||||
The wiki explains the functionality of the plugin as of version **5.3.2**.
|
||||
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.
|
||||
@@ -10,8 +10,16 @@ This will give you knowledge to do things you had no idea were possible, giving
|
||||
|
||||
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), Sponge and modded servers |
|
||||
|
||||
# Limitations of plugins
|
||||
TAB is a plugin.
|
||||
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
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
# 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)
|
||||
* [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.
|
||||
@@ -41,8 +42,14 @@ 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.
|
||||
This is done automatically on Bukkit, BungeeCord and Fabric.
|
||||
This detection is not available on Sponge and Velocity.
|
||||
This is done automatically on Bukkit, BungeeCord and modded platforms.
|
||||
**This detection is not available on Sponge and Velocity**.
|
||||
|
||||
> [!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 (either you use TAB on Sponge / Velocity, or 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.
|
||||
@@ -62,8 +69,8 @@ conditions:
|
||||
nick:
|
||||
conditions:
|
||||
- '%essentials_nickname%=%player%'
|
||||
yes: "%player%" # If nickname = player name -> player is not nicked
|
||||
no: "~%essentials_nickname%" # If nickname != player name -> player is nicked
|
||||
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.
|
||||
|
||||
@@ -80,8 +87,8 @@ conditions:
|
||||
group:
|
||||
conditions:
|
||||
- '%haonick_isNicked%=true'
|
||||
yes: "default"
|
||||
no: "%group%"
|
||||
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).
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* [Notepad++](#notepad-1)
|
||||
* [Sublime Text 3](#sublime-text-3)
|
||||
* [WinSCP](#winscp)
|
||||
* [VSCode](#vscode)
|
||||
***
|
||||
|
||||
# Notepad
|
||||
@@ -25,4 +26,9 @@ Open the file > Click encoding > Click UTF-8 (if that didn't work, use Convert t
|
||||
# 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,194 @@
|
||||
# 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:blocks":"minecraft:item/diamond_helmet">'
|
||||
- 'Diamond chestplate: <sprite:"minecraft:blocks":"minecraft:item/diamond_chestplate">'
|
||||
- 'Diamond leggings: <sprite:"minecraft:blocks":"minecraft:item/diamond_leggings">'
|
||||
- 'Diamond boots: <sprite:"minecraft:blocks":"minecraft:item/diamond_boots">'
|
||||
```
|
||||
<img width="386" height="101" alt="image" src="https://github.com/user-attachments/assets/e9a66305-2ae4-44f4-9d8e-a227fb7591e4" />
|
||||
|
||||
|
||||
## Player sprite
|
||||
> [!WARNING]
|
||||
> In order to use these, you will need to disable MiniMessage support, because head components were not added to MiniMessage yet. Even when they are added, they will have a different syntax, so TAB will be updated to match the format to avoid complications. For now, use the existing syntax for prototyping and testing. To disable MiniMessage support, set:
|
||||
> ```
|
||||
> components:
|
||||
> minimessage-support: false
|
||||
> ```
|
||||
> in **config.yml**.
|
||||
|
||||
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:NAME>` | Shows head defined by player name | name |
|
||||
| `<head:id:UUID>` | Shows head defined by player UUID | uuid |
|
||||
| `<head:signed_texture:VALUE;SIGNATURE>` | Shows head defined by value and signature | value and signature |
|
||||
| `<head:player:NAME` | Connects to Mojang and retrieves value and signature of defined player | value and signature |
|
||||
| `<head:mineskin:ID>` | Connects to Mineskin and retrieves value and signature of specified upload ID | value and signature |
|
||||
| `<head:texture:VALUE>` | Connects to Mojang and retrieves skin value and signature from "texture" | value and signature |
|
||||
|
||||
Here is an example for all types:
|
||||
```
|
||||
footer:
|
||||
- 'Head by id: <head:id:%uuid%>' # This will obviously not work in offline mode
|
||||
- 'Head by name: <head:name:%player%>' # May or may not work in offline mode (see above for full explanation)
|
||||
- 'Head by raw texture: <head:signed_texture:ewogICJ0aW1lc3RhbXAiIDogMTc1NjMxNjc0OTk4MywKICAicHJvZmlsZUlkIiA6ICIyMzdkOGI1NTNmOTc0NzQ5YWE2MGU5ZmU5N2I0NTA2MiIsCiAgInByb2ZpbGVOYW1lIiA6ICJfTkVaTkFNWV8iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmY1ZTNhNWRmODkxYzEzMTdhZjUzMmMzNmY4NDgxNDBhNDBmMGZhMGNlZGRmZmEwNWU5NGU1NzU1OGQxY2Q4YyIKICAgIH0KICB9Cn0=;YFVoqA0CqWgnZhme5s/M7xtadURyLkyLWVsh0vN8BqdfwzN32nqlBJb2pRjkxIs0V21EOeKbGFjgdKQKzPRQdf6sTFQ/x0KOjUg8A/neAiwCvDSDrsTQ2Yf7yoVP6M2PpuB7te19N+I139mGY5psxU100x6GiV/uFfpUfG3XBJog43JtXzRJ9fRtoSeIEzqLrkpCmt6o5Mzo6GZFZc4CtI76OU90Mg9ZvTZTYelvtjFtllxTtkNZCcglzvh5R19+qtzLOzEr+N8m4Ed+5yZyezEb3LeeSgmbSLIjuOKuUupE+2F6yVYP3eKhgGLZ2G+cg9TZZjTCsNMzHqewM/1+qStzTQCdNmggXCGcIfC8HcYsBfdv4SicxBq8ff+BDyveFZMFyREpQNqX/fLmlz16cmxHvBQ9qqA+IzIsBJ7i/mrG78jBhkJsvtcHMHvTviXascCSQP1TCn58D6HJ/Agww6HFTJe/B6sX0Utzm0URE4jZK7wnhrx0q2H8OkCXc5ZwuXALqtvk0uWmZo2RMnIGQNi4nb5AUsGV8pNirhS16MfqZeJ4q0HGaIVscRp4jazab6kMVKusbuqQB1cZNbaao7mP1HAUVCd5geWQL4CQQIc6gv0q3KT2E45d0YeYqpy/RppKMWmg1+aQ5wVGQW4/p2mqXos71FKy6vP0ur6txd8=>'
|
||||
- 'Head by player: <head:player:%player%>'
|
||||
- 'Head by mineskin: <head: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 | ViaBackwards 5.5.0 - [Client disconnects with a packet decoding error](https://github.com/ViaVersion/ViaBackwards/issues/1107) <br /> ViaBackwards 5.5.1+ - (empty) |
|
||||
| BungeeCord | TAB | `<Object components were added in 1.21.9>` |
|
||||
| Velocity | Velocity | 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+**, **Velocity** and **Sponge**.
|
||||
* It **is not** included in **Spigot**, any server software for **1.18.1-**, **BungeeCord**, **Fabric**, **Forge** and **NeoForge**.
|
||||
|
||||
When MiniMessage is detected on your server, it is automatically used. All codes are translated to MiniMessage syntax and then parsed by MiniMessage.
|
||||
|
||||
# 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.
|
||||
@@ -1,72 +0,0 @@
|
||||
# Content
|
||||
* [Introduction](#introduction)
|
||||
* [Usage](#usage)
|
||||
* [Magic codes](#magic-codes)
|
||||
* [Invalid code handling](#invalid-code-handling)
|
||||
* [Compatibility with <1.16](#compatibility-with-116)
|
||||
* [Fonts](#fonts)
|
||||
* [Usage](#usage-1)
|
||||
* [Compatibility with RGB and gradients](#compatibility-with-rgb-and-gradients)
|
||||
|
||||
# Introduction
|
||||
As of 1.16, mojang introduced RGB color support.
|
||||
This allows us to use 256^3 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 at the beginning of text. For 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
|
||||
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**
|
||||

|
||||
@@ -1,18 +1,16 @@
|
||||
# Content
|
||||
* [Backend](#backend)
|
||||
* [BungeeCord / Velocity](#bungeecord--velocity)
|
||||
* [Proxy installation](#proxy-installation)
|
||||
* [Backend installation](#backend-installation)
|
||||
* [Mixed installation](#mixed-installation)
|
||||
* [Proxy](#proxy)
|
||||
* [Proxy installation](#proxy-installation)
|
||||
* [Backend installation](#backend-installation)
|
||||
* [Mixed installation](#mixed-installation)
|
||||
* [Updating the plugin](#updating-the-plugin)
|
||||
|
||||
# Backend
|
||||
Installation on Bukkit / Fabric / Sponge is as simple as it can be.
|
||||
Put the plugin into the plugins folder and restart the server.
|
||||
Dynamic (re)loads at runtime such as `/plugman load tab` to load the plugin are fully supported.
|
||||
However, plugins hooking into TAB may break when you use such ways to (re)load it.
|
||||
Installation on backend servers is as simple as it can be.
|
||||
Put the plugin into the plugins folder and restart the server.
|
||||
|
||||
# BungeeCord / Velocity
|
||||
# Proxy
|
||||
When running a network, you have 3 options:
|
||||
* Installing TAB only on the proxy (recommended)
|
||||
* Installing TAB on all backend servers instead
|
||||
@@ -33,8 +31,8 @@ install [VelocityScoreboardAPI](https://github.com/NEZNAMY/VelocityScoreboardAPI
|
||||
> 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) and [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) can work with all players connected to the proxy
|
||||
* Can use new content for new clients even if a backend server version is old (1.16+ RGB codes, 1.20.3+ scoreboard features)
|
||||
* 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
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ Combine the knowledge gathered by reading the wiki to get interesting results, m
|
||||
* [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)
|
||||
* [Option 1 - Using global playerlist](#option-1---using-global-playerlist)
|
||||
* [Option 2 - Using PlaceholderAPI](#option-2---using-placeholderapi)
|
||||
|
||||
# Displaying kill / death counter in tablist
|
||||
This example uses PlaceholderAPI placeholders.
|
||||
@@ -37,7 +37,7 @@ _DEFAULT_:
|
||||
```
|
||||
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 bungeecord, and you want prefixes to be taken from backend servers, use `%vault_prefix%` (or `%luckperms_prefix%`) with [PlaceholderAPI support on bungeecord](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge).
|
||||
**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:
|
||||
@@ -63,13 +63,13 @@ conditions:
|
||||
tps:
|
||||
conditions:
|
||||
- "%tps%>=19"
|
||||
yes: "<#55FF55>%tps%</#00AA00>"
|
||||
no: "%condition:tps2%"
|
||||
true: "<#55FF55>%tps%</#00AA00>"
|
||||
false: "%condition:tps2%"
|
||||
tps2:
|
||||
conditions:
|
||||
- "%tps%>=15"
|
||||
yes: "<#FFFF55>%tps%</#FFAA00>"
|
||||
no: "<#FF5555>%tps%</#AA0000>"
|
||||
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+.
|
||||
@@ -80,23 +80,23 @@ conditions:
|
||||
mspt:
|
||||
conditions:
|
||||
- "%mspt%<40"
|
||||
yes: "<#55FF55>%mspt%</#00AA00>"
|
||||
no: "%condition:mspt2%"
|
||||
true: "<#55FF55>%mspt%</#00AA00>"
|
||||
false: "%condition:mspt2%"
|
||||
mspt2:
|
||||
conditions:
|
||||
- "%mspt%<50"
|
||||
yes: "<#FFFF55>%mspt%</#FFAA00>"
|
||||
no: "<#FF5555>%mspt%</#AA0000>"
|
||||
true: "<#FFFF55>%mspt%</#FFAA00>"
|
||||
false: "<#FF5555>%mspt%</#AA0000>"
|
||||
ping:
|
||||
conditions:
|
||||
- "%ping%<100"
|
||||
yes: "<#55FF55>%ping%</#00AA00>"
|
||||
no: "%condition:ping2%"
|
||||
true: "<#55FF55>%ping%</#00AA00>"
|
||||
false: "%condition:ping2%"
|
||||
ping2:
|
||||
conditions:
|
||||
- "%ping%<200"
|
||||
yes: "<#FFFF55>%ping%</#FFAA00>"
|
||||
no: "<#FF5555>%ping%</#AA0000>"
|
||||
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:
|
||||
```
|
||||
@@ -137,8 +137,8 @@ conditions:
|
||||
rankOrTeam:
|
||||
conditions:
|
||||
- "%bw1058_player_team%="
|
||||
yes: "%luckperms-prefix%"
|
||||
no: "%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.
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
* [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)
|
||||
* [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
|
||||
|
||||
@@ -6,12 +6,10 @@ The usage can be checked at any time using [**/tab cpu**](https://github.com/NEZ
|
||||
* [#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 anti-override](#5---all-platforms-disable-anti-override)
|
||||
* [#6 - [All platforms] Disable tablist name formatting](#6---all-platforms-disable-tablist-name-formatting)
|
||||
* [#7 - [All platforms] Increase permission refresh interval](#7---all-platforms-increase-permission-refresh-interval)
|
||||
* [#8 - [BungeeCord / Velocity] Disable TAB expansion](#8---bungeecord--velocity-disable-tab-expansion)
|
||||
* [#9 - [BungeeCord / Velocity] Disable update-latency option in global playerlist](#9---bungeecord--velocity-disable-update-latency-option-in-global-playerlist)
|
||||
* [#10 - [BungeeCord] Disable ByteBuf deserialization](#10---bungeecord-disable-bytebuf-deserialization)
|
||||
* [#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)
|
||||
|
||||
# #1 - [All platforms] Static text instead of placeholders
|
||||
Static text doesn't need to be refreshed periodically, resulting in better performance.
|
||||
@@ -23,11 +21,11 @@ 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.
|
||||
|
||||
This only works for PlaceholderAPI placeholders. Internal ones have an interval hardcoded already with values I found the most appropriate.
|
||||
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
|
||||
placeholderapi-refresh-intervals:
|
||||
placeholder-refresh-intervals:
|
||||
default-refresh-interval: 500
|
||||
"%server_uptime%": 1000
|
||||
"%server_tps_1_colored%": 1000
|
||||
@@ -56,27 +54,7 @@ This is because they work by spamming updates every time an animation switches t
|
||||
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 anti-override
|
||||
By default, TAB prevents other plugins from overriding it.
|
||||
This is because many server owners are not competent enough to configure their plugins correctly,
|
||||
such as disabling CMI collision handling which breaks nametags or even disabling team handling in paper.
|
||||
This obviously causes higher CPU usage.
|
||||
TAB logs all override attempts of teams into [anti-override.log](https://github.com/NEZNAMY/TAB/wiki/Action-logging#anti-overridelog) file.
|
||||
If you didn't get the file, it looks like you configured your plugins correctly.
|
||||
In that case, you can disable anti-override for teams in TAB.
|
||||
```
|
||||
scoreboard-teams:
|
||||
anti-override: false
|
||||
```
|
||||
Tablist formatting is trickier, as override attempts are not logged because it would have a lot of false positives.
|
||||
You will need to try and see.
|
||||
|
||||
```
|
||||
tablist-name-formatting:
|
||||
anti-override: false
|
||||
```
|
||||
|
||||
# #6 - [All platforms] Disable tablist name formatting
|
||||
# #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,
|
||||
@@ -87,12 +65,11 @@ However, you can only do this if:
|
||||
|
||||
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.
|
||||
|
||||
# #7 - [All platforms] Increase permission refresh interval
|
||||
# #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)
|
||||
* Prefix/suffix placeholders taking data from your permission plugin
|
||||
|
||||
default value
|
||||
```
|
||||
@@ -102,7 +79,7 @@ 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.
|
||||
|
||||
# #8 - [BungeeCord / Velocity] Disable TAB expansion
|
||||
# #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,
|
||||
@@ -113,24 +90,5 @@ Disabling TAB's PlaceholderAPI expansion if you don't use it improves performanc
|
||||
placeholders:
|
||||
register-tab-expansion: false
|
||||
```
|
||||
# #9 - [BungeeCord / Velocity] 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.
|
||||
|
||||
# #10 - [BungeeCord] Disable ByteBuf deserialization
|
||||
In order for anti-override to work properly, some packets must be manually deserialized due to BungeeCord not doing it. If you don't need it, you can disable those functions, which will also disable the deserialization completely. To do so, you must disable 2 functions (only having 1 disabled is not enough):
|
||||
#1 - Anti-override for teams
|
||||
```
|
||||
scoreboard-teams:
|
||||
anti-override: false
|
||||
```
|
||||
Whether you need anti-override or not depends on the configuration of your plugins.
|
||||
The easiest way is to have it enabled and see if you get `anti-override.log` file in TAB folder.
|
||||
If you don't, you don't need it.
|
||||
If you do, you'll need to do some configuring.
|
||||
[Here](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Sorting-players-in-tablist#additional-note-3---compatibility-issues-with-other-plugins)
|
||||
are a few examples of software and their team names, which you may find helpful.
|
||||
|
||||
#2 - Scoreboard detection of other plugins
|
||||
TAB checks for packets sent by other plugins, and if another plugin sends a scoreboard,
|
||||
TAB hides its own and resends it after the other plugin removes it.
|
||||
This check cannot be disabled if the scoreboard is enabled.
|
||||
# #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.
|
||||
@@ -1,23 +1,23 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Internal placeholders](#internal-placeholders)
|
||||
* [Universal](#universal)
|
||||
* [Backend only](#backend-only)
|
||||
* [BungeeCord only](#bungeecord-only)
|
||||
* [Universal](#universal)
|
||||
* [Backend only](#backend-only)
|
||||
* [Proxy only](#proxy-only)
|
||||
* [PlaceholderAPI](#placeholderapi)
|
||||
* [Relational placeholders](#relational-placeholders)
|
||||
* [About](#about-1)
|
||||
* [Usage](#usage)
|
||||
* [About](#about-1)
|
||||
* [Usage](#usage)
|
||||
* [Refreshing](#refreshing)
|
||||
* [Refresh intervals](#refresh-intervals)
|
||||
* [Sync refreshing](#sync-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)
|
||||
* [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)
|
||||
* [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).
|
||||
@@ -28,50 +28,56 @@ Basic placeholders provided by the plugin. Most of these placeholders were added
|
||||
|
||||
Placeholders must be refreshed.
|
||||
All internal placeholders have a manually defined refresh interval,
|
||||
which I found the most optimal and cannot be changed.
|
||||
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.
|
||||
It is used for placeholders which are in fact constants (such as %player%),
|
||||
`-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 |
|
||||
| %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 map on [fan wiki](https://wiki.vg/Protocol_version_numbers) for all versions or [TAB's source code](https://github.com/NEZNAMY/TAB/blob/master/shared/src/main/java/me/neznamy/tab/shared/ProtocolVersion.java) for releases only. Useful for conditions to create per-version results. |
|
||||
| %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 |
|
||||
| %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) |
|
||||
| %% | -1 | Returns the `%` symbol. Useful to display `%` symbol without breaking all placeholders after it |
|
||||
| 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 map on [fan wiki](https://wiki.vg/Protocol_version_numbers) for all versions or [TAB's source code](https://github.com/NEZNAMY/TAB/blob/master/shared/src/main/java/me/neznamy/tab/shared/ProtocolVersion.java) for releases only. Useful for conditions to create per-version results. |
|
||||
| %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. |
|
||||
| %% | -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 (Bukkit / Sponge / Fabric), they don't work when TAB is on BungeeCord. If you have TAB installed on BungeeCord 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 BungeeCord.
|
||||
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 server, not available on Fabric as it doesn't measure the value) | %server_tps_1% |
|
||||
| %mspt% | 1000 | Server's current milliseconds per tick (Paper / Sponge 8+ / Fabric only) | - |
|
||||
| %tps% | 1000 | TPS of server from the last minute. Measured by the server. Not directly available on Fabric, Forge and Neoforge. 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% |
|
||||
|
||||
## BungeeCord only
|
||||
## Proxy only
|
||||
| Identifier | Refresh interval | Description |
|
||||
|------------------------------|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| %server% | -1 | Name of server where player is, defined in proxy's config. |
|
||||
@@ -110,8 +116,7 @@ Full list of placeholders:
|
||||
| %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 |
|
||||
| %tab_bossbar_visible% | "Enabled" if visible, "Disabled" if not |
|
||||
| %tab_nametag_preview% | "Enabled" if previewing armor stands using /tab nametag preview, "Disabled" if not |
|
||||
| %tab_nametag_visibility% | "Enabled" if player can see nametags, "Disabled" if disabled using /tab nametag toggle |
|
||||
| %tab_nametag_visibility% | "Enabled" if player can see nametags, "Disabled" if disabled using `/tab nametag toggleview` |
|
||||
| %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 (such as %tab_placeholder_animation:name% for %animation:name%) |
|
||||
|
||||
@@ -163,17 +168,17 @@ When using a placeholder, you should know if it's a [TAB's internal placeholder]
|
||||
|
||||
## Internal placeholder is not working
|
||||
All TAB's internal placeholders are listed above.
|
||||
Some of them are bukkit only (meaning they won't work on bungeecord) and some are bungee only.
|
||||
Some of them are backend only (meaning they won't work on proxy) and some are proxy only.
|
||||
> [!IMPORTANT]
|
||||
> Trying to use a bukkit-only placeholder on bungeecord will not work.
|
||||
> Trying to use a backend-only placeholder on proxy will not work.
|
||||
> If you want to use those,
|
||||
> [set up PlaceholderAPI support on bungeecord](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge)
|
||||
> [set up PlaceholderAPI support on proxy](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge)
|
||||
> and find their PlaceholderAPI equivalent.
|
||||
> For example, you can use %vault_prefix% instead of %vault-prefix%,
|
||||
> %player_health_rounded% instead of %health% and so on.
|
||||
|
||||
## PlaceholderAPI placeholder is not working
|
||||
If you have TAB installed on bungeecord, make sure you [set up PlaceholderAPI support on bungeecord](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge) as there is no other way to retrieve data from technically a different server.
|
||||
If you have TAB installed on a proxy, make sure you [set up PlaceholderAPI support on proxy](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge) as there is no other way to retrieve data from technically a different server.
|
||||
|
||||
> [!TIP]
|
||||
> Use `/papi parse me <placeholder>` to check if the placeholder is working.
|
||||
|
||||
@@ -3,8 +3,8 @@ This is a quick guide for [PlaceholderAPI](https://www.spigotmc.org/resources/pl
|
||||
|
||||
# Installation
|
||||
PlaceholderAPI is a standalone bukkit plugin that can be installed just like any other plugin.
|
||||
It does not support BungeeCord.
|
||||
If you have TAB on BungeeCord and wish to use PlaceholderAPI placeholders,
|
||||
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.
|
||||
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
# About
|
||||
When TAB is installed on BungeeCord, 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 BungeeCord.
|
||||
You can download it from [GitHub](https://github.com/NEZNAMY/TAB-Bridge/releases) or [Spigot](https://www.spigotmc.org/resources/83966).
|
||||
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 BungeeCord plugin!
|
||||
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 BungeeCord
|
||||
* 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 BungeeCord
|
||||
* 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,
|
||||
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.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## 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, Velocity, Fabric, Sponge),
|
||||
Support for multiple platforms (Bukkit, BungeeCord, Fabric, Forge, NeoForge, Sponge, 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.
|
||||
@@ -20,9 +20,6 @@ No need to install many plugins, disable features, so they don't conflict with e
|
||||
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.
|
||||
|
||||
## Beyond the limits
|
||||
Mojang decided to put some kind of limitation on almost every feature TAB offers. Other developers simply say "Mojang limit, nothing we can do about it, goodbye". This is not the case here. With every limitation I find, I look for ways to bypass it, and I've found most of them. These bypasses require a ton of work involved, and it's much easier to say "not possible" than actually doing it.
|
||||
|
||||
## Up to date
|
||||
The plugin is not abandoned.
|
||||
It is constantly getting updated to fix reported bugs,
|
||||
@@ -36,10 +33,7 @@ There is a [command](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions#
|
||||
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,
|
||||
the most common being increasing refresh rates for individual placeholders if they're inefficient.
|
||||
This is done on a per-placeholder basis,
|
||||
instead of slowing down the refresh rate of an entire feature, which may break animations.
|
||||
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.
|
||||
|
||||
|
||||
@@ -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`
|
||||
@@ -6,7 +6,7 @@ More information can be found at [Why TAB?](https://github.com/NEZNAMY/TAB/wiki/
|
||||
# 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) or [BuiltByBit](https://builtbybit.com/resources/20631).
|
||||
[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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
dependencies {
|
||||
compileOnlyApi("org.jetbrains:annotations:24.1.0")
|
||||
compileOnlyApi("org.jetbrains:annotations:26.0.2")
|
||||
}
|
||||
|
||||
tasks.javadoc {
|
||||
|
||||
@@ -77,7 +77,7 @@ public interface TabPlayer {
|
||||
* 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 Sponge and Velocity,
|
||||
* 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.
|
||||
@@ -96,7 +96,6 @@ public interface TabPlayer {
|
||||
@NotNull
|
||||
String getExpectedProfileName();
|
||||
|
||||
|
||||
/**
|
||||
* Returns name of the server the player is connected to.
|
||||
* This requires TAB on proxy.
|
||||
|
||||
@@ -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.
|
||||
@@ -78,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.
|
||||
*
|
||||
|
||||
@@ -134,7 +134,7 @@ public interface NameTagManager {
|
||||
* @param prefix
|
||||
* new prefix value
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
* @see #getOriginalPrefix(TabPlayer)
|
||||
* @see #getOriginalRawPrefix(TabPlayer)
|
||||
*/
|
||||
void setPrefix(@NonNull TabPlayer player, @Nullable String prefix);
|
||||
|
||||
@@ -148,7 +148,7 @@ public interface NameTagManager {
|
||||
* @param suffix
|
||||
* new suffix value
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
* @see #getOriginalSuffix(TabPlayer)
|
||||
* @see #getOriginalRawSuffix(TabPlayer)
|
||||
*/
|
||||
void setSuffix(@NonNull TabPlayer player, @Nullable String suffix);
|
||||
|
||||
@@ -160,7 +160,7 @@ public interface NameTagManager {
|
||||
* Player to get custom prefix of
|
||||
* @return Custom prefix assigned using the API.
|
||||
* @see #setPrefix(TabPlayer, String)
|
||||
* @see #getOriginalPrefix(TabPlayer)
|
||||
* @see #getOriginalRawPrefix(TabPlayer)
|
||||
*/
|
||||
@Nullable
|
||||
String getCustomPrefix(@NonNull TabPlayer player);
|
||||
@@ -173,7 +173,7 @@ public interface NameTagManager {
|
||||
* Player to get custom suffix of
|
||||
* @return Custom suffix assigned using the API.
|
||||
* @see #setSuffix(TabPlayer, String)
|
||||
* @see #getOriginalSuffix(TabPlayer)
|
||||
* @see #getOriginalRawSuffix(TabPlayer)
|
||||
*/
|
||||
@Nullable
|
||||
String getCustomSuffix(@NonNull TabPlayer player);
|
||||
@@ -186,7 +186,7 @@ public interface NameTagManager {
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalPrefix(@NonNull TabPlayer player);
|
||||
String getOriginalRawPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic.
|
||||
@@ -196,20 +196,86 @@ public interface NameTagManager {
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalRawSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original prefix assigned by the plugin using internal logic with all placeholders replaced.
|
||||
* @param player
|
||||
* Player to get replaced original prefix of
|
||||
* @return Original prefix assigned by the plugin's internal logic.
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalReplacedPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic with all placeholders replaced.
|
||||
* @param player
|
||||
* Player to get replaced original suffix of
|
||||
* @return Original suffix assigned by the plugin's internal logic.
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalReplacedSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get replaced original prefix of
|
||||
* @return Original prefix assigned by the plugin's internal logic.
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
* @deprecated Use {@link #getOriginalRawPrefix(TabPlayer)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@NotNull
|
||||
String getOriginalPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get replaced original suffix of
|
||||
* @return Original suffix assigned by the plugin's internal logic.
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
* @deprecated Use {@link #getOriginalRawSuffix(TabPlayer)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@NotNull
|
||||
String getOriginalSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Toggles name tag visibility view on all players for specified player.
|
||||
* On first call, name tags of all players will become invisible for specified
|
||||
* player. On second call, they will become visible again.
|
||||
* player. On the second call, they will become visible again.
|
||||
*
|
||||
* @param player
|
||||
* player to toggle name tag visibility view for
|
||||
* @param sendToggleMessage
|
||||
* {@code true} if configured toggle message should be sent, {@code false} if not
|
||||
* {@code true} if the configured toggle message should be sent, {@code false} if not
|
||||
*/
|
||||
void toggleNameTagVisibilityView(@NonNull TabPlayer player, boolean sendToggleMessage);
|
||||
|
||||
/**
|
||||
* Shows back name tag visibility view on all players for specified player.
|
||||
* If the view is not hidden, nothing happens.
|
||||
*
|
||||
* @param player
|
||||
* player to show name tag visibility view for
|
||||
* @param sendToggleMessage
|
||||
* {@code true} if the configured toggle message should be sent, {@code false} if not
|
||||
*/
|
||||
void showNameTagVisibilityView(@NonNull TabPlayer player, boolean sendToggleMessage);
|
||||
|
||||
/**
|
||||
* Hides name tag visibility view on all players for specified player.
|
||||
* If the view is already hidden, nothing happens.
|
||||
*
|
||||
* @param player
|
||||
* player to show name tag visibility view for
|
||||
* @param sendToggleMessage
|
||||
* {@code true} if the configured toggle message should be sent, {@code false} if not
|
||||
*/
|
||||
void hideNameTagVisibilityView(@NonNull TabPlayer player, boolean sendToggleMessage);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if player has hidden name tags by either calling
|
||||
* {@link #toggleNameTagVisibilityView(TabPlayer, boolean)} or using a command,
|
||||
|
||||
@@ -17,7 +17,7 @@ public interface Scoreboard {
|
||||
/**
|
||||
* Returns internal name of this scoreboard. Name is defined in registration,
|
||||
* scoreboards from config use name they were defined with. This value is
|
||||
* used internally and in /tab announce scoreboard command.
|
||||
* used internally and in /tab scoreboard announce command.
|
||||
*
|
||||
* @return custom name of this scoreboard
|
||||
*/
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package me.neznamy.tab.api.scoreboard;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Interface allowing work with scoreboards, such as creating,
|
||||
* sending, toggling and modifying.
|
||||
@@ -54,6 +54,29 @@ public interface ScoreboardManager {
|
||||
* @return map of registered scoreboards
|
||||
*/
|
||||
@NotNull Map<String, Scoreboard> getRegisteredScoreboards();
|
||||
|
||||
/**
|
||||
* Removes scoreboard with specified name from list of scoreboards. If it was displayed to anyone,
|
||||
* it will be removed from their display as well. Then, those players will receive a new scoreboard based
|
||||
* on configuration.
|
||||
*
|
||||
* @param name Name of scoreboard to remove
|
||||
* @throws IllegalArgumentException
|
||||
* if scoreboard with such name does not exist
|
||||
*/
|
||||
void removeScoreboard(@NonNull String name);
|
||||
|
||||
/**
|
||||
* Removes scoreboard from list of scoreboards. If it was displayed to anyone,
|
||||
* it will be removed from their display as well. Then, those players will receive a new scoreboard based
|
||||
* on configuration.
|
||||
*
|
||||
* @param scoreboard
|
||||
* Scoreboard to remove
|
||||
* @throws IllegalArgumentException
|
||||
* if specified scoreboard is not registered
|
||||
*/
|
||||
void removeScoreboard(@NonNull Scoreboard scoreboard);
|
||||
|
||||
/**
|
||||
* Displays scoreboard to defined player. This will disable all display
|
||||
|
||||
@@ -27,7 +27,7 @@ public interface TabListFormatManager {
|
||||
* @param prefix
|
||||
* new prefix value
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
* @see #getOriginalPrefix(TabPlayer)
|
||||
* @see #getOriginalRawPrefix(TabPlayer)
|
||||
*/
|
||||
void setPrefix(@NonNull TabPlayer player, @Nullable String prefix);
|
||||
|
||||
@@ -41,7 +41,7 @@ public interface TabListFormatManager {
|
||||
* @param customName
|
||||
* new customName value
|
||||
* @see #getCustomName(TabPlayer)
|
||||
* @see #getOriginalName(TabPlayer)
|
||||
* @see #getOriginalRawName(TabPlayer)
|
||||
*/
|
||||
void setName(@NonNull TabPlayer player, @Nullable String customName);
|
||||
|
||||
@@ -55,7 +55,7 @@ public interface TabListFormatManager {
|
||||
* @param suffix
|
||||
* new suffix value
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
* @see #getOriginalSuffix(TabPlayer)
|
||||
* @see #getOriginalRawSuffix(TabPlayer)
|
||||
*/
|
||||
void setSuffix(@NonNull TabPlayer player, @Nullable String suffix);
|
||||
|
||||
@@ -67,7 +67,7 @@ public interface TabListFormatManager {
|
||||
* player to get custom prefix of
|
||||
* @return player's custom prefix or {@code null} if not defined
|
||||
* @see #setPrefix(TabPlayer, String)
|
||||
* @see #getOriginalPrefix(TabPlayer)
|
||||
* @see #getOriginalRawPrefix(TabPlayer)
|
||||
*/
|
||||
@Nullable String getCustomPrefix(@NonNull TabPlayer player);
|
||||
|
||||
@@ -104,8 +104,11 @@ public interface TabListFormatManager {
|
||||
* @return player's original prefix
|
||||
* @see #setPrefix(TabPlayer, String)
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
* @deprecated Use {@link #getOriginalRawPrefix(TabPlayer)} instead.
|
||||
*/
|
||||
@NotNull String getOriginalPrefix(@NonNull TabPlayer player);
|
||||
@NotNull
|
||||
@Deprecated
|
||||
String getOriginalPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns player's original name applied using plugin's internal logic.
|
||||
@@ -116,8 +119,11 @@ public interface TabListFormatManager {
|
||||
* @return player's original name
|
||||
* @see #setName(TabPlayer, String)
|
||||
* @see #getCustomName(TabPlayer)
|
||||
* @deprecated Use {@link #getOriginalRawName(TabPlayer)} instead.
|
||||
*/
|
||||
@NotNull String getOriginalName(@NonNull TabPlayer player);
|
||||
@NotNull
|
||||
@Deprecated
|
||||
String getOriginalName(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns player's original suffix applied using plugin's internal logic.
|
||||
@@ -128,6 +134,69 @@ public interface TabListFormatManager {
|
||||
* @return player's original suffix
|
||||
* @see #setSuffix(TabPlayer, String)
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
* @deprecated Use {@link #getOriginalRawSuffix(TabPlayer)} instead.
|
||||
*/
|
||||
@NotNull String getOriginalSuffix(@NonNull TabPlayer player);
|
||||
@NotNull
|
||||
@Deprecated
|
||||
String getOriginalSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original prefix assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get original prefix of
|
||||
* @return Original prefix assigned by the plugin's internal logic.
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalRawPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original name assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get original name of
|
||||
* @return Original name assigned by the plugin's internal logic.
|
||||
* @see #getCustomName(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalRawName(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get original suffix of
|
||||
* @return Original suffix assigned by the plugin's internal logic.
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalRawSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original prefix assigned by the plugin using internal logic with all placeholders replaced.
|
||||
* @param player
|
||||
* Player to get replaced original prefix of
|
||||
* @return Original prefix assigned by the plugin's internal logic.
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalReplacedPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original name assigned by the plugin using internal logic with all placeholders replaced.
|
||||
* @param player
|
||||
* Player to get replaced original name of
|
||||
* @return Original name assigned by the plugin's internal logic.
|
||||
* @see #getCustomName(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalReplacedName(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic with all placeholders replaced.
|
||||
* @param player
|
||||
* Player to get replaced original suffix of
|
||||
* @return Original suffix assigned by the plugin's internal logic.
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalReplacedSuffix(@NonNull TabPlayer player);
|
||||
}
|
||||
@@ -3,7 +3,7 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.github.johnrengelman:shadow:8.1.1")
|
||||
implementation("io.freefair.gradle:lombok-plugin:8.6")
|
||||
implementation("fabric-loom:fabric-loom.gradle.plugin:1.8-SNAPSHOT")
|
||||
implementation("com.gradleup.shadow:shadow-gradle-plugin:9.2.2")
|
||||
implementation("io.freefair.gradle:lombok-plugin:9.0.0")
|
||||
implementation("dev.architectury.loom:dev.architectury.loom.gradle.plugin:1.13-SNAPSHOT")
|
||||
}
|
||||
@@ -3,6 +3,9 @@ rootProject.name = "build-logic"
|
||||
dependencyResolutionManagement {
|
||||
repositories {
|
||||
maven("https://maven.fabricmc.net/")
|
||||
maven("https://maven.architectury.dev/")
|
||||
maven("https://maven.minecraftforge.net/")
|
||||
maven("https://maven.neoforged.net/releases/")
|
||||
gradlePluginPortal()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
plugins {
|
||||
id("tab.standard-conventions")
|
||||
id("com.github.johnrengelman.shadow")
|
||||
id("com.gradleup.shadow")
|
||||
}
|
||||
|
||||
tasks.withType<Zip>().configureEach {
|
||||
isZip64 = true
|
||||
}
|
||||
|
||||
tasks {
|
||||
@@ -11,5 +15,10 @@ tasks {
|
||||
relocate("net.kyori.event", "me.neznamy.tab.libs.net.kyori.event")
|
||||
relocate("me.neznamy.yamlassist", "me.neznamy.tab.libs.me.neznamy.yamlassist")
|
||||
relocate("org.yaml.snakeyaml", "me.neznamy.tab.libs.org.yaml.snakeyaml")
|
||||
relocate("redis.clients.jedis", "me.neznamy.tab.libs.redis.clients.jedis")
|
||||
relocate("org.apache.commons.pool2", "me.neznamy.tab.libs.org.apache.commons.pool2")
|
||||
relocate("org.json", "me.neznamy.tab.libs.org.json")
|
||||
relocate("com.rabbitmq", "me.neznamy.tab.libs.com.rabbitmq")
|
||||
relocate("com.saicone.delivery4j", "me.neznamy.tab.libs.com.saicone.delivery4j")
|
||||
}
|
||||
}
|
||||
@@ -4,37 +4,74 @@ plugins {
|
||||
|
||||
allprojects {
|
||||
group = "me.neznamy"
|
||||
version = "5.0.7"
|
||||
version = "5.4.0"
|
||||
description = "An all-in-one solution that works"
|
||||
|
||||
ext.set("id", "tab")
|
||||
ext.set("website", "https://github.com/NEZNAMY/TAB")
|
||||
ext.set("author", "NEZNAMY")
|
||||
ext.set("credits", "Joseph T. McQuigg (JT122406)")
|
||||
}
|
||||
|
||||
val platforms = setOf(
|
||||
projects.bukkit,
|
||||
projects.bungeecord,
|
||||
projects.component,
|
||||
projects.velocity,
|
||||
projects.sponge7,
|
||||
projects.sponge8,
|
||||
projects.fabric,
|
||||
projects.fabric.v1144,
|
||||
projects.fabric.v1182,
|
||||
projects.fabric.v1203,
|
||||
projects.fabric.v1213
|
||||
).map { it.dependencyProject }
|
||||
val platformPaths = setOf(
|
||||
":bukkit",
|
||||
":bukkit:paper_1_20_5",
|
||||
":bukkit:paper_1_21_2",
|
||||
":bukkit:paper_1_21_4",
|
||||
":bukkit:paper_1_21_9",
|
||||
":bukkit:paper_1_21_11",
|
||||
":bukkit:v1_7_R1",
|
||||
":bukkit:v1_7_R2",
|
||||
":bukkit:v1_7_R3",
|
||||
":bukkit:v1_7_R4",
|
||||
":bukkit:v1_8_R1",
|
||||
":bukkit:v1_8_R2",
|
||||
":bukkit:v1_8_R3",
|
||||
":bukkit:v1_9_R1",
|
||||
":bukkit:v1_9_R2",
|
||||
":bukkit:v1_10_R1",
|
||||
":bukkit:v1_11_R1",
|
||||
":bukkit:v1_12_R1",
|
||||
":bukkit:v1_13_R1",
|
||||
":bukkit:v1_13_R2",
|
||||
":bukkit:v1_14_R1",
|
||||
":bukkit:v1_15_R1",
|
||||
":bukkit:v1_16_R1",
|
||||
":bukkit:v1_16_R2",
|
||||
":bukkit:v1_16_R3",
|
||||
":bukkit:v1_17_R1",
|
||||
":bukkit:v1_18_R1",
|
||||
":bukkit:v1_18_R2",
|
||||
":bukkit:v1_19_R1",
|
||||
":bukkit:v1_19_R2",
|
||||
":bukkit:v1_19_R3",
|
||||
":bukkit:v1_20_R1",
|
||||
":bukkit:v1_20_R2",
|
||||
":bukkit:v1_20_R3",
|
||||
":bukkit:v1_20_R4",
|
||||
":bukkit:v1_21_R1",
|
||||
":bukkit:v1_21_R2",
|
||||
":bukkit:v1_21_R3",
|
||||
":bukkit:v1_21_R4",
|
||||
":bukkit:v1_21_R5",
|
||||
":bukkit:v1_21_R6",
|
||||
":bukkit:v1_21_R7",
|
||||
":bungeecord",
|
||||
":velocity",
|
||||
":fabric",
|
||||
":neoforge",
|
||||
":forge"
|
||||
)
|
||||
|
||||
val special = setOf(
|
||||
projects.api,
|
||||
projects.shared
|
||||
).map { it.dependencyProject }
|
||||
val specialPaths = setOf(
|
||||
":api",
|
||||
":shared"
|
||||
)
|
||||
|
||||
subprojects {
|
||||
when (this) {
|
||||
in platforms -> plugins.apply("tab.platform-conventions")
|
||||
in special -> plugins.apply("tab.standard-conventions")
|
||||
when (path) {
|
||||
in platformPaths -> plugins.apply("tab.platform-conventions")
|
||||
in specialPaths -> plugins.apply("tab.standard-conventions")
|
||||
else -> plugins.apply("tab.base-conventions")
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ dependencies {
|
||||
implementation("org.bstats:bstats-bukkit:3.1.0")
|
||||
compileOnly("org.purpurmc.purpur:purpur-api:1.16.5-R0.1-SNAPSHOT")
|
||||
compileOnly("me.clip:placeholderapi:2.11.6")
|
||||
compileOnly("com.mojang:authlib:1.5.25")
|
||||
compileOnly("com.github.MilkBowl:VaultAPI:1.7") {
|
||||
exclude("org.bukkit", "bukkit")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
plugins {
|
||||
id("io.papermc.paperweight.userdev") version "2.0.0-beta.19"
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("https://jitpack.io") // YamlAssist
|
||||
maven("https://repo.opencollab.dev/maven-snapshots/")
|
||||
maven("https://repo.viaversion.com/")
|
||||
maven {
|
||||
name = "luck-repo"
|
||||
url = uri("https://repo.lucko.me/")
|
||||
content {
|
||||
includeModule("me.lucko", "spark-api")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val version = "1.20.6-R0.1-SNAPSHOT" // 1.20.5 has a broken dependency, but there were no changes, so it's ok
|
||||
|
||||
dependencies {
|
||||
implementation(projects.bukkit)
|
||||
paperweight.paperDevBundle(version)
|
||||
compileOnly("io.papermc.paper:paper-api:${version}")
|
||||
}
|
||||
|
||||
tasks.compileJava {
|
||||
options.release.set(21)
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package me.neznamy.tab.platforms.paper_1_20_5;
|
||||
|
||||
import me.neznamy.tab.shared.chat.TabStyle;
|
||||
import me.neznamy.tab.shared.chat.component.object.TabAtlasSprite;
|
||||
import me.neznamy.tab.shared.chat.component.object.TabObjectComponent;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.shared.chat.component.object.TabPlayerSprite;
|
||||
import net.minecraft.network.chat.*;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Component converter using direct mojang-mapped code.
|
||||
*/
|
||||
public class PaperComponentConverter extends ComponentConverter<Component> {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newTextComponent(@NotNull String text) {
|
||||
return Component.literal(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newTranslatableComponent(@NotNull String key) {
|
||||
return Component.translatable(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newKeybindComponent(@NotNull String keybind) {
|
||||
return Component.keybind(keybind);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newObjectComponent(@NotNull TabAtlasSprite sprite) {
|
||||
return Component.literal(TabObjectComponent.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newObjectComponent(@NotNull TabPlayerSprite sprite) {
|
||||
return Component.literal(TabObjectComponent.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyStyle(@NotNull Component nmsComponent, @NotNull TabStyle modifier) {
|
||||
Style style = Style.EMPTY
|
||||
.withColor(modifier.getColor() == null ? null : TextColor.fromRgb(modifier.getColor().getRgb()))
|
||||
.withBold(modifier.getBold())
|
||||
.withItalic(modifier.getItalic())
|
||||
.withUnderlined(modifier.getUnderlined())
|
||||
.withStrikethrough(modifier.getStrikethrough())
|
||||
.withObfuscated(modifier.getObfuscated())
|
||||
.withFont(modifier.getFont() == null ? null : ResourceLocation.tryParse(modifier.getFont()));
|
||||
((MutableComponent)nmsComponent).setStyle(style);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSibling(@NotNull Component parent, @NotNull Component child) {
|
||||
((MutableComponent)parent).append(child);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package me.neznamy.tab.platforms.paper_1_20_5;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.util.function.FunctionWithException;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Implementation provider using direct Mojang-mapped NMS code for versions 1.20.5 - 1.21.1.
|
||||
*/
|
||||
@Getter
|
||||
public class PaperImplementationProvider implements ImplementationProvider {
|
||||
|
||||
@NotNull
|
||||
private final ComponentConverter<?> componentConverter = new PaperComponentConverter();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Scoreboard newScoreboard(@NotNull BukkitTabPlayer player) {
|
||||
return new PaperPacketScoreboard(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
return new PaperPacketTabList(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public FunctionWithException<BukkitTabPlayer, Channel> getChannelFunction() {
|
||||
return player -> ((CraftPlayer)player.getPlayer()).getHandle().connection.connection.channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPing(@NotNull BukkitTabPlayer player) {
|
||||
return player.getPlayer().getPing();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package me.neznamy.tab.platforms.paper_1_20_5;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.platform.decorators.SafeScoreboard;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.numbers.FixedFormat;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.*;
|
||||
import net.minecraft.world.scores.PlayerTeam;
|
||||
import net.minecraft.world.scores.Scoreboard;
|
||||
import net.minecraft.world.scores.criteria.ObjectiveCriteria;
|
||||
import net.minecraft.world.scores.criteria.ObjectiveCriteria.RenderType;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Scoreboard implementation using direct mojang-mapped code.
|
||||
*/
|
||||
public class PaperPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
|
||||
private static final ChatFormatting[] formats = ChatFormatting.values();
|
||||
private static final net.minecraft.world.scores.Team.CollisionRule[] collisions = net.minecraft.world.scores.Team.CollisionRule.values();
|
||||
private static final net.minecraft.world.scores.Team.Visibility[] visibilities = net.minecraft.world.scores.Team.Visibility.values();
|
||||
private static final Scoreboard dummyScoreboard = new Scoreboard();
|
||||
private static final Field players = ReflectionUtils.getOnlyField(ClientboundSetPlayerTeamPacket.class, Collection.class);
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
* @param player
|
||||
* Player this scoreboard will belong to
|
||||
*/
|
||||
public PaperPacketScoreboard(@NotNull BukkitTabPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerObjective(@NonNull Objective objective) {
|
||||
net.minecraft.world.scores.Objective obj = new net.minecraft.world.scores.Objective(
|
||||
dummyScoreboard,
|
||||
objective.getName(),
|
||||
ObjectiveCriteria.DUMMY,
|
||||
objective.getTitle().convert(),
|
||||
RenderType.values()[objective.getHealthDisplay().ordinal()],
|
||||
false,
|
||||
objective.getNumberFormat() == null ? null : objective.getNumberFormat().toFixedFormat(FixedFormat::new)
|
||||
);
|
||||
objective.setPlatformObjective(obj);
|
||||
sendPacket(new ClientboundSetObjectivePacket(obj, ObjectiveAction.REGISTER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplaySlot(@NonNull Objective objective) {
|
||||
sendPacket(new ClientboundSetDisplayObjectivePacket(
|
||||
net.minecraft.world.scores.DisplaySlot.values()[objective.getDisplaySlot().ordinal()],
|
||||
(net.minecraft.world.scores.Objective) objective.getPlatformObjective()
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterObjective(@NonNull Objective objective) {
|
||||
sendPacket(new ClientboundSetObjectivePacket((net.minecraft.world.scores.Objective) objective.getPlatformObjective(), ObjectiveAction.UNREGISTER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateObjective(@NonNull Objective objective) {
|
||||
net.minecraft.world.scores.Objective obj = (net.minecraft.world.scores.Objective) objective.getPlatformObjective();
|
||||
obj.setDisplayName(objective.getTitle().convert());
|
||||
obj.setRenderType(RenderType.values()[objective.getHealthDisplay().ordinal()]);
|
||||
sendPacket(new ClientboundSetObjectivePacket(obj, ObjectiveAction.UPDATE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScore(@NonNull Score score) {
|
||||
sendPacket(new ClientboundSetScorePacket(
|
||||
score.getHolder(),
|
||||
score.getObjective().getName(),
|
||||
score.getValue(),
|
||||
Optional.ofNullable(score.getDisplayName() == null ? null : score.getDisplayName().convert()),
|
||||
Optional.ofNullable(score.getNumberFormat() == null ? null : score.getNumberFormat().toFixedFormat(FixedFormat::new))
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeScore(@NonNull Score score) {
|
||||
sendPacket(new ClientboundResetScorePacket(score.getHolder(), score.getObjective().getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Object createTeam(@NonNull String name) {
|
||||
return new PlayerTeam(dummyScoreboard, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTeam(@NonNull Team team) {
|
||||
updateTeamProperties(team);
|
||||
PlayerTeam t = (PlayerTeam) team.getPlatformTeam();
|
||||
t.getPlayers().addAll(team.getPlayers());
|
||||
sendPacket(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(t, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterTeam(@NonNull Team team) {
|
||||
sendPacket(ClientboundSetPlayerTeamPacket.createRemovePacket((PlayerTeam) team.getPlatformTeam()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTeam(@NonNull Team team) {
|
||||
updateTeamProperties(team);
|
||||
sendPacket(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket((PlayerTeam) team.getPlatformTeam(), false));
|
||||
}
|
||||
|
||||
private void updateTeamProperties(@NonNull Team team) {
|
||||
PlayerTeam t = (PlayerTeam) team.getPlatformTeam();
|
||||
t.setAllowFriendlyFire((team.getOptions() & 0x01) != 0);
|
||||
t.setSeeFriendlyInvisibles((team.getOptions() & 0x02) != 0);
|
||||
t.setColor(formats[team.getColor().ordinal()]);
|
||||
t.setCollisionRule(collisions[team.getCollision().ordinal()]);
|
||||
t.setNameTagVisibility(visibilities[team.getVisibility().ordinal()]);
|
||||
t.setPlayerPrefix(team.getPrefix().convert());
|
||||
t.setPlayerSuffix(team.getSuffix().convert());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@NotNull
|
||||
public Object onPacketSend(@NonNull Object packet) {
|
||||
if (packet instanceof ClientboundSetDisplayObjectivePacket display) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(player, display.getSlot().ordinal(), display.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetObjectivePacket objective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(player, objective.getMethod(), objective.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetPlayerTeamPacket team) {
|
||||
int action = getMethod(team);
|
||||
if (action != TeamAction.UPDATE) {
|
||||
players.set(team, onTeamPacket(action, team.getName(), team.getPlayers() == null ? Collections.emptyList() : team.getPlayers()));
|
||||
}
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
private int getMethod(@NonNull ClientboundSetPlayerTeamPacket team) {
|
||||
if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 0;
|
||||
} else if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 1;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 3;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the packet to the player.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to send
|
||||
*/
|
||||
private void sendPacket(@NotNull Packet<?> packet) {
|
||||
((CraftPlayer)player.getPlayer()).getHandle().connection.sendPacket(packet);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
package me.neznamy.tab.platforms.paper_1_20_5;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.platform.decorators.TrackedTabList;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundTabListPacket;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* TabList implementation using direct mojang-mapped code.
|
||||
*/
|
||||
public class PaperPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> addPlayer = EnumSet.allOf(ClientboundPlayerInfoUpdatePacket.Action.class);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateDisplayName = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateLatency = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateGameMode = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateListed = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED);
|
||||
|
||||
/**
|
||||
* Constructs new instance.
|
||||
*
|
||||
* @param player
|
||||
* Player this tablist will belong to
|
||||
*/
|
||||
public PaperPacketTabList(@NotNull BukkitTabPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeEntry(@NonNull UUID entry) {
|
||||
sendPacket(new ClientboundPlayerInfoRemovePacket(Collections.singletonList(entry)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDisplayName0(@NonNull UUID entry, @Nullable TabComponent displayName) {
|
||||
sendPacket(updateDisplayName, entry, "", null, false, 0, 0, displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLatency(@NonNull UUID entry, int latency) {
|
||||
sendPacket(updateLatency, entry, "", null, false, latency, 0, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGameMode(@NonNull UUID entry, int gameMode) {
|
||||
sendPacket(updateGameMode, entry, "", null, false, 0, gameMode, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
sendPacket(updateListed, entry, "", null, listed, 0, 0, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListOrder(@NonNull UUID entry, int listOrder) {
|
||||
// Added in 1.21.2
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateHat(@NonNull UUID entry, boolean showHat) {
|
||||
// Added in 1.21.4
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull Entry entry) {
|
||||
sendPacket(addPlayer, entry.getUniqueId(), entry.getName(), entry.getSkin(), entry.isListed(), entry.getLatency(),
|
||||
entry.getGameMode(), entry.getDisplayName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerListHeaderFooter0(@NonNull TabComponent header, @NonNull TabComponent footer) {
|
||||
sendPacket(new ClientboundTabListPacket(header.convert(), footer.convert()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsEntry(@NonNull UUID entry) {
|
||||
return true; // TODO?
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Skin getSkin() {
|
||||
Collection<Property> properties = ((CraftPlayer)player.getPlayer()).getProfile().getProperties().get(TEXTURES_PROPERTY);
|
||||
if (properties.isEmpty()) return null; // Offline mode
|
||||
Property property = properties.iterator().next();
|
||||
return new Skin(property.value(), property.signature());
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Object onPacketSend(@NonNull Object packet) {
|
||||
if (packet instanceof ClientboundTabListPacket tablist) {
|
||||
if (header == null || footer == null) return packet;
|
||||
if (tablist.header() != header.convert() || tablist.footer() != footer.convert()) {
|
||||
return new ClientboundTabListPacket(header.convert(), footer.convert());
|
||||
}
|
||||
}
|
||||
if (packet instanceof ClientboundPlayerInfoUpdatePacket info) {
|
||||
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions = info.actions();
|
||||
List<ClientboundPlayerInfoUpdatePacket.Entry> updatedList = new ArrayList<>();
|
||||
boolean rewritePacket = false;
|
||||
for (ClientboundPlayerInfoUpdatePacket.Entry nmsData : info.entries()) {
|
||||
boolean rewriteEntry = false;
|
||||
Component displayName = nmsData.displayName();
|
||||
int latency = nmsData.latency();
|
||||
int gameMode = nmsData.gameMode().getId();
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME)) {
|
||||
TabComponent forcedDisplayName = getForcedDisplayNames().get(nmsData.profileId());
|
||||
if (forcedDisplayName != null && forcedDisplayName.convert() != displayName) {
|
||||
displayName = forcedDisplayName.convert();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE)) {
|
||||
if (getBlockedSpectators().contains(nmsData.profileId()) && gameMode == 3) {
|
||||
gameMode = 0;
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY)) {
|
||||
if (getForcedLatency() != null) {
|
||||
latency = getForcedLatency();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER)) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(player, nmsData.profileId(), nmsData.profile().getName());
|
||||
}
|
||||
updatedList.add(rewriteEntry ? new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
nmsData.profileId(), nmsData.profile(), nmsData.listed(), latency, GameType.byId(gameMode), displayName,
|
||||
nmsData.chatSession()
|
||||
) : nmsData);
|
||||
}
|
||||
if (rewritePacket) return new ClientboundPlayerInfoUpdatePacket(actions, updatedList);
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
private void sendPacket(@NonNull EnumSet<ClientboundPlayerInfoUpdatePacket.Action> action, @NonNull UUID id, @NonNull String name, @Nullable Skin skin,
|
||||
boolean listed, int latency, int gameMode, @Nullable TabComponent displayName) {
|
||||
ClientboundPlayerInfoUpdatePacket packet = new ClientboundPlayerInfoUpdatePacket(action, new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
id,
|
||||
action.contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER) ? createProfile(id, name, skin) : null,
|
||||
listed,
|
||||
latency,
|
||||
GameType.byId(gameMode),
|
||||
displayName == null ? null : displayName.convert(),
|
||||
null
|
||||
));
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates GameProfile from given parameters.
|
||||
*
|
||||
* @param id
|
||||
* Profile ID
|
||||
* @param name
|
||||
* Profile name
|
||||
* @param skin
|
||||
* Player skin
|
||||
* @return GameProfile from given parameters
|
||||
*/
|
||||
@NotNull
|
||||
private GameProfile createProfile(@NonNull UUID id, @NonNull String name, @Nullable Skin skin) {
|
||||
GameProfile profile = new GameProfile(id, name);
|
||||
if (skin != null) {
|
||||
profile.getProperties().put(TabList.TEXTURES_PROPERTY,
|
||||
new Property(TabList.TEXTURES_PROPERTY, skin.getValue(), skin.getSignature()));
|
||||
}
|
||||
return profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the packet to the player.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to send
|
||||
*/
|
||||
private void sendPacket(@NotNull Packet<?> packet) {
|
||||
((CraftPlayer)player.getPlayer()).getHandle().connection.send(packet);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
plugins {
|
||||
id("io.papermc.paperweight.userdev") version "2.0.0-beta.19"
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("https://jitpack.io") // YamlAssist
|
||||
maven("https://repo.opencollab.dev/maven-snapshots/")
|
||||
maven("https://repo.viaversion.com/")
|
||||
maven {
|
||||
name = "luck-repo"
|
||||
url = uri("https://repo.lucko.me/")
|
||||
content {
|
||||
includeModule("me.lucko", "spark-api")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val version = "1.21.11-R0.1-SNAPSHOT"
|
||||
|
||||
dependencies {
|
||||
implementation(projects.bukkit)
|
||||
paperweight.paperDevBundle(version)
|
||||
compileOnly("io.papermc.paper:paper-api:${version}")
|
||||
}
|
||||
|
||||
tasks.compileJava {
|
||||
options.release.set(21)
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package me.neznamy.tab.platforms.paper_1_21_11;
|
||||
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import com.mojang.authlib.properties.PropertyMap;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.shared.chat.TabStyle;
|
||||
import me.neznamy.tab.shared.chat.component.object.TabAtlasSprite;
|
||||
import me.neznamy.tab.shared.chat.component.object.TabPlayerSprite;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import net.minecraft.network.chat.*;
|
||||
import net.minecraft.network.chat.contents.objects.AtlasSprite;
|
||||
import net.minecraft.network.chat.contents.objects.PlayerSprite;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.world.item.component.ResolvableProfile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Component converter using direct mojang-mapped code.
|
||||
*/
|
||||
public class PaperComponentConverter extends ComponentConverter<Component> {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newTextComponent(@NotNull String text) {
|
||||
return Component.literal(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newTranslatableComponent(@NotNull String key) {
|
||||
return Component.translatable(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newKeybindComponent(@NotNull String keybind) {
|
||||
return Component.keybind(keybind);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newObjectComponent(@NotNull TabAtlasSprite sprite) {
|
||||
return Component.object(new AtlasSprite(Identifier.parse(sprite.getAtlas()), Identifier.parse(sprite.getSprite())));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newObjectComponent(@NotNull TabPlayerSprite sprite) {
|
||||
ResolvableProfile profile;
|
||||
if (sprite.getId() != null) {
|
||||
profile = ResolvableProfile.createUnresolved(sprite.getId());
|
||||
} else if (sprite.getName() != null) {
|
||||
profile = ResolvableProfile.createUnresolved(sprite.getName());
|
||||
} else if (sprite.getSkin() != null) {
|
||||
ImmutableMultimap.Builder<String, Property> builder = ImmutableMultimap.builder();
|
||||
builder.put(TabList.TEXTURES_PROPERTY, new Property(TabList.TEXTURES_PROPERTY, sprite.getSkin().getValue(), sprite.getSkin().getSignature()));
|
||||
profile = ResolvableProfile.createResolved(new GameProfile(NIL_UUID, "", new PropertyMap(builder.build())));
|
||||
} else {
|
||||
throw new IllegalStateException("Player head component does not have id, name or skin set");
|
||||
}
|
||||
return Component.object(new PlayerSprite(profile, sprite.isShowHat()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyStyle(@NotNull Component nmsComponent, @NotNull TabStyle modifier) {
|
||||
Style style = Style.EMPTY
|
||||
.withColor(modifier.getColor() == null ? null : TextColor.fromRgb(modifier.getColor().getRgb()))
|
||||
.withBold(modifier.getBold())
|
||||
.withItalic(modifier.getItalic())
|
||||
.withUnderlined(modifier.getUnderlined())
|
||||
.withStrikethrough(modifier.getStrikethrough())
|
||||
.withObfuscated(modifier.getObfuscated())
|
||||
.withFont(modifier.getFont() == null ? null : new FontDescription.Resource(Identifier.parse(modifier.getFont())));
|
||||
if (modifier.getShadowColor() != null) style = style.withShadowColor(modifier.getShadowColor()); // withShadowColor takes int instead of Integer, bug?
|
||||
((MutableComponent)nmsComponent).setStyle(style);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSibling(@NotNull Component parent, @NotNull Component child) {
|
||||
((MutableComponent)parent).append(child);
|
||||
}
|
||||
}
|
||||