Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6c8d24177 | ||
|
|
ab3bd61d3c | ||
|
|
6a5cee8f0e | ||
|
|
549732fc8b | ||
|
|
09d400c6fb | ||
|
|
7e1cdafa78 | ||
|
|
434c0216d5 | ||
|
|
d5a0ae8e71 | ||
|
|
79e56c6a30 | ||
|
|
11cc1c3f25 | ||
|
|
8b343bcfb6 | ||
|
|
ecd83beb7d | ||
|
|
438f21fb11 | ||
|
|
dd1524cf31 | ||
|
|
0f85aa5384 | ||
|
|
4644a0ae96 | ||
|
|
84b3efe0fc | ||
|
|
511acbd5ff | ||
|
|
8749b3b354 | ||
|
|
b66e63d242 | ||
|
|
ba951238c3 | ||
|
|
a4eb76f1cf | ||
|
|
c486899dcf | ||
|
|
b212f0d5be | ||
|
|
caa534ff7f | ||
|
|
9c2fac6749 | ||
|
|
2a4f918a10 | ||
|
|
b45e2afe4c | ||
|
|
2c7237e5d9 | ||
|
|
26477e3150 | ||
|
|
cba8cb57d5 | ||
|
|
599b4822e5 | ||
|
|
fbd150b353 | ||
|
|
10b252e934 | ||
|
|
e9dfcdeb10 | ||
|
|
9cb2f27754 | ||
|
|
a090a83b7d | ||
|
|
992e661e4c | ||
|
|
3b993d114e | ||
|
|
d181d62466 | ||
|
|
968cef7a12 | ||
|
|
390c2395eb | ||
|
|
adc9444794 | ||
|
|
f086318082 | ||
|
|
1cef4400b9 | ||
|
|
1f879ac91e | ||
|
|
bec129d98e | ||
|
|
152c04e68f | ||
|
|
d6cdacef43 | ||
|
|
09891a075d | ||
|
|
9500bab5b7 | ||
|
|
231edd4bd4 | ||
|
|
433572e759 | ||
|
|
3ec772e87f | ||
|
|
ae8287157c | ||
|
|
f005907b41 | ||
|
|
8ea16044f1 | ||
|
|
e787a28353 | ||
|
|
6925d9564c | ||
|
|
ccd4ea785a | ||
|
|
63e88c09d4 | ||
|
|
296191b502 | ||
|
|
af0151f446 | ||
|
|
2bdfaa167e | ||
|
|
cd96476f9e | ||
|
|
9b0545aa1a | ||
|
|
63823123f8 | ||
|
|
e91728be98 | ||
|
|
e7ecbf1245 | ||
|
|
28c2363b67 | ||
|
|
21a3d4fb55 | ||
|
|
4b459a3ed1 | ||
|
|
ebc6a1b842 | ||
|
|
b72b0f269a | ||
|
|
4cbcd69ed2 | ||
|
|
6ef8b7748c | ||
|
|
8b567cb976 | ||
|
|
d8c231b9ce | ||
|
|
cc4347c881 | ||
|
|
7cc572feb5 | ||
|
|
96d1d1feb4 | ||
|
|
a7d9bd9ab5 | ||
|
|
1cdfdf1d43 | ||
|
|
0762a5e689 | ||
|
|
3e2906ccf8 | ||
|
|
13761e032c | ||
|
|
fb8fa3fa54 | ||
|
|
b89bf5933b | ||
|
|
1c4f404fd2 | ||
|
|
9fe1560f1a | ||
|
|
6a9cca37c6 | ||
|
|
bfde75d4b1 | ||
|
|
a83f98580d | ||
|
|
673542d8e4 | ||
|
|
81c5d89a25 | ||
|
|
bf0bcb0b96 | ||
|
|
ac7a664303 | ||
|
|
182dc67a49 | ||
|
|
27ee82d17c | ||
|
|
9405e4e45d | ||
|
|
8616769e32 | ||
|
|
5d85c4697b | ||
|
|
c54a2b7353 | ||
|
|
35075e88e3 | ||
|
|
1266d34176 | ||
|
|
66ddf0e3ca | ||
|
|
88ab129737 | ||
|
|
bcd293a255 | ||
|
|
4a5ebe6dbd | ||
|
|
ef1c3b1b3b | ||
|
|
f7e68ffb6b | ||
|
|
2cf2153c4d | ||
|
|
7e7d0025fa | ||
|
|
8252b6486e | ||
|
|
378041cb16 | ||
|
|
ee5ff07565 | ||
|
|
80c63dd414 | ||
|
|
e182366566 | ||
|
|
acee89cce3 | ||
|
|
3ef3d14c10 | ||
|
|
74365780a7 | ||
|
|
f6ad80370f | ||
|
|
87eb544936 | ||
|
|
cde0389380 | ||
|
|
9e46ffc4e1 | ||
|
|
f3c35de780 | ||
|
|
75f5378c8c | ||
|
|
19d32127e8 | ||
|
|
2f00aa7750 | ||
|
|
07f5dc68b5 | ||
|
|
96a39d7037 | ||
|
|
409f1c4230 | ||
|
|
c3d2f9aeea | ||
|
|
380b3dd1f6 | ||
|
|
c15a6009a2 | ||
|
|
e4e7c364fd | ||
|
|
438361eed2 | ||
|
|
684b35f2df | ||
|
|
1d603ae76f | ||
|
|
a342b23890 | ||
|
|
c0dde2eaa7 | ||
|
|
6245fe9553 | ||
|
|
fb5be9e2aa | ||
|
|
918620a7dc | ||
|
|
d2855449f0 | ||
|
|
f59326c0ae | ||
|
|
033b9ed035 | ||
|
|
5c299767ec | ||
|
|
818701cd07 | ||
|
|
9b5e63aa25 | ||
|
|
1ad285bd79 | ||
|
|
4507bb179a | ||
|
|
2dd79295a9 | ||
|
|
b21d840e60 | ||
|
|
f3fa40bb0a | ||
|
|
d8e14de0cf | ||
|
|
f7b96eceeb | ||
|
|
6f760939f3 | ||
|
|
5273ad0c5f | ||
|
|
ac12abfb8b | ||
|
|
e5146e7f53 | ||
|
|
62d1210872 | ||
|
|
0d0177cd40 | ||
|
|
227ecf9c9d | ||
|
|
562cd50762 | ||
|
|
ec56d530a6 | ||
|
|
6350714508 | ||
|
|
1b251dad6a | ||
|
|
7765b51a55 | ||
|
|
ff6ba6a8e9 | ||
|
|
ce3485c823 | ||
|
|
90a99d3a79 | ||
|
|
7248dc4fef | ||
|
|
d704db55fa | ||
|
|
0f581e47b1 |
No files matched your search
@@ -0,0 +1,14 @@
|
||||
# About
|
||||
This folder contains the plugin's description as advertised on various marketplaces which use various syntaxes
|
||||
(bbcode, markdown).
|
||||
|
||||
While this is not an accurate folder to have this stored in (`.github`),
|
||||
it is the closest if we don't want to create a folder for this in the root.
|
||||
|
||||
The file structure of this folder is as following:
|
||||
|
||||
| File name | Description |
|
||||
|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| images | Folder containing all images used in the descriptions and wiki for advertising. Used not only as a backup, but for hosting them as well, so we do not need to rely on third party websites. |
|
||||
| description_markdown.md | Plugin description written in **markdown** syntax. Used by **Modrinth**. |
|
||||
| description_bbcode.txt | Plugin description written in **bbcode** syntax. Used by **SpigotMC** and **BuiltByBit**. |
|
||||
@@ -0,0 +1,178 @@
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Section_About.png[/IMG]
|
||||
TAB is an all-in-one plugin for displaying information in various places, which aims to outperform all similar plugins in terms of features, compatibility and performance.
|
||||
The compact configuration allows you to get the plugin to work the way you want regardless of how simple or complex you want it to be or how experienced you are. The default configuration already contains useful values and examples to give you a better understanding and get you started quickly with instant results. The extensive [URL='https://github.com/NEZNAMY/TAB/wiki']wiki[/URL] answers any of your questions.
|
||||
|
||||
[IMG]https://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]
|
||||
[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]
|
||||
[CENTER][B][SIZE=7]Discord?[/SIZE][/B][/CENTER]
|
||||
Official support by me is no longer provided to free users due to limited time and extreme inefficiency (see [URL='https://github.com/NEZNAMY/TAB?tab=readme-ov-file#provided-services']provided services[/URL] for more info).
|
||||
However, you can join this [URL='https://discord.gg/YPqXt63YQj']fresh new community discord[/URL] made by a nice person who promises to help everyone with all plugins, including TAB.
|
||||
|
||||
Before you consider requiring assistance, check out the [URL='https://github.com/NEZNAMY/TAB/wiki']wiki[/URL] first. It will answer any questions you may have and is also constantly getting improved.
|
||||
|
||||
[CENTER][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Section_Features.png[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/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]
|
||||
@@ -0,0 +1,165 @@
|
||||

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

|
||||

|
||||

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

|
||||

|
||||

|
||||
* 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
|
||||
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 236 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 94 KiB |
@@ -23,7 +23,6 @@
|
||||
* [Sorting in tablist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Sorting-players-in-tablist)
|
||||
* [Spectator fix](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Spectator-fix)
|
||||
* [Tablist name formatting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Tablist-name-formatting)
|
||||
* [Unlimited nametag mode](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Unlimited-nametag-mode)
|
||||
|
||||
## Functions
|
||||
* [Animations](https://github.com/NEZNAMY/TAB/wiki/Animations)
|
||||
@@ -35,13 +34,13 @@
|
||||
* [RGB/font usage](https://github.com/NEZNAMY/TAB/wiki/How-to-use-RGB-color-codes)
|
||||
|
||||
## Other
|
||||
* [Client-sided mechanics](https://github.com/NEZNAMY/TAB/wiki/Client%E2%80%90sided-mechanics)
|
||||
* [Quick PlaceholderAPI startup guide](https://github.com/NEZNAMY/TAB/wiki/Quick-PlaceholderAPI-startup-guide)
|
||||
* [How to setup compatibility with glow plugins](https://github.com/NEZNAMY/TAB/wiki/How-to-make-TAB-compatible-with-glow-plugins)
|
||||
* [How to display name from nickname plugins](https://github.com/NEZNAMY/TAB/wiki/How-to-display-name-from-nickname-plugins)
|
||||
* [How to configure weights in LuckPerms](https://github.com/NEZNAMY/TAB/wiki/How-to-setup-weights-priorities)
|
||||
* [How to save config in UTF-8 encoding](https://github.com/NEZNAMY/TAB/wiki/How-to-save-the-config-in-UTF8-encoding)
|
||||
* [Mini guides collection](https://github.com/NEZNAMY/TAB/wiki/Mini-guides-collection)
|
||||
* [Additional information](https://github.com/NEZNAMY/TAB/wiki/Additional-information)
|
||||
* [Bedrock compatibility](https://github.com/NEZNAMY/TAB/wiki/Bedrock-compatibility)
|
||||
* [Client-sided mechanics](https://github.com/NEZNAMY/TAB/wiki/Client%E2%80%90sided-mechanics)
|
||||
* [Developer API](https://github.com/NEZNAMY/TAB/wiki/Developer-API)
|
||||
* [How to display name from nickname plugins](https://github.com/NEZNAMY/TAB/wiki/How-to-display-name-from-nickname-plugins)
|
||||
* [How to save config in UTF-8 encoding](https://github.com/NEZNAMY/TAB/wiki/How-to-save-the-config-in-UTF8-encoding)
|
||||
* [How to set up compatibility with glow plugins](https://github.com/NEZNAMY/TAB/wiki/How-to-make-TAB-compatible-with-glow-plugins)
|
||||
* [Mini guides collection](https://github.com/NEZNAMY/TAB/wiki/Mini-guides-collection)
|
||||
* [Optimizing plugin's CPU usage](https://github.com/NEZNAMY/TAB/wiki/Optimizing-the-plugin)
|
||||
* [Developer API](https://github.com/NEZNAMY/TAB/wiki/Developer-API)
|
||||
* [Quick PlaceholderAPI startup guide](https://github.com/NEZNAMY/TAB/wiki/Quick-PlaceholderAPI-startup-guide)
|
||||
@@ -2,47 +2,18 @@
|
||||
This is a collection of random information about the plugin not necessarily limited to a single feature or function.
|
||||
|
||||
# Content
|
||||
* [Bedrock compatibility](#bedrock-compatibility)
|
||||
* [Detection](#detection)
|
||||
* [Differences](#differences)
|
||||
* [Issues with `.` in name](#issues-with--in-name)
|
||||
* [Vanish detection](#vanish-detection)
|
||||
* [Async player loading](#async-player-loading)
|
||||
* [Scoreboard objective and team naming](#scoreboard-objective-and-team-naming)
|
||||
* [Per-version experience](#per-version-experience)
|
||||
* [Detection](#detection-1)
|
||||
* [Differences](#differences-1)
|
||||
* [Detection](#detection)
|
||||
* [Differences](#differences)
|
||||
* [Debug config option](#debug-config-option)
|
||||
|
||||
# Bedrock compatibility
|
||||
## Detection
|
||||
For TAB to properly detect player as a bedrock player, floodgate and TAB must be installed on the same server instance and if TAB is on bukkit and floodgate is on both bungeecord and bukkit, make sure [they are connected](https://geysermc.org/wiki/floodgate/setup/?platform=proxy-servers).
|
||||
|
||||
To make sure floodgate is configured correctly you have 2 options:
|
||||
* Set `debug: true` in TAB config and check console output on join/reload. It should say `Floodgate returned bedrock status TRUE for player <player>`.
|
||||
* Run `/tab parse <player> %bedrock%`. It should return `true`.
|
||||
|
||||
If any of them say `false` for an actual bedrock player, you didn't connect floodgate correctly.
|
||||
|
||||
## Differences
|
||||
It is job of plugin allowing bedrock clients to connect (probably Geyser) to correctly translate all packets. If you are experiencing an issue on bedrock but not java, it is most likely not an issue in TAB code.
|
||||
|
||||
Currently, TAB does check for bedrock clients for:
|
||||
* Displaying scoreboard numbers as 1-15 instead of all 0 even if it's set to all 0, because lines would not be ordered correctly.
|
||||
* Disabling [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) for bedrock players.
|
||||
* Disabling [Playerlist objective](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Playerlist-Objective) for bedrock players due to many issues with the feature on bedrock.
|
||||
|
||||
These are the only 3 known changes that are required on TAB side.
|
||||
|
||||
## Issues with `.` in name
|
||||
If you configured Geyser to prefix bedrock player names with `.`, it will mess up config loading, because `.` is used to split section path. This means that using `/tab player <playername containing .> ...` will not work.
|
||||
There are 3 solutions available:
|
||||
* Use player UUID if commands are executed via another plugin (`/tab player <uuid> ...`).
|
||||
* Use `playeruuid` type, which accepts player name and saves the online player's UUID (`/tab playeruuid <player name> ...`).
|
||||
* Use a different username prefix than `.`.
|
||||
|
||||
# Vanish detection
|
||||
Although TAB does not manage player vanishing in any way, it checks for vanish status for features to be properly compatible. At the moment, vanishing detection is used for:
|
||||
Although TAB does not manage vanishing players in any way,
|
||||
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.
|
||||
@@ -54,17 +25,27 @@ Permission `tab.seevanished` allows players to:
|
||||
* 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.
|
||||
|
||||
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, [Bridge](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge) must be installed on backend servers to forward vanish status to the proxy.
|
||||
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,
|
||||
[Bridge](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge) must be installed on backend servers
|
||||
to forward vanish status to the proxy.
|
||||
|
||||
Additionally, if PremiumVanish is installed and player's vanish status changes, it is asked if the vanished player can be seen by each player. Players who are marked as being able to see that vanished player by PV do not require `tab.seevaninished` permission.
|
||||
Additionally, if PremiumVanish is installed and vanish status of a player changes,
|
||||
it is asked if the vanished player can be seen by each player.
|
||||
Players who are marked as being able to see that vanished player by PV do not require `tab.seevaninished` permission.
|
||||
|
||||
# Async player loading
|
||||
In order to not slow down the server, TAB loads players asynchronously on join. As a casual user this does not impact you, but there are some cases where you'll feel it:
|
||||
To not slow down the server, TAB loads players asynchronously on join.
|
||||
As a casual user, this does not impact you, but there are some cases where you'll feel it:
|
||||
* Players will not be accessible in the [API](https://github.com/NEZNAMY/TAB/wiki/Developer-API) during PlayerJoinEvent
|
||||
* [TAB's PlaceholderAPI expansion](https://github.com/NEZNAMY/TAB/wiki/Placeholders#placeholderapi) will not be accessible during join process, such as when trying to use it in plugins editing join messages (the exception is `replace_` placeholder, which doesn't directly use any TAB code).
|
||||
* [TAB's PlaceholderAPI expansion](https://github.com/NEZNAMY/TAB/wiki/Placeholders#placeholderapi) will not be accessible during the join process, such as when trying to use it in plugins editing join messages (the exception is `replace_` placeholder, which doesn't directly use any TAB code).
|
||||
|
||||
# Scoreboard objective and team naming
|
||||
There's a well known BungeeCord bug that kicks players if a duplicate team or objective is registered. This message also shows the name of the objective/team. Before reporting this, make sure it actually comes from TAB.
|
||||
There's a well-known BungeeCord bug that kicks players if a duplicate team or objective is registered.
|
||||
This message also shows the name of the objective/team.
|
||||
Before reporting this, make sure it actually comes from TAB.
|
||||
|
||||
TAB's objective and team naming:
|
||||
* Objectives ("Objective ... already exists in this scoreboard")
|
||||
@@ -72,56 +53,55 @@ TAB's objective and team naming:
|
||||
* `TAB-Scoreboard` for [Scoreboard](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Scoreboard)
|
||||
* `TAB-PlayerList` for [Playerlist objective](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Playerlist-Objective)
|
||||
* Teams ("Team ... already exists in this scoreboard")
|
||||
* For sidebar scoreboard: `TAB-SB-TM-x` where `x` is a number from 1 to 15+ (for each line)
|
||||
* For players: This is more complicated to use the 16 character limit to the max and heavily depends on configuration. If you are sorting by player names, part of player name will be there. It also often contains random non-alphanumeric symbols. The most reliable way is the team name (almost) always ending with `A` (or `B`, `C` etc if you tried to sort several players into the same slot).
|
||||
* For sidebar scoreboard: `TAB-Sidebar-x` where `x` is a number from 1 to 15+ (for each line)
|
||||
* For players: This is more complicated to use the 16-character limit to the max and heavily depends on configuration. If you are sorting by player names, part of player name will be there. It also often contains random non-alphanumeric symbols. The most reliable way is the team name (almost) always ending with `A` (or `B`, `C` etc. if you tried to sort several players into the same slot).
|
||||
|
||||
# Per-version experience
|
||||
Minecraft has changed over the years - it had some limits removed, some added, some bugs fixed, but also some bugs added. TAB adapts code based on player's version for best possible experience on each minecraft version.
|
||||
Minecraft has changed over the years.
|
||||
It had some limits removed, some added, some bugs fixed, but also some bugs added.
|
||||
TAB adapts code based on player's version for the best possible experience on each minecraft version.
|
||||
|
||||
## Detection
|
||||
When TAB is installed on a proxy, the proxy's API is used to get player version.
|
||||
When TAB is installed on a proxy, the proxy's API is used to get player's version.
|
||||
When TAB is installed on a backend server, ViaVersion's API is used to get player's version (as it's the only plugin allowing multiple versions, ProtocolSupport is abandoned).
|
||||
|
||||
You can check what version the plugin thinks player has using any of the following:
|
||||
* `/tab parse <player> %player-version%` - Returns version name, if multiple versions share the same protocol, the newer one is returned
|
||||
You can check what version the plugin thinks player has by using any of the following:
|
||||
* `/tab parse <player> %player-version%` - Shows version name, if multiple versions share the same protocol, the newer one is returned
|
||||
* `/tab parse <player> %player-version-id%` - Returns network id of player's version
|
||||
* Set `debug: true` in config and check console messages on player join, it will send a message containing game version ViaVersion API has returned
|
||||
|
||||
Player game version detection may fail. Here are a few possible scenarios why:
|
||||
* ViaVersion is installed on 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 same version as the server in such cases.
|
||||
* 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.
|
||||
|
||||
When game version is not detected correctly, player's experience will be very limited, see below.
|
||||
When a player's game version is not detected correctly, player's experience will be very limited, see below.
|
||||
|
||||
## Differences
|
||||
To ensure the best possible experience, TAB is currently checking for player's version to:
|
||||
* [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout):
|
||||
* Disable for 1.7 and lower due to massive tablist differences and plugin not being adapted to those
|
||||
* Use alternate method of sorting the entries for 1.19.3+ using entry names, as the previous, better option was removed
|
||||
* Use RGB color codes for 1.16+ and use closest (or forced) legacy color for 1.15-
|
||||
* Use 1.9+ bossbar on 1.8 servers for 1.9+ players using ViaVersion API
|
||||
* Disable [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)
|
||||
* Play around <1.13 limitations of [Scoreboard](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Scoreboard)
|
||||
* Cutting nametag prefix/suffix to 16 characters for <1.13, but keeping it full for 1.13+
|
||||
To ensure the best possible experience, TAB is currently checking for player's version to alter its logic in some way.
|
||||
If a player's version is not detected correctly, a side effect might occur instead, making the situation worse.
|
||||
You will not experience all of these, only those that affect the version difference between the server and client.
|
||||
|
||||
When version detection fails, plugin's workarounds will be wrong and cause problems, such as:
|
||||
* Nametag prefix/suffix being cut to 16 characters, even for 1.13+ clients
|
||||
* Scoreboard lines limited to ~26 characters, even for 1.13+ clients
|
||||
* Scoreboard lines limited to 14 characters for < 1.13 clients
|
||||
* Scoreboard lines might be out of order
|
||||
* RGB colors displaying as legacy colors for 1.16+ clients
|
||||
* Layout being out of order for 1.19.3+ clients
|
||||
| Change of logic | Negative side effect if version is not detected correctly |
|
||||
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Disabling [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) for 1.7 players | [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) entries being sent into the tablist of the player, breaking it as the layout is not designed support 1.7 |
|
||||
| use alternate way of sorting [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) entries for 1.19.3 - 1.21.1 as the optimal sorting way cannot be used | [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) entries being out of order for 1.19.3 - 1.21.1 <br />Layout entries appearing in chat complete for <1.19.3 even if they don't have to |
|
||||
| Show 1.9+ bossbar on 1.8 servers for 1.9+ players using ViaVersion API | No 1.9+ bossbar for 1.9+ players on 1.8 server |
|
||||
| Disabling [Tablist name formatting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Tablist-name-formatting) for 1.7 and lower due to a 16-character limit total to take advantage of the mechanic where nametags are displayed in tablist, which extends the limit to up to 48 characters (16 prefix, 16 name, 16 suffix) | Trying to fit the entire formatting into 16 characters, resulting in massive cutting and nametag feature not working |
|
||||
| Play around <1.13 limitations of [Scoreboard](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Scoreboard) | Scoreboard lines limited to ~26 characters, even for 1.13+ clients <br />Scoreboard lines limited to 14 characters for < 1.13 clients |
|
||||
| Cutting nametag prefix/suffix to 16 characters for <1.13, but keeping it full for 1.13+ | Nametag prefix/suffix being cut to 16 characters, even for 1.13+ clients |
|
||||
|
||||
# Debug config option
|
||||
You may have noticed `debug: false` in your config. Enabling it will unlock extra console messages beyond the usual miconfiguration / errors. They give a deeper information about what's going on in the plugin in case a more complex issue comes up. Currently, it offers the following:
|
||||
* Prints thrown errors into console as well, instead of just errors.log file. They are printed into the console even if error log reaches 1MB limit.
|
||||
* Sends a message how long each feature + total it took to process player join/quit or plugin reload. High values may suggest something is not optimized correctly. Originally added for myself when optimizing, but adding/removing it each time would be too much of a hassle, so it remains as a debug message.
|
||||
* Sends a message when plugin detects player name change by a nick plugin. Since lots of things are bound to player names, having players change their name and plugin not detecting it would result in plugin not working correctly them. Therefore, every time a player changes nickname (or resets it), a message should pop up.
|
||||
* Sends message whenever another plugin sends a scoreboard (such as a minigame plugin) and TAB hides it own. Then, when that other plugin removes its scoreboard, TAB sends its own back (and sends a console message).
|
||||
* Sends a message regarding bedrock client status of players who join in using Floodgate API. This includes a message if floodgate is not enabled correctly (API instance is null), as well as true/false bedrock status of players.
|
||||
* Shows network id of protocol version of players who join when ViaVersion is installed. It should show the version players are actually using. If not, plugin may not work correctly for those players. This is usually caused by having ViaVersion on proxy and backend.
|
||||
You may have noticed `debug: false` in your config.
|
||||
Enabling it will unlock extra console messages beyond the usual misconfiguration / errors.
|
||||
They give deeper information about what's going on in the plugin in case a more complex issue comes up.
|
||||
Currently, it offers the following:
|
||||
* Makes plugin print thrown errors into console as well, instead of just errors.log file. They are printed into the console even if the error log reaches the 16MB limit.
|
||||
* Sends a message saying how long each feature + total it took to process player join/quit or plugin reload. High values may suggest something is not optimized correctly. Originally added for myself when optimizing, but adding/removing it each time would be too much of a hassle, so it remains as a debug message.
|
||||
* Sends a message when plugin detects player name change by a nick plugin. Since lots of things are bound to player names, having players change their name and plugin not detecting it would result in plugin not working correctly them. Therefore, every time a player changes their nickname (or resets it), a message should pop up.
|
||||
* Sends a message whenever another plugin sends a scoreboard (such as a mini-game plugin) and TAB hides its own. Then, when that other plugin removes its scoreboard, TAB sends its own back (and sends a console message).
|
||||
* Sends a message regarding the bedrock client status of players who join in using Floodgate API. This includes a message if floodgate is not enabled correctly (API instance is null), as well as true/false bedrock status of players.
|
||||
* Shows network id of protocol version of players who join when ViaVersion is installed. It should show the version players are actually using. If not, the plugin may not work correctly for those players. This is usually caused by having ViaVersion on proxy and backend.
|
||||
* Sends a message whenever a placeholder takes more than 50 milliseconds to retrieve value. If it only happens once, it may be a random hiccup and can be ignored. In case of consistent problems, this may cause plugin overload.
|
||||
* Sends a message if plugin attempted to send packet to a player who left already. On bungeecord 1.20.2+ this causes an error if not checked. This is completely the plugin's fault if it happens, but it cannot be shown to everyone, since it would require steps to reproduce and most users are not going to cooperate, resulting in stalling issues.
|
||||
* On BungeeCord, shows how long did Bridge take to answer player join plugin message. This should be below 100ms. If it's continuously significantly higher, it means bridge is overloaded with the most likely cause being an inefficient placeholder.
|
||||
* On proxy installation, shows how long did Bridge take to answer player join plugin message. This should be below 100ms. If it's continuously significantly higher, it suggests something bad is going on, either bridge being overloaded or the server itself.
|
||||
@@ -5,8 +5,6 @@
|
||||
* [External tools](#external-tools)
|
||||
* [Additional info](#additional-info)
|
||||
* [Additional note 1 - Frame synchronization](#additional-note-1---frame-synchronization)
|
||||
* [Examples](#examples)
|
||||
* [Example 1](#example-1)
|
||||
|
||||
# Creating an animation
|
||||
Animations can be created in **animations.yml** file.
|
||||
@@ -38,71 +36,25 @@ Welcome: #this is name of the animation
|
||||
This is an animation called `Welcome` with `change-interval` of `400` milliseconds, which is 2.5 refreshes per second. `Texts` are the actual frames of animation.
|
||||
|
||||
# Using an animation
|
||||
To use an animation, use `%animation:<name>%` format. In the example above it's `%animation:Welcome%`. Animations are supported everywhere. That includes header/footer, prefix/suffix, belowname, yellow number, bossbar and more.
|
||||
To use an animation, use `%animation:<name>%` format.
|
||||
In the example above it's `%animation:Welcome%`.
|
||||
Animations are supported everywhere.
|
||||
That includes header/footer, prefix/suffix, belowname, playerlist objective, bossbar and more.
|
||||
|
||||
# Tips & Tricks
|
||||
* Animations don't need to be fast. You can use them as a changing text in general.
|
||||
* Animations can also be used as a short alias to a long text. Just create an animation with one frame.
|
||||
* Animations can also be used as a short alias to a long text. You can do this by creating an animation with one frame.
|
||||
|
||||
# External tools
|
||||
If you want an animation that's too complicated to be done manually, you can check out these websites:
|
||||
If you want an animation too complicated to be done manually, you can check out these websites:
|
||||
* https://www.birdflop.com/resources/animtab/
|
||||
* https://starve-l.github.io/tab-animation.html
|
||||
* https://srnyx.com/gradient
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - Frame synchronization
|
||||
All animations start at the same time, which is time of plugin being (re)loaded. Thanks to this, all animations with the same amount of frames and same change interval will be synchronized.
|
||||
If you want to synchronize 2 animations with different change interval and different amount of frames, you need to make sure `frame count`*`change interval` is same for both animations, for example one animation with 10 frames and 1000ms and second animation with 2 frames and 5000ms.
|
||||
|
||||
# Examples
|
||||
## Example 1
|
||||
Swichtes between green and red in an extra smooth way (could replace the default animation bar for a christmas theme).
|
||||
Works on 1.16+ only due to RGB/Hex values being used.
|
||||
|
||||

|
||||
```
|
||||
MyAnimation1:
|
||||
change-interval: 50
|
||||
texts:
|
||||
- "bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m "
|
||||
- "7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m "
|
||||
- "ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m "
|
||||
- "Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m "
|
||||
- "Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m "
|
||||
- "bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m "
|
||||
- "Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m "
|
||||
- "e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m "
|
||||
- "ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m "
|
||||
- "&#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m "
|
||||
- "&#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m "
|
||||
- "&#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m "
|
||||
- "&#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m "
|
||||
- "&#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m "
|
||||
- "&#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m "
|
||||
- "&#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m "
|
||||
- "&#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m ed900&l&m "
|
||||
- "&#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m 7e600&l&m "
|
||||
- "&#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m bf200&l&m "
|
||||
- "&#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m *ff00&l&m "
|
||||
- "&#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m bf200&l&m "
|
||||
- "&#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m 7e600&l&m "
|
||||
- "&#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m ed900&l&m "
|
||||
- "&#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m Dcc00&l&m "
|
||||
- "&#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m Gbf00&l&m "
|
||||
- "&#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m bb300&l&m "
|
||||
- "&#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m Ta600&l&m "
|
||||
- "&#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m e9900&l&m "
|
||||
- "&#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m ϒc00&l&m "
|
||||
- "&#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m &#a18000&l&m "
|
||||
- "ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m &#aa7300&l&m "
|
||||
- "e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m &#b36600&l&m "
|
||||
- "Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m &#bd5900&l&m "
|
||||
- "bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m &#c64d00&l&m "
|
||||
- "Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m &#d04000&l&m "
|
||||
- "Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m &#d93300&l&m "
|
||||
- "ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m &#e32600&l&m "
|
||||
- "7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m &#ec1a00&l&m "
|
||||
- "bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m &#f60d00&l&m "
|
||||
- "*ff00&l&m bf200&l&m 7e600&l&m ed900&l&m Dcc00&l&m Gbf00&l&m bb300&l&m Ta600&l&m e9900&l&m ϒc00&l&m &#a18000&l&m &#aa7300&l&m &#b36600&l&m &#bd5900&l&m &#c64d00&l&m &#d04000&l&m &#d93300&l&m &#e32600&l&m &#ec1a00&l&m &#f60d00&l&m &#ff0000&l&m "
|
||||
```
|
||||
All animations start at the same time, which is time of plugin being (re)loaded.
|
||||
Thanks to this, all animations with the same number of frames and the same change interval will be synchronized.
|
||||
If you want to synchronize multiple animations with a different change interval and different number of frames,
|
||||
you need to make sure `(frame count)*(change interval)` is same for both animations,
|
||||
for example one animation with 10 frames and 1000ms and second animation with 2 frames and 5000ms.
|
||||
@@ -0,0 +1,33 @@
|
||||
# Content
|
||||
* [Detection](#detection)
|
||||
* [Differences](#differences)
|
||||
* [Issues with `.` in name](#issues-with--in-name)
|
||||
|
||||
# Detection
|
||||
For TAB to properly detect player as a bedrock player, floodgate and TAB must be installed on the same server instance.
|
||||
If TAB is installed on bukkit and floodgate is on both bungeecord and bukkit,
|
||||
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:
|
||||
* Set `debug: true` in TAB config and check console output on join/reload. It should say `Floodgate returned bedrock status TRUE for player <player>`.
|
||||
* Run `/tab parse <player> %bedrock%`. It should return `true`.
|
||||
|
||||
If any of them say `false` for an actual bedrock player, you didn't connect floodgate correctly.
|
||||
|
||||
# Differences
|
||||
It is a job of plugin allowing bedrock clients to connect (probably Geyser) to correctly translate all packets.
|
||||
If you are experiencing an issue on bedrock but not java, it is most likely not an issue in TAB code.
|
||||
|
||||
Currently, TAB does check for bedrock clients for:
|
||||
* Disabling [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) for bedrock players.
|
||||
|
||||
This is the only known change required on the TAB's side.
|
||||
|
||||
# Issues with `.` in name
|
||||
If you configured Geyser to prefix bedrock player names with `.`, it will mess up config loading,
|
||||
because `.` is used to split a section path.
|
||||
This means that using `/tab player <playername containing .> ...` will not work.
|
||||
There are three solutions available:
|
||||
* Use player UUID if commands are executed via another plugin (`/tab player <uuid> ...`).
|
||||
* Use `playeruuid` type, which accepts player name and saves the online player's UUID (`/tab playeruuid <player name> ...`).
|
||||
* Use a different username prefix than `.`.
|
||||
@@ -11,7 +11,7 @@ This is a collection of mechanics related to the plugin explaining how does the
|
||||
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 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.
|
||||
When having enough online players for 3–4 columns (or using [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout)) and their name formats are too long, they might overlap. This is caused by attempting to display text wider than the monitor can handle.
|
||||
There isn't really any ideal solution for this. Here are a few tips that might help:
|
||||
* Decrease GUI scale in client options to make text smaller
|
||||
* Make tablist entries shorter, such as avoiding using bold text (&l) or using short aliases for ranks instead of their full names (such as `A` instead of `Admin`).
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
# About
|
||||
This page lists all of the commands and permissions that are available with TAB. Commands have required permissions associated with them.
|
||||
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.
|
||||
* 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.
|
||||
|
||||
# Content
|
||||
* [Configuration](#configuration-commands)
|
||||
@@ -35,7 +36,7 @@ This page lists all of the commands and permissions that are available with TAB.
|
||||
# Configuration commands
|
||||
## /tab \<player/group/playeruuid\> \<name\> \<property\> [value] [options]
|
||||
* **Permission:** `tab.change.<property>`
|
||||
* **Description:** Changes a property of a group/player to the given value. No value argument will result in that property being deleted.
|
||||
* **Description:** Changes a property of a group/player to the given value. No value argument will result in that property being deleted.
|
||||
|
||||
#### Properties
|
||||
* For tablist: `tabprefix`, `customtabname`, and `tabsuffix`.
|
||||
@@ -48,11 +49,11 @@ This page lists all of the commands and permissions that are available with TAB.
|
||||
#### Names for each command type
|
||||
* player: Supports both player name and raw uuid. Player doesn't need to be online.
|
||||
* playeruuid: Requires name of an online player. Equal to using `player` with player's uuid.
|
||||
* group: Uses group names from permission plugin. `_DEFAULT_` is used for default settings for all groups.
|
||||
* group: Using group names from permission plugin. `_DEFAULT_` is used for default settings for all groups.
|
||||
|
||||
## /tab \<player/group/playeruuid\> \<name\> remove
|
||||
* **Permission:** `tab.remove`
|
||||
* **Description:** Removes all direct data from the given player/group.
|
||||
* **Description:** Removes all direct data from the given player/group.
|
||||
|
||||
#### Notes
|
||||
* The `playeruuid` argument requires the name of an **online player** to remove data from.
|
||||
@@ -63,19 +64,19 @@ This page lists all of the commands and permissions that are available with TAB.
|
||||
|
||||
## /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:
|
||||
* **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 of players, their values and source.
|
||||
* List of all configured properties, their values and source.
|
||||
|
||||
## /tab group \<group\>
|
||||
* **Permission:** `tab.groupinfo`
|
||||
* **Description:** Shows all settings applied to the specified group, both global and per-world / per-server. Handly when plugin is connected to MySQL, where you have no other way to effectively check group settings.
|
||||
* **Description:** Shows all settings applied to the specified group, both global and per-world / per-server. Handy when plugin is connected to MySQL, where you have no other way to effectively check group settings.
|
||||
|
||||
## /tab groups
|
||||
* **Permission:** `tab.grouplist`
|
||||
* **Description:** Shows list of all groups that have anything assigned to them, either globally or per-world / per-server. Handy when plugin is connected to MySQL, where you have no other way to effectively check your groups.
|
||||
* **Description:** Shows a list of all groups that have anything assigned to them, either globally or per-world / per-server. Handy when plugin is connected to MySQL, where you have no other way to effectively check your groups.
|
||||
|
||||
# Scoreboard
|
||||
## /tab scoreboard show \<name\> \[player\]
|
||||
@@ -128,16 +129,16 @@ This page lists all of the commands and permissions that are available with TAB.
|
||||
# Other
|
||||
## /tab cpu
|
||||
* **Permission:** `tab.cpu`
|
||||
* **Description:** Shows approximate CPU usage of the plugin from the last 10 seconds. There are parts which are impossible to be measured, so this shows slighty less than the real value is. The content is self-explanatory. All ways to decrease CPU usage can be found at [Optimizing the plugin](https://github.com/NEZNAMY/TAB/wiki/Optimizing-the-plugin).
|
||||
* **Description:** Shows approximate CPU usage of the plugin from the last 10 seconds. There are parts that are impossible to be measured, so this shows slightly less than the real value is. The content is self-explanatory. All major ways to decrease CPU usage can be found at [Optimizing the plugin](https://github.com/NEZNAMY/TAB/wiki/Optimizing-the-plugin).
|
||||
|
||||
## /tab parse \<player\> \<text\>
|
||||
* **Permission:** `tab.parse`
|
||||
* **Description:** Replaces all placeholders (both the plugin's internal ones, and those from PlaceholderAPI if it is installed) in the given `text`. Can be used to test if a placeholder works as expected.
|
||||
* **Description:** Replaces all placeholders (both the plugin's internal ones, and those from PlaceholderAPI if it is installed) in the given `text`. It can be used to verify if a placeholder works as expected.
|
||||
|
||||
# Additional permissions
|
||||
* `tab.admin` - Allows the player to execute all commands.
|
||||
* `tab.bypass` - If per-world player list is enabled as well as this permission, it allows the player to see everyone on the server, regardless of what the per-world player list settings allow. For example, if your per-world player list is set up to isolate worlds A and B, players with this permission will see all players from both A and B on their player list, whereas players that don't will only see either players from world A or players from world B, depending on what world they are in.
|
||||
* `tab.bypass` - If the per-world player list is enabled as well as this permission, it allows the player to see everyone on the server, regardless of what the per-world player list settings allow. For example, if your per-world player list is set up to isolate worlds A and B, players with this permission will see all players from both A and B on their player list, whereas players that don't have the permission will only see either players from world A or players from world B, depending on what world they are in.
|
||||
* `tab.staff` - Allows the player to be counted in the `%staffonline%` placeholder.
|
||||
* `tab.spectatorbypass` - If enabling bypass permission in [Spectator fix](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Spectator-fix), this is the permission.
|
||||
* `tab.tabcomplete` - Allows the player to auto-complete the `/tab` command.
|
||||
* `tab.seevanished` - Allows the player to see other vanished players on the [Global Playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist) and marks the player as able to see vanished players when using [Aligned suffix](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Aligned-Tabsuffix) feature to properly space out suffixes of players based on what the player can and cannot see.
|
||||
* `tab.seevanished` - Allows the player to see other vanished players on the [Global Playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist) and [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout).
|
||||
@@ -28,18 +28,18 @@ 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.1)</td>
|
||||
<td>✔ (1.5 - 1.21.4)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=1><a href="https://www.spongepowered.org/">Sponge</a></td>
|
||||
<td>✔ (1.9<sup>1</sup> - 1.20.4)</td>
|
||||
<td>✔ (1.9<sup>1</sup> - 1.21.4)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td rowspan=2>Modded</td>
|
||||
<td rowspan=1><a href="https://fabricmc.net">Fabric</a></td>
|
||||
<td>✔ (1.14.4 - 1.21.1)</td>
|
||||
<td>✔ (1.14 - 1.21.4)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=1><a href="https://minecraftforge.net">Forge</a></td>
|
||||
@@ -63,20 +63,26 @@ It is compiled with Java 8 and therefore supports any version of 8 and above.
|
||||
* 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>2</sup> Latest only doesn't mean only the latest build will work, it means the plugin was made to be compatible with latest version/build. Since breaking changes don't happen too often, it means a wide range of versions is usually supported. When a breaking change occurs, plugin is updated to support new version, automatically making old versions incompatible. Since proxies support all client versions, there is never a reason to stay outdated, so you can always safely update to new version version/build of your proxy software if plugin requires it.
|
||||
<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.
|
||||
Since breaking changes don't happen too often, it means a wide range of versions is usually supported.
|
||||
When a breaking change occurs, the plugin is updated to support the new version,
|
||||
automatically making old versions incompatible.
|
||||
Since proxies support all client versions, there is never a reason to stay outdated,
|
||||
so you can always safely update to 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 [Bridge](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge)) |
|
||||
| [BossBar](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Bossbar) | ✔ | ✔ | ✔ | ✔ (1.9+) | ✔ (1.9+) |
|
||||
| [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 [Bridge](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge)) |
|
||||
| [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 [Bridge](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge)) |
|
||||
| [Scoreboard](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Scoreboard) | ✔ | ❗ | ✔ | ✔ | ❗ (via [Bridge](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge)) |
|
||||
| [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) | ✔ | ✔ | ✔ | ✔ | ✔ |
|
||||
|
||||
@@ -85,21 +91,25 @@ It is compiled with Java 8 and therefore supports any version of 8 and above.
|
||||
❌ = Completely missing
|
||||
|
||||
# Plugin hooks
|
||||
In order to enhance user experience, TAB hooks into other plugins for better experience. This set of plugins is different for each platform based on their availability. Some are available on all platforms, some only in a few.
|
||||
To enhance user experience, TAB hooks into other plugins for better experience.
|
||||
This set of plugins is different for each platform based on their availability.
|
||||
Some are available on all platforms, some only in a few.
|
||||
## All platforms
|
||||
[**Floodgate**](https://github.com/GeyserMC/Floodgate) - For properly detecting bedrock players to adapt features for best possible user experience.
|
||||
[**Floodgate**](https://github.com/GeyserMC/Floodgate) - For properly detecting bedrock players to adapt features for the best possible user experience.
|
||||
[**LuckPerms**](https://github.com/LuckPerms/LuckPerms) - Detecting permission groups of players for per-group settings.
|
||||
[**ViaVersion**](https://github.com/ViaVersion/ViaVersion) - For properly detecting player version to adapt features for best possible user experience.
|
||||
[**ViaVersion**](https://github.com/ViaVersion/ViaVersion) - For properly detecting player's version to adapt features for the best possible user experience.
|
||||
|
||||
## Bukkit
|
||||
[**LibsDisguises**](https://github.com/libraryaddict/LibsDisguises) - Detecting disguised players to disable collision to avoid endless push by colliding with own copy created by LibsDisguises.
|
||||
[**PlaceholderAPI**](https://github.com/PlaceholderAPI/PlaceholderAPI) - Allows users to use its placeholders inside TAB.
|
||||
[**PremiumVanish**](https://www.spigotmc.org/resources/14404) - Supporting PV's vanish levels instead of using a basic vanish compatibility system.
|
||||
[**PremiumVanish**](https://www.spigotmc.org/resources/14404) - Supporting PremiumVanish's vanishing levels instead of using a basic compatibility system.
|
||||
[**Vault**](https://github.com/milkbowl/Vault) - Detecting permission groups of players for per-group settings.
|
||||
|
||||
## BungeeCord
|
||||
[**PremiumVanish**](https://www.spigotmc.org/resources/14404) - Supporting PV's vanish levels instead of using a basic vanish compatibility system.
|
||||
[**RedisBungee**](https://github.com/ProxioDev/RedisBungee) - Communicating with other proxies to properly display visuals on players on another proxy.
|
||||
[**PremiumVanish**](https://www.spigotmc.org/resources/14404) -
|
||||
Supporting PremiumVanish's vanishing levels instead of using a basic compatibility system.
|
||||
[**RedisBungee**](https://github.com/ProxioDev/RedisBungee) -
|
||||
Communicating with other proxies to properly display visuals on players on another proxy.
|
||||
|
||||
## Fabric
|
||||
[**fabric-permissions-api**](https://github.com/lucko/fabric-permissions-api) - Supporting permission nodes instead of OP levels.
|
||||
@@ -108,21 +118,27 @@ In order to enhance user experience, TAB hooks into other plugins for better exp
|
||||
*None*
|
||||
|
||||
## Velocity
|
||||
[**PremiumVanish**](https://www.spigotmc.org/resources/14404) - Supporting PV's vanish levels instead of using a basic vanish compatibility system.
|
||||
[**RedisBungee**](https://github.com/ProxioDev/RedisBungee) - Communicating with other proxies to properly display visuals on players on another proxy.
|
||||
[**PremiumVanish**](https://www.spigotmc.org/resources/14404) -
|
||||
Supporting PremiumVanish's vanishing levels instead of using a basic compatibility system.
|
||||
[**RedisBungee**](https://github.com/ProxioDev/RedisBungee) -
|
||||
Communicating with other proxies to properly display visuals on players on another proxy.
|
||||
[**VelocityScoreboardAPI**](https://github.com/NEZNAMY/VelocityScoreboardAPI) -
|
||||
Sending scoreboard packets (scoreboard-teams, belowname-objective, playerlist-objective, scoreboard)
|
||||
|
||||
# Compatibility issues
|
||||
* **Glow plugins** will fail to apply glow color correctly. Check [How to make the plugin compatible with glow plugins](https://github.com/NEZNAMY/TAB/wiki/How-to-make-TAB-compatible-with-glow-plugins) for more information.
|
||||
* **[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.
|
||||
* **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. Just avoid this combination - either install ViaVersion on all backend servers instead or install TAB on BungeeCord instead.
|
||||
* **Custom clients / resource packs** - Unofficially modified minecraft clients often tend to break things. Just Lunar client has 3 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 clean vanilla client. If it works there, it's an issue with the client / resource pack and TAB cannot do anything about it. Here are a few bugs in LunarClient / FeatherClient that you may run into when using TAB:
|
||||
* **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).
|
||||
* **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 own nametag using F5 even if set to invisible by the plugin.
|
||||
* When scoreboard is set to use all 0s, lines are rendered in opposite order on 1.20.3+.
|
||||
* 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 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.
|
||||
* **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.
|
||||
@@ -12,7 +12,6 @@
|
||||
* [Sorting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Sorting-players-in-tablist#api)
|
||||
* [Tablist name formatting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Tablist-name-formatting#api)
|
||||
* [Placeholders](https://github.com/NEZNAMY/TAB/wiki/Placeholders#api)
|
||||
* [Unlimited nametag mode](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Unlimited-nametag-mode#api)
|
||||
|
||||
# Adding the dependency
|
||||
|
||||
@@ -27,12 +26,12 @@ For Maven users, you can add the API dependency like this:
|
||||
<dependency>
|
||||
<groupId>com.github.NEZNAMY</groupId>
|
||||
<artifactId>TAB-API</artifactId>
|
||||
<version>4.1.8</version>
|
||||
<version>5.0.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
Or, for Gradle users, here's a few examples:
|
||||
Or, for Gradle users, here are a few examples:
|
||||
|
||||
Groovy:
|
||||
```groovy
|
||||
@@ -41,7 +40,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'com.github.NEZNAMY:TAB-API:4.1.8'
|
||||
compileOnly 'com.github.NEZNAMY:TAB-API:5.0.5'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -52,7 +51,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("com.github.NEZNAMY", "TAB-API", "4.1.8")
|
||||
compileOnly("com.github.NEZNAMY", "TAB-API", "5.0.5")
|
||||
}
|
||||
```
|
||||
|
||||
@@ -62,17 +61,27 @@ If you relocate, the API that you are calling will also get relocated in your co
|
||||
Ensure that you are using **`<scope>provided</scope>` for Maven**, or **`compileOnly` for Gradle**.
|
||||
|
||||
# Getting started
|
||||
First of all, you need to get an instance of the API. You can do this with `TabAPI.getInstance()`.
|
||||
The `TabAPI` class that you want to import is located in the `me.neznamy.tab.api` package. If you do not see this imported, or it is imported but the package is not `me.neznamy.tab.api`, then you have the **wrong class**.
|
||||
First, you need to get an instance of the API.
|
||||
You can do this with `TabAPI.getInstance()`.
|
||||
The `TabAPI` class that you want to import is located in the `me.neznamy.tab.api` package.
|
||||
If you do not see this imported,
|
||||
or it is imported but the package is not `me.neznamy.tab.api`, then you have the **wrong class**.
|
||||
|
||||
Now you have the instance, you can get a `TabPlayer` with the methods `getPlayer(UUID)` and `getPlayer(String)`, to get players by UUID and name respectively.
|
||||
If no player was found with the UUID or the name that you gave, these methods will return `null`. It is important that you catch this, to avoid running in to a `NullPointerException`. You should **NOT** assume that just because a player has logged in that TAB will already have a player for them, as players are processed asynchronously. This will be especially true for join events like `PlayerJoinEvent`.
|
||||
|
||||
If you want to be 100% sure that the player you want is loaded when you want to process them, use `PlayerLoadEvent`. This will give you the `TabPlayer` that has been loaded, so that you can process that `TabPlayer`. See below for more details how to use the event.
|
||||
If you want to be 100% sure that the player you want is loaded when you want to process them, use `PlayerLoadEvent`.
|
||||
This will give you the `TabPlayer` that has been loaded, so that you can process that `TabPlayer`.
|
||||
See below for more details on how to use the event.
|
||||
|
||||
# Lifespan of API calls
|
||||
All API calls result in temporary changes to the plugin's logic. When the plugin is reloaded or server restarted, all previous API calls will lose effect. This also applies for players after they reconnect - they are reset back. If you want to perform long-term changes to player's prefix or suffix, call TAB's [commands](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions) from your plugin.
|
||||
If you want to re-apply your changes on plugin reload, listen to [events](#events) using plugin's own event system, specifically `TabLoadEvent`, which is called on plugin reload.
|
||||
All API calls result in temporary changes to the plugin's logic.
|
||||
When the plugin is reloaded or server restarted, all previous API calls will lose effect.
|
||||
This also applies for players after they reconnect—they are reset back.
|
||||
If you want to perform long-term changes to player's prefix or suffix,
|
||||
call TAB's [commands](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions) from your plugin.
|
||||
If you want to re-apply your changes on plugin reload, listen to [events](#events) using plugin's own event system,
|
||||
specifically `TabLoadEvent`, which is called on plugin reload.
|
||||
|
||||
# Events
|
||||
TAB is using a custom platform-independent event API. As such, the same event listener code will work on all supported platforms. Usage is also different, let's take a look at an example:
|
||||
@@ -82,7 +91,7 @@ TabAPI.getInstance().getEventBus().register(PlayerLoadEvent.class, event -> {
|
||||
//do something
|
||||
});
|
||||
```
|
||||
Currently, the plugin provides 3 events:
|
||||
TAB plugin provides the following events:
|
||||
* `TabLoadEvent` - Called when the plugin has finished its load, either on startup or plugin reload.
|
||||
* `PlayerLoadEvent` - Called when the plugin has finished loading a player (either join or plugin reload).
|
||||
* `PlaceholderRegisterEvent` - Called when the plugin is about to register a parser for used PlaceholderAPI placeholder, allowing to override it.
|
||||
@@ -5,24 +5,48 @@
|
||||
* [anti-override.log](#anti-overridelog)
|
||||
|
||||
# About
|
||||
TAB logs various events in up to 3 files to keep the console clean. All of these notifications are negative, so they should be looked at.
|
||||
TAB logs various events in multiple files to keep the console clean.
|
||||
All of these notifications are negative, so they should be looked at.
|
||||
|
||||
Files are only created when something is about to get logged. This means if you have none of these files in your folder, everything is good. Also, it is safe to delete the logs any time while server is running without needing to reload the plugin or anything.
|
||||
Files are only created when something is about to get logged.
|
||||
This means if you have none of these files in your folder, everything is good.
|
||||
It is safe to delete the logs any time while the server is running without needing to reload the plugin or anything.
|
||||
|
||||
All files have their sizes limited to 1MB to avoid giant files consisting of the same error repeating over and over. Don't forget these files are **logs**, therefore, after solving the problems you must delete them. These files will not delete themselves.
|
||||
After deleting a file, there is no need to perform any other action. Every time an error is about to be logged, file is created if it doesn't exist.
|
||||
All files have their sizes limited to 16 MB to avoid giant files consisting of the same error repeating over and over.
|
||||
Remember these files are **logs**; therefore, after solving the problems you must delete them.
|
||||
These files will not delete themselves.
|
||||
After deleting a file, there is no need to perform any other action.
|
||||
Every time an error is about to be logged, the file is created if it doesn't exist.
|
||||
|
||||
Java errors usually contain stack traces. If you got an error spamming with exception message but no stack trace, the most common cause is java not including it because too many errors were thrown already. To bypass this check, add `-XX:-OmitStackTraceInFastThrow` to your startup parameters.
|
||||
Java errors usually contain stack traces.
|
||||
If you got an error spamming with an error message but no stack trace,
|
||||
the most common cause is java not including it because too many errors were thrown already.
|
||||
To bypass this check, add `-XX:-OmitStackTraceInFastThrow` to your startup parameters.
|
||||
|
||||
# errors.log
|
||||
No one likes having their console spammed with errors. Fixing errors is the most reliable solution, however that takes time and you usually don't get an update fixing an error the second you report it. Because of that, all plugin errors are moved to this file instead.
|
||||
No one likes having their console spammed with errors.
|
||||
Fixing errors is the most reliable solution, however, that takes time,
|
||||
and you usually don't get an update fixing an error the second you report it.
|
||||
Because of that, all plugin errors are moved to this file instead.
|
||||
|
||||
# placeholder-errors.log
|
||||
This file is used to track errors thrown by PlaceholderAPI expansions when trying to retrieve value of a placeholder. These should be reported to the expansion author. First line(s) of error should give you a good idea which expansion it is, as well as the actual placeholder which threw the error (displayed on top of the error).
|
||||
This file is used
|
||||
to track errors thrown by PlaceholderAPI expansions when trying to retrieve the value of a placeholder.
|
||||
These should be reported to the expansion author.
|
||||
First line(s) of error should give you a good idea which expansion it is,
|
||||
as well as the actual placeholder which threw the error
|
||||
(displayed on top of the error).
|
||||
|
||||
# anti-override.log
|
||||
This file logs all attempts of other plugins to override TAB's visuals. This is checking for features that only 1 plugin can be displaying info in at once (such as nametag prefix/suffix, tablist prefix/suffix). This means that (at least) one of your plugins is not configured correctly and you didn't disable functions you don't want. If you want TAB to use a feature, disable it in other plugins. If you want a different plugin to display it, disable it in TAB (disabled features do not log this).
|
||||
This file logs all attempts of other plugins to override TAB's visuals.
|
||||
This is checking for features that only a single plugin can be displaying info in at once
|
||||
(such as nametag prefix/suffix, tablist prefix/suffix).
|
||||
This means that (at least) one of your plugins is not configured correctly,
|
||||
and you didn't disable functions you don't want.
|
||||
If you want TAB to use a feature, disable it in other plugins.
|
||||
If you want a different plugin to display it, disable it in TAB (disabled features do not log this).
|
||||
|
||||
It is unfortunately not possible to easily figure out which plugin is causing it, you can only guess from the message.
|
||||
|
||||
Although this is technically unnecessary since TAB automatically blocks other plugins from overriding it, it's good to have your plugins configured properly. This might come in handy when moving TAB from bukkit to bungeecord where anti-override does not work too well due to missing functions in bungeecord, so you won't suddenly experience half of the features to not work when moving to bungeecord.
|
||||
Although this is technically unnecessary since TAB automatically blocks other plugins from overriding it,
|
||||
it's good to have your plugins configured properly.
|
||||
@@ -4,47 +4,72 @@
|
||||
* [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-)
|
||||
* [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)
|
||||
|
||||
# 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.
|
||||
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 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.
|
||||
|
||||
The feature's properties are displayed as `[score]` + space + `text`, where `[score]` is:
|
||||
* `number` for 1.20.2- (will show `0` on NPCs)
|
||||
* `fancy-display-players` for 1.20.3+ (will show `fancy-display-default` on NPCs)
|
||||
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)
|
||||
|
||||
# Configuration
|
||||
| Option name | Default value | Description |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| enabled | true | Enables / Disables the feature |
|
||||
| number | %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 simiplicity. |
|
||||
| fancy-display-players | &c%health% | [1.20.3+] Any text, supports placeholders with per-player output. Only visible on 1.20.3+. |
|
||||
| fancy-display-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+. |
|
||||
| text | Health | Text displayed after number. 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+. |
|
||||
| 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. |
|
||||
|
||||
# Additional Info
|
||||
## Additional note 1 - Copying nametag visibility rule
|
||||
The minecraft feature is programmed to be affected by nametag visibility rule. This means that when nametag is set to invisible, belowname will be invisible as well.
|
||||
The minecraft feature is programmed to be affected by nametag visibility rule.
|
||||
This means that when the nametag is set to invisible, belowname will be invisible as well.
|
||||
|
||||
## Additional note 2 - Hidden on sneak on 1.8
|
||||
Belowname is not visible on 1.8.x clients when player is sneaking. This is client-sided behavior and cannot be changed by the server.
|
||||
|
||||
## Additional note 3 - Visible on NPCs
|
||||
Belowname objective is automatically attached to all entities of player type with the default value of
|
||||
`0` (<1.20.3) or value configured as `fancy-value-default` (1.20.3+).
|
||||
This includes player NPCs.
|
||||
|
||||
There is currently only one way to make them not visible on NPCs.
|
||||
From [Additional note 1 - Copying nametag visibility rule](#additional-note-1---copying-nametag-visibility-rule) we know
|
||||
that belowname is not visible if player's nametag is invisible.
|
||||
NPC plugin can take advantage of this by using teams to hide the original name and display a hologram instead.
|
||||
|
||||
This is how you can achieve it using the following popular NPC plugins:
|
||||
* **Citizens**:
|
||||
* 1 - Select the NPC (`/npc select <ID>` or `/npc select` to select the nearest NPC)
|
||||
* 2 - Hide its original nametag (which also hides belowname) using `/npc name`
|
||||
* 3 - Display your desired text using `/npc hologram add <text>` ([more info](https://wiki.citizensnpcs.co/Commands#:~:text=the%20NPC%20hitbox-,/npc%20hologram,-add%20%5Btext%5D%20%7C%20set))
|
||||
|
||||
# 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: `❤`. Make sure you [save config in UTF-8 encoding](https://github.com/NEZNAMY/TAB/wiki/How-to-save-the-config-in-UTF8-encoding) so it's loaded correctly.
|
||||
If you want to show health of players and display a heart symbol as text, you can use this one: `❤`.
|
||||
```
|
||||
belowname-objective:
|
||||
text: "&4❤"
|
||||
title: "&4❤"
|
||||
```
|
||||
> [!IMPORTANT]
|
||||
> Make sure your config is saved in UTF-8 encoding to properly read the heart symbol.
|
||||
|
||||
## 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:
|
||||
@@ -52,7 +77,85 @@ If you want health to display health as 0-10 instead of 0-20, you can achieve it
|
||||
* `%math_0_{player_health}*5%` for 0-100
|
||||
|
||||
# Limitations
|
||||
* The format is a **[score] + space + shared text**, where [score] is either a white number (1.20.2-) or any text (1.20.3+).
|
||||
* The text is same on all players, therefore cannot be personalized (such as player's faction). Only the [score] can be per-player.
|
||||
* It appears on all entites of player type. **This includes player NPCs.**
|
||||
* Text length is limited to 32 characters on <1.13
|
||||
* [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.
|
||||
* 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.**
|
||||
|
||||
# Examples
|
||||
## Example 1 - Per-world values
|
||||
This feature doesn't directly support per-world values or similar.
|
||||
However, this can be achieved with conditions.
|
||||
Let's make `fancy-value` conditional based on player's world.
|
||||
Let's make an example with 3 worlds.
|
||||
Check if player is in world `world1`, then show one text.
|
||||
If not, check if player is in world `world2`, then show another text.
|
||||
If not, show the final text.
|
||||
This can be achieved by chaining 2 conditions:
|
||||
```
|
||||
conditions:
|
||||
belowname1:
|
||||
conditions:
|
||||
- "%world%=world1"
|
||||
true: "Text to display in world world1" # Player is in world world1, display the text
|
||||
false: "%condition:belowname2%" # Player is not in world world1, check another condition
|
||||
belowname2:
|
||||
conditions:
|
||||
- "%world%=world2"
|
||||
true: "Text to display in world world2" # Player is in world world2, display the text
|
||||
false: "Text to display in other worlds" # Player is not in any of the 2 worlds
|
||||
```
|
||||
> [!WARNING]
|
||||
> DO NOT JUST RANDOMLY PASTE THIS ENTIRE "CONDITIONS" SECTION INTO YOUR CONFIG!
|
||||
> INSTEAD, EDIT YOUR EXISTING CONDITIONS SECTION TO PREVENT HAVING THE SECTION TWICE,
|
||||
> HAVING SECOND ONE COMPLETELY OVERRIDE THE FIRST ONE!
|
||||
|
||||
Finally, use this condition as value in `fancy-value`:
|
||||
```
|
||||
belowname-objective:
|
||||
fancy-value: "%condition:belowname1%"
|
||||
```
|
||||
If you are under 1.20.3 and want to make `value` and `title` conditional,
|
||||
create two condition chains, one for each value and use them.
|
||||
|
||||
> [!NOTE]
|
||||
> This is just an example, the plugin is not limited to displaying different values only per world.
|
||||
> If you want per server values on BungeeCord, 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.
|
||||
|
||||
## Example 2 - Hiding `title` for 1.20.3+ players
|
||||
1.20.3 has replaced `value` field,
|
||||
which is limited to a white number with value configurable as `fancy-value`, which has no limits.
|
||||
However, `title` field is still visible on 1.20.3+.
|
||||
If you support both version ranges and want to make the best out of the new functionality,
|
||||
you might want to not show `title` to 1.20.3+ players anymore,
|
||||
since you can fully customize the text you want to display in `fancy-value`.
|
||||
|
||||
First, let's remind ourselves what `title` *actually* is.
|
||||
It is actually called scoreboard title.
|
||||
Yes, just like the one on top of sidebar, just displayed elsewhere.
|
||||
This is why it displays on all players and placeholders are parsed for the viewing player.
|
||||
With this knowledge, all we need to do is check for player's version and only show something for <1.20.3.
|
||||
For this, we will use `%player-version-id%` placeholder,
|
||||
which returns the network protocol version of player's game version, which can then be compared to.
|
||||
```
|
||||
conditions:
|
||||
version:
|
||||
- "%player-version-id%>=765" # 1.20.3 is 765
|
||||
true: "" # Show empty value for 1.20.3+
|
||||
false: "Some text to display"
|
||||
```
|
||||
> [!WARNING]
|
||||
> DO NOT JUST RANDOMLY PASTE THIS ENTIRE "CONDITIONS" SECTION INTO YOUR CONFIG!
|
||||
> INSTEAD, EDIT YOUR EXISTING CONDITIONS SECTION TO PREVENT HAVING THE SECTION TWICE,
|
||||
> HAVING SECOND ONE COMPLETELY OVERRIDE THE FIRST ONE!
|
||||
```
|
||||
belowname-objective:
|
||||
title: "%condition:version%"
|
||||
```
|
||||
Unfortunately, due to the limitations of this feature,
|
||||
there is a forced space between `value`/`fancy-value` and `title`,
|
||||
even if the `title` is empty.
|
||||
You'll either need to live with it, or put some shared text there to avoid having a space at the end.
|
||||
@@ -11,22 +11,21 @@
|
||||
* [Announce command](#announce-command)
|
||||
* [Additional settings](#additional-settings)
|
||||
* [Limitations](#limitations)
|
||||
* [on <1.9](#on--19)
|
||||
* [Additional info](#additional-info)
|
||||
* [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)
|
||||
* [1.8 vs 1.9 bossbar](#18-vs-19-bossbar)
|
||||
* [Background](#background)
|
||||
* [Execution by plugins](#execution-by-plugins)
|
||||
* [Execution by TAB](#execution-by-tab)
|
||||
* [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)
|
||||
|
||||
# About
|
||||

|
||||
Bars with text on top of the screen originally designed to display health of ender dragon & wither, but plugins found another use for it. In 1.9 mojang added a packet dedicated to displaying text without requiring an entity and allowing customizable color and style as well.
|
||||
Bars with text on top of the screen originally designed to display the health of ender dragon & wither,
|
||||
but plugins found another use for it.
|
||||
In 1.9, mojang added a packet
|
||||
dedicated to displaying text without requiring an entity and allowing customizable color and style as well.
|
||||
TAB only supports this new functionality, and the feature does not support 1.8 and lower.
|
||||
|
||||
This feature can be configured in **config.yml** under **bossbar** section.
|
||||
|
||||
@@ -44,14 +43,14 @@ bossbar:
|
||||
Every bossbar line has 4 properties:
|
||||
|
||||
### style
|
||||
Type of bossbar division. Only visible on 1.9+ clients.
|
||||
Type of bossbar division.
|
||||
You can choose from 5 styles: **PROGRESS**, **NOTCHED_6**, **NOTCHED_10**, **NOTCHED_12** and **NOTCHED_20**
|
||||

|
||||
These were defined by mojang, no other options are available. Other plugins may be using different names, but it's the same result in the end.
|
||||
|
||||
|
||||
### color
|
||||
Color of bossbar. Only visible on 1.9+ clients. Old clients will see it purple.
|
||||
Color of bossbar.
|
||||
You can choose from 7 colors: **BLUE**, **GREEN**, **PINK**, **PURPLE**, **RED**, **WHITE** and **YELLOW**
|
||||

|
||||
These were defined by mojang, no other options are available.
|
||||
@@ -62,8 +61,9 @@ A number from 0 to 100. Accepts decimals.
|
||||

|
||||
If you want to show the progress of a placeholder's value relative to a maximum one, you can use the [Math Expansion](https://github.com/PlaceholderAPI/PlaceholderAPI/wiki/Placeholders#math) from PlaceholderAPI and use a placeholder like this one: `%math_{placeholder_current_value}/{placeholder_max_value}*100%` or `%math_{placeholder_current_value}/<max_value>*100%` if your max value is fixed.
|
||||
|
||||
Notes:
|
||||
Replace the text in between the `{}` with the actual placeholder you want to use and `<max_value>` with a valid number (i.e. 20).
|
||||
> [!NOTE]
|
||||
> Replace the text in between the `{}` with the actual placeholder you want to use and `<max_value>` with a valid number
|
||||
(i.e., 20).
|
||||
You cannot use the `%placeholder%` format inside the math placeholder.
|
||||
|
||||
Example for showing a player's health: `%math_{player_health}/20*100%` or `%math_{player_health}/{player_max_health}*100%`
|
||||
@@ -101,33 +101,34 @@ 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 announce 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 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%`.
|
||||
|
||||
## Additional settings
|
||||
| Option name | Default value | Description |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| enabled | false | Enables / Disables the feature |
|
||||
| toggle-command | /bossbar | A command to toggle bossbar visibility for player running the command. This command requires `tab.bossbar.toggle` permission. <br />**Note:** 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, disabling bossbar using `toggle-command` is remembered between reloads and restarts. |
|
||||
| hidden-by-default | false | When enabled, bossbar will automatically be hidden until toggle command is used. |
|
||||
| Option name | Default value | Description |
|
||||
|------------------------|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | false | Enables / Disables the feature |
|
||||
| toggle-command | /bossbar | A command to toggle bossbar visibility for player running the command. This command requires `tab.bossbar.toggle` permission. <br />**Note:** 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, disabling bossbar using `toggle-command` is remembered between reloads and restarts. |
|
||||
| hidden-by-default | false | When enabled, bossbar will automatically be hidden until toggle command is used. |
|
||||
|
||||
# Limitations
|
||||
* Does not support newlines. If you want to display more lines, you'll need to create multiple bossbars.
|
||||
* The bar itself cannot be removed from the server side. However, it can be removed with a resource pack.
|
||||
## on < 1.9
|
||||
* **Will not display at all if TAB is installed on bungeecord** (bungeecord is missing entity packets needed to make it work)
|
||||
* Doesn't offer color and style features.
|
||||
* Only one line can be displayed at a time.
|
||||
* You can see the fog if you don't disable particles in options.
|
||||
* Text length is limited to 64 characters on <1.7
|
||||
* May not be visible when looking at blocks
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - Hiding bar itself
|
||||
If you want to hide the bossbar itself and only show text, this is possible, but not from the plugin's side. You'll need to create a custom resource pack where the bar doesn't show up and only text does. Then, you need to force your players to get the resource pack.
|
||||
If you want to hide the bossbar itself and only show text, this is possible, but not from the plugin's side.
|
||||
You'll need to create a custom resource pack where the bar is invisible.
|
||||
Then, you need to force your players to get the resource pack.
|
||||
|
||||
## Additional note 2 - Not hiding on server switch
|
||||
When under a BungeeCord 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.
|
||||
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.
|
||||
|
||||
# API
|
||||
*To get started with the API, see [Developer API](https://github.com/NEZNAMY/TAB/wiki/Developer-API) page.*
|
||||
@@ -139,11 +140,11 @@ A boss bar is made up of a few things:
|
||||
* A title. This is the display message of the boss bar.
|
||||
* The progress from 0 to 100.
|
||||
* The color. This determines what color the boss bar will appear when it is shown to clients.
|
||||
* The style. This determines how many segments, if any, the boss bar will be split in to.
|
||||
* The style. This determines how many segments, if any, the boss bar will be split to.
|
||||
|
||||
Let's start with methods in `BossBarManager`:
|
||||
* `BossBarManager#createBossBar(String, float, BarColor, BarStyle` - Creates new bossbar using direct values.
|
||||
* `BossBarManager#createBossBar(String, String, String, String` - Creates new bossbar. Accepts all of the previous as strings, to allow for placeholders, though the given placeholders must match the requirements (progress will be a number, color and style matching enum names).
|
||||
* `BossBarManager#createBossBar(String, String, String, String` - Creates new bossbar. Accepts all the previous parameters as strings, to allow for placeholders, though the given placeholders must match the requirements (progress will be a number, color and style matching enum names).
|
||||
* `BossBarManager#getBossBar(String)` - Returns bossbar by name defined in config.
|
||||
* `BossBarManager#toggleBossBar(TabPlayer, boolean)` - Toggles all bossbars for specified player. The boolean flags whether toggle message defined in messages.yml should be sent to the player or not.
|
||||
* `BossBarManager#hasBossBarVisible(TabPlayer)` - Returns `true` if player has bossbars visible, `false` if disabled using toggling.
|
||||
@@ -172,21 +173,9 @@ 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.
|
||||
|
||||
# 1.8 vs 1.9 bossbar
|
||||
The way of displaying information in bossbar is completely different on 1.8 and 1.9+. Here you can find out why.
|
||||
|
||||
## Background
|
||||
Server owners have always been looking for ways to display information. Another way they discovered is by spawning a fake ender dragon / wither, making it invisible, giving it custom name and teleporting it near player. This way, however, has several flaws as you can see above. As of 1.9, mojang decided to add a packet purely for displaying text without requiring an entity. They also added options to set color and style of the bossbar.
|
||||
|
||||
## Execution by plugins
|
||||
With introduction of 1.9 bossbar which is much easier to use, plugins have switched over to that method. However, this feature cannot be used for <1.9 clients as the feature did not exist back then. For this reason you can see some bossbar plugins saying "supports 1.9 and higher", as they don't want to mess with entities.
|
||||
|
||||
## Execution by TAB
|
||||
TAB will attempt to display 1.9 bossbar whenever possible, entity otherwise. 1.9+ clients will always see 1.9 bossbar (even on a 1.8 server thanks to viaversion api). <1.9 clients will see an invisible entity. On bungeecord, however, <1.9 clients won't see anything as bungeecord did not implement entity packets required to make it work.
|
||||
|
||||
# Tips & Tricks
|
||||
## Tip 1 - Animated bossbar color
|
||||
You can animate color of a bossbar using [animations](https://github.com/NEZNAMY/TAB/wiki/Animations).
|
||||
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
|
||||
```
|
||||
BossColor:
|
||||
@@ -208,7 +197,12 @@ 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
|
||||
If you want the plugin to switch between bossbars based on a condition, first consider using condition for text itself (or some other property). If this is not an option (you want text, color, style and progress to be different, which would result in 4 conditions), create 2 bars and give them the same condition, except negate it. If your original condition uses `=`, make second condition use `!=`. For number comparisons, negate `<` using `>=` and so on.
|
||||
If you want the plugin to switch between bossbars based on a condition, first consider using condition for text itself
|
||||
(or some other property).
|
||||
If this is not an option (you want text, color, style and progress to be different, which would result in 4 conditions),
|
||||
create 2 bars and give them the same condition, except, negate it.
|
||||
If your original condition uses `=`, make second condition use `!=`.
|
||||
For number comparisons, negate `<` using `>=` and so on.
|
||||
**Example**:
|
||||
```
|
||||
bars:
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
* [Example 2 - Conditions in conditions](#example-2---conditions-in-conditions)
|
||||
|
||||
# About
|
||||
Conditions / conditional placeholders allow you to create output which depends on output of other placeholders or permission requirement.
|
||||
Conditions / conditional placeholders allow you
|
||||
to create output which depends on the output of other placeholders or permission requirement.
|
||||
They have 2 main uses in the plugin:
|
||||
* Display condition which must be met to be able to see something (bossbar, scoreboard, layout)
|
||||
* Conditional placeholders which return defined outputs in both cases if condition passes or fails
|
||||
* Conditional placeholders which return defined outputs in both cases if the condition passes or fails
|
||||
|
||||
# Condition types
|
||||
## Number comparations
|
||||
@@ -46,15 +47,17 @@ Example: `%world%!=world` will pass if player is in any world except `world`.
|
||||
**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).
|
||||
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).
|
||||
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).
|
||||
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, 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.
|
||||
**Note 2**: For string operators, 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
|
||||
@@ -67,7 +70,7 @@ This value can be found under `type` field. Types are:
|
||||
* `AND` - all sub-conditions must be met for the final condition to pass
|
||||
* `OR` - at least one sub-condition must be met for the final condition to pass
|
||||
|
||||
If you only defined one subcondition, you don't need to define type at all, since it's not used for anything.
|
||||
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.
|
||||
@@ -93,7 +96,9 @@ conditions:
|
||||
You have 2 ways to use conditions.
|
||||
|
||||
## Displaying text
|
||||
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.
|
||||
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.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
@@ -110,7 +115,9 @@ Use with `%condition:serverName%`
|
||||
</details>
|
||||
|
||||
## 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.
|
||||
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.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
@@ -154,9 +161,12 @@ display-condition: "%server%=lobby|%server%=lobby2"
|
||||
</details>
|
||||
|
||||
# Refresh interval
|
||||
Conditions are just placeholders afterall, and, as such, they must be refreshed priodically. Refresh intervals of conditions are not directly configurable. They are based on placeholders used inside (subconditions, yes/no values).
|
||||
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).
|
||||
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).
|
||||
To configure refresh intervals of placeholders,
|
||||
check out the [Optimization guide](https://github.com/NEZNAMY/TAB/wiki/Optimizing-the-plugin#2---placeholder-refresh-intervals).
|
||||
|
||||
# Examples
|
||||
## Example 1 - Chaining conditional placeholders
|
||||
@@ -187,8 +197,10 @@ 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.
|
||||
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:
|
||||
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.
|
||||
For example, if we want to check that player is in server `lobby` **and** in worlds **either** `world1` or `world2`,
|
||||
it can be achieved in the following way:
|
||||
```
|
||||
conditions:
|
||||
world:
|
||||
|
||||
@@ -11,17 +11,20 @@ This feature allows you to see players from other servers under a bungeecord net
|
||||
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.
|
||||
|
||||
# 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. |
|
||||
| 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). |
|
||||
|
||||
## Grouping players only from certain servers
|
||||
In case you want multiple servers to share playerlist, but not with every server, simply create a server group and put servers there. The default example
|
||||
In case you want multiple servers to share playerlist,
|
||||
but not with every server, create a server group and put servers there.
|
||||
The default example
|
||||
```
|
||||
global-playerlist:
|
||||
server-groups:
|
||||
@@ -32,17 +35,21 @@ global-playerlist:
|
||||
- server1
|
||||
- server2
|
||||
```
|
||||
contains 2 groups, each of them consisting of 2 servers. Server group name can be anything (in our case they're called "lobbies" and "group2"). Under group name, list the actual server names defined in config.yml of bungeecord.
|
||||
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.
|
||||
|
||||
With this setup, "lobby1" and "lobby2" will share playerlist, as well as "server1" with "server2". All unlisted servers are automatically put into a hidden default group and share playerlist. This means that all other servers except these 4 will share playerlist.
|
||||
|
||||
To make all servers share playerlist, simply clear server groups and set
|
||||
To make all servers share the playerlist, simply clear server groups and set
|
||||
```
|
||||
server-groups: {}
|
||||
```
|
||||
|
||||
## Configuring isolated servers
|
||||
If you want servers which are isolated (no one will see these players and they will not see anyone on other servers), simply create a new group and only put that 1 server there. For example:
|
||||
If you want servers which are isolated (no one will see these players, and they will not see anyone on other servers),
|
||||
create a new group and only put that 1 server there.
|
||||
For example:
|
||||
```
|
||||
global-playerlist:
|
||||
server-groups:
|
||||
@@ -53,7 +60,9 @@ global-playerlist:
|
||||
```
|
||||
|
||||
## Seeing all players on the network from some server
|
||||
If despite configuring server groups you want players to see everyone on the network if they're connected to specific server(s), you can simply list those servers at
|
||||
If, despite configuring server groups,
|
||||
you want players to see everyone on the network if they're connected to specific server(s),
|
||||
you can list those servers at
|
||||
```
|
||||
global-playerlist:
|
||||
spy-servers:
|
||||
|
||||
@@ -16,9 +16,9 @@ Minecraft feature **introduced in 1.8** showing text above and below playerlist.
|
||||

|
||||
|
||||
# Configuration
|
||||
| Option name | Default value | Description |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| enabled | true | Enables / Disables the feature |
|
||||
| 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. |
|
||||
|
||||
## Global settings
|
||||
@@ -65,7 +65,9 @@ header-footer:
|
||||
- "Header in all worlds starting with lobby-"
|
||||
```
|
||||
|
||||
**Note**: To make per-world work on BungeeCord, install the [TAB-Bridge](https://www.mc-market.org/resources/21641) plugin on your backend servers.
|
||||
> [!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**
|
||||
@@ -87,7 +89,7 @@ Same for users, which can be configured in **users.yml**.
|
||||
## Additional note 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(nother) plugin that sends some, or even empty header/footer on join.
|
||||
* Install a plugin that sends some, or even empty header/footer on join.
|
||||
|
||||
# Tips & Tricks
|
||||
## Tip 1 - Dynamic line count
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
* [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 - Entries in chat complete [1.19.3 - 1.21.1]](#additional-note-3---entries-in-chat-complete-1193---1211)
|
||||
* [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)
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Per-server columns](#example-1---per-server-columns)
|
||||
|
||||
@@ -25,7 +26,10 @@ This feature is only available for versions **1.8** and up due to massive tablis
|
||||
Layouts can be creating in config under `layout.layouts` section. Each layout contains 3 settings: Fixed slots, player groups and display condition (optional).
|
||||
|
||||
## Display condition
|
||||
Condition that must be met for player to see the layout. If player does not meet the condition, next defined layout's condition is checked. If player does not meet any defined display condition, they will see default tablist. Display condition is optional and doesn't need to be set.
|
||||
Condition that must be met for player to see the layout.
|
||||
If player does not meet the condition, the next defined layout's condition is checked.
|
||||
If a player does not meet any defined display condition, they will see the default tablist.
|
||||
Display condition is optional and doesn't need to be set.
|
||||
For list of possible condition types see [Conditions page](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders).
|
||||
Example:
|
||||
```
|
||||
@@ -38,7 +42,7 @@ This layout will only be visible to players with `tab.staff` permission.
|
||||
## 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`.
|
||||
`SLOT` - the position of the fixed slot. It can be from 1 to 80. By default, the direction is set to columns, so the first column is 1-20.
|
||||
`SLOT` - The position of the fixed slot. It can be from 1 to 80. By default, the direction is set to columns, so the first column is 1-20.
|
||||
`TEXT` - the text. It supports placeholders.
|
||||
`SKIN` - layout's skin, see below for configuration.
|
||||
Example:
|
||||
@@ -54,10 +58,14 @@ layouts:
|
||||
```
|
||||
|
||||
## Player groups
|
||||
These are groups of players which meet the specified condition. They consist of 2 parts - condition and slots.
|
||||
These are groups of players that meet the specified condition. They consist of 2 parts - condition and slots.
|
||||
|
||||
**1. Condition**
|
||||
Condition players must meet to be displayed in the group. If a player doesn't meet condition for group, the next group's condition is checked (groups are checked in the order they are defined in config). If player doesn't meet any codnition, they are not displayed at all. Display condition is not required (can be used for default group).
|
||||
The condition players must meet to be displayed in the group.
|
||||
If a player doesn't meet condition for a group, the next group's condition is checked
|
||||
(groups are checked in the order they are defined in config).
|
||||
If player doesn't meet any condition, they are not displayed at all.
|
||||
Display condition is not required (can be used to make a "default" group with the remaining players).
|
||||
|
||||
**2. Slots**
|
||||
Slot intervals dedicated to the group. Interval `1-5` would mean all slots from 1 to 5. In case you want to define multiple intervals to exclude some slots, define another interval below the first one.
|
||||
@@ -77,7 +85,11 @@ layouts:
|
||||
In this example, slots `24-40` will be reserved for players with `tab.staff` permission. Players without that permission will be in slots `44-80`.
|
||||
|
||||
# Managing multiple layouts with conditions
|
||||
You can define multiple layouts and display them based on a condition. To do so, define `condition` for layouts. Conditions are checked in the order layouts are defined in config. If layout doesn't specify condition, it is displayed with no requirement. If player does not meet display condition for any layout, they will see the classic tablist.
|
||||
You can define multiple layouts and display them based on a condition.
|
||||
To do so, define `condition` for layouts.
|
||||
Conditions are checked in the order layouts are defined in config.
|
||||
If layout doesn't specify condition, it is displayed with no requirement.
|
||||
If a player does not meet display condition for any layout, they will see the classic tablist.
|
||||
Example:
|
||||
```
|
||||
layouts:
|
||||
@@ -132,13 +144,13 @@ Yellow: 1307755006
|
||||
```
|
||||
|
||||
# Additional settings
|
||||
| Option name | Default value | Description |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| direction | COLUMNS | Defines direction of slots. Options are COLUMNS (top to bottom, left to right) and ROWS (left to right, top to bottom). This does not only change the slot numbers in configuration, but will also affect the way players are being filled into player groups. |
|
||||
| enable-remaining-players-text | true | When enabled, the last slot of player group will show how many more players there are, instead of using the last slot for one more player. |
|
||||
| remaining-players-text | "... and %s more" | Text to show if option above is enabled. |
|
||||
| default-skin | "mineskin:1753261242" | Default skin to display for fixed slots that do not define a skin, empty slots and fixed slots with invalid skin. |
|
||||
| empty-slot-ping-value | 1000 | Ping value to use for fixed slots and empty slots. The ping intervals for bars are client sided and are as following: <br />- Negative value: ✖ <br />- 0 - 149: 5 bars <br />- 150 - 299: 4 bars <br />- 300 - 599: 3 bars <br />- 600 - 999: 2 bars <br />- 1000+: 1 bar |
|
||||
| Option name | Default value | Description |
|
||||
|-------------------------------|----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| direction | COLUMNS | Defines direction of slots. Options are COLUMNS (top to bottom, left to right) and ROWS (left to right, top to bottom). This does not only change the slot numbers in configuration, but will also affect the way players are being filled into player groups. |
|
||||
| enable-remaining-players-text | true | When enabled, the last slot of player group will show how many more players there are, instead of using the last slot for one more player. |
|
||||
| remaining-players-text | "... and %s more" | Text to show if option above is enabled. |
|
||||
| default-skin | "mineskin:383747683" | Default skin to display for fixed slots that do not define a skin, empty slots and fixed slots with invalid skin. |
|
||||
| empty-slot-ping-value | 1000 | Ping value to use for fixed slots and empty slots. The ping intervals for bars are client sided and are as following: <br />- Negative value: ✖ <br />- 0 - 149: 5 bars <br />- 150 - 299: 4 bars <br />- 300 - 599: 3 bars <br />- 600 - 999: 2 bars <br />- 1000+: 1 bar |
|
||||
|
||||

|
||||

|
||||
@@ -152,20 +164,31 @@ As a result, it is impossible for TAB to assign a different value for each fake
|
||||
## Additional note 2 - 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 just 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 BungeeCord. Because of this, if you use layout, you can disable global playerlist to reduce resource usage.
|
||||
|
||||
## Additional note 3 - Entries in chat complete [1.19.3 - 1.21.1]
|
||||
Since 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**: In order to hide entries from chat complete on 1.21.2+, the server also has to be 1.21.2+ so it can send new content to the players (having TAB installed on proxy counts as using latest version).
|
||||
**Note 2**: The 1.21.2+ improvement was added in [dev builds](https://github.com/NEZNAMY/TAB/actions) (v5) and will not be added into v4.
|
||||
## 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
|
||||
Layout works by adding 80 fake players into the tablist, pushing real player entries out of view. Because of this, when using [per world playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Per-world-playerlist), the feature will only hide the real players, which are outside of tablist and not visible anyway and not touch the layout entries. However, you can replicate the same effect using layout feature itself, using conditions.
|
||||
Layout works by adding 80 fake players into the tablist, pushing real player entries out of view.
|
||||
Because of this,
|
||||
when using [per world playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Per-world-playerlist),
|
||||
the feature will only hide the real players,
|
||||
which are outside tablist and not visible anyway and not touch the layout entries.
|
||||
However, you can replicate the same effect using layout feature itself, using conditions.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
*We are going to ignore fixed slots in the examples, as they don't affect anything and you can just configure them however you want.*
|
||||
Let's create 2 layouts, one for world `world1` and one for world `world2`. Each layout only displays players in that world.
|
||||
*We are going to ignore fixed slots in the examples,
|
||||
as they don't affect anything, and you can just configure them however you want.*
|
||||
Let's create 2 layouts, one for world `world1` and one for world `world2`.
|
||||
Each layout only displays players in that world.
|
||||
```
|
||||
layouts:
|
||||
layout1:
|
||||
@@ -210,13 +233,23 @@ 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
|
||||
Layout works by creating 80 fake entries, pushing real players out of the tablist.
|
||||
Unfortunately, players must be spawned around the player viewing the tablist to see the second layer of their skin.
|
||||
Since those fake entries you see are not the actual players and aren't spawned,
|
||||
as a result, you won't see the second layers of skins.
|
||||
This can only be fixed by actually letting the real entries display in the tablist,
|
||||
which would require a rework of the feature, which is not planned.
|
||||
**1.21.4 has added a new tablist option called "show hats", which layout sets to true.
|
||||
They will be visible for 1.21.4+ players on 1.21.4+ servers (using a proxy counts as being latest).**
|
||||
|
||||
# Examples
|
||||
## Example 1 - Per-server columns
|
||||
```
|
||||
layout:
|
||||
enabled: true
|
||||
direction: COLUMNS
|
||||
default-skin: mineskin:1753261242
|
||||
default-skin: mineskin:383747683
|
||||
enable-remaining-players-text: true
|
||||
remaining-players-text: '... and %s more'
|
||||
empty-slot-ping-value: 1000
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* [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)
|
||||
* [API](#api)
|
||||
* [Changing prefix and suffix](#changing-prefix-and-suffix)
|
||||
* [Collision](#collision)
|
||||
@@ -55,7 +56,9 @@ _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.
|
||||
Properties can also be set as "default" for everyone who does not have them defined.
|
||||
For that purpose, a group keyword `_DEFAULT_` was made.
|
||||
Example:
|
||||
**groups.yml**
|
||||
```
|
||||
admin:
|
||||
@@ -92,7 +95,7 @@ per-world:
|
||||
```
|
||||
|
||||
## Priority system
|
||||
Full list of priorities looks like this:
|
||||
The full list of priorities looks like this:
|
||||
1. value set using the [API](#api)
|
||||
2. per-world / per-server applied to username
|
||||
3. value applied to username
|
||||
@@ -105,25 +108,29 @@ Full list of priorities looks like this:
|
||||
|
||||
This list is browsed through until the first match is found. If no match is found, empty value is used.
|
||||
|
||||
Values are taken independently from each other. This means you can set per-world tagprefix, but only keep one global tagsuffix for example.
|
||||
Values are taken independently of each other.
|
||||
This means you can set per-world tagprefix, but only keep one global tagsuffix, for example.
|
||||
|
||||
You can see source of a value displayed on player by using `/tab debug <player>` and checking "source" part of the value you are looking for.
|
||||
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.
|
||||
|
||||
## 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. Amount of placeholders is not limited and they can be used in combination with static text as well.
|
||||
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 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. |
|
||||
|
||||
# Tips & Tricks
|
||||
If you want TAB to only take prefixes/suffixes from permission plugin, delete all groups from **grous.yml** and only keep this:
|
||||
If you want TAB to only take prefixes/suffixes from the permission plugin,
|
||||
delete all groups from **groups.yml** and only keep this:
|
||||
```
|
||||
_DEFAULT_:
|
||||
tagprefix: "%luckperms-prefix%"
|
||||
@@ -131,24 +138,50 @@ _DEFAULT_:
|
||||
```
|
||||
|
||||
# Limitations
|
||||
* Prefix/suffix length is limited to 16 characters (including color codes) on <1.13. There is no reachable limit on 1.13+.
|
||||
* Name cannot be effectively changed and plugin doesn't offer it.
|
||||
* Since 1.13, the name can only have one code. That is either color or magic code (such as &4 or &l), but not both.
|
||||
* [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.
|
||||
* Name color and glow color are managed by the same value, which means they cannot be different.
|
||||
* The same value manages name color and glow color, which means they cannot be different.
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - NPC (in)compatibility
|
||||
Teams are bound to player names, not uuids or entity ids. Because of that, they will affect all player entities with that name. This includes NPCs with same names as online players and prefixes/suffixes will be displayed on those as well. To avoid it, make their names not match any online player and use holograms to display them instead (Citizens has an option for this).
|
||||
Teams are bound to player names, not uuids or entity ids.
|
||||
Because of that, they will affect all player entities with that name.
|
||||
This includes NPCs with the same names as online players, and prefixes/suffixes will be displayed on those as well.
|
||||
To avoid it, make their names not match any online player and use holograms to display them instead
|
||||
(Citizens plugin has an option for this).
|
||||
|
||||
## Additional note 2 - Prefix/suffix on pets
|
||||
Since 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 TAB supports it doesn't sound like fun doing.
|
||||
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.
|
||||
|
||||
## Additional note 4 - F1 view
|
||||
Using teams causes player nametags to remain visible when using F1 view. This cannot be avoided by the plugin in any way. The only possible solution would be to modify the client.
|
||||
Using teams causes player nametags to remain visible when using F1 view.
|
||||
The plugin cannot avoid this in any way.
|
||||
The only possible solution would be to modify the client.
|
||||
|
||||
## Additional note 5 - Transparent players
|
||||
Minecraft's teams can show players in the same team transparent (partially invisible).
|
||||
This requires both players (viewer and target) to be in the same team.
|
||||
As such, this effect is impossible to achieve with TAB,
|
||||
because it puts every player into a different team
|
||||
to properly sort players and give them different prefix/suffix in nametag
|
||||
(and more, such as collision and nametag visibility).
|
||||
|
||||
If you want this effect, the only way is to use another plugin that offers this and disable TAB's teams entirely by setting
|
||||
```
|
||||
scoreboard-teams:
|
||||
enabled: false
|
||||
```
|
||||
In config.yml. Keep in mind, you'll not be able to use any team features if you do so.
|
||||
|
||||
# API
|
||||
*To get started with the API, see [Developer API](https://github.com/NEZNAMY/TAB/wiki/Developer-API) page.*
|
||||
@@ -165,11 +198,15 @@ To get custom values previously set using the API (they will return `null` if no
|
||||
* `NameTagManager#getCustomPrefix(TabPlayer)`
|
||||
* `NameTagManager#getCustomSuffix(TabPlayer)`
|
||||
|
||||
To get original value set by the plugin based on configuration:
|
||||
To get the original value set by the plugin based on configuration:
|
||||
* `NameTagManager#getOriginalPrefix(TabPlayer)`
|
||||
* `NameTagManager#getOriginalSuffix(TabPlayer)`
|
||||
|
||||
**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).
|
||||
> [!NOTE]
|
||||
> These values are only temporary,
|
||||
> meaning they won't get saved anywhere and will get reset on player quit or plugin reload.
|
||||
> If you wish to save these values into file,
|
||||
> use [commands](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions#tab-playergroupplayeruuid-name-property-value-options).
|
||||
|
||||
## Collision
|
||||
* `NameTagManager#getCollisionRule(TabPlayer)` - Returns forced collision rule using the API, `null` if no value was forced and player follows the configuration.
|
||||
@@ -177,11 +214,11 @@ To get original value set by the plugin based on configuration:
|
||||
|
||||
## Manipulating visibility
|
||||
* `NameTagManager#hideNametag(TabPlayer)` - Hides player's nametag from all players
|
||||
* `NameTagManager#hideNametag(TabPlayer, TabPlayer)` - Hides player's nametag from a specific player, where the first `TabPlayer` is the player who's nametag you want to hide, and the second `TabPlayer` is the player who you want to hide the first player's nametag from.
|
||||
* `NameTagManager#hideNametag(TabPlayer, TabPlayer)` - Hides player's nametag from a specific player, where the first `TabPlayer` is the player whose nametag you want to hide, and the second `TabPlayer` is the player who you want to hide the first player's nametag from.
|
||||
* `NameTagManager#showNametag(TabPlayer)` - Shows player's nametag back again for everyone
|
||||
* `NameTagManager#showNametag(TabPlayer, TabPlayer)` - Shows player's nametag back. The first `TabPlayer` is the player who's nametag you want to show, and the second `TabPlayer` is the player who you want to show the first player's nametag to.
|
||||
* `NameTagManager#showNametag(TabPlayer, TabPlayer)` - Shows player's nametag back. The first `TabPlayer` is the player whose nametag you want to show, and the second `TabPlayer` is the player who you want to show the first player's nametag to.
|
||||
* `NameTagManager#hasHiddenNametag(TabPlayer)` - Returns `true` if player has hidden nametag for everyone, `false` if not
|
||||
* `NameTagManager#hasHiddenNametag(TabPlayer, TabPlayer)` - Returns `true` if player has hidden anmetag for specific player, `false` if not. The first `TabPlayer` is the player who's nametag you want to check is hidden, and the second `TabPlayer` is the player who you want to check if they can see the first player's nametag.
|
||||
* `NameTagManager#hasHiddenNametag(TabPlayer, TabPlayer)` - Returns `true` if player has hidden nametag for specific player, `false` if not. The first `TabPlayer` is the player whose nametag you want to check is hidden, and the second `TabPlayer` is the player who you want to check if they can see the first player's nametag.
|
||||
|
||||
## Disabling team handling
|
||||
* `NameTagManager#pauseTeamHandling(TabPlayer)` - Pauses team handling for a specific player. This will unregister the player's team and disable anti-override for teams.
|
||||
|
||||
@@ -9,12 +9,12 @@ This feature can be configured in **config.yml** under **per-world-playerlist**
|
||||
To use it, you need TAB installed on bukkit server. This feature is not available on BungeeCord.
|
||||
|
||||
# Configuration
|
||||
| Option name | Default value | Description |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| enabled | false | Enables / Disables the feature. |
|
||||
| allow-bypass-permission | false | If enabled, players with `tab.bypass` permission will see everyone in tablist despite this feature enabled. |
|
||||
| ignore-effect-in-worlds | *List* | List of worlds where players will see everyone in tablist, not just players in the same world / world group |
|
||||
| shared-playerlist-world-groups | *Map* | See [Grouping playerlist from multiple worlds](#grouping-playerlist-from-multiple-worlds) |
|
||||
| Option name | Default value | Description |
|
||||
|--------------------------------|---------------|-------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | false | Enables / Disables the feature. |
|
||||
| allow-bypass-permission | false | If enabled, players with `tab.bypass` permission will see everyone in tablist despite this feature enabled. |
|
||||
| ignore-effect-in-worlds | *List* | List of worlds where players will see everyone in tablist, not just players in the same world / world group |
|
||||
| shared-playerlist-world-groups | *Map* | See [Grouping playerlist from multiple worlds](#grouping-playerlist-from-multiple-worlds) |
|
||||
|
||||
## Grouping playerlist from multiple worlds
|
||||
In case you want multiple worlds to share playerlist despite this option enabled, create a group and put world names there. The default example
|
||||
@@ -28,6 +28,8 @@ per-world-playerlist:
|
||||
- paintball
|
||||
- bedwars
|
||||
```
|
||||
contains 2 groups, each of them consisting of 2 worlds. World group name can be anything (in our case they're called "lobby" and "minigames"). Under group name, list the actual world names.
|
||||
Contains 2 groups, each of them consisting of 2 worlds.
|
||||
World group name can be anything (in our case, they're called "lobby" and "minigames").
|
||||
Under group name, list the actual world names.
|
||||
|
||||
With this setup, "lobby1" and "lobby2" will share playerlist, as well as "paintball" with "bedwars". All other worlds will have playerlist not shared with any other worlds. Creating a group for 1 world only is completely useless.
|
||||
@@ -1,5 +1,9 @@
|
||||
# About
|
||||
By default, the server sends information about ping of players to everyone, which you can see in the tablist as the green bar. Some modified clients allow to see the exact value instead of just bars. This feature spoofs ping value of all players to the configured value, hiding their true ping. I don't know why would anyone want to do that.
|
||||
By default, the server sends information about ping of players to everyone,
|
||||
which you can see in the tablist as the green bar.
|
||||
Some modified clients allow seeing the exact value instead of just bars.
|
||||
This feature spoofs the ping value of all players to the configured value, hiding their true ping.
|
||||
I don't know why anyone would want to do that.
|
||||
|
||||
# Configuration
|
||||
Find this section in your **config.yml**
|
||||
@@ -12,11 +16,11 @@ To enable the feature, set `enabled: true`.
|
||||
When the feature is enabled, everyone's ping value will be shown as value configured in `value` field.
|
||||
|
||||
The ping intervals for bars are client sided and are as following:
|
||||
| Ping value | Displayed icon |
|
||||
| Ping value | Displayed icon |
|
||||
| ----------- | -------------- |
|
||||
| Negative |  |
|
||||
| 0 - 149 |  |
|
||||
| 150 - 299 |  |
|
||||
| 300 - 599 |  |
|
||||
| 600 - 999 |  |
|
||||
| 1000+ |  |
|
||||
| Negative | |
|
||||
| 0 - 149 | |
|
||||
| 150 - 299 | |
|
||||
| 300 - 599 | |
|
||||
| 600 - 999 | |
|
||||
| 1000+ | |
|
||||
@@ -10,9 +10,14 @@
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Adding brackets to placeholder output if it returns non-empty value](#example-1---adding-brackets-to-placeholder-output-if-it-returns-non-empty-value)
|
||||
* [Example 2 - Replicating PlaceholderAPI's %player_colored_ping%](#example-2---replicating-placeholderapis-player_colored_ping)
|
||||
* [Example 3 - Using both original and replaced output](#example-3---using-both-original-and-replaced-output)
|
||||
|
||||
# About
|
||||
Most placeholders don't have fully configurable output, making you unable to customize it as you'd like. This is especially a problem with placeholders such as vanish or afk ones that return "yes" or "no" instead of some fancy text. It is job of the plugins providing placeholders to allow control over outputs, but for plugins that don't we have a solution - now you're able to configure output of any placeholder in many ways.
|
||||
Most placeholders don't have fully configurable output, making you unable to customize it as you'd like.
|
||||
This is especially a problem with placeholders such as vanish or afk ones that return "yes"
|
||||
or "no" instead of some fancy text.
|
||||
It is a job of the plugins providing placeholders to allow control over outputs,
|
||||
but for plugins that don't we have a solution - now you're able to configure output of any placeholder in many ways.
|
||||
|
||||
# Configuration
|
||||
Open **config.yml** and find this section:
|
||||
@@ -25,7 +30,7 @@ placeholder-output-replacements:
|
||||
## Supported replacement patterns
|
||||
|
||||
### Pattern 1: Exact text
|
||||
If placeholder's output is exact to the text on left side, it will return text on the right side.
|
||||
If the placeholder's output is exact to the text on the left side, it will return text on the right side.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
@@ -40,11 +45,17 @@ placeholder-output-replacements:
|
||||
|
||||
</details>
|
||||
|
||||
**Note 1:** If you want to replace empty output, use `""` or `''` on the left side.
|
||||
**Note 2:** The text must match exactly, including color codes. To check 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.
|
||||
> [!NOTE]
|
||||
> If you want to replace empty output, use `""` or `''` on the left side.
|
||||
|
||||
> [!NOTE]
|
||||
> The text must match exactly, including color codes.
|
||||
> To check the color codes a placeholder returns use
|
||||
> [`/tab parse <player> <placeholder>`](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions#tab-parse-text)
|
||||
> and check "Without colors" part.
|
||||
|
||||
### Pattern 2: Number intervals
|
||||
Output will be replaced if it's numeric and belongs in configured interval.
|
||||
Output will be replaced if it's numeric and belongs in a configured interval.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
@@ -57,9 +68,12 @@ placeholder-output-replacements:
|
||||
```
|
||||
</details>
|
||||
|
||||
**Note:** If a number is included in more than 1 interval (just like 5 and 15 from the example above), the one higher is used. In this case, 15 would give `Solid` and 5 would give `Bad`.
|
||||
> [!NOTE]
|
||||
> If a number is included in more than 1 interval (just like 5 and 15 from the example above), the one higher is used.
|
||||
> In this case, 15 would give `Solid` and 5 would give `Bad`.
|
||||
|
||||
Intervals can be defined using both `-` and `~`. If you need support for negative values, use `~` for interval instead of `-`.
|
||||
Intervals can be defined using both `-` and `~`.
|
||||
If you need support for negative values, use `~` for an interval instead of `-`.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
@@ -88,7 +102,8 @@ placeholder-output-replacements:
|
||||
</details>
|
||||
|
||||
## Supported content in values
|
||||
You can use placeholders inside outputs, including the original placeholder you are altering. It will return original output of the placeholder.
|
||||
You can use placeholders inside outputs, including the original placeholder you are altering.
|
||||
It will return the original output of the placeholder.
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
@@ -101,18 +116,23 @@ placeholder-output-replacements:
|
||||
"else": "%tps% (Terrible)"
|
||||
```
|
||||
|
||||
With this example, if TPS reaches for example 17.5, the output would be `17.5 (Solid)`.
|
||||
With this example, if TPS reaches, for example 17.5, the output would be `17.5 (Solid)`.
|
||||
</details>
|
||||
|
||||
# Using in other plugins
|
||||
These replacements are only supported inside TAB. They won't work in other plugins.
|
||||
If you want to use these in other plugins, you'll need to [enable tab's PlaceholderAPI expansion](https://github.com/NEZNAMY/TAB/wiki/Placeholders#placeholderapi) and use `%tab_replace_<placeholder>%`. If you for example configure output for %player_health%, use `%tab_replace_player_health%`.
|
||||
If you want to use these in other plugins, you'll need to [enable tab's PlaceholderAPI expansion](https://github.com/NEZNAMY/TAB/wiki/Placeholders#placeholderapi) and use `%tab_replace_<placeholder>%`. If you, for example, configure output for %player_health%, use `%tab_replace_player_health%`.
|
||||
|
||||
This only works for PlaceholderAPI placeholders, not TAB's internal ones. For TAB's internal ones use `%tab_placeholder_<placeholder>`, such as for %health% use `%tab_placeholder_health%`.
|
||||
|
||||
# Examples
|
||||
## Example 1 - Adding brackets to placeholder output if it returns non-empty value
|
||||
When displaying faction or clan of players, you may want to add brackets if player is in a faction/clan, but not show them if they are not in one. To achieve this, we are going to use [Pattern 1: Exact text](#pattern-1-exact-text) and [Pattern 3: else](#pattern-3-else). If placeholder returned nothing, show nothing. Otherwise, show the output with added brackets:
|
||||
When displaying faction or clan of players, you may want to add brackets if a player is in a faction/clan,
|
||||
but not show them if they are not in one.
|
||||
To achieve this,
|
||||
we are going to use [Pattern 1: Exact text](#pattern-1-exact-text) and [Pattern 3: else](#pattern-3-else).
|
||||
If the placeholder returned nothing, show nothing.
|
||||
Otherwise, show the output with added brackets:
|
||||
```
|
||||
placeholder-output-replacements:
|
||||
"%my_placeholder%":
|
||||
@@ -128,7 +148,9 @@ placeholder-output-replacements:
|
||||
```
|
||||
**Don't forget that parse command applies replacements, so when trying to see what placeholder returns, you should disable any previously configured replacements for that placeholder to see the correct raw output**.
|
||||
## Example 2 - Replicating PlaceholderAPI's %player_colored_ping%
|
||||
*Please note that this is just an example to demonstrate the plugin's functionality. It is not supposed to discourage anyone from using PlaceholderAPI or any of its placeholders.*
|
||||
> [!NOTE]
|
||||
> Please note that this is just an example to demonstrate the plugin's functionality.
|
||||
> It is not supposed to discourage anyone from using PlaceholderAPI or any of its placeholders.*
|
||||
|
||||
The placeholder allows you to configure intervals in config.yml. Default values are <50 for good, <100 for medium and 100+ for high. We can achieve this using [Pattern 2: Number intervals](#pattern-2-number-intervals) and [Pattern 3: else](#pattern-3-else). When put together, it looks as following:
|
||||
```
|
||||
@@ -138,4 +160,37 @@ placeholder-output-replacements:
|
||||
"51-100": "&e%ping%"
|
||||
"else": "&c%ping%"
|
||||
```
|
||||
Keep in mind that now the placeholder will no longer return just a number, which breaks features like [Yellow Number](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Yellow-number), which require a numeric input. If you want that feature and ping to be displayed there, replacements won't work for you and you'll need to use [Conditional placeholders](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) instead to achieve colored ping.
|
||||
Keep in mind that now the placeholder will no longer return just a number,
|
||||
which can break features like [Playerlist Objective](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Playerlist-Objective),
|
||||
which require a numeric input (for versions prior to 1.20.3).
|
||||
If you want that feature and ping to be displayed there, replacements won't work for you,
|
||||
and you'll need
|
||||
to use [Conditional placeholders](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) instead
|
||||
to achieve colored ping.
|
||||
|
||||
# Example 3 - Using both original and replaced output
|
||||
Once configured, replacements are applied as the placeholder output everywhere. It is not directly possible to use original output in one place and replaced in another.
|
||||
|
||||
If you need this, you should consider [conditional placeholders](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) instead.
|
||||
If conditional placeholders are too complicated to use, there are alternate ways. The main point of the solution is to create different placeholder that eventually calls the same function and returns the same result. This can be done by "wrapping" the placeholder into another one. The easiest way using existing TAB's functions is using animations. Create an animation with a single frame that contains the placeholder and configure replacements for that placeholder instead.
|
||||
<details>
|
||||
<summary>Example for %ping%</summary>
|
||||
|
||||
**animations.yml**:
|
||||
```
|
||||
ping:
|
||||
change-interval: 50 # Actual value doesn't matter
|
||||
texts:
|
||||
- "%ping%"
|
||||
```
|
||||
Then, configure replacements for the animation in **config.yml**:
|
||||
```
|
||||
placeholder-output-replacements:
|
||||
"%animation:ping%":
|
||||
"0-50": "&a%animation:ping%" # %ping% would work too
|
||||
"51-100": "&e%animation:ping%"
|
||||
"else": "&c%animation:ping%"
|
||||
```
|
||||
Now, you can use `%ping%` for original output and `%animation:ping%` for replaced.
|
||||
|
||||
</details>
|
||||
@@ -18,15 +18,16 @@ 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. 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. |
|
||||
|
||||
# Limitations
|
||||
On 1.20.2 and lower, only 2 display types are supported - number and hearts. The number's color is yellow and cannot be changed.
|
||||
* [1.5 - 1.20.2] Only 2 display types are supported - yellow number and hearts.
|
||||
* [1.5 - 1.20.2] A yellow 0 will appear on all tablist entries that aren't actual players (such as NPCs and [layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) entries) and it cannot be removed.
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - Spectator gamemode
|
||||
|
||||
@@ -18,8 +18,9 @@
|
||||
* [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 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)
|
||||
|
||||
# About
|
||||
Scoreboard objective with SIDEBAR display slot.
|
||||
@@ -32,10 +33,12 @@ Scoreboards can be created in `scoreboards` section. You can define as many scor
|
||||
Each scoreboard defines up to 3 parameters:
|
||||
|
||||
## title
|
||||
Title of the scoreboard. Limited to 32 characters on MineCraft versions below 1.13 (including color codes. It is automatically centered by the client.
|
||||
Title of the scoreboard.
|
||||
Limited to 32 characters on MineCraft versions below 1.13 (including color codes).
|
||||
It is automatically centered by the client.
|
||||
|
||||
## lines
|
||||
Up to 15 lines of text. You can define more, but client won't display them.
|
||||
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:
|
||||
```
|
||||
@@ -47,10 +50,21 @@ Since 1.20.3, you can also configure the value on the right side, which no longe
|
||||
Will give you the following:
|
||||

|
||||
|
||||
The right side text will not be visible on 1.20.2 and lower and numbers will be displayed instead. In order to properly see the right side not only the client has to be 1.20.3+, but the server as well, since plugin cannot send a packet that does not exist (on older versions). BungeeCord always includes new content and therefore counts as latest version. This can be used to send new content to new players while having outdated server version.
|
||||
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
|
||||
Left side of the text is automatically aligned to the left, while the right side is automatically aligned to the right. This is done by the client and is out of plugin's control. If you want to center a line, you'll need to do it manually. If dynamic placeholder output length is preventing your from doing it, you can try to bypass it by adding spaces before and after it to artificially increase and force the scoreboard width, such as `- " Centered text "` (or more spaces if needed).
|
||||
The left side of the text is automatically aligned to the left,
|
||||
while the right side is automatically aligned to the right.
|
||||
This is done by the client and is out of plugin's control.
|
||||
If you want to center a line, you'll need to do it manually.
|
||||
If dynamic placeholder output length is preventing your from doing it,
|
||||
you can try to bypass it by adding spaces before and after it to artificially increase and force the scoreboard width,
|
||||
such as
|
||||
`- " Centered text "` (or more spaces if needed).
|
||||
|
||||
### Empty placeholder output
|
||||
When a line consists only of a placeholder that returned empty output, the line will be hidden completely. This is intentional to allow dynamic scoreboard size based on placeholder output. This is not the case if empty line is configured (`""`), to allow empty lines in configuration.
|
||||
@@ -59,7 +73,12 @@ When a line consists only of a placeholder that returned empty output, the line
|
||||
A [condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) that must be met to display this scoreboard. If it isn't met for the player, the next scoreboard's condition is checked.
|
||||
|
||||
# Chaining scoreboards
|
||||
When defining more than 1 scoreboard in config, the plugin will display the correct scoreboard based on conditions. Plugin goes through all defined scoreboards, starting with the scoreboard on top. If the scoreboard's condition is met or not set, it is displayed. If not, next defined scoreboard is checked and so on. If no suitable scoreboard is found (the last one has a condition requirement which wasn't met), none is displayed. Example:
|
||||
When defining more than 1 scoreboard in config, the plugin will display the correct scoreboard based on conditions.
|
||||
The plugin goes through all defined scoreboards, starting with the scoreboard on top.
|
||||
If the scoreboard's condition is met or not set, it is displayed.
|
||||
If not, the next defined scoreboard is checked and so on.
|
||||
If no suitable scoreboard is found (the last one has a condition requirement which wasn't met), none is displayed.
|
||||
Example:
|
||||
```
|
||||
scoreboards:
|
||||
scoreboard1:
|
||||
@@ -81,46 +100,68 @@ Scoreboard `scoreboard1` is checked first. If condition is not met, `scoreboard2
|
||||
If a player meets both conditions (has defined permission and is in defined world), `scoreboard1` will be displayed, because it is defined first and therefore has the highest priority. You can switch scoreboards based on your priority needs.
|
||||
|
||||
# Announce command
|
||||
This takes priority over current scoreboard. Once the announce is over, previous scoreboard is restored.
|
||||
This takes priority over the current scoreboard.
|
||||
Once the announcement is over, the previous scoreboard is restored.
|
||||
`/tab announce scoreboard <name> <time>`
|
||||
name - name of scoreboard to be displayed
|
||||
time - amount of seconds to display the scoreboard for
|
||||
time - number of seconds to display the scoreboard for
|
||||
|
||||
# Additional settings
|
||||
| Option name | Default value | Description |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| enabled | false | Enables / Disables the feature |
|
||||
| toggle-command | /sb | Command that can be used to toggle scoreboard for the player running the command. Players need `tab.scoreboard.toggle` permission to use it. <br />**Note:** 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. |
|
||||
| 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. |
|
||||
| respect-other-plugins | true | When enabled, TAB will hide its scoreboard if another plugin sent one and send it back once the other plugin's scoreboard is hidden. |
|
||||
| Option name | Default value | Description |
|
||||
|----------------------------|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | false | Enables / Disables the feature |
|
||||
| toggle-command | /sb | Command that can be used to toggle scoreboard for the player running the command. Players need `tab.scoreboard.toggle` permission to use it. <br />**Note:** 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. |
|
||||
| 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
|
||||
* Title is limited to 32 characters (including color codes) on <1.13.
|
||||
* Line length is limited to 28 characters (including color codes) on <1.13 (68 on lines with static text / [Longer lines](#longer-lines)).
|
||||
* Only displays up to 15 lines.
|
||||
* The red numbers on the right really cannot be removed from the plugin side (a client modification / resource pack is needed) on 1.20.2 and lower. They no longer appear on 1.20.3+ and instead any text can be configured (see above).
|
||||
* [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.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.
|
||||
|
||||
# Longer lines
|
||||
In order to make sure the scoreboard never flickers, it's only using prefix/suffix components to display text. These can easily be changed without any visual issues. The player name part, however, cannot be changed. A line has to be completely removed and a new one added. There's a chance a frame is rendered between these 2 packets are sent, causing the scoreboard to have 1 line missing for 1 frame, causing visual issue known as "flickering".
|
||||
To make sure the scoreboard never flickers, it's only using prefix/suffix components to display text.
|
||||
These can easily be changed without any visual issues.
|
||||
The player name part, however, cannot be changed.
|
||||
A line has to be completely removed and a new one added.
|
||||
There's a chance a frame is rendered between these 2 packets are sent,
|
||||
causing the scoreboard to have 1 line missing for 1 frame, causing the visual issue known as "flickering".
|
||||
|
||||
However, if your scoreboard only has placeholders that don't change value often (pretty much any placeholder except animations, really), you can make TAB use player name part, allowing you to use additional up to 40 characters. To do so, add `Long|` prefix to all lines which should use this bypass.
|
||||
However,
|
||||
if your scoreboard only has placeholders that don't change value often
|
||||
(pretty much any placeholder except animations, really),
|
||||
you can make TAB use player name part,
|
||||
allowing you to use an additional up to 40 characters.
|
||||
To do so, add `Long|` prefix to all lines that should use this bypass.
|
||||
```
|
||||
lines:
|
||||
- "Classic line with shorter limit"
|
||||
- "Long|Long line with much higher character limit"
|
||||
```
|
||||
This bypass is automatically enabled for all lines which only use static text (since there's nothing to refresh and cause flickering), therefore doing it for such lines (like in the example above) has no effect.
|
||||
This bypass is automatically enabled for all lines that only use static text
|
||||
(since there's nothing to refresh and cause flickering),
|
||||
therefore doing it for such lines (like in the example above) has no effect.
|
||||
|
||||
# Compatibility with other plugins
|
||||
TAB automatically detects scoreboard coming from other plugins and when one is sent, TAB hides its own scoreboard. Later, when the other plugin hides its scoreboard, TAB will send its scoreboard back to the player.
|
||||
TAB automatically detects scoreboard coming from other plugins, and when one is sent, TAB hides its own scoreboard.
|
||||
Later, when the other plugin hides its scoreboard, TAB will send its scoreboard back to the player.
|
||||
|
||||
This detection must be available on your platform. For that, see Scoreboard section on [compatibility page](https://github.com/NEZNAMY/TAB/wiki/Compatibility#supported-features-per-platform). If it says ✔, the detection is available. If it says ❗, it means this detection is not available on your platform. As a result, when the other plugin hides its scoreboard, TAB will not be able to resend its own.
|
||||
This detection must be available on your platform.
|
||||
For that,
|
||||
see the Scoreboard section on [compatibility page](https://github.com/NEZNAMY/TAB/wiki/Compatibility#supported-features-per-platform).
|
||||
If it says ✔, the detection is available.
|
||||
If it says ❗, it means this detection is not available on your platform.
|
||||
As a result, when the other plugin hides its scoreboard, TAB will not be able to resend its own.
|
||||
|
||||
If you want this detection and it's not supported by your platform, you can achieve it using an alternate solution with conditions that will make TAB display no scoreboard if the condition is not met. For this, you'll need to have more information about when exactly do plugins send scoreboards and how to detect it.
|
||||
If you want this detection,
|
||||
and it's not supported by your platform,
|
||||
you can achieve it
|
||||
using an alternate solution with conditions that will make TAB display no scoreboard if the condition is not met.
|
||||
For this, you'll need to have more information about when exactly do plugins send scoreboards and how to detect it.
|
||||
|
||||
<details>
|
||||
<summary>Example using PremiumVanish</summary>
|
||||
@@ -143,8 +184,11 @@ would turn into
|
||||
lines:
|
||||
- 'Line of text'
|
||||
```
|
||||
Don't forget to add this condition to all of your scoreboards if you have more than 1 (for those with an existing condition merge them using `;`).
|
||||
Keep in mind [placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements) apply to placeholders here as well, so if you configured a fancy output for that placeholder, you'll need to use it in the display condition as well. To see what exactly has placeholder returned, use `/tab parse <player> <placeholder>`.
|
||||
Remember to add this condition to all of your scoreboards if you have more than 1
|
||||
(for those with an existing condition merge them using `;`).
|
||||
Keep in mind [placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements) apply to placeholders here as well,
|
||||
so if you configured a fancy output for that placeholder, you'll need to use it in the display condition as well.
|
||||
To see what exactly has placeholder returned, use `/tab parse <player> <placeholder>`.
|
||||
</details>
|
||||
|
||||
# API
|
||||
@@ -165,11 +209,17 @@ To change whether a player can see scoreboards, use `ScoreboardManager#setScoreb
|
||||
To toggle whether a player can see scoreboards, use `ScoreboardManager#toggleScoreboard(TabPlayer, boolean)`. This will either make scoreboards visible if they are not already, or make them hidden if they are currently visible.
|
||||
|
||||
## Announcing a scoreboard
|
||||
To announce a scoreboard to all players on the server for a given amount of ticks, use `ScoreboardManager#announceScoreboard(String, int)`, which will lookup a scoreboard with the given `String` name, and if one is found, send it to all players for the given `int` ticks.
|
||||
To announce a scoreboard to all players on the server for a given number of ticks,
|
||||
use `ScoreboardManager#announceScoreboard(String, int)`,
|
||||
which will look up a scoreboard with the given `String` name,
|
||||
and if one is found, send it to all players for the given `int` ticks.
|
||||
|
||||
# Examples
|
||||
## Example 1 - per-world scoreboards
|
||||
We will be using a condition of "equals" (=) type and check for output of `%world%` placeholder. If condition is met, player is in that world and scoreboard is displayed. If not, checking for next scoreboard's condition. If none of the conditions are met, display default scoreboard.
|
||||
## Example 1 - Per-world scoreboards
|
||||
We will be using a condition of "equals" (=) type and check for output of `%world%` placeholder.
|
||||
If condition is met, it means player is in that world and the scoreboard is displayed.
|
||||
If not, check for the next scoreboard's condition.
|
||||
If none of the conditions are met, display the default scoreboard.
|
||||
```
|
||||
scoreboards:
|
||||
# start
|
||||
@@ -196,7 +246,11 @@ We will be using a condition of "equals" (=) type and check for output of `%worl
|
||||
lines:
|
||||
- 'You are not in any of the worlds listed above'
|
||||
```
|
||||
*Note: This is just an example, the plugin is not limited to displaying scoreboard only per world. If you want per server scoreboards on BungeeCord, 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.*
|
||||
> [!NOTE]
|
||||
> This is just an example, the plugin is not limited to displaying scoreboard only per world.
|
||||
> If you want per server scoreboards on proxy, use %server% with server names.
|
||||
> If you want worldguard regions, use %worldguard_region_name% with region names.
|
||||
> This works for any placeholder offered by the plugin or by PlaceholderAPI.
|
||||
|
||||
## Example 2 - Periodical scoreboard switching
|
||||
We can use [animations](https://github.com/NEZNAMY/TAB/wiki/Animations) to make the plugin switch between scoreboards using display condition. Let's say we want to switch between 2 scoreboards. First, we create an animation:
|
||||
@@ -209,7 +263,10 @@ switchingScoreboard:
|
||||
- "2"
|
||||
```
|
||||
This animation will switch frames every 10 seconds.
|
||||
Then, we will use output of this animation as a display condition. If animation is on the first frame, display first scoreboard. Otherwise, display second scoreboard.
|
||||
Then, we will use the output of this animation as a display condition.
|
||||
If animation is on the first frame, display the first scoreboard.
|
||||
Otherwise, display the second scoreboard.
|
||||
Result:
|
||||
**config.yml**
|
||||
```
|
||||
scoreboards:
|
||||
@@ -224,4 +281,38 @@ Then, we will use output of this animation as a display condition. If animation
|
||||
lines:
|
||||
- 'Text'
|
||||
```
|
||||
We don't need to define display condition for 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).
|
||||
We don't need to define display condition for the second scoreboard,
|
||||
since if animation is not on the first frame, it has to be on the second one.
|
||||
If using more than 2, you will need to define display condition for all of them (except the last one).
|
||||
|
||||
# Example 3 - Per-version scoreboards
|
||||
1.20.3 has added new features to scoreboards, which are not visible to older clients. If you want to use new features for new players while still displaying things properly for older players, you'll need to create 2 different scoreboards.
|
||||
You'll find 2 placeholders useful for this:
|
||||
* `%player-version-id%` - Returns network ID of player's protocol version. Unlike with version names, you can perform numerical comparisons with these. You can find all version IDs [here](https://github.com/NEZNAMY/TAB/blob/master/shared/src/main/java/me/neznamy/tab/shared/ProtocolVersion.java). For example, 1.20.3 is 765.
|
||||
* `%bedrock%` - Returns `true` if player is using the bedrock edition, which does not support new functions either.
|
||||
|
||||
We only want the first scoreboard for players with version 765 or greater and not bedrock players. This can be achieved with the following condition: `display-condition: "%player-version-id%>=765;%bedrock%=false"`.
|
||||
|
||||
Let's go ahead and set it up (with proper spacing):
|
||||
```
|
||||
scoreboards:
|
||||
scoreboard-1.20.3+:
|
||||
title: "Scoreboard for 1.20.3+ and not bedrock"
|
||||
display-condition: "%player-version-id%>=765;%bedrock%=false" # Only display it to players using 1.20.3+ AND NOT bedrock edition
|
||||
lines:
|
||||
- "* &eOnline&7:||%online%"
|
||||
- "* &eCurrent World&7:||%worldonline%"
|
||||
- "* &eStaff&7:||%staffonline%"
|
||||
- "* &bRank&7:||%group%"
|
||||
- "* &bPing&7:||%ping%&8ms"
|
||||
- "* &bWorld&7:||%world%"
|
||||
scoreboard:
|
||||
title: "Scoreboard for <1.20.3 and bedrock"
|
||||
lines:
|
||||
- "* &eOnline&7: &f%online%"
|
||||
- "* &eCurrent World&7: &f%worldonline%"
|
||||
- "* &eStaff&7: &f%staffonline%"
|
||||
- "* &bRank&7: &f%group%"
|
||||
- "* &bPing&7: &f%ping%&8ms"
|
||||
- "* &bWorld&7: &f%world%"
|
||||
```
|
||||
@@ -21,16 +21,22 @@
|
||||
# Enabling
|
||||
To enable sorting, you must have either [Nametags](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Nametags) or [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) (or both) enabled.
|
||||
|
||||
To **verify** you enabled sorting, run `/tab debug`. It will say `Sorting type:` followed by anything except `DISABLED`.
|
||||
> [!TIP]
|
||||
> To verify you enabled sorting, run `/tab debug`. It will say `Sorting type:` followed by anything except `DISABLED`.
|
||||
|
||||
# Methods of sorting
|
||||
Below are all of the different methods that you can use to sort players in TAB.
|
||||
Below are all the different methods that you can use to sort players.
|
||||
|
||||
## GROUPS
|
||||
This is the default and recommended method. Players will be sorted by their primary permission group, according to the configured group list.
|
||||
|
||||
First, put your players into groups in your permission plugin. All ways to do it can be found at [How to assign players into groups](https://github.com/NEZNAMY/TAB/wiki/How-to-assign-players-into-groups).
|
||||
**Verify** player's group using `/tab debug <player>`. It should say `Primary permission group:` followed by group you configured. If not, you did not assign players into groups correctly.
|
||||
First, put your players into groups in your permission plugin.
|
||||
All the ways to do it can be found
|
||||
at [How to assign players into groups](https://github.com/NEZNAMY/TAB/wiki/How-to-assign-players-into-groups).
|
||||
> [!TIP]
|
||||
> Verify player's group using `/tab debug <player>`.
|
||||
It should say `Primary permission group:` followed by group you configured.
|
||||
If not, you did not assign players into groups correctly.
|
||||
|
||||
Second, place all of your groups in to a comma separated list **in order of priority** into `sorting-types`. Example:
|
||||
```yaml
|
||||
@@ -38,7 +44,8 @@ scoreboard-teams:
|
||||
sorting-types:
|
||||
- "GROUPS:owner,admin,mod,default"
|
||||
```
|
||||
**Verify** configured sorting priority of players using `/tab debug <player>`.
|
||||
> [!TIP]
|
||||
> Verify configured sorting priority of players using `/tab debug <player>`.
|
||||
|
||||
It should show a message like this:
|
||||

|
||||
@@ -48,8 +55,12 @@ If a group is not in the list, you will get the following:
|
||||
If that's the case, you forgot to add that group into the list.
|
||||
|
||||
## PERMISSIONS
|
||||
**This method is not recommended, as many low quality servers give OP to every staff member and don't know how to negate permissions, making this option not function as intended. If you think you can pull it off, and sorting by primary group is not an option, you can give this a try.
|
||||
This method is, however, handy when trying to sort specific players **without** assigning them into a group.**
|
||||
> [!CAUTION]
|
||||
> This method is not recommended,
|
||||
> as many low quality servers give OP to every staff member and don't know how to negate permissions,
|
||||
> making this option not function as intended.
|
||||
> If you think you can pull it off, and sorting by primary group is not an option, you can give this a try.
|
||||
This method is, however, handy when trying to sort specific players without assigning them into a group.
|
||||
|
||||
This method will sort players based on permission nodes they have.
|
||||
Place all of your permissions in to a comma separated list **in order of priority**.
|
||||
@@ -60,6 +71,8 @@ scoreboard-teams:
|
||||
sorting-types:
|
||||
- "PERMISSIONS:my.permission.1,my.permission.2,my.permission.3"
|
||||
```
|
||||
> [!TIP]
|
||||
> Verify sorting permissions of a player using `/tab debug <player>`
|
||||
|
||||
## PLACEHOLDER
|
||||
This method sorts players using the output of a placeholder and comparing that to pre-defined values.
|
||||
@@ -73,7 +86,7 @@ scoreboard-teams:
|
||||
```
|
||||
|
||||
## PLACEHOLDER_A_TO_Z
|
||||
This method sorts players alphabetically according to the output of a placeholder.
|
||||
This method sorts players alphabetically, according to the output of a placeholder.
|
||||
To configure this sorting type, write the placeholder that you want to use. That's it.
|
||||
For example, if you want to sort players by their name alphabetically, you would do that using a configuration such as `PLACEHOLDER_A_TO_Z:%player%`.
|
||||
Example:
|
||||
@@ -84,10 +97,10 @@ scoreboard-teams:
|
||||
```
|
||||
|
||||
## PLACEHOLDER_Z_TO_A
|
||||
This method sorts players reverse alphabetically according to the output of a placeholder.
|
||||
This method sorts players reverse alphabetically, according to the output of a placeholder.
|
||||
This is identical to the above A to Z sorting, except that the alphabet is backwards, so Z comes first, and A comes last.
|
||||
To configure this sorting type, write the placeholder that you want to use. That's it.
|
||||
For example, if you want to sort players by their name reverse alphabetiically, you would do that using a configuration such as `PLACEHOLDER_Z_TO_A:%player%`.
|
||||
For example, if you want to sort players by their name reverse alphabetically, you would do that using a configuration such as `PLACEHOLDER_Z_TO_A:%player%`.
|
||||
Example:
|
||||
```yaml
|
||||
scoreboard-teams:
|
||||
@@ -96,11 +109,11 @@ scoreboard-teams:
|
||||
```
|
||||
|
||||
## PLACEHOLDER_LOW_TO_HIGH
|
||||
This method sorts players numerically depending on the output of a **numeric** placeholder from lowest value to highest value.
|
||||
This method sorts players numerically depending on the output of a **numeric** placeholder from the lowest value to the highest value.
|
||||
**Only placeholders that output number values will work with this sorting type!**
|
||||
Supported number interval is from -1,000,000,000 to 1,000,000,000 and 5 decimal places.
|
||||
To configure this sorting type, write the placeholder that you want to use. That's it.
|
||||
For example, if you want to sort players using the output of the `%health%` placeholder from lowest health to highest, you would do that using a configuration such as `PLACEHOLDER_LOW_TO_HIGH:%health%`.
|
||||
For example, if you want to sort players using the output of the `%health%` placeholder from the lowest health to highest, you would do that using a configuration such as `PLACEHOLDER_LOW_TO_HIGH:%health%`.
|
||||
Example:
|
||||
```yaml
|
||||
scoreboard-teams:
|
||||
@@ -109,7 +122,7 @@ scoreboard-teams:
|
||||
```
|
||||
|
||||
## PLACEHOLDER_HIGH_TO_LOW
|
||||
This method sorts players numerically depending on the output of a **numeric** placeholder fro highest value to lowest value.
|
||||
This method sorts players numerically depending on the output of a **numeric** placeholder from the highest value to the lowest value.
|
||||
**Only placeholders that output number values will work with this sorting type!**
|
||||
Supported number interval is from -1,000,000,000 to 1,000,000,000 and 5 decimal places.
|
||||
To configure this sorting type, write the placeholder that you want to use. That's it.
|
||||
@@ -138,7 +151,10 @@ Since `sorting-types` is a list, you are able to use more than one sorting type.
|
||||
- "GROUPS:owner,admin,mod,helper,builder,vip,default"
|
||||
- "PLACEHOLDER_A_TO_Z:%player%"
|
||||
```
|
||||
Here, players are sorted by their group first. Owner goes above admin etc. However, if 2 people have the same group (such as admin), next sorting type decides final order. In this case, admin with alphabetically lower username will be higher in the tablist.
|
||||
Here, players are sorted by their group first.
|
||||
Owner goes above admin etc. However,
|
||||
if 2 people have the same group (such as admin), the next sorting type decides the final order.
|
||||
In this case, admin with alphabetically lower username will be higher in the tablist.
|
||||
|
||||
A common request is putting AFK players on the bottom of tablist. This can be achieved with the following configuration:
|
||||
```
|
||||
@@ -147,14 +163,19 @@ A common request is putting AFK players on the bottom of tablist. This can be ac
|
||||
- "GROUPS:owner,admin,mod,helper,builder,vip,default"
|
||||
- "PLACEHOLDER_A_TO_Z:%player%"
|
||||
```
|
||||
With AFK status taking the highest priority, AFK players will be always sorted below players which are not AFK. Both player groups (afk and non-afk) then follow the rest of the logic explained above to define the final order. If trying to copypaste this example, keep in mind [Placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements) work here as well, so if you are using a fancier output for %essentials_afk%, you will need to use outputs respectively when defining sorting as well.
|
||||
With AFK status taking the highest priority, AFK players will always be sorted below players which are not AFK.
|
||||
Both player groups (afk and non-afk) then follow the rest of the logic explained above to define the final order.
|
||||
If trying to copy-paste this example, keep
|
||||
in mind [Placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements) work here as well,
|
||||
so if you are using a fancier output for %essentials_afk%,
|
||||
you will need to use outputs respectively when defining sorting as well.
|
||||
|
||||
Although you can theoretically use as many sorting types as you want, there are still strict limits set by mojang. See more about these limits and how to avoid them as much as possible at [Additional note 1 - Limitations](#additional-note-1---limitations).
|
||||
|
||||
# Additional settings
|
||||
| Option name | Default value | Description |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| case-sensitive-sorting | true | When enabled, players will be sorted as A-Z a-z. When disabled, Aa-Zz. |
|
||||
| Option name | Default value | Description |
|
||||
|------------------------|---------------|------------------------------------------------------------------------|
|
||||
| case-sensitive-sorting | true | When enabled, players will be sorted as A-Z a-z. When disabled, Aa-Zz. |
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - Limitations
|
||||
@@ -163,37 +184,58 @@ All sorting elements must together build a team name up to 16 characters long. B
|
||||
* `PLACEHOLDER_LOW_TO_HIGH` and `PLACEHOLDER_HIGH_TO_LOW` - 3 characters
|
||||
* `PLACEHOLDER_A_TO_Z` and `PLACEHOLDER_Z_TO_A` - as many as used
|
||||
|
||||
All your sorting types must be within a 15 character limit. Any characters above that will be cut off (TAB reserves 1 character to ensure each player is in a unique team). To get the most out of it, use the 1-character sorting types where possible.
|
||||
All your sorting types must be within a 15-character limit.
|
||||
Any characters above that will be cut off (TAB reserves 1 character to ensure each player is in a unique team).
|
||||
To get the most out of it, use the 1-character sorting types where possible.
|
||||
|
||||
You can bypass this limit by using [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) feature. Player ordering is fully plugin-sided and therefore is not artificialy limited.
|
||||
You can bypass this limit by using [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) feature.
|
||||
Player ordering is fully plugin-sided and therefore is not artificially limited.
|
||||
|
||||
## Additional note 2 - per-world sorting
|
||||
Defining a per-world sorting type is not supported. However, this can be achieved with [Conditional placeholders](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders). Simply check for %world% and return one placeholder if it matches, another one if not. This will work with anything, not just worlds (server, regions, etc).
|
||||
Defining a per-world sorting type is not supported.
|
||||
However,
|
||||
this can be achieved with [Conditional placeholders](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders).
|
||||
Check for %world% and return one placeholder if it matches, another one if not.
|
||||
This will work with anything, not just worlds (server, regions, etc.).
|
||||
|
||||
## Additional note 3 - Compatibility issues with other plugins
|
||||
As you already know by now, sorting is managed by scoreboard teams (their names to be exact). Player can only be member of one team. In other words, only one plugin can handle teams at a time. Having multiple plugins handle teams is supposed to end in a disaster.
|
||||
As you already know by now, sorting is managed by scoreboard teams (their names to be exact).
|
||||
Player can only be a member of one team.
|
||||
In other words, only one plugin can handle teams at a time.
|
||||
Having multiple plugins handling teams is supposed to end in a disaster.
|
||||
|
||||
Fortunately, TAB contains a function that prevents other plugins from assigning players into teams. 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 the file exists, most of the time you can guess where the teams come from by their name.
|
||||
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 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`.
|
||||
* `CIT-xxxxxxxxxxxx` - Citizens NPC with the same name as some online player. Make NPC names not match real players and use holograms to display your desired text (/npc name or something).
|
||||
* `PVP-xxxxxxxxxxxx` - Team coming from [PvPManager](https://www.spigotmc.org/resources/pvpmanager-lite.845/) plugin.
|
||||
|
||||
This detection, however, is not 100%. Because of that, you may still be experiencing a compatibility issue even with anti-override enabled. To identify such issue, check if /tab reload fixes your sorting issue. If it does, it's a compatibility issue of some sort. If not, it is most likely a misconfiguration issue.
|
||||
This detection, however, is not 100%.
|
||||
Because of that, you may still be experiencing a compatibility issue even with anti-override enabled.
|
||||
To identify such an issue, check if /tab reload fixes your sorting issue.
|
||||
If it does, it's a compatibility issue of some sort.
|
||||
If not, it is most likely a misconfiguration issue.
|
||||
|
||||
# Common mistakes
|
||||
Every possible mistake could be called "not reading this wiki page", but that would make this section pointless. For that reason let's call it list of mistakes made when following this page.
|
||||
Every possible mistake could be called "not reading this wiki page", but that would make this section pointless.
|
||||
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 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.
|
||||
* 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.
|
||||
* 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.
|
||||
@@ -203,8 +245,13 @@ The most common mistakes include:
|
||||
|
||||
To access this feature, you'll need to obtain `SortingManager` instance. Get it using `TabAPI.getInstance().getSortingManager()`. If sorting is disabled, the method will return `null`.
|
||||
|
||||
You can change player's team name using following methods:
|
||||
You can change player's team name using the following methods:
|
||||
* `SortingManager#forceTeamName(TabPlayer, String)` - Sets player's team name to specified value (and performs team unregister & register with new name).
|
||||
* `SortingManager#getForcedTeamName(TabPlayer)` - Returns player's forced team name using the method above. Will return `null` if no value is set.
|
||||
|
||||
Unfortunately, there is no simple way of just changing one's position while still accounting for other players. This is because the plugin supports a lot of sorting options, not just groups, so doing amateur stuff like "priority 1, 2" doesn't make sense. If you are really only interested in sorting by groups and changing group which player is sorted as, you can use `TabPlayer#setTemporaryGroup(String)`. To reset group back to normal, call the function with `null` argument.
|
||||
Unfortunately, there is no simple way of just changing one's position while still accounting for other players.
|
||||
This is because the plugin supports a lot of sorting options, not just groups,
|
||||
so doing amateur stuff like "priority 1, 2" doesn't make sense.
|
||||
If you are really only interested in sorting by groups and changing group which player is sorted as,
|
||||
you can use `TabPlayer#setTemporaryGroup(String)`.
|
||||
To reset the group back to normal, call the function with `null` argument.
|
||||
@@ -6,7 +6,9 @@
|
||||
* [Additional note 1 - Seeing yourself still as spectator](#additional-note-1---seeing-yourself-still-as-spectator)
|
||||
|
||||
# About
|
||||
With the introduction of spectator gamemode in 1.8, players having it automatically appear on the bottom of tablist with transparent name and missing [Yellow number](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Yellow-number). This feature cancels gamemode change packets to spectator gamemode, cancelling this minecraft feature.
|
||||
With the introduction of spectator gamemode in 1.8,
|
||||
players having it automatically appear on the bottom of tablist with transparent name and missing [Playerlist Objective](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Playerlist-Objective).
|
||||
This feature cancels gamemode change packets to spectator gamemode, cancelling this minecraft feature.
|
||||
|
||||
# Enabling
|
||||
To enable this feature, open **config.yml** and set
|
||||
@@ -16,10 +18,14 @@ prevent-spectator-effect:
|
||||
```
|
||||
|
||||
# Permissions
|
||||
| Permission | Description |
|
||||
| ------------- | ------------- |
|
||||
| `tab.spectatorbypass` | Players with this permission will see spectators the usual way despite this feature being enabled. If you don't want players (or even staff members) to bypass this feature, don't give them that permission. |
|
||||
| Permission | Description |
|
||||
|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `tab.spectatorbypass` | Players with this permission will see spectators the usual way despite this feature being enabled. If you don't want players (or even staff members) to bypass this feature, don't give them that permission. |
|
||||
|
||||
# Additional info
|
||||
## Additional note 1 - Seeing yourself still as spectator
|
||||
Receiving information about going spectator gamemode allows players to clip through walls. Cancelling this on self would result in inability to go through walls. To avoid this, the information will be cancelled for every player except the one going spectator gamemode. Therefore, if you change gamemode to spectator, you will still see yourself on the bottom, but no one else will (unless someone has the bypass permission).
|
||||
Receiving information about going spectator gamemode allows players to clip through walls.
|
||||
Cancelling this on self would result in inability to go through walls.
|
||||
To avoid this, the information will be canceled for every player except the one going spectator gamemode.
|
||||
Therefore, if you change gamemode to spectator, you will still see yourself on the bottom,
|
||||
but no one else will (unless someone has the bypass permission).
|
||||
@@ -11,7 +11,13 @@
|
||||
* [API](#api)
|
||||
|
||||
# About
|
||||
This feature allows you to configure player name formats in the tablist. It was added to minecraft in version 1.8. Versions 1.7 and lower only allow up to 16 characters including name, which is too limiting and not suppored by this plugin. If you wish to have prefix/suffix for 1.7 and lower, take advantage of [this client-sided mechanic](https://github.com/NEZNAMY/TAB/wiki/Client%E2%80%90sided-mechanics#nametag-format-in-tablist) and configure tagprefix/tagsuffix, which will appear in the tablist.
|
||||
This feature allows you to configure player name formats in the tablist.
|
||||
It was added to minecraft in version 1.8.
|
||||
Versions 1.7 and lower only allow up to 16 characters including name,
|
||||
which is too limiting and not supported by this plugin.
|
||||
If you wish to have prefix/suffix for 1.7 and lower,
|
||||
take advantage of [this client-sided mechanic](https://github.com/NEZNAMY/TAB/wiki/Client%E2%80%90sided-mechanics#nametag-format-in-tablist) and configure tagprefix/tagsuffix,
|
||||
which will appear in the tablist.
|
||||

|
||||
|
||||
Settings of this feature can be configured in **config.yml** under **tablist-name-formatting** section.
|
||||
@@ -23,11 +29,20 @@ The display name is split into 3 parts for convenience:
|
||||
`customtabname` - second part of the text, it will be used as player name. If customtabname is not defined at all (not just setting empty value!), player's original name will be used instead
|
||||
`tabsuffix` - last part of the text, this is where suffix is usually configured
|
||||
|
||||
These values are then merged together and displayed in the tablist.
|
||||
These values are then merged and displayed in the tablist.
|
||||

|
||||
|
||||
You are free to use the 3 properties in any way you want since they are only split for convenience.
|
||||
However, it is still a good idea to use them for their designed purpose to not get lost a poor configuration.
|
||||
This means that the text which should appear before player's name should be put into `tabprefix`,
|
||||
any placeholder that is supposed to display player's name (such as from a nickname plugin)
|
||||
should go into `customtabname` and any text that should appear after player's name should be put into `tabsuffix`.
|
||||
|
||||
## Groups and users
|
||||
Properties can be applied in 2 ways: groups and users. Users can be defined by both username and their UUID. Values applied to users take priority over groups.
|
||||
Properties can be applied in 2 ways: groups and users.
|
||||
Users can be defined by both username and their UUID.
|
||||
Values applied to users take priority over groups.
|
||||
Example:
|
||||
**groups.yml**
|
||||
```
|
||||
admin:
|
||||
@@ -46,7 +61,9 @@ _NEZNAMY_:
|
||||
```
|
||||
This can also be achieved with commands, in this case `/tab player _NEZNAMY_ tabprefix "&6&lTAB &r"` or `/tab playeruuid _NEZNAMY_ tabprefix "&6&lTAB &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.
|
||||
Properties can also be set as "default" for everyone who does not have them defined.
|
||||
For that purpose, a group keyword `_DEFAULT_` was made.
|
||||
Example:
|
||||
**groups.yml**
|
||||
```
|
||||
admin:
|
||||
@@ -82,7 +99,7 @@ per-world:
|
||||
```
|
||||
|
||||
## Priority system
|
||||
Full list of priorities looks like this:
|
||||
The full list of priorities looks like this:
|
||||
1. value set using the [API](#api)
|
||||
2. per-world / per-server applied to username
|
||||
3. value applied to username
|
||||
@@ -95,22 +112,26 @@ Full list of priorities looks like this:
|
||||
|
||||
This list is browsed through until the first match is found. If no match is found, empty value is used (except `customtabname`, which defaults to player's name).
|
||||
|
||||
Values are taken independently from each other. This means you can set per-world tabprefix, but only keep one global tabsuffix for example.
|
||||
Values are taken independently of each other.
|
||||
This means you can set per-world tabprefix, but only keep one global tabsuffix, for example.
|
||||
|
||||
You can see source of a value displayed on player by using `/tab debug <player>` and checking "source" part of the value you are looking for.
|
||||
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.
|
||||
|
||||
## 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. Amount of placeholders is not limited and they can be used in combination with static text as well.
|
||||
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 |
|
||||
| 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. |
|
||||
| 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
|
||||
If you want TAB to only take prefixes/suffixes from permission plugin, delete all groups from **groups.yml** and only keep this:
|
||||
If you want TAB to only take prefixes/suffixes from your permission plugin,
|
||||
delete all groups from **groups.yml** and only keep this:
|
||||
```
|
||||
_DEFAULT_:
|
||||
tabprefix: "%luckperms-prefix%"
|
||||
@@ -126,14 +147,15 @@ To set the values for the respective formatting, use the following:
|
||||
* `TabListFormatManager#setPrefix(TabPlayer, String)`
|
||||
* `TabListFormatManager#setName(TabPlayer, String)`
|
||||
* `TabListFormatManager#setSuffix(TabPlayer, String)`
|
||||
To reset the values, set them to `null`.
|
||||
|
||||
To reset the values, set them to `null`.
|
||||
|
||||
To get custom values previously set using the API (they will return `null` if no custom value is set):
|
||||
* `TabListFormatManager#getCustomPrefix(TabPlayer)`
|
||||
* `TabListFormatManager#getCustomName(TabPlayer)`
|
||||
* `TabListFormatManager#getCustomSuffix(TabPlayer)`
|
||||
|
||||
To get original value set by the plugin based on configuration:
|
||||
To get the original value set by the plugin based on configuration:
|
||||
* `TabListFormatManager#getOriginalPrefix(TabPlayer)`
|
||||
* `TabListFormatManager#getOriginalName(TabPlayer)`
|
||||
* `TabListFormatManager#getOriginalSuffix(TabPlayer)`
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
When a plugin for linking proxies is detected, TAB automatically enables its hook to add support for it. No configuration is needed.
|
||||
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)
|
||||
|
||||
@@ -7,6 +8,6 @@ Supported features:
|
||||
* [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)
|
||||
* [Yellow Number](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Yellow-number)
|
||||
* [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,22 +1,22 @@
|
||||
# Content
|
||||
* [#1 - Why are NPCs showing up in the tablist?](#1---why-are-npcs-showing-up-in-the-tablist)
|
||||
* [#2 - How to make TAB work with LuckPerms?](#2---how-to-make-tab-work-with-luckperms)
|
||||
* [#3 - How can i make belowname not affect NPCs but keep it for players?](#3---how-can-i-make-belowname-not-affect-npcs-but-keep-it-for-players)
|
||||
* [#4 - I enabled MySQL and my prefix is now gone!](#4---i-enabled-mysql-and-my-prefix-is-now-gone)
|
||||
* [#5 - Why is player sorting not working?](#5---why-is-player-sorting-not-working)
|
||||
* [#6 - How to add players to %staffonline% placeholder?](#6---how-to-add-players-to-the-staffonline-placeholder)
|
||||
* [#7 - How to make player heads visible in tablist?](#7---how-to-make-player-heads-visible-in-tablist)
|
||||
* [#8 - Where can i find current default config files?](https://github.com/NEZNAMY/TAB/tree/master/shared/src/main/resources)
|
||||
* [#9 - How can I split players into multiple columns?](#9---how-can-i-split-players-into-multiple-columns)
|
||||
* [#10 - How to use space in prefix/suffix command?](#10---how-to-use-spaces-in-prefixsuffix-command)
|
||||
* [#11 - Can I change/remove the green connection bar in tablist?](#11---can-i-changeremove-the-green-connection-bar-in-tablist)
|
||||
* [#12 - Placeholder is not working](#12---placeholder-is-not-working)
|
||||
* [#13 - How can I display ItemsAdder images?](#13---how-can-i-display-itemsadder-images)
|
||||
* [#14 - How can I use UTF characters in configuration?](#14---how-can-i-use-utf-characters-in-configuration)
|
||||
* [#15 - Is there a way to remove all players from tablist?](#15---is-there-a-way-to-remove-all-players-from-tablist)
|
||||
* [#16 - How to add images to tablist?](#16---how-to-add-images-to-tablist)
|
||||
* [#17 - Is MiniMessage supported?](#17---is-minimessage-supported)
|
||||
* [#18 - Is it possible to show amount of players in a specific group, similar to staffonline placeholder?](#18---is-it-possible-to-show-amount-of-players-in-a-specific-group-similar-to-staffonline-placeholder)
|
||||
* [#3 - I enabled MySQL, and my prefix is now gone!](#3---i-enabled-mysql-and-my-prefix-is-now-gone)
|
||||
* [#4 - Why is player sorting not working?](#4---why-is-player-sorting-not-working)
|
||||
* [#5 - How to add players to %staffonline% placeholder?](#5---how-to-add-players-to-the-staffonline-placeholder)
|
||||
* [#6 - How to make player heads visible in tablist?](#6---how-to-make-player-heads-visible-in-tablist)
|
||||
* [#7 - Where can i find current default config files?](#7---where-can-i-find-current-default-config-files)
|
||||
* [#8 - How can I split players into multiple columns?](#8---how-can-i-split-players-into-multiple-columns)
|
||||
* [#9 - How to use space in prefix/suffix command?](#9---how-to-use-spaces-in-prefixsuffix-command)
|
||||
* [#10 - Can I change/remove the green connection bar in tablist?](#10---can-i-changeremove-the-green-connection-bar-in-tablist)
|
||||
* [#11 - Placeholder is not working](#11---placeholder-is-not-working)
|
||||
* [#12 - How can I display ItemsAdder images?](#12---how-can-i-display-itemsadder-images)
|
||||
* [#13 - How can I use UTF characters in configuration?](#13---how-can-i-use-utf-characters-in-configuration)
|
||||
* [#14 - Is there a way to remove all players from tablist?](#14---is-there-a-way-to-remove-all-players-from-tablist)
|
||||
* [#15 - How to add images to tablist?](#15---how-to-add-images-to-tablist)
|
||||
* [#16 - Is MiniMessage supported?](#16---is-minimessage-supported)
|
||||
* [#17 - Is it possible to show the number of players in a specific group, similar to staffonline placeholder?](#17---is-it-possible-to-show-the-number-of-players-in-a-specific-group-similar-to-staffonline-placeholder)
|
||||
* [#18 - Why is the plugin flagged as a virus by Windows defender?](#18---why-is-the-plugin-flagged-as-a-virus-by-windows-defender)
|
||||
|
||||
## #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).
|
||||
@@ -28,72 +28,112 @@ See [Citizens FAQ](https://wiki.citizensnpcs.co/Frequently_Asked_Questions#Why_a
|
||||
* 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 - How can I make belowname not affect NPCs but keep it for players?
|
||||
Make NPC plugin hide their original names (using teams) and place holograms for displaying text.
|
||||
|
||||
## #4 - I enabled MySQL and my prefix is now gone!
|
||||
## #3 - I enabled MySQL, and my prefix is now gone!
|
||||
When enabling [MySQL](https://github.com/NEZNAMY/TAB/wiki/MySQL), it will be used as a data storage and groups.yml / users.yml files will no longer be used.
|
||||
If you want to upload your configuration to MySQL (or download it back to files), use [MySQL conversion commands](https://github.com/NEZNAMY/TAB/wiki/MySQL#data-conversion) - [`/tab mysql upload`](https://github.com/NEZNAMY/TAB/wiki/MySQL#uploading-from-files-to-mysql) and [`/tab mysql download`](https://github.com/NEZNAMY/TAB/wiki/MySQL#downloading-from-mysql-to-files), respectively.
|
||||
After you are done, run `/tab reload` for the changes to take effect.
|
||||
|
||||
## #5 - Why is player sorting not working?
|
||||
## #4 - Why is player sorting not working?
|
||||
See [Common mistakes section on sorting page](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Sorting-players-in-tablist#common-mistakes).
|
||||
|
||||
## #6 - How to add players to the %staffonline% placeholder?
|
||||
## #5 - How to add players to the %staffonline% placeholder?
|
||||
Give them the `tab.staff` permission.
|
||||
|
||||
## #7 - How to make player heads visible in tablist?
|
||||
Players who did not buy the game will never be able to see heads. Player heads are displayed by the client when connection to the server is an online connection authenticated through Mojang. It cannot be directly controlled by plugins. The intended way to reach this is by setting `online-mode=true` in `server.properties`.
|
||||
If you want to allow pirates on your server, you can still display heads for players who bought the game by changing their connections to online connections. Most commonly used plugins for this are [FastLogin](https://www.spigotmc.org/resources/14153/) and [JPremium](https://www.spigotmc.org/resources/27766/), which change connections of premium players who enabled it to online connections.
|
||||
Same goes for disabling heads - you cannot disable them if you have online mode enabled.
|
||||
## #6 - How to make player heads visible in tablist?
|
||||
Players who did not buy the game will never be able to see heads.
|
||||
The client displays Player heads when connection to the server is an online connection authenticated through Mojang.
|
||||
It cannot be directly controlled by plugins.
|
||||
The intended way to reach this is by setting `online-mode=true` in `server.properties`.
|
||||
If you want to allow pirates on your server,
|
||||
you can still display heads for players who bought the game by changing their connections to online connections.
|
||||
Most commonly used plugins for this are [FastLogin](https://www.spigotmc.org/resources/14153/) and [JPremium](https://www.spigotmc.org/resources/27766/),
|
||||
which change connections of premium players who enabled it to online connections.
|
||||
The same goes for disabling heads - you cannot disable them if you have online mode enabled.
|
||||
|
||||
## #8 - Where can i find current default config files?
|
||||
You can find all default files in the [source code](https://github.com/NEZNAMY/TAB/tree/master/shared/src/main/resources). You can also delete or rename a file and the plugin will regenerate it.
|
||||
## #7 - Where can i find current default config files?
|
||||
You can do any of the following:
|
||||
* Check the [source code](https://github.com/NEZNAMY/TAB/tree/master/shared/src/main/resources/config).
|
||||
* Delete or rename a file, and the plugin will regenerate it.
|
||||
* Open the plugin jar as a zip file and take files from there.
|
||||
|
||||
## #9 - How can I split players into multiple columns?
|
||||
Players are put into columns by the client, it is not managed by the server. The only way is to get more players. They automatically split into more columns at 21, 41 and 61 players (due to limit of 20 entries per column). If you don't mind getting all 80 slots filled with fake player slots, check out the [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) feature.
|
||||
## #8 - How can I split players into multiple columns?
|
||||
The client puts players into columns, it is not managed by the server.
|
||||
The only way is to get more players.
|
||||
They automatically split into more columns at 21, 41 and 61 players (due to limit of 20 entries per column).
|
||||
If you don't mind getting all 80 slots filled with fake player slots,
|
||||
check out the [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) feature.
|
||||
|
||||
## #10 - How to use spaces in prefix/suffix command?
|
||||
## #9 - How to use spaces in prefix/suffix command?
|
||||
Use "", for example `/tab group owner tabprefix "&2&lOwner&r "`
|
||||
|
||||
## #11 - Can I change/remove the green connection bar in tablist?
|
||||
Connection bar is client sided and cannot be retextured or removed by TAB. You will need a custom minecraft client or a resource pack.
|
||||
## #10 - Can I change/remove the green connection bar in tablist?
|
||||
The connection bar is client sided and cannot be re-textured or removed by TAB.
|
||||
You will need a custom minecraft client or a resource pack.
|
||||
|
||||
## #12 - Placeholder is not working
|
||||
## #11 - Placeholder is not working
|
||||
Most common reasons for a placeholder to not work include:
|
||||
* Using % symbol by itself, which breaks placeholder starts and ends and therefore breaks all placeholders after it (use %% to display the symbol)
|
||||
* Trying to use a PlaceholderAPI placeholder without downloading its expansion or not having PlaceholderAPI installed at all
|
||||
* Trying to use [TAB's internal 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/)
|
||||
|
||||
Full list of reasons can be found on the [Placeholders](https://github.com/NEZNAMY/TAB/wiki/Placeholders#placeholder-is-not-working) page.
|
||||
The full list of reasons can be found on the [Placeholders](https://github.com/NEZNAMY/TAB/wiki/Placeholders#placeholder-is-not-working) page.
|
||||
|
||||
## #13 - How can I display ItemsAdder images?
|
||||
ItemsAdder offers placeholders, which return the respective symbol to which your desired image is bound to. You can get them using ItemsAdder's PlaceholderAPI expansion using their `%img_<something>%` placeholder. ItemsAdder's internal placeholders (`:something:`) will not work in TAB.
|
||||
## #12 - How can I display ItemsAdder images?
|
||||
ItemsAdder offers placeholders, which return the respective symbol to which your desired image is bound to. You can get them using ItemsAdder's PlaceholderAPI expansion using their `%img_<name>%` placeholder. ItemsAdder's internal placeholders (`:something:`) will not work in TAB.
|
||||
|
||||
## #14 - How can I use UTF characters in configuration?
|
||||
If you are unable to change the references
|
||||
(for example, because they are defined in permission plugin and used elsewhere as well),
|
||||
you can use [PlaceholderAPI](https://github.com/NEZNAMY/TAB/wiki/Quick-PlaceholderAPI-startup-guide)'s `imgfix` expansion
|
||||
that replaces format of given placeholders into the correct format.
|
||||
Example: `%luckperms_prefix%` -> `%imgfix_{luckperms_prefix}%`
|
||||
|
||||
## #13 - How can I use UTF characters in configuration?
|
||||
**Option 1**: [Save the file in UTF-8 encoding](https://github.com/NEZNAMY/TAB/wiki/How-to-save-the-config-in-UTF8-encoding) and use your desired symbol directly.
|
||||
|
||||
**Option 2**: Find hex code of your symbol (4 hexadecimal numbers) and use `\uxxxx` format, where `xxxx` is hexcode of the symbol.
|
||||
Make sure to also wrap the text into `""` for the text to properly take `\` as an escape symbol. Using `''` will result in text being display literally, not as a code.
|
||||
**Option 2**: Find hex code of your symbol (4 hexadecimal numbers) and use `\uxxxx` format,
|
||||
where `xxxx` is hex code of the symbol.
|
||||
Make sure to also wrap the text into `""` for the text to properly take `\` as an escape symbol.
|
||||
Using `''` will result in the text being display literally, not as a code.
|
||||
|
||||
**Note:** Minecraft does not support every single UTF symbol and displays unsupported symbols as a box. You can try sending your symbol into chat and see if it works or not. If not, it's not supported by MC.
|
||||
|
||||
## #15 - 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 game, get a plugin that hides all players. If you want to see them in game however, your only choice is to put a lot of empty lines into header, which will push all players out of the screen.
|
||||
## #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,
|
||||
which will push all players out of the screen.
|
||||
|
||||
## #16 - How to add images to tablist?
|
||||
You can check out [this reddit post](https://www.reddit.com/r/admincraft/comments/llrgty/comment/gnswdcz/?utm_source=share&utm_medium=web2x&context=3). When using the symbol in configuration using \u format, don't forget to use `""` in config instead of `''`.
|
||||
## #15 - How to add images to tablist?
|
||||
You can check out [this reddit post](https://www.reddit.com/r/admincraft/comments/llrgty/comment/gnswdcz/?utm_source=share&utm_medium=web2x&context=3).
|
||||
When using the symbol in configuration using \u format, remember to use `""` in config instead of `''`.
|
||||
|
||||
## #17 - Is MiniMessage supported?
|
||||
Kind of. MiniMessage support **is** included, however, this doesn't mean it is guaranteed to work. Here are a few reasons why it may not work for you:
|
||||
* MiniMessage library must be included in your server software. TAB does not include this library.
|
||||
* It **is** included in Paper 1.16.5 and higher, Velocity and Sponge 8.
|
||||
* It **is not** included in Spigot, any server software for 1.16.4 and lower, BungeeCord (and any of its forks), Sponge 7 and Fabric.
|
||||
* You may not use any legacy color codes (&) in the text where you want MiniMessage support. If you use them, MiniMessage parser will throw an error. Therefore, if trying to use both legacy colors and MiniMessage syntax, MiniMessage syntax will not work.
|
||||
* A plugin/mod might be shading an outdated/incomplete version of Adventure without relocating it, and java class loader might make TAB use the wrong source of the duplicated library.
|
||||
## #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**.
|
||||
|
||||
This list is not final. There might still be other reasons why MiniMessage won't work for you which are not known yet. If you believe MiniMessage should be supported on your server but doesn't work, open a bug report.
|
||||
If you believe MiniMessage should be supported on your server but doesn't work, open a bug report.
|
||||
|
||||
## #18 - Is it possible to show amount of players in a specific group, similar to staffonline placeholder?
|
||||
The plugin's internal placeholders are limited and this kind of functionality is not included. However, you can achieve this using PlaceholderAPI's `PlayerList` expansion and following [this example](https://github.com/Tanguygab/PlayerList-PlaceholderAPI-Expansion/wiki#list-of-players-in-group).
|
||||
## #17 - Is it possible to show the number of players in a specific group, similar to staffonline placeholder?
|
||||
The plugin's internal placeholders are limited, and this kind of functionality is not included.
|
||||
However,
|
||||
you can achieve this using PlaceholderAPI's `PlayerList` expansion
|
||||
and following [this example](https://github.com/Tanguygab/PlayerList-PlaceholderAPI-Expansion/wiki#list-of-players-in-group).
|
||||
|
||||
## #18 - Why is the plugin flagged as a virus by Windows defender?
|
||||
First, this is a false positive.
|
||||
[Here](https://www.spigotmc.org/threads/windows-defender-false-positives.639507/)'s a spigot thread confirming it.
|
||||
|
||||
After experimenting with VirusTotal,
|
||||
it turns out the antivirus software available on the website used flags [bStats](https://github.com/Bastian/bStats) library as malicious.
|
||||
Its purpose is to collect anonymous data about servers and submitting it to [bStats.org](https://bstats.org/),
|
||||
where plugin authors can see how many servers use their plugins (if they don't disable it).
|
||||
It also checks for CPU and OS types, which could be the reason for the false positive.
|
||||
[Here](https://bstats.org/plugin/bukkit/TAB%20Reborn/5304) is one of TAB's pages as an example.
|
||||
|
||||
Windows defender could be flagging it for the same reason.
|
||||
@@ -1,18 +1,37 @@
|
||||
# About the wiki
|
||||
The wiki explains functionality of the plugin as of version **4.1.8**. 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, as there is never a reason to be outdated. Support for older MC versions is not being removed and new plugin version is simply superior to any of the previous versions, as it contains more optimizations, fixes and features.
|
||||
The wiki explains the functionality of the plugin as of version **5.0.5**.
|
||||
If your config looks different or is missing some features, you are using an old version of the plugin.
|
||||
To get the latest version, check [releases](https://github.com/NEZNAMY/TAB/releases/).
|
||||
Wiki for older plugin versions is not available.
|
||||
|
||||
If you plan to run your server for longer than 1 week, it's a good idea to read this wiki as it explains everything about the plugin, giving you knowledge to do things you had no idea were possible, giving you an advantage over everyone else.
|
||||
If you plan to run your server for longer than 1 week,
|
||||
it's a good idea to read this wiki as it explains everything about the plugin.
|
||||
This will give you knowledge to do things you had no idea were possible, giving you an advantage over everyone else.
|
||||
|
||||
A lot of examples on the wiki use PlaceholderAPI placeholders without explaining its installation step by step. If you are going to use the examples and aren't familiar with the plugin, check out [Quick PlaceholderAPI startup guide](https://github.com/NEZNAMY/TAB/wiki/Quick-PlaceholderAPI-startup-guide).
|
||||
|
||||
# Limitations of plugins
|
||||
TAB is a plugin. It only modifies the server behavior to your liking. It does not add anything into the game. Because of that, you'll need to carefully read limitations of each feature to know what they are capable of and what they are not capable of. Some of the undesired behavior can be altered using a resource pack and some using a modified client. Both of these are out of scope of TAB as a plugin, therefore no advanced information regarding this is provided.
|
||||
TAB is a plugin.
|
||||
It only modifies the server behavior to your liking.
|
||||
It does not add anything into the game.
|
||||
Because of that, you'll need
|
||||
to carefully read the limitations of each feature to know what they are capable of and what they are not capable of.
|
||||
Some of the undesired behavior can be altered using a resource pack and some using a modified client.
|
||||
Both of these are out of scope of TAB as a plugin; therefore, no advanced information regarding this is provided.
|
||||
|
||||
# Public plugin
|
||||
TAB is a public plugin designed to satisfy needs of majority of servers.
|
||||
TAB is a public plugin designed to satisfy the needs of a majority of servers.
|
||||
|
||||
This means it has functions not everyone will need. All you need to do is disable functions you don't want. Disabled features do not consume the CPU at all.
|
||||
|
||||
On the other hand, it cannot contain everything everyone can think of. There must be a balance between providing as much as possible while making the configuration as short and readable as possible. This is not an easy task. Majority of things that are not supported directly can be achieved using different ways. Adding direct way for everything everyone asks for would not only take a lot of time, but make the plugin harder to configure for everyone as well as introduce a lot of duplicate ways to achieve things, making the plugin overcomplicated.
|
||||
If your need is very specific and not available in the plugin in any way, you should look into private plugin development. You will end up with a plugin made just for you with everything you want and nothing else.
|
||||
On the other hand, it cannot contain everything everyone can think of.
|
||||
There must be a balance
|
||||
between providing as much as possible while making the configuration as short and readable as possible.
|
||||
This is not an easy task.
|
||||
The majority of things that are not supported directly can be achieved in different ways.
|
||||
Adding direct way for everything everyone asks for would not only take a lot of time,
|
||||
but make the plugin harder to configure for everyone, as well as introduce a lot of duplicate ways to achieve things,
|
||||
making the plugin overcomplicated.
|
||||
If your need is very specific and not available in the plugin in any way,
|
||||
you should look into private plugin development.
|
||||
You will end up with a plugin made just for you with everything you want and nothing else.
|
||||
@@ -2,7 +2,7 @@
|
||||
* [About](#about)
|
||||
* [Option 1: Primary group from permission plugin](#option-1-primary-group-from-permission-plugin)
|
||||
* [Option 2: Permission nodes](#option-2-permission-nodes)
|
||||
* [Taking groups from backend servers when TAB is on BungeeCord](#taking-groups-from-backend-servers-when-tab-is-on-bungeecord)
|
||||
* [Taking groups from backend servers when TAB is on proxy](#taking-groups-from-backend-servers-when-tab-is-on-proxy)
|
||||
|
||||
## About
|
||||
TAB uses groups to assign properties (such as tabprefix) and sort players in tablist (if sorting by groups). You have 2 ways of configuring primary groups of players in TAB.
|
||||
@@ -12,25 +12,41 @@ First option hooks into your permission plugin and takes groups from it. Therefo
|
||||
If your permission plugin is not supported, you can use [Option 2](#option-2-permission-nodes).
|
||||
|
||||
## Option 1: Primary group from permission plugin
|
||||
This is the default method and recommended. TAB will ask your permission plugin for player's primary group.
|
||||
To use it, keep `assign-groups-by-permissions: false` in your config.
|
||||
This is the default method and recommended.
|
||||
TAB will ask your permission plugin for player's primary group.
|
||||
There are 2 simple steps to this:
|
||||
* Keep `assign-groups-by-permissions: false` in your config
|
||||
* Put players into groups in your permission plugin
|
||||
> [!CAUTION]
|
||||
> If assigning players into multiple groups, make sure their weights are correct
|
||||
> (for luckperms /lp group \<group\> setweight \<number\>).
|
||||
|
||||
Put players into groups in your permission plugin (don't forget to configure weights - for luckperms /lp group \<group\> setweight \<number\>).
|
||||
|
||||
**Verify** group using `/tab debug <player>`. It should say `Primary permission group: <your group>`.
|
||||
> [!TIP]
|
||||
> Verify player's group using `/tab debug <player>`. It should say `Primary permission group: <your group>`.
|
||||
|
||||
## Option 2: Permission nodes
|
||||
Instead of taking whole groups, TAB will check for permission nodes and assign groups based on highest permission.
|
||||
Instead of taking whole groups, TAB will check for permission nodes and assign groups based on the highest permission.
|
||||
1. Go to config.yml and set `assign-groups-by-permissions: true`.
|
||||
2. Give `tab.group.<group name>` permission to the user/permission group.
|
||||
3. Put all possible groups into `primary-group-finding-list`. This is needed because:
|
||||
#1 - there's no way to get list of permissions of a player, only checking for a permission. The list will be used for list of permissions to check for.
|
||||
#2 - if a player has permission for more than one group, the list will be used to pick the correct one (the one higher in the list).
|
||||
3. Put all possible groups into `primary-group-finding-list`.
|
||||
This is necessary because:
|
||||
#1 - there's no way to get the list of permissions, only checking for a permission.
|
||||
The list will be used for a list of permissions to check for.
|
||||
#2 - if a player has permission for more than one group, the list will be used to pick the correct one
|
||||
(the one higher in the list).
|
||||
|
||||
**Don't forget that OP = all permissions!** That's the whole point of OP function. To grant all permissions. In that case, you need to negate permissions in your permission plugin for other groups which are higher than player's wanted group (depending on your permission plugin it can be achieved using `-tab.group.groupname` or setting the permission value to false).
|
||||
> [!WARNING]
|
||||
> Remember that OP = all permissions!
|
||||
> That's the whole point of OP function.
|
||||
> To grant all permissions.
|
||||
> In that case,
|
||||
> you need to negate permissions in your permission plugin for other groups which are higher than player's wanted group.
|
||||
|
||||
# Taking groups from backend servers when TAB is on BungeeCord
|
||||
By default, TAB takes groups from permission plugin installed on the same server instance. In case of proxy installation, groups are by default taken from the proxy. To see how is your proxy permission plugin configured, use its respective command (for LuckPerms it's `/lpb user <player> info` instead of `/lp`).
|
||||
# Taking groups from backend servers when TAB is on proxy
|
||||
By default, TAB takes groups from the permission plugin installed on the same server instance.
|
||||
In the case of proxy installation, groups are by default taken from the proxy.
|
||||
To see how is your proxy permission plugin configured, use its respective command
|
||||
(for LuckPerms it's `/lpb user <player> info` instead of `/lp`).
|
||||
|
||||
If you don't have your permission plugin synced using MySQL for sharing groups and don't wish to, and want groups to be taken from backend servers instead, enable the config option:
|
||||
```
|
||||
@@ -38,4 +54,5 @@ use-bukkit-permissions-manager: true
|
||||
```
|
||||
When enabling it, all group **and** permission requests will be done through [Bridge plugin](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge) to take data from backend servers. Your groups will now match data from backend server a player is connected to (in case of LuckPerms `/lp user <player> info`).
|
||||
|
||||
When assigning by permissions instead of taking primary group directly from permission plugin, the permission nodes (`tab.group.<name>`) will be taken from backend servers instead.
|
||||
When assigning by permissions instead of taking the primary group directly from permission plugin,
|
||||
the permission nodes (`tab.group.<name>`) will be taken from backend servers instead.
|
||||
@@ -3,10 +3,16 @@
|
||||
* [Nametag](#nametag)
|
||||
* [Tips & Tricks](#tips--tricks)
|
||||
* [Tip 1 - Nickname prefix](#tip-1---nickname-prefix)
|
||||
* [Tip 2 - Sorting nicked players with lowest priority](#tip-2---sorting-nicked-players-with-lowest-priority)
|
||||
* [Tip 2 - Sorting nicked players with the lowest priority](#tip-2---sorting-nicked-players-with-the-lowest-priority)
|
||||
|
||||
# Tablist
|
||||
This one is easy. The tablist format of players is one text that's split into 3 parts in the plugin for convenience (tabprefix, customtabname, tabsuffix). Using `customtabname` you can configure name part into any placeholder you want, including one from your nickname plugin. All you need is a working PlaceholderAPI placeholder from your nickname plugin. Example:
|
||||
This one is straightforward.
|
||||
The tablist format of players is one text split into 3 parts in the plugin for convenience
|
||||
(tabprefix, customtabname, tabsuffix).
|
||||
Using `customtabname` you can configure name part into any placeholder you want,
|
||||
including one from your nickname plugin.
|
||||
All you need is a working PlaceholderAPI placeholder from your nickname plugin.
|
||||
Example:
|
||||
**groups.yml**
|
||||
```
|
||||
_DEFAULT_:
|
||||
@@ -16,16 +22,37 @@ or using in-game command `/tab group _DEFAULT_ customtabname %essentials_nicknam
|
||||
|
||||
This example uses `%essentials_nickname%` placeholder from Essentials. Giving it to `_DEFAULT_` group keyword makes it a default value for all groups that do not override this property.
|
||||
|
||||
**WARNING: Do NOT put nickname placeholder into tabprefix! You will end up with double names!**
|
||||
> [!CAUTION]
|
||||
> Do NOT put nickname placeholder into tabprefix!
|
||||
> You will end up with double names!
|
||||
> Put the nickname placeholder into customtabname instead.
|
||||
|
||||
# Nametag
|
||||
Nametags are more complicated, because they consist of player's username, team prefix and team suffix. There is no intended way to do this. The only way is changing it using a nickname plugin. Some nickname plugins actually change name in game profile, which also changes it in nametag. You will need to find one that offers this and then use it. This is a complicated process with lots of side effects, so TAB does not offer it.
|
||||
Nametags are more complicated because they consist of player's username, team prefix and team suffix.
|
||||
There is no intended way to do this.
|
||||
The only way is changing it using a nickname plugin.
|
||||
Some nickname plugins actually change name in game profile, which also changes it in nametag.
|
||||
You will need to find one that offers this and then use it.
|
||||
This is a complicated process with lots of side effects, so TAB does not offer it.
|
||||
|
||||
# Proper compatibility with plugins that change profile name
|
||||
If using a nickname plugin that changes player's profile name in order to change it in the name tag, this has lots of side effects. Most notably, it breaks all name-bound features, especially [nametags](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Nametags) and [sorting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Sorting-players-in-tablist). For that reason, TAB must detect name change. This is done automatically on Bukkit, BungeeCord and Fabric. This detection is not available on Sponge and Velocity.
|
||||
If using a nickname plugin that changes player's profile name to change it in the name tag,
|
||||
this has lots of side effects.
|
||||
Most notably, it breaks all name-bound features,
|
||||
especially [nametags](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Nametags) and [sorting](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Sorting-players-in-tablist).
|
||||
For that reason, TAB must detect name change.
|
||||
This is done automatically on Bukkit, BungeeCord and Fabric.
|
||||
This detection is not available on Sponge and Velocity.
|
||||
|
||||
In order for TAB to properly detect name change, player UUID must remain the same, otherwise it's a random entry with a random uuid and random name, which TAB isn't able to match with actual players. Make sure your nickname plugin is not changing UUID of players. If UUID changes, plugin won't be able to properly format names even in the tablist, since entries there are bound to UUIDs and by changing it, it will break.
|
||||
Identifying whether name change detection is working properly or not can be checked by setting `debug: true` in config and checking console on name change. It should say `Processing name change of player <player name> to <new nickname>`. If it doesn't, something went wrong, most likely UUID not matching.
|
||||
In order for TAB to properly detect name change, player UUID must remain the same,
|
||||
otherwise it's a random entry with a random uuid and random name, which TAB isn't able to match with actual players.
|
||||
Make sure your nickname plugin is not changing UUID of players.
|
||||
If UUID changes, the plugin won't be able to properly format names even in the tablist,
|
||||
since entries there are bound to UUIDs and by changing it, it will break.
|
||||
Identifying whether name change detection is working properly or not can be checked
|
||||
by setting `debug: true` in config and checking console on name change.
|
||||
It should say `Processing name change of player <player name> to <new nickname>`.
|
||||
If it doesn't, something went wrong, most likely UUID not matching.
|
||||
|
||||
# Tips & Tricks
|
||||
## Tip 1 - Nickname prefix
|
||||
@@ -38,9 +65,9 @@ conditions:
|
||||
yes: "%player%" # If nickname = player name -> player is not nicked
|
||||
no: "~%essentials_nickname%" # If nickname != player name -> player is nicked
|
||||
```
|
||||
Then, use `%condition:nick%` in your `customtabname` & `customtagname` instead of the placeholder directly.
|
||||
Then, use `%condition:nick%` in your `customtabname` instead of the placeholder directly.
|
||||
|
||||
# Tip 2 - Sorting nicked players with lowest priority
|
||||
# Tip 2 - Sorting nicked players with the lowest priority
|
||||
Let's say your sorting list looks like this:
|
||||
```
|
||||
sorting-types:
|
||||
|
||||
@@ -11,8 +11,10 @@ Glow color is managed by scoreboard teams, which also handle nametag formatting
|
||||
|
||||
## Solution
|
||||
The solution to get around this issue is to use the glow plugin's placeholder (if it has any).
|
||||
This placeholder has to be at the end of the player's `tagprefix` as it has to be the last color in the prefix.
|
||||
**NOTE: For Minecraft version 1.9 - 1.12 the prefix can't be longer than 14 characters due to [16 character limit](https://github.com/NEZNAMY/TAB/wiki/Limitations#name-tags) total (glow placeholder adds 2 characters - `&` and the color code)**
|
||||
This placeholder has to be at the end of the player's `tagprefix` as it has to be the last color in the prefix.
|
||||
> [!WARNING]
|
||||
> For Minecraft versions below 1.13 the prefix can't be longer than 14 characters due to [16-character limit](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Nametags#limitations) total
|
||||
(glow placeholder adds 2 characters - `&` and the color code)
|
||||
|
||||
**Example:**
|
||||
This example uses the placeholder of the [eGlow](https://www.spigotmc.org/resources/63295/) plugin.
|
||||
@@ -23,16 +25,7 @@ _DEFAULT_:
|
||||
tagprefix: '%vault-prefix%%eglow_glowcolor%'
|
||||
```
|
||||
|
||||
Keep in mind glow color is the same as name color. That's because there's only one field handling both values. However, you can bypass this with [Unlimited nametag mode](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Unlimited-nametag-mode). When enabling it, you'll get access to `customtagname` property, which is really just a part of the final armor stand string and can be freely modified.
|
||||
|
||||
To do so, you can configure for example
|
||||
```
|
||||
_DEFAULT_:
|
||||
customtagname: '&2%player%'
|
||||
```
|
||||
With this example, all players will have green visible name, despite their glow color.
|
||||
|
||||
## Examples of glow plugins
|
||||
- [eGlow](https://www.spigotmc.org/resources/63295/) (%eglow_glowcolor%) (Paid)
|
||||
- [CMI](https://www.spigotmc.org/resources/3742/) (%cmi_user_glow_code%) (Paid)
|
||||
- ... more ?
|
||||
- ... more?
|
||||
@@ -4,13 +4,14 @@
|
||||
* [Magic codes](#magic-codes)
|
||||
* [Invalid code handling](#invalid-code-handling)
|
||||
* [Compatibility with <1.16](#compatibility-with-116)
|
||||
* [Manually defining legacy color](#manually-defining-legacy-color)
|
||||
* [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.
|
||||
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:
|
||||
@@ -27,8 +28,8 @@ Gradients:
|
||||
|
||||
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.**
|
||||
**Don't forget to replace `RRGGBB` with actual hexadecimal numbers, for example `FFAA00`** (yes, some people straight up copy "RRGGBB" and ask why is it not working):
|
||||
This color code has 256 red, 170 green and 0 blue. It is equal to the legacy color `6` (gold/orange).
|
||||
> [!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.
|
||||
|
||||
@@ -41,27 +42,15 @@ For gradients, put the magic codes at the beginning of text. For example `<#00FF
|
||||
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. The plugin will find the closest legacy color to the desired RGB combination and will use that color instead.
|
||||
|
||||
## Manually defining legacy color
|
||||
If you want to specify a legacy color to use instead of plugin finding the closest one, you can define it by adding `|L` after RGB code, where `L` is a legacy color to use (0-9 a-f).
|
||||
Usage for classic codes:
|
||||
* `#RRGGBB|L`
|
||||
* `&#RRGGBB|L`
|
||||
* `{#RRGGBB|L}`
|
||||
* `#<RRGGBB|L>`
|
||||
* `<#RRGGBB|L>`
|
||||
* `&x&R&R&G&G&B&B|L`
|
||||
|
||||
For gradients, defining color will result in the whole text having the same color instead of each character converting to closest colors, resulting in color groups. To define it, put `|L` after the begin color of gradient.
|
||||
Usage:
|
||||
* `<#RRGGBB|L>Text</#RRGGBB>`
|
||||
* `{#RRGGBB|L>}Text{#RRGGBB<}`
|
||||
* `<$#RRGGBB|L>Text<$#RRGGBB>`
|
||||
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.
|
||||
**Warning!** This does NOT refer to different character sets! This refers to different fonts defined in resource packs or MC itself.
|
||||
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.
|
||||
|
||||
@@ -1,39 +1,65 @@
|
||||
# Content
|
||||
* [Bukkit/Spigot](#bukkitspigot)
|
||||
* [BungeeCord](#bungeecord)
|
||||
* [Backend](#backend)
|
||||
* [BungeeCord / Velocity](#bungeecord--velocity)
|
||||
* [Proxy installation](#proxy-installation)
|
||||
* [Backend installation](#backend-installation)
|
||||
* [Mixed installation](#mixed-installation)
|
||||
* [Updating the plugin](#updating-the-plugin)
|
||||
|
||||
# Bukkit/Spigot
|
||||
Installation on Bukkit/Spigot/Paper is as simple as it can be. Just put the plugin into 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 plugman to reload it.
|
||||
# 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.
|
||||
|
||||
# BungeeCord / Velocity
|
||||
When running a network, you have 3 options:
|
||||
* Installing TAB only on the proxy (recommended)
|
||||
* Installing TAB on all backend servers instead
|
||||
* Installing TAB everywhere and disabling features, so they don't conflict (not recommended)
|
||||
|
||||
See below for more information regarding each way.
|
||||
|
||||
# BungeeCord
|
||||
## Proxy installation
|
||||
This is the recommended setup. Put the plugin into plugins folder of the proxy server and restart it.
|
||||
**Recommended**: Install [TAB-Bridge](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge) on your backend servers for PlaceholderAPI support and more.
|
||||
**Note**: With BungeeCord installation use **/btab** command instead of **/tab**.
|
||||
This is the recommended setup.
|
||||
Put the plugin into the plugins folder of the proxy server and restart it.
|
||||
**Recommended**:
|
||||
Install [TAB-Bridge](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge) on your **backend servers** for PlaceholderAPI support and more.
|
||||
**Recommended**:
|
||||
If you are using **Velocity**,
|
||||
install [VelocityScoreboardAPI](https://github.com/NEZNAMY/VelocityScoreboardAPI/) plugin **on the proxy** for scoreboard-related features to work.
|
||||
|
||||
> [!NOTE]
|
||||
> With proxy installation, use **/btab** command instead of **/tab**.
|
||||
|
||||
Advantages of proxy installation compared to installing on all backend servers instead:
|
||||
* Can use the [Global player list](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist)
|
||||
* Can use new content for new clients even if 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) 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)
|
||||
* 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
|
||||
|
||||
|
||||
Disadvantages compared to installing on all backend servers instead:
|
||||
* No [per-world player list](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Per-world-playerlist) (can be achieved by installing the plugin on backend servers and disabling all features except the per-world player list)
|
||||
|
||||
## Backend installation
|
||||
Just like when not using BungeeCord, install the plugin on all servers where you want the plugin. However, this setup is not recommended (see advantages of proxy installation).
|
||||
Just like when not running a network, install the plugin on all servers where you want the plugin. However, this setup is not as good (see advantages of proxy installation).
|
||||
|
||||
## Mixed installation
|
||||
Mixed installation is absolutely not recommended and should be avoided. It requires you to disable features to make only 1 instance handle a single feature at a time, which most people fail miserably to do, resulting in issues such as header/footer flashing between proxy and backend configuration. With bridge you are able to achieve almost anything with proxy installation.
|
||||
Mixed installation is absolutely not recommended and should be avoided.
|
||||
It requires you to disable features to make only 1 instance handle a single feature at a time,
|
||||
which most people fail miserably to do,
|
||||
resulting in issues such as header/footer flashing between proxy and backend configuration.
|
||||
With bridge, you are able to achieve almost anything with proxy installation.
|
||||
|
||||
# Updating the plugin
|
||||
Updating the plugin is always as simple as replacing old jar with the new one.
|
||||
|
||||
You do not need to reset your configuration files or make any manual changes to them. If any changes to configuration are made (changed / removed / added), TAB will automatically convert your existing configuration files to the latest format (most notably 2.9.2 -> 3.0.0, but any other changes as well).
|
||||
You do not need to reset your configuration files or make any manual changes to them.
|
||||
If any changes to configuration are made (changed / removed / added),
|
||||
TAB will automatically convert your existing configuration files to the latest format
|
||||
(most notably 2.9.2 → 3.0.0, but any other changes as well).
|
||||
|
||||
Downgrading is completely unsupported, as old plugin version cannot know what the future config format is / will be. Just like Minecraft itself. There is no reason for downgrading anyway, as every version is superior to older versions released before it.
|
||||
Downgrading is completely unsupported, as an old plugin version cannot know what the future config format is / will be.
|
||||
Just like Minecraft itself.
|
||||
There is no reason for downgrading anyway, as every version is superior to older versions released before it.
|
||||
@@ -2,14 +2,14 @@
|
||||
This is collection if minecraft issues/bugs you may experience when using TAB, which are not TAB bugs and cannot be fixed with a plugin.
|
||||
|
||||
# 1.5.x - 1.12.x - Unwanted space
|
||||
You may see unwanted space at the end of a line of text even if you didn't configure any. This is a client sided bug. To avoid it, add &r after ending bold segment (for example prefix &4&lAdmin&r&6).
|
||||
You may see unwanted space at the end of a line of text even if you didn't configure any.
|
||||
This is a client sided bug.
|
||||
To avoid it, add `&r` after ending bold segment (for example, prefix `&4&lAdmin&r&6`).
|
||||
|
||||
# 1.15.x - Strikethrough and underline
|
||||
Using &m (strikethrough) and &n (underline) does not work in header, last line of scoreboard and possibly other places ([MC-180110](https://bugs.mojang.com/browse/MC-180110)).
|
||||
Using &m (strikethrough) and &n (underline) does not work in header,
|
||||
last line of the scoreboard and possibly other places
|
||||
([MC-180110](https://bugs.mojang.com/browse/MC-180110)).
|
||||
|
||||
# 1.20 - 1.20.4 - Chat over tablist
|
||||
Visual bug rendering chat over the tablist ([MC-263256](https://bugs.mojang.com/browse/MC-263256)).
|
||||
|
||||
# 1.20.3+ - Text not bold
|
||||
Since 1.20.3 text configured to be bold (using &l) may not appear bold. Steps to reproduce are currently unknown, if you have any information that may help, let us know.
|
||||
Clue #1 - It might be a BungeeCord bug breaking bold text. It may or may not have been fixed.
|
||||
Visual bug rendering chat over the tablist ([MC-263256](https://bugs.mojang.com/browse/MC-263256)).
|
||||
@@ -2,10 +2,9 @@
|
||||
Combine the knowledge gathered by reading the wiki to get interesting results, most frequently asked ones listed here.
|
||||
* [Displaying kill / death counter in tablist](#displaying-kill--death-counter-in-tablist)
|
||||
* [Taking prefixes/suffixes from permission plugin](#taking-prefixessuffixes-from-permission-plugin)
|
||||
* [Showing player version in tablist](#showing-player-version-in-tablist)
|
||||
* [Showing player's version in tablist](#showing-players-version-in-tablist)
|
||||
* [Replicating Purpur's TPSBar](#replicating-purpurs-tpsbar)
|
||||
* [BedWars1058 compatibility](#bedwars1058-compatibility)
|
||||
* [Moving nametag when player wears a hat](#moving-nametag-when-player-wears-a-hat)
|
||||
* [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)
|
||||
@@ -38,16 +37,25 @@ _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 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).
|
||||
|
||||
# Showing player version in tablist
|
||||
# Showing player's version in tablist
|
||||
Run `/tab group _DEFAULT_ tabsuffix " &8[&3%player-version%&8]"` or any other color combination you want. You can also include other placeholders with it. You can also modify it directly in **groups.yml** file instead. With the provided example command, you'll get the following result:
|
||||

|
||||
|
||||
# Replicating Purpur's TPSBar
|
||||
*This guide was made purely for demonstration of TAB's functionality to show you can even do things like this with conditions. It is not meant to be used as a replacement for Purpur or any of its functions or discouraging users from using Purpur.*
|
||||
|
||||
By default, Purpur's TPSBar shows server's TPS, MSPT and player ping. These change color from green to red based on value. The easier way to achieve this is with [Placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements-(premium-only)), however, it alters placeholders everywhere inside TAB, which would result in features like [Yellow number](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Yellow-number) to stop working correctly when %ping% is used, since it would contain color codes now. For that reason, we will use [Conditions](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) instead.
|
||||
By default, Purpur's TPSBar shows server's TPS, MSPT and player ping.
|
||||
These change colors from green to red based on value.
|
||||
The easier way
|
||||
to achieve this is with [Placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements-(premium-only)),
|
||||
however, it alters placeholders everywhere inside TAB,
|
||||
which would result in features like [Playerlist objective](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Playerlist-Objective)
|
||||
to stop working correctly when %ping% is used,
|
||||
since it would contain color codes now.
|
||||
For that reason,
|
||||
we will use [Conditions](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) instead.
|
||||
|
||||
When TPS is above 19, it displays as `<#55FF55>value</#00AA00>`. When above 15, `<#FFFF55>value</#FFAA00>`, otherwise `<#FF5555>value</#AA0000>`. This can be achieved with 2 conditions:
|
||||
```
|
||||
@@ -119,8 +127,11 @@ To display only the first letter of the team, download this PlaceholderAPI expan
|
||||
and use `%bw1058plus_team_letter%` instead, if you want the color as well, put `%bw1058plus_team_color%` right before.
|
||||
|
||||
## Rank in lobby & Team name in game
|
||||
If you want to display the rank of the player while he's in the lobby or waiting lobby, BUT show the team name while in game, then don't worry, there's a way =)
|
||||
You can create a condition which checks if the player's current team = nothing (which means the player isn't playing), and return either the rank or the team name depending on that condition. Example:
|
||||
If you want to display the rank of the player while he's in the lobby or waiting lobby,
|
||||
BUT show the team name while in the game, then don't worry, there's a way.
|
||||
You can create a condition which checks if the player's current team = nothing (which means the player isn't playing),
|
||||
and return either the rank or the team name depending on that condition.
|
||||
Example:
|
||||
```yml
|
||||
conditions:
|
||||
rankOrTeam:
|
||||
@@ -131,117 +142,28 @@ conditions:
|
||||
```
|
||||
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.
|
||||
|
||||
# Moving nametag when player wears a hat
|
||||
Unfortunately, there is no simple solution to this problem. We are going to use conditions with [unlimited nametag mode](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Unlimited-nametag-mode) to reach our results.
|
||||
|
||||
First, enable [unlimited nametag mode](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Unlimited-nametag-mode) by setting
|
||||
```
|
||||
scoreboard-teams:
|
||||
enabled: true
|
||||
unlimited-nametag-mode:
|
||||
enabled: true
|
||||
```
|
||||
in config.yml.
|
||||
|
||||
Second, define static lines, which will be used in case player has a hat. Let's make them 1 block higher than normal (hint: default space between lines is 0.26 blocks).
|
||||
```
|
||||
unlimited-nametag-mode:
|
||||
enabled: true
|
||||
dynamic-lines:
|
||||
- abovenameNormal
|
||||
- nametagNormal
|
||||
- belownameNormal
|
||||
static-lines:
|
||||
abovenameHat: 1.52
|
||||
nametagHat: 1.26
|
||||
belownameHat: 1
|
||||
```
|
||||
|
||||
Now, we are going to assume your configuration is [taking prefixes/suffixes from permission plugin](#taking-prefixessuffixes-from-permission-plugin), because otherwise we would end up with a TON of conditions, which would take too much brain power create and maintain. Let's create 2 conditions: 1 for having a hat, 1 for not having a hat. In the example, we will use `%magicosmetics_equipped_HAT%` placeholder. It return `true` if player has a hat, `false` if not.
|
||||
```
|
||||
conditions:
|
||||
nametagNormal:
|
||||
conditions:
|
||||
- '%magicosmetics_equipped_HAT%=false'
|
||||
true: '%vault-prefix%%player%%vault-suffix%'
|
||||
false: ""
|
||||
nametagHat:
|
||||
conditions:
|
||||
- '%magicosmetics_equipped_HAT%=true'
|
||||
true: '%vault-prefix%%player%%vault-suffix%'
|
||||
false: ""
|
||||
```
|
||||
Let's use it in groups.yml
|
||||
```
|
||||
_DEFAULT_:
|
||||
nametagNormal: "%condition:nametagNormal%"
|
||||
nametagHat: "%condition:nametagHat%"
|
||||
```
|
||||
Obviously don't forget to add your tabprefix and stuff. If you are using abovename and/or belowname as well, do the same for those lines as well. We already created static lines for them, let's create conditions for them.
|
||||
```
|
||||
conditions:
|
||||
nametagNormal:
|
||||
conditions:
|
||||
- '%magicosmetics_equipped_HAT%=false'
|
||||
true: '%vault-prefix%%player%%vault-suffix%'
|
||||
false: ""
|
||||
nametagHat:
|
||||
conditions:
|
||||
- '%magicosmetics_equipped_HAT%=true'
|
||||
true: '%vault-prefix%%player%%vault-suffix%'
|
||||
false: ""
|
||||
abovenameNormal:
|
||||
conditions:
|
||||
- '%magicosmetics_equipped_HAT%=false'
|
||||
true: 'abovename text'
|
||||
false: ""
|
||||
abovenameHat:
|
||||
conditions:
|
||||
- '%magicosmetics_equipped_HAT%=true'
|
||||
true: 'abovename text'
|
||||
false: ""
|
||||
belownameNormal:
|
||||
conditions:
|
||||
- '%magicosmetics_equipped_HAT%=false'
|
||||
true: 'belownametext'
|
||||
false: ""
|
||||
belownameHat:
|
||||
conditions:
|
||||
- '%magicosmetics_equipped_HAT%=true'
|
||||
true: 'belowname text'
|
||||
false: ""
|
||||
```
|
||||
and use in groups.yml
|
||||
```
|
||||
_DEFAULT_:
|
||||
nametagNormal: "%condition:nametagNormal%"
|
||||
nametagHat: "%condition:nametagHat%"
|
||||
abovenameNormal: "%condition:abovenameNormal%"
|
||||
abovenameHat: "%condition:abovenameHat%"
|
||||
belownameNormal: "%condition:belownameNormal%"
|
||||
belownameHat: "%condition:belownameHat%"
|
||||
```
|
||||
If you are not using all 3 lines, you can also remove them from static lines. You may also need to adjust static height, since you may want different height of the prefix+name+suffix line based on if you have belowname or not, to avoid the line being too high.
|
||||
|
||||
# Displaying AFK status in tablist
|
||||
First, you'll need to get an AFK plugin. TAB does not track player AFK status. Then, find a PlaceholderAPI placeholder for your AFK plugin in their documentation, such as
|
||||
* `%essentials_afk%` for Essentials
|
||||
* `%cmi_user_afk_symbol%` for CMI
|
||||
* `%purpur_player_afk%` for Purpur (server software)
|
||||
|
||||
Don't forget to install PlaceholderAPI and the respective expansion of your afk plugin.
|
||||
Remember to install PlaceholderAPI and the respective expansion of your afk plugin.
|
||||
|
||||
Then, use the placeholder in configuration wherever you want it. Assuming you want it for all players, use `_DEFAULT_` group keyword in **groups.yml** for default settings for all groups. Combined with other settings, it may look like this for tabsufffix:
|
||||
Then, use the placeholder in configuration wherever you want it.
|
||||
Assuming you want it for all players,
|
||||
use `_DEFAULT_` group keyword in **groups.yml** for default settings for all groups.
|
||||
Combined with other settings, it may look like this for tabsuffix:
|
||||
```
|
||||
_DEFAULT_:
|
||||
tabsuffix: "%luckperms-suffix%%essentials_afk%"
|
||||
```
|
||||
Or running an in-game command: `/tab group _DEFAULT_ tabsuffix %luckperms-suffix%%essentials_afk%`.
|
||||
This is not limited to displaying AFK status in suffix, you can also using it in tabprefix instead (or nametags).
|
||||
This is not limited to displaying AFK status in suffix, you can also use it in tabprefix instead (or nametags).
|
||||
|
||||
|
||||
Finally, you will most likely need to set up [placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements) for the placeholder, as lots of them, including the %essentials_afk% placeholder used as an example, return `yes` and `no` values, which you most likely want to customize.
|
||||
As mentioned, by default, Essentials' afk placeholder returns `yes` / `no` (unless modified in PlaceholderAPI's config.yml). Other placeholders may return different values. To find out what a placeholder returned, use `/tab parse <player> <placeholder>`. Don't forget to include color codes as well.
|
||||
As mentioned, by default, Essentials' afk placeholder returns `yes` / `no` (unless modified in PlaceholderAPI's config.yml). Other placeholders may return different values. To find out what a placeholder returned, use `/tab parse <player> <placeholder>`. Remember to include color codes as well.
|
||||
An example customization may look like this:
|
||||
```
|
||||
placeholder-output-replacements:
|
||||
@@ -249,11 +171,18 @@ placeholder-output-replacements:
|
||||
"yes": " &4&lAFK"
|
||||
"no": "" # display nothing if not afk
|
||||
```
|
||||
Keep in mind that some placeholders don't need this. For example CMI has 2 placeholders - %cmi_user_afk% that returns true/false, and %cmi_user_afk_symbol% that returns AFK text configured in CMI configuration. Therefore, if you decide to use the latter one, you don't need to set up replacements.
|
||||
Keep in mind that some placeholders don't need this.
|
||||
For example, CMI has 2 placeholders - %cmi_user_afk% that returns true/false,
|
||||
and %cmi_user_afk_symbol% that returns AFK text configured in CMI configuration.
|
||||
Therefore, if you decide to use the latter one, you don't need to set up replacements.
|
||||
|
||||
# Showing combined online player count from multiple servers
|
||||
## Option 1 - Using global playerlist
|
||||
First way is to install TAB on the proxy and enable [global playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist). It allows you to create groups of servers that share playerlist. These groups can then be used to show player count on those servers using a placeholder. Using the following example:
|
||||
The first way is to install TAB on the proxy
|
||||
and enable [global playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist).
|
||||
It allows you to create groups of servers that share playerlist.
|
||||
These groups can then be used to show player count on those servers using a placeholder.
|
||||
Using the following example:
|
||||
```
|
||||
global-playerlist:
|
||||
enabled: true
|
||||
@@ -264,7 +193,10 @@ global-playerlist:
|
||||
```
|
||||
Servers `lobby1` and `lobby2` will share playerlist. You will also be able to use placeholder formula `%playerlist-group_<group>%`, in this case `%playerlist-group_lobbies%`. It will show amount of players on `lobby1` and `lobby2` combined.
|
||||
|
||||
Advantage of this is the natural compatibility with global playerlist's settings, which is also its disavantage, since global playerlist has to be configured that way. When using [layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) feature, global playerlist is redundant and having it enabled only for the placeholder is inefficient.
|
||||
Advantage of this is the natural compatibility with global playerlist's settings,
|
||||
which is also its disadvantage, since global playerlist has to be configured that way.
|
||||
When using [layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) feature,
|
||||
global playerlist is redundant and having it enabled only for the placeholder is inefficient.
|
||||
|
||||
## Option 2 - Using PlaceholderAPI
|
||||
Unlike the first option, this one offers much more freedom, but also requires another plugin. You'll need to [download PlaceholderAPI and its expansions called math and bungee](https://github.com/NEZNAMY/TAB/wiki/Quick-PlaceholderAPI-startup-guide) (`/papi ecloud download bungee`, `/papi ecloud download math`, `/papi reload`).
|
||||
|
||||
@@ -11,20 +11,24 @@
|
||||
By default, groups and users are stored in separate files (groups.yml and users.yml).
|
||||
Enabling MySQL will use it as storage of groups and users instead of the files.
|
||||
|
||||
playerdata.yml file (for toggling scoreboard/bossbar and remembering decision) is not affected and will still be used instead of MySQL. It may be added in the future.
|
||||
`playerdata.yml` file (for toggling scoreboard/bossbar and remembering the decision)
|
||||
is not affected and will still be used instead of MySQL.
|
||||
It may be added in the future.
|
||||
|
||||
All tables from TAB are prefixed with `tab_`, currently `tab_groups` for groups and `tab_users` for users.
|
||||
|
||||
# Availability
|
||||
Before attempting to use the function, make sure your server software has an integrated MySQL driver. TAB does not contain it by itself. See compatibility matrix below for current information about compatibility:
|
||||
Before attempting to use the function, make sure your server software has an integrated MySQL driver.
|
||||
TAB does not contain it by itself.
|
||||
See the compatibility table below for current information about compatibility:
|
||||
|
||||
| Platform | Available |
|
||||
| ------------- | ------------- |
|
||||
| Bukkit | ✔ |
|
||||
| BungeeCord | ✔ |
|
||||
| Fabric | ❌ |
|
||||
| Sponge | ❌ |
|
||||
| Velocity | ❌ |
|
||||
| Platform | Available |
|
||||
|------------|-----------|
|
||||
| Bukkit | ✔ |
|
||||
| BungeeCord | ✔ |
|
||||
| Fabric | ❌ |
|
||||
| Sponge | ❌ |
|
||||
| Velocity | ❌ |
|
||||
|
||||
# Enabling
|
||||
Find this section in **config.yml**:
|
||||
@@ -41,11 +45,14 @@ mysql:
|
||||
Enabling it will enable MySQL. The other settings are pretty straight forward.
|
||||
|
||||
# Configuration changes
|
||||
Once enabled, configured values in groups.yml and users.yml will not be visible anymore, which is expected, because your database is empty when created. This is not a bug. All you need to do is [upload your data to the database](#uploading-from-files-to-mysql).
|
||||
Once enabled, configured values in groups.yml and users.yml will not be visible anymore,
|
||||
which is expected because your database is empty when created.
|
||||
This is not a bug.
|
||||
All you need to do is [upload your data to the database](#uploading-from-files-to-mysql).
|
||||
|
||||
Since groups.yml and users.yml files will no longer be used, making any changes to them will take no effect. If you wish to perform any changes, you have 2 options:
|
||||
* Use in-game commands, which will upload changes to the database
|
||||
* Upload the file to database after every change (will not work for removing though) (useful when enabling for the first time).
|
||||
* Upload the file to the database after every change (will not work for removing though) (useful when enabling for the first time).
|
||||
|
||||
# Data conversion
|
||||
## Downloading from MySQL to files
|
||||
@@ -56,13 +63,15 @@ Existing data in files will not intentionally be deleted, but may get overwritte
|
||||
## Uploading from files to MySQL
|
||||
This can be done using `/tab mysql upload` command (permission is `tab.mysql.upload`). It will upload all content from groups.yml and users.yml into MySQL.
|
||||
This command requires the MySQL function enabled.
|
||||
Existing data in database will not intentionally be deleted, but may get overwritten.
|
||||
Existing data in the database will not intentionally be deleted, but may get overwritten.
|
||||
|
||||
# Synchronization frequency
|
||||
When using files to store data, it's simple - groups.yml and users.yml files are loaded into memory and read from when needed. When a command is ran to update something, it is updated in memory and saved into files as well.
|
||||
When using files to store data, it's simple -
|
||||
groups.yml and users.yml files are loaded into memory and read from when needed.
|
||||
When a command is run to update something, it is updated in memory and saved into files as well.
|
||||
|
||||
When using MySQL, the plugin has to keep data up to date with other servers, but at the same time not kill the server with requests all the time.
|
||||
For writing, both groups and users, whenever a command is used to update something, the update is sent to the database immediately.
|
||||
For reading, data is updated as following:
|
||||
* Groups - All data from groups table is loaded into memory on load (server start, plugin reload). When a player joins in or any other action, values from memory are checked. Therefore, if a change is made on another server, it will not be visible until plugin reload.
|
||||
* Users - Nothing is loaded on plugin load. Whenever a player joins, all data of that player is requested from the database. Therefore, if player's data changes on another server, it is visible immediately when player joins this one, without the need to reload the plugin.
|
||||
* Groups - All data from groups table is loaded into memory on a load (server start, plugin reload). When a player joins in or any other action, values from memory are checked. Therefore, if a change is made on another server, it will not be visible until the plugin is reloaded.
|
||||
* Users - Nothing is loaded on a plugin load. Whenever a player joins, all data of that player is requested from the database. Therefore, if a player's data changes on another server, it is visible immediately when a player joins this one, without the need to reload the plugin.
|
||||
@@ -5,15 +5,20 @@ The usage can be checked at any time using [**/tab cpu**](https://github.com/NEZ
|
||||
* [#1 - [All platforms] Static text instead of placeholders](#1---all-platforms-static-text-instead-of-placeholders)
|
||||
* [#2 - [All platforms] Placeholder refresh intervals](#2---all-platforms-placeholder-refresh-intervals)
|
||||
* [#3 - [All platforms] Don't use RGB](#3---all-platforms-dont-use-rgb)
|
||||
* [#4 - [All platforms] Disable anti-override](#4---all-platforms-disable-anti-override)
|
||||
* [#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 - [BungeeCord / Velocity] Disable TAB expansion](#7---bungeecord--velocity-disable-tab-expansion)
|
||||
* [#8 - [BungeeCord] Disable ByteBuf deserialization](#8---bungeecord-disable-bytebuf-deserialization)
|
||||
* [#9 - [Velocity] Disable header/footer translation](#9---velocity-disable-headerfooter-translation)
|
||||
* [#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)
|
||||
|
||||
# #1 - [All platforms] Static text instead of placeholders
|
||||
Static text doesn't need to be refreshed periorically, resulting in better performance. Some placeholders can be replaced with static text, such as placeholder for max player counts, since that value doesn't change at runtime. Another option is to configure prefixes per-group in config instead of using placeholders to take those values from permission plugin.
|
||||
Static text doesn't need to be refreshed periodically, resulting in better performance.
|
||||
Some placeholders can be replaced with static text, such as placeholder for max player counts,
|
||||
since that value doesn't change at runtime.
|
||||
Another option is to configure prefixes per-group in config
|
||||
instead of using placeholders to take those values from your permission plugin.
|
||||
|
||||
# #2 - [All platforms] Placeholder refresh intervals
|
||||
Some placeholders take a long time to process and result in high cpu usage. However, this can be optimized by configuring refresh interval of placeholders.
|
||||
@@ -35,70 +40,97 @@ Refresh interval is in milliseconds. It must be divisible by 50.
|
||||
|
||||
`default-refresh-interval` is refresh interval for all unlisted PlaceholderAPI placeholders.
|
||||
|
||||
Keep in mind that CPU measurement is reset every 10 seconds. This means that if you configure a higher refresh interval than 10000, there will be intervals when placeholder didn't refresh at all, making it look like the CPU is perfect, while on the next refresh it may be high. For this reason, if you want to cleanly track usage, keep interval at 10000 at most. Using a higher interval will help if needed, but may lead to misleading info in cpu output.
|
||||
Keep in mind that CPU measurement is reset every 10 seconds.
|
||||
This means that if you configure a higher refresh interval than 10000,
|
||||
there will be intervals when placeholder didn't refresh at all,
|
||||
making it look like the CPU is perfect, while on the next refresh it may be high.
|
||||
For this reason, if you want to cleanly track usage, keep the interval at 10000 at most.
|
||||
Using a higher interval will help if needed, but may lead to misleading info in cpu output.
|
||||
|
||||
# #3 - [All platforms] Don't use RGB
|
||||
Though RGB colors look good, they require the text to be split into several components with `color` field used instead of the whole text pasted into the `text` field. This is a complicated process that takes quite some time. Sticking to legacy colors results in better performance.
|
||||
|
||||
# #4 - [All platforms] 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 attemps 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.
|
||||
# #4 - [All platforms] Don't use animations
|
||||
While animations look cool, they also have a high resource usage.
|
||||
This is because they work by spamming updates every time an animation switches to a new frame.
|
||||
When animations are not used, no updates need to be sent (unless another placeholder changes value),
|
||||
not causing extra CPU usage.
|
||||
|
||||
# #5 - [All platforms] Disable 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 tricker, as override attempts are not logged, because it would have a lot of false positives. You will need to try and see.
|
||||
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
|
||||
```
|
||||
|
||||
# #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, nametag format appears in tablist if tablist name is not defined. You can take advantage of this to effectively disable one entire feature and its cpu usage, while not losing on anything. However, you can only do this if:
|
||||
# #6 - [All platforms] Disable tablist name formatting
|
||||
As we already know from [Client-sided mechanics](https://github.com/NEZNAMY/TAB/wiki/Client%E2%80%90sided-mechanics#nametag-format-in-tablist) page,
|
||||
the nametag format appears in tablist if tablist name is not defined.
|
||||
You can take advantage of this to effectively disable one entire feature and its cpu usage,
|
||||
while not losing on anything.
|
||||
However, you can only do this if:
|
||||
* You are fine with nametag and tablist formats being identical, which also means all [nametag limitations](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Nametags#limitations) will transfer to tablist as well
|
||||
* You don't have any plugin formatting the tablist names
|
||||
|
||||
Whether you have another plugin attempting to handle them or not may not be easy to identify with a lot of plugins and not enough time spent configuring them. In that case, your best choice is to try it and see. If tablist names break, it means you have another plugin and cannot take advantage of this optimization option.
|
||||
|
||||
# #6 - [All platforms] Increase permission refresh interval
|
||||
# #7 - [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 permission plugin
|
||||
* Prefix/suffix placeholders taking data from your permission plugin
|
||||
|
||||
Default value
|
||||
default value
|
||||
```
|
||||
permission-refresh-interval: 1000
|
||||
```
|
||||
refreshes them every second. If you don't need any permission/group changes to take effect within a second, you can increase this value for better performance.
|
||||
Refreshes them every second.
|
||||
If you don't need any permission/group changes to take effect within a second,
|
||||
you can increase this value for better performance.
|
||||
|
||||
# #7 - [BungeeCord / Velocity] Disable TAB expansion
|
||||
In order to maximize performance of TAB's response to PlaceholderAPI request, values are tracked in advance and then quickly returned. This process takes resources and is especially heavy on proxy installation, where values must be constantly sent to bridge using plugin messages.
|
||||
# #8 - [BungeeCord / Velocity] Disable TAB expansion
|
||||
To maximize the performance of TAB's response to PlaceholderAPI request,
|
||||
values are tracked in advance and then quickly returned.
|
||||
This process takes resources and is especially heavy on proxy installation,
|
||||
where values must be constantly sent to bridge using plugin messages.
|
||||
Disabling TAB's PlaceholderAPI expansion if you don't use it improves performance.
|
||||
**config.yml**:
|
||||
```
|
||||
placeholders:
|
||||
register-tab-expansion: false
|
||||
```
|
||||
# #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.
|
||||
|
||||
# #8 - [BungeeCord] Disable ByteBuf deserialization
|
||||
# #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 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.
|
||||
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
|
||||
```
|
||||
scoreboard:
|
||||
respect-other-plugins: false
|
||||
```
|
||||
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. If you don't use scoreboard feature, this option is naturally disabled. If you do, but don't need compatibility with other plugins, you can disable this option.
|
||||
|
||||
# #9 - [Velocity] Disable header/footer translation
|
||||
Velocity offers header/footer translation of translatable components, however, TAB does not use these. Despite that, attempts to "translate" it are still there, causing the whole feature to use up to 3x more CPU than it would without it. There is no way to disable this inside Velocit itself, however, there is a third party [fork](https://github.com/GemstoneGG/Velocity-CTD/) that offers it.
|
||||
**Use at your own risk**.
|
||||
After installing, default velocity.toml file will contain `translate-header-footer = true` option. If just upgrading, you will need to add it there yourself. Setting it to `false` will disable this function.
|
||||
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.
|
||||
@@ -26,59 +26,69 @@ TAB offers various placeholders to display the most common information. It also
|
||||
|
||||
Basic placeholders provided by the plugin. Most of these placeholders were added because they were requested by people who don't want to install another plugin just to show username. Some of them have configurable output in config.yml in `Placeholders` section. Unused placeholders do not affect performance in any way.
|
||||
|
||||
Placeholders must be refreshed. All internal placeholders have manually defined refresh interval, which I found the most optimal and cannot be changed. Time is in milliseconds. `-1` is used for placeholders which are in fact constants (such as %player%), or fire an event each time they change, which can be listened to (such as %world%) and value updated. Refresh interval for conditions is set to be equal to fastest refreshing placeholder used inside each condition.
|
||||
Placeholders must be refreshed.
|
||||
All internal placeholders have a manually defined refresh interval,
|
||||
which I found the most optimal and cannot be changed.
|
||||
Time is in milliseconds.
|
||||
It 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 |
|
||||
| %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 |
|
||||
|
||||
## 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.
|
||||
| Identifier | Refresh interval | Description | PlaceholderAPI alternative |
|
||||
| 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% |
|
||||
| %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) | - |
|
||||
|
||||
## BungeeCord only
|
||||
| Identifier | Refresh interval | Description |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| %server% | -1 | Name of server where player is, defined in proxy's config. |
|
||||
| %serveronline% | 1000 | Amount of online players on server where the player is (excluding vanished players) |
|
||||
| %online_\<servername\>% | 1000 | Amount of online players on specified server (excluding vanished players) |
|
||||
| %playerlist-group_\<group\>% | 1000 | Amount of online players in specified [global playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist) group (therefore the feature must be enabled) |
|
||||
| Identifier | Refresh interval | Description |
|
||||
|------------------------------|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| %server% | -1 | Name of server where player is, defined in proxy's config. |
|
||||
| %serveronline% | 1000 | Amount of online players on server where the player is (excluding vanished players) |
|
||||
| %online_\<server name\>% | 1000 | Amount of online players on specified server (excluding vanished players) |
|
||||
| %playerlist-group_\<group\>% | 1000 | Amount of online players in specified [global playerlist](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist) group (therefore the feature must be enabled) |
|
||||
|
||||
# PlaceholderAPI
|
||||
PlaceholderAPI is supported and relational placeholders are supported too. When parsing relational placeholders, TAB puts viewer as the first player argument and target player as second argument.
|
||||
PlaceholderAPI is supported and relational placeholders are supported too.
|
||||
When parsing relational placeholders,
|
||||
TAB puts viewer as the first player argument and target player as the second argument.
|
||||
|
||||
You can find most of placeholders that PlaceholderAPI offers on [PlaceholderAPI wiki](https://github.com/PlaceholderAPI/PlaceholderAPI/wiki/Placeholders). Some plugins are not listed there, for those you'll need to check their own wiki for placeholders.
|
||||
You can find most of the placeholders
|
||||
that PlaceholderAPI offers on [PlaceholderAPI wiki](https://github.com/PlaceholderAPI/PlaceholderAPI/wiki/Placeholders).
|
||||
Some plugins are not listed there, for those you'll need to check their own wiki for placeholders.
|
||||
|
||||
TAB also offers its own placeholders into PlaceholderAPI. In order to enable TAB's expansion, set
|
||||
TAB also offers its own placeholders into PlaceholderAPI. To enable TAB's expansion, set
|
||||
```
|
||||
placeholders:
|
||||
register-tab-expansion: true
|
||||
@@ -92,17 +102,11 @@ Full list of placeholders:
|
||||
| %tab_tagprefix% | Current tagprefix with replaced placeholders |
|
||||
| %tab_tagsuffix% | Current tagsuffix with replaced placeholders |
|
||||
| %tab_customtabname% | Current customtabname with replaced placeholders |
|
||||
| %tab_customtagname% | Current customtagname with replaced placeholders |
|
||||
| %tab_belowname% | Current belowname with replaced placeholders |
|
||||
| %tab_abovename% | Current abovename with replaced placeholders |
|
||||
| %tab_tabprefix_raw% | Raw tabprefix containing unparsed placeholders |
|
||||
| %tab_tabsuffix_raw% | Raw tabsuffix containing unparsed placeholders |
|
||||
| %tab_tagprefix_raw% | Raw tagprefix containing unparsed placeholders |
|
||||
| %tab_tagsuffix_raw% | Raw tagsuffix containing unparsed placeholders |
|
||||
| %tab_customtabname_raw% | Raw customtabname containing unparsed placeholders |
|
||||
| %tab_customtagname_raw% | Raw customtagname containing unparsed placeholders |
|
||||
| %tab_belowname_raw% | Raw belowname containing unparsed placeholders |
|
||||
| %tab_abovename_raw% | Raw abovename containing unparsed placeholders |
|
||||
| %tab_tabprefix_raw% | Raw tabprefix containing raw placeholders |
|
||||
| %tab_tabsuffix_raw% | Raw tabsuffix containing raw placeholders |
|
||||
| %tab_tagprefix_raw% | Raw tagprefix containing raw placeholders |
|
||||
| %tab_tagsuffix_raw% | Raw tagsuffix containing raw placeholders |
|
||||
| %tab_customtabname_raw% | Raw customtabname containing raw 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 |
|
||||
@@ -113,7 +117,13 @@ Full list of placeholders:
|
||||
|
||||
# Relational placeholders
|
||||
## About
|
||||
Unlike classic placeholders which take either 0 (placeholders with same output for all players) or 1 (per-player placeholders) players, relational placeholders take in 2 players. The first usage was to display relation between two players, specifically enemies / allies (red / green) for factions, allowing players to see faction names of other players colored based on relation. While the usage is not limited to this, the name of the 2-player placeholder type has been established as "relational" and will be called that everywhere.
|
||||
Unlike classic placeholders which take either 0
|
||||
(placeholders with the same output for all players) or 1 (per-player placeholders) players,
|
||||
relational placeholders take in 2 players.
|
||||
The first usage was to display relation between two players, specifically enemies / allies (red / green) for factions,
|
||||
allowing players to see faction names of other players colored based on relation.
|
||||
While the usage is not limited to this, the name of the 2-player placeholder type has been established as "relational"
|
||||
and will be called that everywhere.
|
||||
|
||||
## Usage
|
||||
TAB does not offer any internal relational placeholders. However, it has full support for PlaceholderAPI placeholders. You can also register your own relational placeholders using the [API](#relational-placeholders-1). In PlaceholderAPI, all relational placeholder identifiers must start with `%rel_`. This rule is adopted and used in TAB as well (including those registered via API).
|
||||
@@ -126,31 +136,48 @@ public String onPlaceholderRequest(Player viewer, Player target, String identifi
|
||||
where `viewer` is the player looking and `target` is the player the value is being displayed on.
|
||||
|
||||
When trying to use placeholders from other plugins, you will need to check their documentation and search for relational placeholders. If your plugin does not appear to offer any, you ran out of luck and TAB cannot do anything about it.
|
||||
In order to properly distinguish viewer/target (if needed), your relational placeholder expansion must follow the same order as TAB does. Since PlaceholderAPI never created any convention regarding this and instead calls the players `one` and `two`, I had to decide and this is the decision.
|
||||
To properly distinguish viewer/target (if needed), your relational placeholder expansion must follow the same order as TAB does. Since PlaceholderAPI never created any convention regarding this, and instead it calls the players `one` and `two`, I had to decide and this is the decision.
|
||||
|
||||
# Refreshing
|
||||
## Refresh intervals
|
||||
TAB is refreshing placeholders in intervals. For internal placeholders it's using values I found the most optimal and set directly in the plugin. Refresh intervals for PlaceholderAPI placeholders can be [configured](https://github.com/NEZNAMY/TAB/wiki/Optimizing-the-plugin#2---placeholder-refresh-intervals).
|
||||
|
||||
## Sync refreshing
|
||||
By default, all placeholders are refreshed asynchronously so they don't slow down the server, since reading should be a thread-safe operation. Some placeholders, however, require to be refreshed in the main thread, causing problems or throwing errors when refreshed asynchronously. For these, replace them with `%sync:<original placeholder>%` and they will be refreshed in the main thread, for example `%server_total_entities%` -> `%sync:server_total_entities%`.
|
||||
Keep in mind that now you should configure reasonable refresh interval for these placeholders to not cause TPS drops (with async placeholders it doesn't really matter). Configured refresh intervals and CPU usage of placeholders can be checked using `/tab cpu`.
|
||||
By default, all placeholders are refreshed asynchronously,
|
||||
so they don't slow down the server, since reading should be a thread-safe operation.
|
||||
Some placeholders, however, require to be refreshed in the main thread,
|
||||
causing problems or throwing errors when refreshed asynchronously.
|
||||
For these, replace them with `%sync:<original placeholder>%` and they will be refreshed in the main thread,
|
||||
for example `%server_total_entities%` -> `%sync:server_total_entities%`.
|
||||
Keep in mind that now you should configure a reasonable refresh interval for these placeholders to not cause TPS drops
|
||||
(with async placeholders it doesn't really matter).
|
||||
Configured refresh intervals and CPU usage of placeholders can be checked using `/tab cpu`.
|
||||
|
||||
# Placeholder is not working
|
||||
When using a placeholder, you should know if it's a [TAB's internal placeholder](#internal-placeholders) or a [PlaceholderAPI placeholder](https://github.com/PlaceholderAPI/PlaceholderAPI/wiki/Placeholders). If you don't, that's the problem.
|
||||
|
||||
**Note:** Don't forget that using `%` symbol will mess up placeholder starts and ends, breaking all placeholders after it. To make the symbol display correctly without messing up placeholders, use `%%` to display the symbol.
|
||||
**Example:** `Sale 100% OFF! %some_placeholder%` -> `Sale 100%% OFF! %some_placeholder%`.
|
||||
> [!CAUTION]
|
||||
> Remember that using `%` symbol will mess up placeholder starts and ends, breaking all placeholders after it.
|
||||
> To make the symbol display correctly without messing up placeholders, use `%%` to display the symbol.
|
||||
> **Example:** `Sale 100% OFF! %some_placeholder%` -> `Sale 100%% OFF! %some_placeholder%`.
|
||||
|
||||
## Internal placeholder is not working
|
||||
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. **Trying to use a bukkit-only placeholder on bungeecord will not work.**
|
||||
If you want to use those, [set up PlaceholderAPI support on bungeecord](https://github.com/NEZNAMY/TAB/wiki/TAB-Bridge) and find their PlaceholderAPI equivalent. Large portion of those are included on [PlaceholderAPI's wiki](https://github.com/PlaceholderAPI/PlaceholderAPI/wiki/Placeholders).
|
||||
For example you can use %vault_prefix% instead of %vault-prefix%, %player_health% instead of %health% and so on.
|
||||
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.
|
||||
> [!IMPORTANT]
|
||||
> Trying to use a bukkit-only placeholder on bungeecord will not work.
|
||||
> If you want to use those,
|
||||
> [set up PlaceholderAPI support on bungeecord](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 on bukkit or the previous step did not work, make sure it works when using `/papi parse me <placeholder>`. If it does not work, the issue is not on TAB's end.
|
||||
> [!TIP]
|
||||
> Use `/papi parse me <placeholder>` to check if the placeholder is working.
|
||||
> If it does not work, the issue is not on TAB's end.
|
||||
|
||||
# API
|
||||
*To get started with the API, see [Developer API](https://github.com/NEZNAMY/TAB/wiki/Developer-API) page.*
|
||||
@@ -159,7 +186,7 @@ For working with placeholders, you will need the `PlaceholderManager`. Get it us
|
||||
|
||||
Placeholders have two attributes:
|
||||
* An identifier, which is used to uniquely identify the placeholder. This is also what's usually used for replacement. For example, in `%uptime%`, the identifier is `%uptime%`.
|
||||
* A refresh rate in milliseconds, which is how often the placeholder's refresh function will be called, to get a new value to display. Use `-1` to make the placeholder never refresh periodically. This can be used for either constants or placeholders that update on events and you wish to update their value manually using functions in respective placeholder interface.
|
||||
* A refresh rate in milliseconds, which is how often the placeholder's refresh function will be called, to get a new value to display. Use `-1` to make the placeholder never refresh periodically. This can be used for either constants or placeholders that update on events, and you wish to update their value manually using functions in the respective placeholder interface.
|
||||
|
||||
## Server placeholders
|
||||
Server placeholders are global to the entire plugin. Their values are not dependent on player.
|
||||
@@ -178,7 +205,7 @@ This placeholder will show current system time and update every 50 milliseconds.
|
||||
|
||||
## Player placeholders
|
||||
Player placeholders are calculated on a per-player basis. These depend on the player that we want to get the value for.
|
||||
Examples of player placeholders would be nickname and prefix.
|
||||
Examples of player placeholders would be username and prefix.
|
||||
|
||||
To register a new player placeholder, use `PlaceholderManager#registerPlayerPlaceholder(String, int, Function<TabPlayer, Object>)`. The first two parameters are explained above, and the last parameter is a function that will be called to refresh the value of the placeholder.
|
||||
<details>
|
||||
@@ -208,5 +235,7 @@ TabAPI.getInstance().getPlaceholderManager().registerRelationalPlaceholder("%rel
|
||||
});
|
||||
```
|
||||
|
||||
This placeholder will show version of players, but only to those, who have `tab.staff` permission. First player in the method is viewer, second player is target. Same order is applied when hooking into PlaceholderAPI as well.
|
||||
This placeholder will show the version of players, but only to those, who have `tab.staff` permission.
|
||||
The first player in the method is viewer, the second player is target.
|
||||
The same order is applied when hooking into PlaceholderAPI as well.
|
||||
</details>
|
||||
@@ -1,25 +1,29 @@
|
||||
# About
|
||||
This is a quick guide for [PlaceholderAPI](https://www.spigotmc.org/resources/placeholderapi.6245/) plugin, which is often referred to on the wiki and we also get many assistance requests with TAB which turn out to be asking for help with PlaceholderAPI. Whether its documentation is not clear enough, missing information or users just don't read it isn't the topic here to judge, instead, a quick guide with everything needed is provided.
|
||||
This is a quick guide for [PlaceholderAPI](https://www.spigotmc.org/resources/placeholderapi.6245/) plugin, which is often referred to on the wiki, and we also get many assistance requests with TAB which turn out to be asking for help with PlaceholderAPI. Whether its documentation is not clear enough, missing information or users just don't read it isn't the topic here to judge, instead, a quick guide with everything needed is provided.
|
||||
|
||||
# Installation
|
||||
PlaceholderAPI is a standalone bukkit plugin which 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, 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.
|
||||
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,
|
||||
you'll need to install [Bridge](https://www.spigotmc.org/resources/83966) plugin on backend servers.
|
||||
Alongside other features, it forwards PlaceholderAPI support to the proxy.
|
||||
|
||||
# Expansions
|
||||
In order to effectively scale and allow the level of modification it does, PlaceholderAPI is using placeholder packages called expansions. They are loaded into the plugin on startup. Each expansion can be created and modified independently of the main plugin's update frequency. Each expansion has a name, which is used to identify its placeholders.
|
||||
The syntax is `%<expansion name>_<placeholder>%`, where `<expansion name>` is name of the expansion, for example `player` and `<placeholder>` is placeholder of the expansion, for example `health`, which returns player's health. The full placeholder syntax will then be `%player_health%`.
|
||||
You can therefore guess name of the expansion which a placeholder you are trying to use comes from. You have 2 ways of getting expansions. Which one it is for your specific placeholder expansion should be included in documentation.
|
||||
To effectively scale and allow the level of modification it does,
|
||||
PlaceholderAPI is using placeholder packages called expansions.
|
||||
They are loaded into the plugin on startup.
|
||||
Each expansion can be created and modified independently of the main plugin's update frequency.
|
||||
Each expansion has a name, which is used to identify its placeholders.
|
||||
The syntax is `%<expansion>_<placeholder>%`, where `<expansion>` is name of the expansion,
|
||||
for example `player` and `<placeholder>` is placeholder of the expansion, for example `health`,
|
||||
which returns player's health.
|
||||
The full placeholder syntax will then be `%player_health%`.
|
||||
|
||||
## External expansions
|
||||
First way is using external jars, which are stored on [PlaceholderAPI website](https://api.extendedclip.com/all/). You can get them by either manually downloading them into `plugins/PlaceholderAPI/expansions/` folder, or by running `/papi ecloud download <expansion name>`.
|
||||
To load new expansions, run `/papi reload`.
|
||||
Some plugins offer their own expansions,
|
||||
which are either integrated into the plugin itself or external on PlaceholderAPI cloud.
|
||||
Integrated expansions are not downloaded; instead, plugins register them automatically.
|
||||
|
||||
## Expansions in plugins
|
||||
PlaceholderAPI expansion is in the end just a java class (or a set of classes), which can also be included in the plugin they are hooking into. If wiki of the plugin says something like "no download command" or "expansion is included in the plugin", it's this case. You can also identify this case by trying the previous method and download command saying expansion was not found.
|
||||
If no further installation steps are provided, these expansions are automatically enabled when their respective plugin is installed.
|
||||
|
||||
# Managing installed expansions
|
||||
To see what expansions are currently enabled, run `/papi list`. It will show list of all currently enabled expansions. If you downloaded an expansion but it's not in the list, it may have failed to enable due to an error. Check console if you got any errors on startup.
|
||||
Updating expansions can be done in the same way as installing them. For external expansions, run the download command or download it manually and reload. For expansions in plugins, they always contain "latest" (the only) version of the expansion, so if a new placeholder was added, you need to update the plugin.
|
||||
You can download / update external expansions using `/papi ecloud download <expansion>`. After downloading it, run `/papi reload` to enable it.
|
||||
|
||||
# Checking if placeholder is working
|
||||
To check if a placeholder is working, run `/papi parse <player> <placeholder>`. You can also use `me` as player, which parses placeholder for the player who ran the command. If the command outputs the identifier you entered and not the actual output, it means you either entered and invalid placeholder or you are missing an expansion (or you have an outdated version of the expansion), see above.
|
||||
@@ -2,22 +2,27 @@
|
||||
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).
|
||||
|
||||
# Installation
|
||||
Installation is as simple as it can be. Put it into plugins folder of your backend servers. **Bridge is NOT a BungeeCord plugin!** Bridge itself has no config file, as everything is configured in the main plugin.
|
||||
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 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 nametag invisible (compensation for 1.8.x client sided bug)
|
||||
* Allow detection if player is disguised to disable collision to prevent endless push
|
||||
* Forwarding permission groups of players if no permission plugin is installed on BungeeCord
|
||||
* Forwarding vanish status for compatibility with global playerlist / layout 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 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
|
||||
* Encodes scoreboard packets (if TAB is installed on Velocity, which doesn't offer them)
|
||||
* Allow TAB's PlaceholderAPI expansion with TAB on BungeeCord
|
||||
* Forward player's gamemode for spectator fix feature to work
|
||||
|
||||
# Compatibility
|
||||
Just like with Minecraft, when there is a change in the communication protocol, older software will not be compatible with the new one. You should always be running latest versions of both TAB and Bridge.
|
||||
Just like with Minecraft, when there is a change in the communication protocol,
|
||||
older software will not be compatible with the new one.
|
||||
You should always be running the latest versions of both TAB and Bridge.
|
||||
|
||||
# Confirming it works
|
||||
You have many ways to verify TAB and Bridge are properly connected. Besides checking if the features above work, the easiest one is to run `/btab debug <player>`.
|
||||
@@ -25,4 +30,4 @@ If it's properly connected, you'll get a message saying this:
|
||||

|
||||
If it's not properly connected, you'll get this message:
|
||||

|
||||
If this is the case, it means Bridge is either not installed or versions are not compatible. Just update both to the latest version.
|
||||
If this is the case, it means Bridge is either not installed or versions are not compatible. Update both to the latest version.
|
||||
@@ -1,18 +1,18 @@
|
||||
# ---------------------------------------
|
||||
# THIS PAGE IS WORK IN PROGRESS
|
||||
# THIS PAGE IS A WORK IN PROGRESS
|
||||
# ---------------------------------------
|
||||
|
||||
# About
|
||||
This page compares TAB to other plugins offering similar features based on various parameters.
|
||||
|
||||
### Open issues
|
||||
Amount of open issues on GitHub. Keep in mind this number shouldn't be taken 100% seriously, because:
|
||||
Number of open issues on GitHub. Keep in mind this number shouldn't be taken 100% seriously, because:
|
||||
* People often open issues to ask for help instead of reporting an issue.
|
||||
* If nobody is using a plugin, nobody can find bugs. Bug not found doesn't mean it's not there.
|
||||
* Some of the issues may be feature requests, which may not be present elsewhere as those are not accepted.
|
||||
* Some issues may be feature requests, which may not be present elsewhere as those are not accepted.
|
||||
|
||||
### Price
|
||||
The price to obtain the jar. Most plugins are free, some are paid.
|
||||
The price to get the jar. Most plugins are free, some are paid.
|
||||
|
||||
### Minecraft
|
||||
Supported Minecraft versions by the plugin.
|
||||
@@ -30,118 +30,118 @@ Supported platforms by the plugin. Full tracked list includes:
|
||||
Whether the plugin runs in server's main thread (sync) or in a different thread (async). If a plugin is running sync, it may slow down the server's TPS. All of these features can be done async.
|
||||
|
||||
# Belowname
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB) |
|
||||
| ------------- | ------------- |
|
||||
| **Open issues** |  |
|
||||
| **Price** |  |
|
||||
| **Minecraft** | 1.5+ |
|
||||
| **Platforms** |      |
|
||||
| **Async** | ✔ |
|
||||
| PlaceholderAPI support | ✔ |
|
||||
| Configurable number | ✔ |
|
||||
| Configurable text | ✔ |
|
||||
| 1.20.3+ NumberFormat support | ✔ |
|
||||
| Conditionally disable the feature | If any specified condition is met |
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB) |
|
||||
|-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **Open issues** |  |
|
||||
| **Price** |  |
|
||||
| **Minecraft** | 1.5+ |
|
||||
| **Platforms** |      |
|
||||
| **Async** | ✔ |
|
||||
| PlaceholderAPI support | ✔ |
|
||||
| Configurable number | ✔ |
|
||||
| Configurable text | ✔ |
|
||||
| 1.20.3+ NumberFormat support | ✔ |
|
||||
| Conditionally disable the feature | If any specified condition is met |
|
||||
|
||||
# Bossbar
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB)| [UltraBar](https://github.com/ryandw11/UltraBar) | [AnimaBossBar](https://www.spigotmc.org/resources/bossbar-spigot-free-bossbar-plugin-1-9-1-18-1.59135/) |
|
||||
| ------------- | ------------- | ------------- | ------------- |
|
||||
| **Open issues** |  |  | - |
|
||||
| **Price** |  |  |  |
|
||||
| **Minecraft** | 1.5+ | 1.12+ | 1.9 - 1.18.1 |
|
||||
| **Platforms** |      |  |  |
|
||||
| **Async** | ✔ | ❌ | ❌ |
|
||||
| Announcements | ✔ (defined in config) | ✔ (defined at runtime) | ✔ (defined at runtime) |
|
||||
| Toggle command | ✔ (customizable) | ❌ | ❌ |
|
||||
| Display condition | Anything that has a placeholder | On join / death / command / in worldguard region | ❌ |
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB) | [UltraBar](https://github.com/ryandw11/UltraBar) | [AnimaBossBar](https://www.spigotmc.org/resources/bossbar-spigot-free-bossbar-plugin-1-9-1-18-1.59135/) |
|
||||
|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
|
||||
| **Open issues** |  |  | - |
|
||||
| **Price** |  |  |  |
|
||||
| **Minecraft** | 1.5+ | 1.12+ | 1.9 - 1.18.1 |
|
||||
| **Platforms** |      |  |  |
|
||||
| **Async** | ✔ | ❌ | ❌ |
|
||||
| Announcements | ✔ (defined in config) | ✔ (defined at runtime) | ✔ (defined at runtime) |
|
||||
| Toggle command | ✔ (customizable) | ❌ | ❌ |
|
||||
| Display condition | Anything that has a placeholder | On join / death / command / in worldguard region | ❌ |
|
||||
|
||||
# Global Playerlist
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB)| [BungeeTabListPlus](https://github.com/CodeCrafter47/BungeeTabListPlus) | [Velocitab](https://github.com/WiIIiam278/Velocitab) |
|
||||
| ------------- | ------------- | ------------- | ------------- |
|
||||
| **Open issues** |  |  |  |
|
||||
| **Price** |  |  |  |
|
||||
| **Platforms** |   |  |  |
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB) | [BungeeTabListPlus](https://github.com/CodeCrafter47/BungeeTabListPlus) | [Velocitab](https://github.com/WiIIiam278/Velocitab) |
|
||||
|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|
|
||||
| **Open issues** |  |  |  |
|
||||
| **Price** |  |  |  |
|
||||
| **Platforms** |   |  |  |
|
||||
|
||||
# Header/Footer
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB)| [TabList](https://github.com/montlikadani/TabList) |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| **Open issues** |  |  |
|
||||
| **Price** |  |  |
|
||||
| **Platforms** |      |    |
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB) | [TabList](https://github.com/montlikadani/TabList) |
|
||||
|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **Open issues** |  |  |
|
||||
| **Price** |  |  |
|
||||
| **Platforms** |      |    |
|
||||
|
||||
# Layout
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB)| [BungeeTabListPlus](https://github.com/CodeCrafter47/BungeeTabListPlus) |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| **Open issues** |  |  |
|
||||
| **Price** |  |  |
|
||||
| **Platforms** |      |   |
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB) | [BungeeTabListPlus](https://github.com/CodeCrafter47/BungeeTabListPlus) |
|
||||
|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **Open issues** |  |  |
|
||||
| **Price** |  |  |
|
||||
| **Platforms** |      |   |
|
||||
|
||||
# Nametags
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB)| [NametagEdit](https://github.com/sgtcaze/NametagEdit) |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| **Open issues** |  |  |
|
||||
| **Price** |  |  |
|
||||
| **Minecraft** | 1.5+ | 1.7+ |
|
||||
| **Platforms** |      |  |
|
||||
| **Async** | ✔ | ❌ |
|
||||
| Customization | Per-group<br />Per-player<br />Per-world<br />Per-server | Per-group<br />Per-player |
|
||||
| PlaceholderAPI support | ✔ | ✔ |
|
||||
| Configurable collision | ✔ | ✔ |
|
||||
| Configurable nametag visibility | ✔ | ❌ |
|
||||
| Conditionally disable the feature | If any specified condition is met | ❌ |
|
||||
| Bonus | - Option to use armor stands to bypass<br /> all limits and support multiple lines<br />- Anti-override to avoid random plugins breaking it | - |
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB) | [NametagEdit](https://github.com/sgtcaze/NametagEdit) |
|
||||
|-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|
|
||||
| **Open issues** |  |  |
|
||||
| **Price** |  |  |
|
||||
| **Minecraft** | 1.5+ | 1.7+ |
|
||||
| **Platforms** |      |  |
|
||||
| **Async** | ✔ | ❌ |
|
||||
| Customization | Per-group<br />Per-player<br />Per-world<br />Per-server | Per-group<br />Per-player |
|
||||
| PlaceholderAPI support | ✔ | ✔ |
|
||||
| Configurable collision | ✔ | ✔ |
|
||||
| Configurable nametag visibility | ✔ | ❌ |
|
||||
| Conditionally disable the feature | If any specified condition is met | ❌ |
|
||||
| Bonus | - Option to use armor stands to bypass<br /> all limits and support multiple lines<br />- Anti-override to avoid random plugins breaking it | - |
|
||||
|
||||
# Per world playerlist
|
||||
|
||||
# Playerlist objective
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB)| [TabList](https://github.com/montlikadani/TabList) |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| **Open issues** |  |  |
|
||||
| **Price** |  |  |
|
||||
| **Platforms** |      |   |
|
||||
| Display any number | ✔ | ✔ |
|
||||
| Supports hearts display type | ✔ | ✔ |
|
||||
| 1.20.3+ NumberFormat support | ✔ | ❌ |
|
||||
| Conditionally disable the feature | When any specified condition is met | Disable in worlds |
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB) | [TabList](https://github.com/montlikadani/TabList) |
|
||||
|-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **Open issues** |  |  |
|
||||
| **Price** |  |  |
|
||||
| **Platforms** |      |   |
|
||||
| Display any number | ✔ | ✔ |
|
||||
| Supports hearts display type | ✔ | ✔ |
|
||||
| 1.20.3+ NumberFormat support | ✔ | ❌ |
|
||||
| Conditionally disable the feature | When any specified condition is met | Disable in worlds |
|
||||
|
||||
# Scoreboard
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB)| [RealScoreboard](https://github.com/joserodpt/RealScoreboard) | [AnimatedScoreboard](https://www.spigotmc.org/resources/20848/) | [SternalBoard](https://github.com/ShieldCommunity/SternalBoard) | [KiteBoard](https://github.com/Niall7459/KiteBoard-Documentation) |
|
||||
| ------------- | ------------- | ------------- | ------------- | ------------- | ------------- |
|
||||
| **Open issues** |  |  | - |  |  |
|
||||
| **Price** |  |  |  |  |  |
|
||||
| **Minecraft** | 1.5+ | 1.13+ | 1.8+ | 1.7+ | 1.8 - 1.20.1 |
|
||||
| **Platforms** |      |  |  |  |  |
|
||||
| **Async** | ✔ | ✔ | ✔ | ✔ | ✔ |
|
||||
| Customizable toggle command | ✔ | ❌ | ❌ | ❌ | ❌ |
|
||||
| 1.20.3+ NumberFormat support | ✔ | ❌ | ❌ | ❌ | ❌ |
|
||||
| Max line length limit (<1.13 / 1.13+) |  /  | - /  |  /  |  /  |  /  |
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB) | [RealScoreboard](https://github.com/joserodpt/RealScoreboard) | [AnimatedScoreboard](https://www.spigotmc.org/resources/20848/) | [SternalBoard](https://github.com/ShieldCommunity/SternalBoard) | [KiteBoard](https://github.com/Niall7459/KiteBoard-Documentation) |
|
||||
|---------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **Open issues** |  |  | - |  |  |
|
||||
| **Price** |  |  |  |  |  |
|
||||
| **Minecraft** | 1.5+ | 1.13+ | 1.8+ | 1.7+ | 1.8 - 1.20.1 |
|
||||
| **Platforms** |      |  |  |  |  |
|
||||
| **Async** | ✔ | ✔ | ✔ | ✔ | ✔ |
|
||||
| Customizable toggle command | ✔ | ❌ | ❌ | ❌ | ❌ |
|
||||
| 1.20.3+ NumberFormat support | ✔ | ❌ | ❌ | ❌ | ❌ |
|
||||
| Max line length limit (<1.13 / 1.13+) |  /  | - /  |  /  |  /  |  /  |
|
||||
|
||||
| Attribute | [FeatherBoard](https://www.spigotmc.org/resources/featherboard.2691/) | [UltraScoreboards](https://www.spigotmc.org/resources/ultra-scoreboards.93726/) | [QuickBoard](https://github.com/tadeas-drab/QuickBoard) | [SimpleScore](https://github.com/r4g3baby/SimpleScore) | [InfiniteScoreboard](https://www.spigotmc.org/resources/infinite-scoreboard.87425/) |
|
||||
| ------------- | ------------- | ------------- | ------------- | ------------- | ------------- |
|
||||
| **Open issues** | - | - |  |  | - |
|
||||
| **Price** |  |  |  |  |  |
|
||||
| **Minecraft** | 1.7+ | 1.8+ | 1.8 - 1.16.1 | 1.8+ | 1.8 - 1.19 |
|
||||
| **Platforms** |  |   |  |  |  |
|
||||
| **Async** | ✔ | ❌ | ❌ | ❌ | ✔ |
|
||||
| Customizable toggle command | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||
| 1.20.3+ NumberFormat support | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||
| Attribute | [FeatherBoard](https://www.spigotmc.org/resources/featherboard.2691/) | [UltraScoreboards](https://www.spigotmc.org/resources/ultra-scoreboards.93726/) | [QuickBoard](https://github.com/tadeas-drab/QuickBoard) | [SimpleScore](https://github.com/r4g3baby/SimpleScore) | [InfiniteScoreboard](https://www.spigotmc.org/resources/infinite-scoreboard.87425/) |
|
||||
|---------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **Open issues** | - | - |  |  | - |
|
||||
| **Price** |  |  |  |  |  |
|
||||
| **Minecraft** | 1.7+ | 1.8+ | 1.8 - 1.16.1 | 1.8+ | 1.8 - 1.19 |
|
||||
| **Platforms** |  |   |  |  |  |
|
||||
| **Async** | ✔ | ❌ | ❌ | ❌ | ✔ |
|
||||
| Customizable toggle command | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||
| 1.20.3+ NumberFormat support | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||
| Max line length limit (<1.13 / 1.13+) | - /  |  /  |  /  |  /  |  /  |
|
||||
|
||||
# Sorting
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB)| [NametagEdit](https://github.com/sgtcaze/NametagEdit) | [TabList](https://github.com/montlikadani/TabList) | [Velocitab](https://github.com/WiIIiam278/Velocitab) |
|
||||
| ------------- | ------------- | ------------- | ------------- | ------------- |
|
||||
| **Open issues** |  |  |  |  |
|
||||
| **Price** |  |  |  |  |
|
||||
| **Minecraft** | 1.8+ | 1.8+ | 1.8+ | 1.8+ |
|
||||
| **Platforms** |      |  |   |  |
|
||||
| **Async** | ✔ | ❌ | ✔ | ✔ |
|
||||
| Sorting options | Groups<br />Permissions<br />Placeholder alphabetically<br />Placeholder numerically<br />Pre-defined placeholder values | Groups | Groups | Placeholder alphabetically<br />Placeholder numerically |
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB) | [NametagEdit](https://github.com/sgtcaze/NametagEdit) | [TabList](https://github.com/montlikadani/TabList) | [Velocitab](https://github.com/WiIIiam278/Velocitab) |
|
||||
|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|
|
||||
| **Open issues** |  |  |  |  |
|
||||
| **Price** |  |  |  |  |
|
||||
| **Minecraft** | 1.8+ | 1.8+ | 1.8+ | 1.8+ |
|
||||
| **Platforms** |      |  |   |  |
|
||||
| **Async** | ✔ | ❌ | ✔ | ✔ |
|
||||
| Sorting options | Groups<br />Permissions<br />Placeholder alphabetically<br />Placeholder numerically<br />Pre-defined placeholder values | Groups | Groups | Placeholder alphabetically<br />Placeholder numerically |
|
||||
|
||||
# Tablist name formatting
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB)| [TabList](https://github.com/montlikadani/TabList) | [BungeeTabListPlus](https://github.com/CodeCrafter47/BungeeTabListPlus) | [SimpleTabList](https://github.com/TheYIMIR/SimpleTabList) | [Velocitab](https://github.com/WiIIiam278/Velocitab) |
|
||||
| ------------- | ------------- | ------------- | ------------- | ------------- | ------------- |
|
||||
| **Open issues** |  |  |  |  |  |
|
||||
| **Price** |  |  |  |  |  |
|
||||
| **Minecraft** | 1.8+ | 1.8+ | 1.8+ | 1.16+ | 1.8+ |
|
||||
| **Platforms** |      |    |   |  |  |
|
||||
| **Async** | ✔ | ✔ | ✔ | ❌ | ✔ |
|
||||
| Attribute | [TAB](https://github.com/NEZNAMY/TAB) | [TabList](https://github.com/montlikadani/TabList) | [BungeeTabListPlus](https://github.com/CodeCrafter47/BungeeTabListPlus) | [SimpleTabList](https://github.com/TheYIMIR/SimpleTabList) | [Velocitab](https://github.com/WiIIiam278/Velocitab) |
|
||||
|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|
|
||||
| **Open issues** |  |  |  |  |  |
|
||||
| **Price** |  |  |  |  |  |
|
||||
| **Minecraft** | 1.8+ | 1.8+ | 1.8+ | 1.16+ | 1.8+ |
|
||||
| **Platforms** |      |    |   |  |  |
|
||||
| **Async** | ✔ | ✔ | ✔ | ❌ | ✔ |
|
||||
@@ -1,20 +1,47 @@
|
||||
## 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), with everything contained in a single jar which you can download directly. No need to browse version history, ask what plugin version you need for your server version, visit random websites looking for the download button, or anything similar. The same jar supports all versions & platforms, and the latest plugin version will always work for you.
|
||||
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),
|
||||
with everything contained in a single jar which you can download directly.
|
||||
No need to browse version history, ask what plugin version you need for your server version,
|
||||
visit random websites looking for the download button, or anything similar.
|
||||
The same jar supports all versions & platforms, and the latest plugin version will always work for you.
|
||||
|
||||
## It works
|
||||
The plugin doesn't spam your console with errors, doesn't have compatibility issues with half of the plugins, and doesn't just decide to randomly stop working for no reason. It just works. Bug reports are fixed with highest priority and preferred over adding new features. It's not unusual for a plugin of this size to have a 3-digit open issue count on github. Meanwhile TAB is usually at 1-digit count.
|
||||
The plugin doesn't spam your console with errors, doesn't have compatibility issues with half of the plugins,
|
||||
and doesn't just decide to randomly stop working for no reason.
|
||||
It just works.
|
||||
Bug reports are fixed with the highest priority and preferred over adding new features.
|
||||
It's not unusual for a plugin of this size to have a 3-digit open issue count on GitHub.
|
||||
Meanwhile, TAB is always at 1-digit count.
|
||||
|
||||
## Feature packed
|
||||
All of the most requested features in a single plugin. No need to install many plugins, disable features so they don't conflict with each other, or be forced to run your server on a version that all of the plugins support in common. All features, all server versions in a single plugin.
|
||||
All the most requested features in a single plugin.
|
||||
No need to install many plugins, disable features, so they don't conflict with each other,
|
||||
or be forced to run your server on a version that all the plugins support in common.
|
||||
All features, all server versions in a single plugin.
|
||||
|
||||
## 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, add support for new MC versions as they come out and get new optimizations that can help it run as smoothly as possible, whilst still working the way you want it to.
|
||||
The plugin is not abandoned.
|
||||
It is constantly getting updated to fix reported bugs,
|
||||
add support for new MC versions as they come out and get new optimizations.
|
||||
All that can help it run as smoothly as possible, whilst still working the way you want it to.
|
||||
|
||||
## High performance
|
||||
Unlike with other plugins where "high performance" often means your CPU usage will be high, TAB has a very low CPU footprint. There is a [command](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions#tab-cpu) available that shows the entire plugin's CPU usage. Here you can see which part of TAB is occupying the most of your CPU, and 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. 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.
|
||||
Unlike with other plugins where "high performance"
|
||||
often means your CPU usage will be high, TAB has a very low CPU footprint.
|
||||
There is a [command](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions#tab-cpu) available
|
||||
that shows the entire plugin's CPU usage.
|
||||
Here you can see which part of TAB is occupying the most of your CPU.
|
||||
There are [many ways to optimize TAB](https://github.com/NEZNAMY/TAB/wiki/Optimizing-the-plugin)
|
||||
to get the most out of it,
|
||||
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.
|
||||
Performance is also actively monitored on large servers, and observations show that it performs very well,
|
||||
meaning it will almost certainly perform even better on smaller servers.
|
||||
|
||||
## Simple yet powerful configuration
|
||||
Compared to other plugins, each feature is easier to configure and actually offers more.
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
distribution: 'temurin'
|
||||
java-version: 21
|
||||
- name: Cache Gradle
|
||||
uses: actions/cache@v4.0.2 # https://github.com/actions/cache/releases
|
||||
uses: actions/cache@v4.2.0 # https://github.com/actions/cache/releases
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
|
||||
@@ -17,21 +17,24 @@ public interface TabPlayer {
|
||||
*
|
||||
* @return Player's name
|
||||
*/
|
||||
@NotNull String getName();
|
||||
@NotNull
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Returns player's UUID
|
||||
*
|
||||
* @return Player's UUID
|
||||
*/
|
||||
@NotNull UUID getUniqueId();
|
||||
@NotNull
|
||||
UUID getUniqueId();
|
||||
|
||||
/**
|
||||
* Returns platform-specific entity
|
||||
*
|
||||
* @return platform's player object
|
||||
*/
|
||||
@NotNull Object getPlayer();
|
||||
@NotNull
|
||||
Object getPlayer();
|
||||
|
||||
/**
|
||||
* Returns true once the player is successfully loaded (onJoin method ran through all methods)
|
||||
@@ -47,7 +50,8 @@ public interface TabPlayer {
|
||||
*
|
||||
* @return player's primary permission group
|
||||
*/
|
||||
@NotNull String getGroup();
|
||||
@NotNull
|
||||
String getGroup();
|
||||
|
||||
/**
|
||||
* Temporarily overrides player's group and applies all changes coming from new group.
|
||||
@@ -91,4 +95,32 @@ public interface TabPlayer {
|
||||
*/
|
||||
@NotNull
|
||||
String getExpectedProfileName();
|
||||
|
||||
|
||||
/**
|
||||
* Returns name of the server the player is connected to.
|
||||
* This requires TAB on proxy.
|
||||
* On backend installation, this method returns {@code "N/A"}.
|
||||
*
|
||||
* @return Player's server on proxy or {@code "N/A"} on backend installation
|
||||
*/
|
||||
@NotNull
|
||||
String getServer();
|
||||
|
||||
/**
|
||||
* Returns name of the world the player is in.
|
||||
* On proxy installation, TAB-Bridge must be installed to forward this info to the proxy.
|
||||
* Otherwise, it will return {@code "N/A"}.
|
||||
*
|
||||
* @return Player's world or {@code "N/A"} on proxy installation without TAB-Bridge installed
|
||||
*/
|
||||
@NotNull
|
||||
String getWorld();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this player is a bedrock player, {@code false} if not.
|
||||
*
|
||||
* @return {@code true} if this player is a bedrock player, {@code false} if not
|
||||
*/
|
||||
boolean isBedrockPlayer();
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package me.neznamy.tab.api.integration;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public abstract class VanishIntegration {
|
||||
|
||||
/** List of all registered VanishIntegration handlers */
|
||||
private static final List<VanishIntegration> HANDLERS = new ArrayList<>();
|
||||
|
||||
/** Name of the plugin this integration is associated with */
|
||||
@NotNull
|
||||
private final String plugin;
|
||||
|
||||
/**
|
||||
* Determines if a viewer can see a target player.
|
||||
*
|
||||
* @param viewer
|
||||
* The player attempting to view another player
|
||||
* @param target
|
||||
* The player being viewed
|
||||
* @return {@code true} if the viewer can see the target, {@code false} otherwise
|
||||
*/
|
||||
public abstract boolean canSee(@NotNull TabPlayer viewer, @NotNull TabPlayer target);
|
||||
|
||||
/**
|
||||
* Checks if the specified player is in a vanished state.
|
||||
*
|
||||
* @param player
|
||||
* The player to check
|
||||
* @return {@code true} if the player is vanished, {@code false} otherwise
|
||||
*/
|
||||
public abstract boolean isVanished(@NotNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Registers this integration handler to the global list of handlers.
|
||||
*/
|
||||
public void register() {
|
||||
registerHandler(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this integration handler from the global list of handlers.
|
||||
*/
|
||||
public void unregister() {
|
||||
unregisterHandler(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a VanishIntegration handler to the global list of handlers.
|
||||
*
|
||||
* @param handler
|
||||
* The handler to register
|
||||
*/
|
||||
public static void registerHandler(@NotNull VanishIntegration handler) {
|
||||
HANDLERS.add(handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a VanishIntegration handler from the global list of handlers.
|
||||
*
|
||||
* @param handler
|
||||
* The handler to unregister
|
||||
*/
|
||||
public static void unregisterHandler(@NotNull VanishIntegration handler) {
|
||||
HANDLERS.remove(handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of all registered VanishIntegration handlers.
|
||||
*
|
||||
* @return A list of registered VanishIntegration handlers
|
||||
*/
|
||||
@NotNull
|
||||
public static List<VanishIntegration> getHandlers() {
|
||||
return HANDLERS;
|
||||
}
|
||||
}
|
||||
@@ -5,5 +5,5 @@ 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.6-SNAPSHOT")
|
||||
implementation("fabric-loom:fabric-loom.gradle.plugin:1.8-SNAPSHOT")
|
||||
}
|
||||
@@ -4,7 +4,7 @@ plugins {
|
||||
|
||||
allprojects {
|
||||
group = "me.neznamy"
|
||||
version = "5.0.0"
|
||||
version = "5.0.6"
|
||||
description = "An all-in-one solution that works"
|
||||
|
||||
ext.set("id", "tab")
|
||||
@@ -22,7 +22,8 @@ val platforms = setOf(
|
||||
projects.fabric,
|
||||
projects.fabric.v1144,
|
||||
projects.fabric.v1182,
|
||||
projects.fabric.v1203
|
||||
projects.fabric.v1203,
|
||||
projects.fabric.v1213
|
||||
).map { it.dependencyProject }
|
||||
|
||||
val special = setOf(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
dependencies {
|
||||
implementation(projects.shared)
|
||||
implementation("org.bstats:bstats-bukkit:3.0.1")
|
||||
api(projects.shared)
|
||||
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")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id("io.papermc.paperweight.userdev") version "1.7.1"
|
||||
id("io.papermc.paperweight.userdev") version "2.0.0-beta.8"
|
||||
}
|
||||
|
||||
repositories {
|
||||
@@ -9,11 +9,10 @@ repositories {
|
||||
maven("https://oss.sonatype.org/content/repositories/snapshots")
|
||||
}
|
||||
|
||||
val version = "1.21.1-R0.1-SNAPSHOT"
|
||||
val version = "1.21.4-R0.1-SNAPSHOT"
|
||||
|
||||
dependencies {
|
||||
implementation(projects.bukkit)
|
||||
implementation(projects.shared) // No idea why is this needed when Bukkit already contains it
|
||||
paperweight.paperDevBundle(version)
|
||||
compileOnly("io.papermc.paper:paper-api:${version}")
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ package me.neznamy.tab.platforms.paper;
|
||||
|
||||
import me.neznamy.tab.platforms.bukkit.nms.converter.ComponentConverter;
|
||||
import me.neznamy.tab.shared.chat.ChatModifier;
|
||||
import me.neznamy.tab.shared.chat.SimpleComponent;
|
||||
import me.neznamy.tab.shared.chat.StructuredComponent;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import me.neznamy.tab.shared.chat.component.KeybindComponent;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import me.neznamy.tab.shared.chat.component.TextComponent;
|
||||
import me.neznamy.tab.shared.chat.component.TranslatableComponent;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.network.chat.Style;
|
||||
@@ -13,50 +13,40 @@ import net.minecraft.network.chat.TextColor;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Component converter using direct mojang-mapped code for versions 1.20.5+.
|
||||
* Component converter using direct mojang-mapped code for versions 1.21.4+.
|
||||
*/
|
||||
@SuppressWarnings("unused") // Used via reflection
|
||||
public class PaperComponentConverter extends ComponentConverter {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component convert(@NotNull TabComponent component, boolean modern) {
|
||||
if (component instanceof SimpleComponent) return Component.literal(((SimpleComponent) component).getText());
|
||||
public Component convert(@NotNull TabComponent component) {
|
||||
// Component type
|
||||
MutableComponent nmsComponent = switch (component) {
|
||||
case TextComponent text -> Component.literal(text.getText());
|
||||
case TranslatableComponent translatable -> Component.translatable(translatable.getKey());
|
||||
case KeybindComponent keybind -> Component.keybind(keybind.getKeybind());
|
||||
default -> throw new IllegalStateException("Unexpected component type: " + component.getClass().getName());
|
||||
};
|
||||
|
||||
StructuredComponent component1 = (StructuredComponent) component;
|
||||
MutableComponent nmsComponent = Component.literal(component1.getText());
|
||||
nmsComponent.setStyle(createModifierModern(component1.getModifier(), modern));
|
||||
for (StructuredComponent extra : component1.getExtra()) {
|
||||
nmsComponent.append(convert(extra, modern));
|
||||
// Component style
|
||||
ChatModifier modifier = component.getModifier();
|
||||
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()));
|
||||
if (modifier.getShadowColor() != null) style = style.withShadowColor(modifier.getShadowColor()); // withShadowColor takes int instead of Integer, bug?
|
||||
nmsComponent.setStyle(style);
|
||||
|
||||
// Extra
|
||||
for (TabComponent extra : component.getExtra()) {
|
||||
nmsComponent.append(convert(extra));
|
||||
}
|
||||
return nmsComponent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Style createModifierModern(@NotNull ChatModifier modifier, boolean modern) {
|
||||
TextColor color = null;
|
||||
if (modifier.getColor() != null) {
|
||||
if (modern) {
|
||||
color = TextColor.fromRgb(modifier.getColor().getRgb());
|
||||
} else {
|
||||
color = TextColor.fromRgb(modifier.getColor().getLegacyColor().getRgb());
|
||||
}
|
||||
}
|
||||
List<ChatFormatting> formats = new ArrayList<>();
|
||||
if (modifier.isBold()) formats.add(ChatFormatting.BOLD);
|
||||
if (modifier.isItalic()) formats.add(ChatFormatting.ITALIC);
|
||||
if (modifier.isUnderlined()) formats.add(ChatFormatting.UNDERLINE);
|
||||
if (modifier.isStrikethrough()) formats.add(ChatFormatting.STRIKETHROUGH);
|
||||
if (modifier.isObfuscated()) formats.add(ChatFormatting.OBFUSCATED);
|
||||
|
||||
Style style = Style.EMPTY;
|
||||
if (color != null) style = style.withColor(color);
|
||||
if (!formats.isEmpty()) style = style.applyFormats(formats.toArray(new ChatFormatting[0]));
|
||||
if (modifier.getFont() != null) style = style.withFont(ResourceLocation.tryParse(modifier.getFont()));
|
||||
return style;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package me.neznamy.tab.platforms.paper;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.util.FunctionWithException;
|
||||
import me.neznamy.tab.shared.util.function.FunctionWithException;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
|
||||
/**
|
||||
@@ -12,6 +12,6 @@ import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
public class PaperLoader {
|
||||
|
||||
/** Channel getter using direct NMS code */
|
||||
public static FunctionWithException<BukkitTabPlayer, Channel> getChannel =
|
||||
public static final FunctionWithException<BukkitTabPlayer, Channel> getChannel =
|
||||
player -> ((CraftPlayer)player.getPlayer()).getHandle().connection.connection.channel;
|
||||
}
|
||||
@@ -58,7 +58,7 @@ public class PaperPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
dummyScoreboard,
|
||||
objective.getName(),
|
||||
ObjectiveCriteria.DUMMY,
|
||||
objective.getTitle().convert(player.getVersion()),
|
||||
objective.getTitle().convert(),
|
||||
ObjectiveCriteria.RenderType.values()[objective.getHealthDisplay().ordinal()],
|
||||
false,
|
||||
objective.getNumberFormat() == null ? null : objective.getNumberFormat().toFixedFormat(FixedFormat::new)
|
||||
@@ -76,7 +76,7 @@ public class PaperPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
@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(player.getVersion()));
|
||||
obj.setDisplayName(objective.getTitle().convert());
|
||||
obj.setRenderType(ObjectiveCriteria.RenderType.values()[objective.getHealthDisplay().ordinal()]);
|
||||
sendPacket(new ClientboundSetObjectivePacket(obj, ObjectiveAction.UPDATE));
|
||||
}
|
||||
@@ -88,7 +88,7 @@ public class PaperPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
score.getHolder(),
|
||||
score.getObjective().getName(),
|
||||
score.getValue(),
|
||||
Optional.ofNullable(score.getDisplayName() == null ? null : score.getDisplayName().convert(player.getVersion())),
|
||||
Optional.ofNullable(score.getDisplayName() == null ? null : score.getDisplayName().convert()),
|
||||
Optional.ofNullable(score.getNumberFormat() == null ? null : score.getNumberFormat().toFixedFormat(FixedFormat::new))
|
||||
)
|
||||
);
|
||||
@@ -128,11 +128,11 @@ public class PaperPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
PlayerTeam t = (PlayerTeam) team.getPlatformTeam();
|
||||
t.setAllowFriendlyFire((team.getOptions() & 0x01) != 0);
|
||||
t.setSeeFriendlyInvisibles((team.getOptions() & 0x02) != 0);
|
||||
t.setColor(formats[team.getColor().ordinal()]);
|
||||
t.setColor(formats[team.getColor().getLegacyColor().ordinal()]);
|
||||
t.setCollisionRule(collisions[team.getCollision().ordinal()]);
|
||||
t.setNameTagVisibility(visibilities[team.getVisibility().ordinal()]);
|
||||
t.setPlayerPrefix(team.getPrefix().convert(player.getVersion()));
|
||||
t.setPlayerSuffix(team.getSuffix().convert(player.getVersion()));
|
||||
t.setPlayerPrefix(team.getPrefix().convert());
|
||||
t.setPlayerSuffix(team.getSuffix().convert());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -7,7 +7,7 @@ import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.tablist.TabListBase;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import net.minecraft.network.chat.Component;
|
||||
@@ -24,16 +24,18 @@ import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* TabList implementation using direct mojang-mapped code for versions 1.20.5+.
|
||||
* TabList implementation using direct mojang-mapped code for versions 1.21.4+.
|
||||
*/
|
||||
@SuppressWarnings("unused") // Used via reflection
|
||||
public class PaperPacketTabList extends TabListBase<Component> {
|
||||
|
||||
private final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateDisplayName = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME);
|
||||
private final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateLatency = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY);
|
||||
private final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateGameMode = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE);
|
||||
private final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateListed = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED);
|
||||
private 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);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateListOrder = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LIST_ORDER);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateHat = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_HAT);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> addPlayer = EnumSet.allOf(ClientboundPlayerInfoUpdatePacket.Action.class);
|
||||
|
||||
private static final Field entries;
|
||||
|
||||
@@ -63,48 +65,56 @@ public class PaperPacketTabList extends TabListBase<Component> {
|
||||
@Override
|
||||
public void updateDisplayName(@NonNull UUID entry, @Nullable Component displayName) {
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(updateDisplayName, new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
entry, null, false, 0, null, displayName, null
|
||||
entry, null, false, 0, null, displayName, false, 0, null
|
||||
)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLatency(@NonNull UUID entry, int latency) {
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(updateLatency, new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
entry, null, false, latency, null, null, null
|
||||
entry, null, false, latency, null, null, false, 0, null
|
||||
)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGameMode(@NonNull UUID entry, int gameMode) {
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(updateGameMode, new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
entry, null, false, 0, GameType.byId(gameMode), null, null
|
||||
entry, null, false, 0, GameType.byId(gameMode), null, false, 0, null
|
||||
)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(updateListed, new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
entry, null, listed, 0, null, null, null
|
||||
entry, null, listed, 0, null, null, false, 0, null
|
||||
)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListOrder(@NonNull UUID entry, int listOrder) {
|
||||
// TODO update module to 1.21.2 when it comes out
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(updateListOrder, new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
entry, null, false, 0, null, null, false, listOrder, null
|
||||
)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateHat(@NonNull UUID entry, boolean showHat) {
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(updateHat, new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
entry, null, false, 0, null, null, showHat, 0, null
|
||||
)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, boolean listed, int latency,
|
||||
int gameMode, @Nullable Component displayName, int listOrder) {
|
||||
int gameMode, @Nullable Component displayName, int listOrder, boolean showHat) {
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(addPlayer, new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
id, createProfile(id, name, skin), listed, latency, GameType.byId(gameMode), displayName, null
|
||||
id, createProfile(id, name, skin), listed, latency, GameType.byId(gameMode), displayName, showHat, listOrder, null
|
||||
)));
|
||||
// TODO update module to 1.21.2 when it comes out
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerListHeaderFooter(@NonNull TabComponent header, @NonNull TabComponent footer) {
|
||||
sendPacket(new ClientboundTabListPacket(header.convert(player.getVersion()), footer.convert(player.getVersion())));
|
||||
sendPacket(new ClientboundTabListPacket(header.convert(), footer.convert()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -136,7 +146,8 @@ public class PaperPacketTabList extends TabListBase<Component> {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(player, nmsData.profileId(), nmsData.profile().getName());
|
||||
}
|
||||
updatedList.add(rewriteEntry ? new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
nmsData.profileId(), nmsData.profile(), nmsData.listed(), latency, nmsData.gameMode(), displayName, nmsData.chatSession()
|
||||
nmsData.profileId(), nmsData.profile(), nmsData.listed(), latency, nmsData.gameMode(), displayName,
|
||||
nmsData.showHat(), nmsData.listOrder(), nmsData.chatSession()
|
||||
) : nmsData);
|
||||
}
|
||||
if (rewritePacket) entries.set(info, updatedList);
|
||||
|
||||
@@ -7,7 +7,7 @@ import me.neznamy.tab.platforms.bukkit.nms.BukkitReflection;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
import me.neznamy.tab.shared.features.injection.NettyPipelineInjector;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import me.neznamy.tab.shared.util.FunctionWithException;
|
||||
import me.neznamy.tab.shared.util.function.FunctionWithException;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -19,6 +19,17 @@ import java.util.EnumSet;
|
||||
*/
|
||||
public class BukkitPipelineInjector extends NettyPipelineInjector {
|
||||
|
||||
/** Versions supported by paper module that uses direct mojang-mapped NMS for latest MC version */
|
||||
private static final EnumSet<ProtocolVersion> paperNativeVersions = EnumSet.of(
|
||||
ProtocolVersion.V1_20_5,
|
||||
ProtocolVersion.V1_20_6,
|
||||
ProtocolVersion.V1_21,
|
||||
ProtocolVersion.V1_21_1,
|
||||
ProtocolVersion.V1_21_2,
|
||||
ProtocolVersion.V1_21_3,
|
||||
ProtocolVersion.V1_21_4
|
||||
);
|
||||
|
||||
/** Function for getting player's channel */
|
||||
@Setter
|
||||
private static FunctionWithException<BukkitTabPlayer, Channel> getChannel;
|
||||
@@ -40,13 +51,7 @@ public class BukkitPipelineInjector extends NettyPipelineInjector {
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void tryLoad(@NotNull ProtocolVersion serverVersion) {
|
||||
try {
|
||||
boolean versionCheck = EnumSet.of(
|
||||
ProtocolVersion.V1_20_5,
|
||||
ProtocolVersion.V1_20_6,
|
||||
ProtocolVersion.V1_21,
|
||||
ProtocolVersion.V1_21_1
|
||||
).contains(serverVersion);
|
||||
if (ReflectionUtils.classExists("org.bukkit.craftbukkit.CraftServer") && versionCheck) {
|
||||
if (ReflectionUtils.classExists("org.bukkit.craftbukkit.CraftServer") && paperNativeVersions.contains(serverVersion)) {
|
||||
getChannel = (FunctionWithException<BukkitTabPlayer, Channel>) Class.forName("me.neznamy.tab.platforms.paper.PaperLoader").getDeclaredField("getChannel").get(null);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package me.neznamy.tab.platforms.bukkit;
|
||||
|
||||
import me.neznamy.tab.platforms.bukkit.platform.BukkitPlatform;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import me.neznamy.tab.shared.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
@@ -23,7 +24,7 @@ public class BukkitTabCommand implements CommandExecutor, TabCompleter {
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if (TAB.getInstance().isPluginDisabled()) {
|
||||
for (String message : TAB.getInstance().getDisabledCommand().execute(args, sender.hasPermission(TabConstants.Permission.COMMAND_RELOAD), sender.hasPermission(TabConstants.Permission.COMMAND_ALL))) {
|
||||
sender.sendMessage(EnumChatFormat.color(message));
|
||||
sender.sendMessage(((BukkitPlatform)TAB.getInstance().getPlatform()).toBukkitFormat(TabComponent.fromColoredText(message)));
|
||||
}
|
||||
} else {
|
||||
TabPlayer p = null;
|
||||
|
||||
@@ -8,7 +8,7 @@ import me.neznamy.tab.platforms.bukkit.nms.PingRetriever;
|
||||
import me.neznamy.tab.platforms.bukkit.platform.BukkitPlatform;
|
||||
import me.neznamy.tab.platforms.bukkit.tablist.TabListBase;
|
||||
import me.neznamy.tab.shared.backend.BackendTabPlayer;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
@@ -57,7 +57,7 @@ public class BukkitTabPlayer extends BackendTabPlayer {
|
||||
|
||||
@Override
|
||||
public void sendMessage(@NotNull TabComponent message) {
|
||||
getPlayer().sendMessage(getPlatform().toBukkitFormat(message, getVersion().supportsRGB()));
|
||||
getPlayer().sendMessage(getPlatform().toBukkitFormat(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,7 +4,6 @@ import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
import me.neznamy.tab.shared.chat.EnumChatFormat;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -58,8 +57,7 @@ public class BukkitUtils {
|
||||
public static void compatibilityError(@NotNull Exception exception, @NotNull String failedCheck,
|
||||
@Nullable String fallback, @NotNull String... missingFeatures) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(EnumChatFormat.RED);
|
||||
sb.append("[TAB] Failed to initialize minecraft fields for ");
|
||||
sb.append("§c[TAB] Failed to initialize minecraft fields for ");
|
||||
sb.append(failedCheck);
|
||||
sb.append(" due to a compatibility error. ");
|
||||
if (fallback != null) {
|
||||
@@ -81,7 +79,7 @@ public class BukkitUtils {
|
||||
*/
|
||||
public static void sendCompatibilityMessage() {
|
||||
if (!compatibilityIssue) return;
|
||||
Bukkit.getConsoleSender().sendMessage(EnumChatFormat.RED + "[TAB] Please update the plugin to " +
|
||||
Bukkit.getConsoleSender().sendMessage("§c[TAB] Please update the plugin to " +
|
||||
"a version with native support for your server version for optimal experience. This plugin version " +
|
||||
"was made for " + ProtocolVersion.V1_5.getFriendlyName() + " - " + ProtocolVersion.LATEST_KNOWN_VERSION.getFriendlyName() + ".");
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package me.neznamy.tab.platforms.bukkit.bossbar;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.neznamy.tab.api.bossbar.BarColor;
|
||||
import me.neznamy.tab.api.bossbar.BarStyle;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.platform.decorators.SafeBossBar;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -28,7 +28,7 @@ public class BukkitBossBar extends SafeBossBar<BossBar> {
|
||||
@NotNull
|
||||
public BossBar constructBossBar(@NotNull TabComponent title, float progress, @NotNull BarColor color, @NotNull BarStyle style) {
|
||||
BossBar bar = Bukkit.createBossBar(
|
||||
player.getPlatform().toBukkitFormat(title, player.getVersion().supportsRGB()),
|
||||
player.getPlatform().toBukkitFormat(title),
|
||||
org.bukkit.boss.BarColor.valueOf(color.name()),
|
||||
styles[style.ordinal()]
|
||||
);
|
||||
@@ -43,7 +43,7 @@ public class BukkitBossBar extends SafeBossBar<BossBar> {
|
||||
|
||||
@Override
|
||||
public void updateTitle(SafeBossBar<BossBar>.@NotNull BossBarInfo bar) {
|
||||
bar.getBossBar().setTitle(player.getPlatform().toBukkitFormat(bar.getTitle(), player.getVersion().supportsRGB()));
|
||||
bar.getBossBar().setTitle(player.getPlatform().toBukkitFormat(bar.getTitle()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,7 +8,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import me.neznamy.tab.api.bossbar.BarColor;
|
||||
import me.neznamy.tab.api.bossbar.BarStyle;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import me.neznamy.tab.shared.platform.decorators.SafeBossBar;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package me.neznamy.tab.platforms.bukkit.features;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitUtils;
|
||||
import me.neznamy.tab.shared.config.files.config.PerWorldPlayerListConfiguration;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import me.neznamy.tab.shared.features.PerWorldPlayerListConfiguration;
|
||||
import me.neznamy.tab.shared.features.types.Loadable;
|
||||
import me.neznamy.tab.shared.features.types.TabFeature;
|
||||
import me.neznamy.tab.shared.features.types.UnLoadable;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -15,12 +15,11 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import me.neznamy.tab.shared.features.types.TabFeature;
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* Per-world-PlayerList feature handler
|
||||
*/
|
||||
@@ -115,10 +114,10 @@ public class PerWorldPlayerList extends TabFeature implements Listener, Loadable
|
||||
*/
|
||||
private boolean shouldSee(@NotNull Player viewer, @NotNull Player target) {
|
||||
if (target == viewer) return true;
|
||||
if ((configuration.allowBypassPermission && viewer.hasPermission(TabConstants.Permission.PER_WORLD_PLAYERLIST_BYPASS)) || configuration.ignoredWorlds.contains(viewer.getWorld().getName())) return true;
|
||||
if ((configuration.isAllowBypassPermission() && viewer.hasPermission(TabConstants.Permission.PER_WORLD_PLAYERLIST_BYPASS)) || configuration.getIgnoredWorlds().contains(viewer.getWorld().getName())) return true;
|
||||
String viewerWorldGroup = viewer.getWorld().getName() + "-default"; //preventing unwanted behavior when some group is called exactly like a world
|
||||
String targetWorldGroup = target.getWorld().getName() + "-default";
|
||||
for (Entry<String, List<String>> group : configuration.sharedWorlds.entrySet()) {
|
||||
for (Entry<String, List<String>> group : configuration.getSharedWorlds().entrySet()) {
|
||||
if (group.getValue() != null) {
|
||||
if (group.getValue().contains(viewer.getWorld().getName())) viewerWorldGroup = group.getKey();
|
||||
if (group.getValue().contains(target.getWorld().getName())) targetWorldGroup = group.getKey();
|
||||
|
||||
@@ -2,7 +2,7 @@ package me.neznamy.tab.platforms.bukkit.header;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -25,8 +25,8 @@ public class BukkitHeaderFooter extends HeaderFooter {
|
||||
@SuppressWarnings("deprecation") // Marked as deprecated by Paper to make us use their methods instead
|
||||
public void set(@NotNull BukkitTabPlayer player, @NotNull TabComponent header, @NotNull TabComponent footer) {
|
||||
player.getPlayer().setPlayerListHeaderFooter(
|
||||
player.getPlatform().toBukkitFormat(header, player.getVersion().supportsRGB()),
|
||||
player.getPlatform().toBukkitFormat(footer, player.getVersion().supportsRGB())
|
||||
player.getPlatform().toBukkitFormat(header),
|
||||
player.getPlatform().toBukkitFormat(footer)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package me.neznamy.tab.platforms.bukkit.header;
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitUtils;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.BukkitReflection;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.converter.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketSender;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.util.BiFunctionWithException;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import me.neznamy.tab.shared.util.function.BiFunctionWithException;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -52,6 +52,6 @@ public class PacketHeaderFooter extends HeaderFooter {
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void set(@NotNull BukkitTabPlayer player, @NotNull TabComponent header, @NotNull TabComponent footer) {
|
||||
packetSender.sendPacket(player, createPacket.apply(header.convert(player.getVersion()), footer.convert(player.getVersion())));
|
||||
packetSender.sendPacket(player, createPacket.apply(header.convert(), footer.convert()));
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package me.neznamy.tab.platforms.bukkit.header;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -20,6 +20,6 @@ public class PaperHeaderFooter extends HeaderFooter {
|
||||
|
||||
@Override
|
||||
public void set(@NotNull BukkitTabPlayer player, @NotNull TabComponent header, @NotNull TabComponent footer) {
|
||||
player.getPlayer().sendPlayerListHeaderAndFooter(header.toAdventure(player.getVersion()), footer.toAdventure(player.getVersion()));
|
||||
player.getPlayer().sendPlayerListHeaderAndFooter(header.toAdventure(), footer.toAdventure());
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package me.neznamy.tab.platforms.bukkit.hook;
|
||||
|
||||
import de.myzelyam.api.vanish.VanishAPI;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.hook.PremiumVanishHook;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class BukkitPremiumVanishHook extends PremiumVanishHook {
|
||||
|
||||
@Override
|
||||
public synchronized boolean canSee(@NotNull TabPlayer viewer, @NotNull TabPlayer target) {
|
||||
public boolean canSee(@NotNull TabPlayer viewer, @NotNull TabPlayer target) {
|
||||
return VanishAPI.canSee(((BukkitTabPlayer)viewer).getPlayer(), ((BukkitTabPlayer)target).getPlayer());
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package me.neznamy.tab.platforms.bukkit.nms;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.shared.util.FunctionWithException;
|
||||
import me.neznamy.tab.shared.util.function.FunctionWithException;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -33,6 +33,11 @@ public class BukkitReflection {
|
||||
@Getter
|
||||
private static final boolean is1_20_3Plus = ReflectionUtils.classExists("net.minecraft.network.protocol.game.ClientboundResetScorePacket");
|
||||
|
||||
/** Flag determining whether the server version is at least 1.21.4 or not */
|
||||
@Getter
|
||||
private static final boolean is1_21_4Plus = serverVersion.minorVersion >= 21 &&
|
||||
ReflectionUtils.getFields(getClass("network.chat.Style", "network.chat.ChatModifier"), Integer.class).size() == 1;
|
||||
|
||||
@NotNull
|
||||
@SneakyThrows
|
||||
private static Method getHandle() {
|
||||
@@ -78,7 +83,7 @@ public class BukkitReflection {
|
||||
* if class does not exist
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static Class<?> getClass(@NotNull String... names) throws ClassNotFoundException {
|
||||
public static Class<?> getClass(@NotNull String... names) {
|
||||
for (String name : names) {
|
||||
try {
|
||||
return serverVersion.getClass.apply(name);
|
||||
|
||||
@@ -2,7 +2,7 @@ package me.neznamy.tab.platforms.bukkit.nms;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.util.BiConsumerWithException;
|
||||
import me.neznamy.tab.shared.util.function.BiConsumerWithException;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package me.neznamy.tab.platforms.bukkit.nms;
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitUtils;
|
||||
import me.neznamy.tab.shared.util.ToIntFunction;
|
||||
import me.neznamy.tab.shared.util.function.ToIntFunction;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.converter;
|
||||
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitUtils;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* Interface for converting TAB component into NMS components (1.7+).
|
||||
* Interface for converting TAB components into NMS components (1.7+).
|
||||
*/
|
||||
public abstract class ComponentConverter {
|
||||
|
||||
/** Versions supported by paper module that uses direct mojang-mapped NMS */
|
||||
private static final EnumSet<ProtocolVersion> paperNativeVersions = EnumSet.of(
|
||||
ProtocolVersion.V1_21_4
|
||||
);
|
||||
|
||||
/** Instance of this class */
|
||||
@Nullable
|
||||
public static ComponentConverter INSTANCE;
|
||||
@@ -18,10 +28,28 @@ public abstract class ComponentConverter {
|
||||
*
|
||||
* @param component
|
||||
* Component to convert
|
||||
* @param modern
|
||||
* Whether client supports RGB or not
|
||||
* @return Converted component
|
||||
*/
|
||||
@NotNull
|
||||
public abstract Object convert(@NotNull TabComponent component, boolean modern);
|
||||
public abstract Object convert(@NotNull TabComponent component);
|
||||
|
||||
/**
|
||||
* Attempts to load component converter.
|
||||
*
|
||||
* @param serverVersion
|
||||
* Server version
|
||||
*/
|
||||
public static void tryLoad(@NotNull ProtocolVersion serverVersion) {
|
||||
try {
|
||||
if (ReflectionUtils.classExists("org.bukkit.craftbukkit.CraftServer") && paperNativeVersions.contains(serverVersion)) {
|
||||
INSTANCE = (ComponentConverter) Class.forName("me.neznamy.tab.platforms.paper.PaperComponentConverter").getConstructor().newInstance();
|
||||
} else {
|
||||
INSTANCE = new ReflectionComponentConverter();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (BukkitUtils.PRINT_EXCEPTIONS) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,30 +2,29 @@ package me.neznamy.tab.platforms.bukkit.nms.converter;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.BukkitReflection;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
import me.neznamy.tab.shared.chat.ChatModifier;
|
||||
import me.neznamy.tab.shared.chat.SimpleComponent;
|
||||
import me.neznamy.tab.shared.chat.StructuredComponent;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.util.FunctionWithException;
|
||||
import me.neznamy.tab.shared.chat.component.KeybindComponent;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import me.neznamy.tab.shared.chat.component.TextComponent;
|
||||
import me.neznamy.tab.shared.chat.component.TranslatableComponent;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import me.neznamy.tab.shared.util.function.FunctionWithException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Class for converting TAB component into NMS components (1.7+).
|
||||
* Class for converting TAB components into NMS components (1.7+).
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public class ReflectionComponentConverter extends ComponentConverter {
|
||||
|
||||
private final FunctionWithException<String, Object> newTextComponent;
|
||||
private final BiFunction<ChatModifier, Boolean, Object> convertModifier;
|
||||
private final FunctionWithException<String, Object> newTranslatableComponent;
|
||||
private final FunctionWithException<String, Object> newKeybindComponent;
|
||||
|
||||
private final Class<?> ChatModifier = BukkitReflection.getClass("network.chat.Style", "network.chat.ChatModifier", "ChatModifier");
|
||||
private final Class<Enum> EnumChatFormat = (Class<Enum>) BukkitReflection.getClass("ChatFormatting", "EnumChatFormat");
|
||||
@@ -42,16 +41,23 @@ public class ReflectionComponentConverter extends ComponentConverter {
|
||||
private Method ResourceLocation_tryParse;
|
||||
|
||||
/**
|
||||
* Constructs new instance and loads all NMS classes, constructors and methods.
|
||||
* Constructs new instance and loads all NMS classes, constructors, and methods.
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If something failed
|
||||
*/
|
||||
private ReflectionComponentConverter() throws ReflectiveOperationException {
|
||||
public ReflectionComponentConverter() throws ReflectiveOperationException {
|
||||
Class<?> IChatBaseComponent = BukkitReflection.getClass("network.chat.Component", "network.chat.IChatBaseComponent", "IChatBaseComponent");
|
||||
if (BukkitReflection.getMinorVersion() >= 19) {
|
||||
Method IChatBaseComponent_b = ReflectionUtils.getMethod(IChatBaseComponent, new String[] {"b", "literal"}, String.class);
|
||||
newTextComponent = text -> IChatBaseComponent_b.invoke(null, text);
|
||||
|
||||
Method IChatBaseComponent_c = ReflectionUtils.getMethod(IChatBaseComponent, new String[] {"c", "translatable"}, String.class);
|
||||
newTranslatableComponent = text -> IChatBaseComponent_c.invoke(null, text);
|
||||
|
||||
Method IChatBaseComponent_d = ReflectionUtils.getMethod(IChatBaseComponent, new String[] {"d", "keybind"}, String.class);
|
||||
newKeybindComponent = text -> IChatBaseComponent_d.invoke(null, text);
|
||||
|
||||
Class<?> IChatMutableComponent = BukkitReflection.getClass("network.chat.MutableComponent", "network.chat.IChatMutableComponent", "IChatMutableComponent");
|
||||
Component_modifier = ReflectionUtils.getOnlyField(IChatMutableComponent, ChatModifier);
|
||||
ChatBaseComponent_addSibling = ReflectionUtils.getOnlyMethod(IChatMutableComponent, IChatMutableComponent, IChatBaseComponent);
|
||||
@@ -59,9 +65,18 @@ public class ReflectionComponentConverter extends ComponentConverter {
|
||||
Class<?> ChatComponentText = BukkitReflection.getClass("network.chat.TextComponent", "network.chat.ChatComponentText", "ChatComponentText");
|
||||
Constructor<?> newChatComponentText = ChatComponentText.getConstructor(String.class);
|
||||
newTextComponent = newChatComponentText::newInstance;
|
||||
|
||||
Class<?> ChatMessage = BukkitReflection.getClass("network.chat.TranslatableComponent", "network.chat.ChatMessage", "ChatMessage");
|
||||
Constructor<?> newChatMessage = ChatMessage.getConstructor(String.class, Object[].class);
|
||||
newTranslatableComponent = text -> newChatMessage.newInstance(text, new Object[0]);
|
||||
|
||||
newKeybindComponent = text -> {
|
||||
throw new UnsupportedOperationException("Keybind component conversion is not implemented on < 1.19");
|
||||
};
|
||||
|
||||
Class<?> ChatBaseComponent = BukkitReflection.getClass("network.chat.BaseComponent", "network.chat.ChatBaseComponent", "ChatBaseComponent");
|
||||
Component_modifier = ReflectionUtils.getOnlyField(ChatBaseComponent, ChatModifier);
|
||||
ChatBaseComponent_addSibling = ReflectionUtils.getOnlyMethod(ChatComponentText, IChatBaseComponent, IChatBaseComponent);
|
||||
ChatBaseComponent_addSibling = ReflectionUtils.getOnlyMethod(ChatBaseComponent, IChatBaseComponent, IChatBaseComponent);
|
||||
}
|
||||
if (BukkitReflection.getMinorVersion() >= 16) {
|
||||
Class<?> chatHexColor = BukkitReflection.getClass("network.chat.TextColor", "network.chat.ChatHexColor", "ChatHexColor");
|
||||
@@ -70,89 +85,87 @@ public class ReflectionComponentConverter extends ComponentConverter {
|
||||
Class<?> chatHoverable = BukkitReflection.getClass("network.chat.HoverEvent", "network.chat.ChatHoverable", "ChatHoverable");
|
||||
ResourceLocation_tryParse = ReflectionUtils.getMethod(ResourceLocation, new String[]{"tryParse", "m_135820_", "a"}, String.class);
|
||||
ChatHexColor_fromRGB = ReflectionUtils.getMethods(chatHexColor, chatHexColor, int.class).get(0); // There should only be 1, but some mods add more
|
||||
newChatModifier = ReflectionUtils.setAccessible(ChatModifier.getDeclaredConstructor(chatHexColor, Boolean.class, Boolean.class, Boolean.class,
|
||||
Boolean.class, Boolean.class, chatClickable, chatHoverable, String.class, ResourceLocation));
|
||||
convertModifier = this::createModifierModern;
|
||||
if (BukkitReflection.is1_21_4Plus()) {
|
||||
// 1.21.4+
|
||||
newChatModifier = ReflectionUtils.setAccessible(ChatModifier.getDeclaredConstructor(chatHexColor, Integer.class, Boolean.class, Boolean.class,
|
||||
Boolean.class, Boolean.class, Boolean.class, chatClickable, chatHoverable, String.class, ResourceLocation));
|
||||
} else {
|
||||
// 1.21.3-
|
||||
newChatModifier = ReflectionUtils.setAccessible(ChatModifier.getDeclaredConstructor(chatHexColor, Boolean.class, Boolean.class, Boolean.class,
|
||||
Boolean.class, Boolean.class, chatClickable, chatHoverable, String.class, ResourceLocation));
|
||||
}
|
||||
} else {
|
||||
newChatModifier = ChatModifier.getConstructor();
|
||||
ChatModifier_setColor = ReflectionUtils.getOnlyMethod(ChatModifier, ChatModifier, EnumChatFormat);
|
||||
convertModifier = (modifier, protocolVersion) -> createModifierLegacy(modifier);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@NotNull
|
||||
public Object convert(@NotNull TabComponent component, boolean modern) {
|
||||
if (component instanceof SimpleComponent) return newTextComponent.apply(((SimpleComponent) component).getText());
|
||||
public Object convert(@NotNull TabComponent component) {
|
||||
// Component type
|
||||
Object nmsComponent;
|
||||
if (component instanceof TextComponent) {
|
||||
nmsComponent = newTextComponent.apply(((TextComponent) component).getText());
|
||||
} else if (component instanceof TranslatableComponent) {
|
||||
nmsComponent = newTranslatableComponent.apply(((TranslatableComponent) component).getKey());
|
||||
} else if (component instanceof KeybindComponent) {
|
||||
nmsComponent = newKeybindComponent.apply(((KeybindComponent) component).getKeybind());
|
||||
} else {
|
||||
throw new IllegalStateException("Unexpected component type: " + component.getClass().getName());
|
||||
}
|
||||
|
||||
StructuredComponent component1 = (StructuredComponent) component;
|
||||
Object nmsComponent = newTextComponent.apply(component1.getText());
|
||||
Component_modifier.set(nmsComponent, convertModifier.apply(component1.getModifier(), modern));
|
||||
for (StructuredComponent extra : component1.getExtra()) {
|
||||
ChatBaseComponent_addSibling.invoke(nmsComponent, convert(extra, modern));
|
||||
// Component style
|
||||
Component_modifier.set(nmsComponent, convertStyle(component.getModifier()));
|
||||
|
||||
// Extra
|
||||
for (TabComponent extra : component.getExtra()) {
|
||||
ChatBaseComponent_addSibling.invoke(nmsComponent, convert(extra));
|
||||
}
|
||||
return nmsComponent;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private Object createModifierModern(@NotNull ChatModifier modifier, boolean modern) {
|
||||
Object color = null;
|
||||
if (modifier.getColor() != null) {
|
||||
if (modern) {
|
||||
color = ChatHexColor_fromRGB.invoke(null, modifier.getColor().getRgb());
|
||||
} else {
|
||||
color = ChatHexColor_fromRGB.invoke(null, modifier.getColor().getLegacyColor().getRgb());
|
||||
private Object convertStyle(@NotNull ChatModifier modifier) {
|
||||
if (BukkitReflection.is1_21_4Plus()) {
|
||||
return newChatModifier.newInstance(
|
||||
modifier.getColor() == null ? null : ChatHexColor_fromRGB.invoke(null, modifier.getColor().getRgb()),
|
||||
modifier.getShadowColor(),
|
||||
modifier.getBold(),
|
||||
modifier.getItalic(),
|
||||
modifier.getItalic(),
|
||||
modifier.getUnderlined(),
|
||||
modifier.getObfuscated(),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
modifier.getFont() == null ? null : ResourceLocation_tryParse.invoke(null, modifier.getFont())
|
||||
);
|
||||
} else if (BukkitReflection.getMinorVersion() >= 16) {
|
||||
return newChatModifier.newInstance(
|
||||
modifier.getColor() == null ? null : ChatHexColor_fromRGB.invoke(null, modifier.getColor().getRgb()),
|
||||
modifier.getBold(),
|
||||
modifier.getItalic(),
|
||||
modifier.getItalic(),
|
||||
modifier.getUnderlined(),
|
||||
modifier.getObfuscated(),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
modifier.getFont() == null ? null : ResourceLocation_tryParse.invoke(null, modifier.getFont())
|
||||
);
|
||||
} else {
|
||||
Object nmsModifier = newChatModifier.newInstance();
|
||||
if (modifier.getColor() != null) {
|
||||
ChatModifier_setColor.invoke(nmsModifier, Enum.valueOf(EnumChatFormat, modifier.getColor().getLegacyColor().name()));
|
||||
}
|
||||
}
|
||||
return newChatModifier.newInstance(
|
||||
color,
|
||||
modifier.isBold(),
|
||||
modifier.isItalic(),
|
||||
modifier.isUnderlined(),
|
||||
modifier.isStrikethrough(),
|
||||
modifier.isObfuscated(),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
modifier.getFont() == null ? null : ResourceLocation_tryParse.invoke(null, modifier.getFont())
|
||||
);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private Object createModifierLegacy(@NotNull ChatModifier modifier) {
|
||||
Object nmsModifier = newChatModifier.newInstance();
|
||||
if (modifier.getColor() != null) {
|
||||
ChatModifier_setColor.invoke(nmsModifier, Enum.valueOf(EnumChatFormat, modifier.getColor().getLegacyColor().name()));
|
||||
}
|
||||
if (modifier.isBold()) magicCodes.get(0).set(nmsModifier, true);
|
||||
if (modifier.isItalic()) magicCodes.get(1).set(nmsModifier, true);
|
||||
if (modifier.isStrikethrough()) magicCodes.get(2).set(nmsModifier, true);
|
||||
if (modifier.isUnderlined()) magicCodes.get(3).set(nmsModifier, true);
|
||||
if (modifier.isObfuscated()) magicCodes.get(4).set(nmsModifier, true);
|
||||
return nmsModifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to load component converter.
|
||||
*
|
||||
* @param serverVersion
|
||||
* Server version
|
||||
*/
|
||||
public static void tryLoad(@NotNull ProtocolVersion serverVersion) {
|
||||
try {
|
||||
boolean versionCheck = EnumSet.of(
|
||||
ProtocolVersion.V1_20_5,
|
||||
ProtocolVersion.V1_20_6,
|
||||
ProtocolVersion.V1_21,
|
||||
ProtocolVersion.V1_21_1
|
||||
).contains(serverVersion);
|
||||
if (ReflectionUtils.classExists("org.bukkit.craftbukkit.CraftServer") && versionCheck) {
|
||||
INSTANCE = (ComponentConverter) Class.forName("me.neznamy.tab.platforms.paper.PaperComponentConverter").getConstructor().newInstance();
|
||||
} else {
|
||||
INSTANCE = new ReflectionComponentConverter();
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
magicCodes.get(0).set(nmsModifier, modifier.getBold());
|
||||
magicCodes.get(1).set(nmsModifier, modifier.getItalic());
|
||||
magicCodes.get(2).set(nmsModifier, modifier.getStrikethrough());
|
||||
magicCodes.get(3).set(nmsModifier, modifier.getUnderlined());
|
||||
magicCodes.get(4).set(nmsModifier, modifier.getObfuscated());
|
||||
return nmsModifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,34 +6,29 @@ import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.neznamy.tab.platforms.bukkit.*;
|
||||
import me.neznamy.tab.platforms.bukkit.bossbar.BukkitBossBar;
|
||||
import me.neznamy.tab.platforms.bukkit.bossbar.ViaBossBar;
|
||||
import me.neznamy.tab.platforms.bukkit.features.BukkitTabExpansion;
|
||||
import me.neznamy.tab.platforms.bukkit.features.PerWorldPlayerList;
|
||||
import me.neznamy.tab.platforms.bukkit.header.HeaderFooter;
|
||||
import me.neznamy.tab.platforms.bukkit.hook.BukkitPremiumVanishHook;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.BukkitReflection;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.converter.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PingRetriever;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.converter.ReflectionComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.converter.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.scoreboard.ScoreboardLoader;
|
||||
import me.neznamy.tab.platforms.bukkit.tablist.TabListBase;
|
||||
import me.neznamy.tab.shared.GroupManager;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import me.neznamy.tab.shared.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.shared.chat.StructuredComponent;
|
||||
import me.neznamy.tab.shared.chat.SimpleComponent;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.config.files.config.PerWorldPlayerListConfiguration;
|
||||
import me.neznamy.tab.shared.backend.BackendPlatform;
|
||||
import me.neznamy.tab.shared.chat.component.*;
|
||||
import me.neznamy.tab.shared.features.PerWorldPlayerListConfiguration;
|
||||
import me.neznamy.tab.shared.features.PlaceholderManagerImpl;
|
||||
import me.neznamy.tab.shared.features.injection.PipelineInjector;
|
||||
import me.neznamy.tab.shared.features.types.TabFeature;
|
||||
import me.neznamy.tab.platforms.bukkit.features.BukkitTabExpansion;
|
||||
import me.neznamy.tab.platforms.bukkit.features.PerWorldPlayerList;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.backend.BackendPlatform;
|
||||
import me.neznamy.tab.shared.features.PlaceholderManagerImpl;
|
||||
import me.neznamy.tab.shared.hook.LuckPermsHook;
|
||||
import me.neznamy.tab.shared.hook.PremiumVanishHook;
|
||||
import me.neznamy.tab.shared.placeholders.types.PlayerPlaceholderImpl;
|
||||
import me.neznamy.tab.shared.placeholders.expansion.EmptyTabExpansion;
|
||||
import me.neznamy.tab.shared.placeholders.expansion.TabExpansion;
|
||||
import me.neznamy.tab.shared.placeholders.types.PlayerPlaceholderImpl;
|
||||
import me.neznamy.tab.shared.platform.BossBar;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
@@ -42,6 +37,7 @@ import me.neznamy.tab.shared.platform.impl.AdventureBossBar;
|
||||
import me.neznamy.tab.shared.platform.impl.DummyBossBar;
|
||||
import me.neznamy.tab.shared.util.PerformanceUtil;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.milkbowl.vault.chat.Chat;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
@@ -99,10 +95,10 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
//not spigot
|
||||
}
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("PremiumVanish")) {
|
||||
PremiumVanishHook.setInstance(new BukkitPremiumVanishHook());
|
||||
new BukkitPremiumVanishHook().register();
|
||||
}
|
||||
PingRetriever.tryLoad();
|
||||
ReflectionComponentConverter.tryLoad(serverVersion);
|
||||
ComponentConverter.tryLoad(serverVersion);
|
||||
ScoreboardLoader.findInstance(serverVersion);
|
||||
TabListBase.findInstance(serverVersion);
|
||||
if (BukkitReflection.getMinorVersion() >= 8) {
|
||||
@@ -110,7 +106,7 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
BukkitPipelineInjector.tryLoad(serverVersion);
|
||||
}
|
||||
BukkitUtils.sendCompatibilityMessage();
|
||||
Bukkit.getConsoleSender().sendMessage("[TAB] " + EnumChatFormat.GRAY + "Loaded NMS hook in " + (System.currentTimeMillis()-time) + "ms");
|
||||
Bukkit.getConsoleSender().sendMessage("[TAB] §7Loaded NMS hook in " + (System.currentTimeMillis()-time) + "ms");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -209,12 +205,12 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
|
||||
@Override
|
||||
public void logInfo(@NotNull TabComponent message) {
|
||||
Bukkit.getConsoleSender().sendMessage("[TAB] " + toBukkitFormat(message, true));
|
||||
Bukkit.getConsoleSender().sendMessage("[TAB] " + toBukkitFormat(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logWarn(@NotNull TabComponent message) {
|
||||
Bukkit.getConsoleSender().sendMessage(EnumChatFormat.RED + "[TAB] [WARN] " + toBukkitFormat(message, true));
|
||||
Bukkit.getConsoleSender().sendMessage("§c[TAB] [WARN] " + toBukkitFormat(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -230,13 +226,13 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
|
||||
@Override
|
||||
public void registerCommand() {
|
||||
PluginCommand command = Bukkit.getPluginCommand(TabConstants.COMMAND_BACKEND);
|
||||
PluginCommand command = Bukkit.getPluginCommand(getCommand());
|
||||
if (command != null) {
|
||||
BukkitTabCommand cmd = new BukkitTabCommand();
|
||||
command.setExecutor(cmd);
|
||||
command.setTabCompleter(cmd);
|
||||
} else {
|
||||
logWarn(TabComponent.fromColoredText("Failed to register command, is it defined in plugin.yml?"));
|
||||
logWarn(new SimpleTextComponent("Failed to register command, is it defined in plugin.yml?"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,9 +253,9 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Object convertComponent(@NotNull TabComponent component, boolean modern) {
|
||||
public Object convertComponent(@NotNull TabComponent component) {
|
||||
if (ComponentConverter.INSTANCE != null) {
|
||||
return ComponentConverter.INSTANCE.convert(component, modern);
|
||||
return ComponentConverter.INSTANCE.convert(component);
|
||||
} else {
|
||||
return component;
|
||||
}
|
||||
@@ -275,7 +271,8 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
@Override
|
||||
@NotNull
|
||||
public BossBar createBossBar(@NotNull TabPlayer player) {
|
||||
if (AdventureBossBar.isAvailable()) return new AdventureBossBar(player);
|
||||
//noinspection ConstantValue
|
||||
if (AdventureBossBar.isAvailable() && Audience.class.isAssignableFrom(Player.class)) return new AdventureBossBar(player);
|
||||
|
||||
// 1.9+ server, handle using API, potential 1.8 players are handled by ViaVersion
|
||||
if (BukkitReflection.getMinorVersion() >= 9) return new BukkitBossBar((BukkitTabPlayer) player);
|
||||
@@ -294,6 +291,26 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
return TabListBase.getInstance().apply((BukkitTabPlayer) player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsNumberFormat() {
|
||||
return serverVersion.getNetworkId() >= ProtocolVersion.V1_20_3.getNetworkId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsListOrder() {
|
||||
return serverVersion.getNetworkId() >= ProtocolVersion.V1_21_2.getNetworkId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsScoreboards() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSafeFromPacketEventsBug() {
|
||||
return serverVersion.getMinorVersion() >= 13;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public GroupManager detectPermissionPlugin() {
|
||||
@@ -338,42 +355,39 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
Bukkit.getScheduler().runTask(plugin, task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSee(@NotNull TabPlayer viewer, @NotNull TabPlayer target) {
|
||||
if (BackendPlatform.super.canSee(viewer, target)) return true;
|
||||
return ((BukkitTabPlayer)viewer).getPlayer().canSee(((BukkitTabPlayer)target).getPlayer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts component to legacy string using bukkit RGB format if supported by both server and client.
|
||||
* Converts component to string using bukkit RGB format if supported by the server.
|
||||
* If not, closest legacy color is used instead.
|
||||
*
|
||||
* @param component
|
||||
* Component to convert
|
||||
* @param rgbClient
|
||||
* Whether client accepts RGB colors or not.
|
||||
* @return Converted string using bukkit color format
|
||||
*/
|
||||
@NotNull
|
||||
public String toBukkitFormat(@NotNull TabComponent component, boolean rgbClient) {
|
||||
if (component instanceof SimpleComponent) return component.toLegacyText();
|
||||
StructuredComponent iComponent = (StructuredComponent) component;
|
||||
public String toBukkitFormat(@NotNull TabComponent component) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (iComponent.getModifier().getColor() != null) {
|
||||
if (serverVersion.supportsRGB() && rgbClient) {
|
||||
String hexCode = iComponent.getModifier().getColor().getHexCode();
|
||||
char c = EnumChatFormat.COLOR_CHAR;
|
||||
sb.append(c).append("x").append(c).append(hexCode.charAt(0)).append(c).append(hexCode.charAt(1))
|
||||
.append(c).append(hexCode.charAt(2)).append(c).append(hexCode.charAt(3))
|
||||
.append(c).append(hexCode.charAt(4)).append(c).append(hexCode.charAt(5));
|
||||
if (component.getModifier().getColor() != null) {
|
||||
if (serverVersion.supportsRGB()) {
|
||||
String hexCode = component.getModifier().getColor().getHexCode();
|
||||
sb.append('§').append("x").append('§').append(hexCode.charAt(0)).append('§').append(hexCode.charAt(1))
|
||||
.append('§').append(hexCode.charAt(2)).append('§').append(hexCode.charAt(3))
|
||||
.append('§').append(hexCode.charAt(4)).append('§').append(hexCode.charAt(5));
|
||||
} else {
|
||||
sb.append(iComponent.getModifier().getColor().getLegacyColor());
|
||||
sb.append('§').append(component.getModifier().getColor().getLegacyColor().getCharacter());
|
||||
}
|
||||
}
|
||||
sb.append(iComponent.getModifier().getMagicCodes());
|
||||
sb.append(iComponent.getText());
|
||||
for (StructuredComponent extra : iComponent.getExtra()) {
|
||||
sb.append(toBukkitFormat(extra, rgbClient));
|
||||
sb.append(component.getModifier().getMagicCodes());
|
||||
if (component instanceof TextComponent) {
|
||||
sb.append(((TextComponent) component).getText());
|
||||
} else if (component instanceof TranslatableComponent) {
|
||||
sb.append(((TranslatableComponent) component).getKey());
|
||||
} else if (component instanceof KeybindComponent) {
|
||||
sb.append(((KeybindComponent) component).getKeybind());
|
||||
} else {
|
||||
throw new IllegalStateException("Unexpected component type: " + component.getClass().getName());
|
||||
}
|
||||
for (TabComponent extra : component.getExtra()) {
|
||||
sb.append(toBukkitFormat(extra));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||