Tablist Manipulation using Tablisknu

Tutorial by: Tlatoani

This is a tutorial to explain how to use Tablisknu’s tablist features.

All names of syntaxes that are capitalized and in italics like Display Name of Player Tab are the names of the syntaxes as used in the documentation, so you can know where to find them in Tablisknu’s documentation.

What is the Tablist

The tablist is the list of player names that you view in the Minecraft client by default using the tab button (hence, tablist). In official (Mojang) contexts this is more properly called the playerlist, but tablist is common and is the term used relating to Tablisknu. The tablist doesn’t have to be just a list of players, or even list players at all, as it can be modified from that using packets; you don’t need to know packets for Tablisknu but that is how it is done internally (and if you wanted, you could instead implement Tablisknu’s features using MundoSK packets). Tablisknu provides features that allow you to perform these modifications in Skript, and those syntaxes are the subject of this tutorial.

Tablist Groups

Before we go into syntaxes that actually modify the tablist, we need to cover an important topic related to organization of players - tablist groups! Tablist groups allow you to make tablist modifications to a whole group of players at once. This is useful when there are certain things that should be the case for certain groups of players, like teams in a minigame, factions, players in each world, or even just all the players on your server. You can also make modifications to tablists of multiple players by using lists of players (for example {_player 1}, {_player 2}, and {_player 3}), however the advantage of tablist groups is that when you add players to a tablist group, all of the modifications that have been applied to that tablist group will immediately be applied to the tablist of that player (exluding modifications that have since been overriden), which is extremely useful.

Tablist groups are specified using a string which you could call their name. They don’t have to be created - the moment you add players to a tablist group or modify the tablist of a tablist group (even if it doesn’t have players) the tablist group is automatically created. In addition to the tablist groups identified by name, there is one more tablist group - the global tablist group. This is a single tablist group that contains all players on your server. It exists to allow you to conveniently make tablist modifications that apply to all players without having to create a new tablist group and add every player that joins to the group. If in a tablist syntax you don’t refer to a player or list of players or a tablist group by name, the effect will be applied to (or the expression will be evaluated based on) the global tablist group.

An important aspect of tablist groups is that players can be in multiple tablist groups, and can also have their tablists modified individually while being in one or more tablist groups, and this will be fine as long as those tablist groups all concern different aspects of the tablist (meaning a particular aspect isn’t modified for two tablist groups with the same player). In fact, it’s intended that you should be able to personalize each player’s tablist to some extent with information specific to them (ex. experience level, amount of currency they have, stats, etc.) while still having them in one or more tablist groups and/or modifying the global tablist group.

When getting the values of expressions for certain aspects of the tablist for a tablist group rather than a specific player, the value you’ll get is based only on the modifications that you’ve made to the tablist of the tablist group (not on any values that the tablists of players in the group might otherwise have). You can imagine that, when you are modifying a tablist group, that group actually has a single tablist, so when you make a modification to the tablist, that modification is made to the tablists of all the players in the group, but it is also made to that single tablist belonging to the group, and values will be read from that tablist. (This is actually how it’s done internally, though that tablist is not one that’s shown to any player). These values are also the ones used to make the necessary modifications to players who are added to the tablist group later.

All of that being said, there are a few effects you should know relating to tablist groups:

Add Players to Tablist Group

add %players% to tablist group %string%

This is the most important one: it adds the specified players to the specified tablist group.

Remove Players from Tablist Group

remove %players% from tablist group %string%

This one is pretty simple - it just removes the specified players from the specified tablist group. Note that this doesn’t make any changes to the tablists of those players; if there was anything modified in the tablist group that you want to undo now that they’re not in the tablist group, you’ll need to add code that makes those changes.

Empty Tablist Group

empty tablist group %string%

Delete Tablist Group

delete tablist group %string%

Both of these effects remove all players from the specified tablist group. The difference is that the second will also clear modifications made to the tablist group, while the first will not. This means that if you add a player to the group after doing the first effect, their tablist will have appropriate modifications made to it, but if you add a player to the group after doing the second effect, their tablist will not be modified in any way as that would essentially be a new tablist group.

Finally, an expression:

Members of Tablist Group

[the] members of tablist group %string%
tablist group %string%'s members

This is just a list of the players who are currently in the specified tablist group.

One last note about tablist groups: all syntaxes which relate to observing/modifying tablists need to know which tablist(s) you are referring to; for this purpose, all those syntaxes (really meaning all the syntaxes which will be discussed from this point on) have a component something like [ … (%-players%|group %-string%) … ] (the … indicate additional words, like of or the, or possibly just empty space). If you use the %-players% options, then the modification will be made for the player you specify, or, if you specify a list of players, then for each player in the list. If you use the group %-string% option, then the modification will be made for the tablist group you specify, meaning that it will be applied to each player in the tablist group and to any players that are added to the tablist group later (unless the modification is overriden). Notice that the syntax is enclosed in [ and ], meaning it is optional. If you leave it out completely, the modification will be made to the global tablist group, meaning (as explained prior) that it will be applied to all players on the server and any player who joins the server later (unless, as before, it is overriden).

Now that that’s clear, let’s get into the tablist!

A Tab

The first thing to discuss when we’re talking about tablists is the individual “atoms” that make up the tablist - the tabs. A tab consists of four components:

The display name, which is the name (type string) that is shown as part of the tab. This is probably the most important of the tab, and the reason they exist in the first place - to show the names of players. The display name, unlike player nametags, can be as long as you want, though obviously if you make it too long it won’t fit in the Minecraft window.

The icon, which is the player head that appears to the left of the display name. This has type skin, and can be set to any skin you want regardless of the source.

The latency bars, which is a set of five bars to the right of the display name, a certain number of which are green, traditionally used to indicate the strength of a player’s connection. This is of type number, though it’s really an integer between 0 and 5 inclusive.

The score, which is only visible if there’s an objective displayed in the tablist (more on that later). When visible, this is a yellow integer (positive or negative) to the right of the latency bars, and in practice can be as big (or small) as you need (technically it is limited by the Java maximum int value to be between -2,147,483,648 and 2,147,483,647 (inclusive) and more practically by the amount of space on the Minecraft screen). This is also of type number.

All of these components can be set (except for the icon in case of a tab belonging to an actual player; instead you have to modify the displayed skin of that player using Tablisknu’s skin features, which will also modify the icon). They can also be reset, in which case they’ll return to their default state, and with respect to tablist groups, any previous change will be ignored when applying changes to newly added players.

An important concept for icons is the default icon, which has an expression:

The default icon is the icon which tabs have if they haven’t had a specific skin set as their icon. This expression is actually settable, meaning that you can change the default icon. When you change it, all tabs that hadn’t had a specific skin set and so were using the previous default icon will now have the new default icon (any tabs that were specifically set to use the skin that happened to be the previous default icon will not be affected). By default the default icon is a completely white skin.

Score Enabling and Disabling

By default, tablists don’t have scores in them. If you like, you can use some external scoreboard system to put scores in the tablist, however Tablisknu offers built-in syntaxes for dealing with tablist scores that are completely integrated with Tablisknu’s other tablist features (if you use an external scoreboard system, you will not be able to use Tablisknu’s score syntaxes).

In a particular tablist, scores can either be enabled or disabled. If scores are enabled, then every tab has a score (as previously stated, the default is 0), and if scores are disabled, then there are no scores on the tab (unless you use an external system). Fairly simple.

If a player with scores enabled joins a tablist group in which scores are disabled, even if scores were explicitly disabled for that group, that player will continue to have scores enabled. If a player joins a tablist group with scores enabled, then regardless of whether that player had scores enabled previously, they will now be enabled.

There are two syntaxes relating to the enabling/disabling of scores in the tablist:

This tells you whether scores are enabled or disables in the specified tablist(s). You can set this, however if you know beforehand whether you’re enabling or disabling it’s better to use the following effect:

This, as implied by the syntax, either enables or disables scores in the specified tablist(s).

Tabs of Actual Players

The first type of tab that we’re going to look at is tabs that belong to actual players, which are referred to as player tabs. First, let’s look at the basic syntaxes that allow modification of the components of a player tab:

Fairly straightforward, this is the display name of the player tab belonging to the specified player for the specified tablist(s). The first %player% identifies which player this player tab belongs to, while the second is one of the options for identifying the tablist(s). One thing of note is that when not set, rather than being empty like other tabs, this displays as the player’s name (since the default Minecraft tablist is just the names of the players).

This is the amount of latency bars of the player tab belonging to the specified player for the specified tablist(s). Like above, the first %player% identifies which player this player tab belongs to, while the second is one of the options for identifying the tablist(s). One thing of note is that when not set, rather than being 5 green bars like other tabs, this will then vary its latency bars based on the player’s connection (which is the default Minecraft tablist behavior). Initially upon being reset however it will display 5 green bars regardless of the player’s connection, this should be updated after 30 seconds to a minute.

This is the score of the player tab belonging to the specified player for the specified tablist(s). Like above, the first %player% identifies which player this player tab belongs to, while the second is one of the options for identifying the tablist(s).

As previously stated, the icon of a player tab can’t be modified without setting the displayed skin of the player. Hence, it doesn’t appear here as a syntax (the syntax for setting the displayed skin is Displayed Skin of Player if you want to look it up in the docs).

In addition to modifying the components of a player tab, you can also show and hide players tabs.

This effect either shows or hides the player tabs of the specified players (notice how unlike the previous expressions, here you can specify multiple players and the effect will be applied to the player tabs of all of those players) for the specified tablist(s).

If this boolean expression is false, then all player tabs are hidden in the specified tablist(s). Players that join will automatically be hidden in the specified tablist(s). If this is true however, that does not necessarily mean that all player tabs are visible. It may even be true while all player tabs are currently hidden through use of the aformentioned Show or Hide in Tablist effect. What it means for this expression to be true is that a player who joins will not automatically be hidden. Setting this expression to false means that all player tabs will be hidden in the specified tablist(s) and any players who join will also be automatically be hidden in the specified tablist(s). Setting this expression to true, regardless of the current value, means that all player tabs will be shown in the specified tablist(s) (and of course, players who join will not be automatically be hidden). Note that this expression will also become true if you use the Show or Hide in Tablist effect to show one or more player tabs - in that case all other player tabs will remain as they were before (they will not all be shown) but this expression will become true and players who join will not automatically be hidden.

This effect is simple - it will show all players tabs and return all of them to their default state (in effect, undoing all player tab modifications that have been performed) in the specified tablist(s).

Simple Tabs

The next type of tab we’re going to cover is the simple tab. A simple tab is an artificial tab that is created by Tablisknu rather than belonging to a player. You create it using an effect, and then it appears in the players’ tablists. Simple.

There is one thing that simple tabs have that other tabs don’t have, and that’s the concept of priority. The priority of a simple tab is a string (at most 12 characters) that determines its position in the tablist relative to other simple tabs. The simple tabs are ordered according to the alphabetic order of their priorities, which should be fairly straightforward to understand.

All of that being said, let’s get into the first effect relating to simple tabs - the one that lets you create them.

This effect creates a simple tab with the specified id (the first string expression) for the specified tablist(s) with the specified components, which are the normal components of a tab (display name, icon, latency bars, score) as well as the priority. The id uniquely identifies the simple tab - if you try to create another simple tab with the same id for the same tablist(s), the previous one will be replaced. If you don’t specify a priority, the first 12 characters of the id will be used as the priority.

Now let’s go through the expressions that allow you to modify the components, starting with the priority.

This is the priority of the specified simple tab (remember, a simple tab is specified by its id, which is the first string expression in the syntax) for the specified tablist(s). This is an expression of type string.

This is the score of the specified simple tab for the specified tablist(s).

And lastly, it would be stupid if once you created a simple tab, it was there forever. Which is why there are syntaxes for deleting them too!

Delete Simple Tab

delete [the] simple tab %string% [for (%-players%|group %-string%)]

This deletes the specified simple tab for the specified tablist(s).

Delete All Simple Tabs

delete all simple tabs [for (%-players%|group %-string%)]

This deletes all the simple tabs that are in the specified tablist(s).

The Array Tablist

This is (at least in my opinion) the most useful tablist feature that Tablisknu has to offer. What the array tablist is is an arrangement of the tablist into a grid so that each tab can be identified by its column and then its row (this order is important, as all array tablist syntaxes follow this order for identifying the tab). This allows you to create tablists where you always know where the display name, icon, etc. you’re setting is going to end up in terms of position. Array tablists don’t have player tabs in them; instead, all of the tabs are array tabs (the player tabs are hidden unless you specify a 4x20 array tablist, the default, in which case the player tabs are secretly hiding after all of the array tabs since Minecraft can only display a maximum of 80 tabs. This fact will be important later, but I’ll remind you, so you don’t need to worry about it).

The first syntaxes you should know have to do with enabling/disabling the array tablist.

This effect either enables or disables the array tablist for the specified tablist(s). We’ll talk about enabling first.

When you enable the array tablist, all tabs will be removed and replaced with a grid of tabs with the dimensions specified in the syntax. You can have between 1 and 4 columns, with 4 being the default, and you can have between 1 and 20 rows, with 20 being the default. Note however, that you can’t use any combination of amount of columns 1-4 and amount of rows 1-20. Instead, each amount of columns has a certain range of amount of rows it can have:

1: 1 to 20

2: 11 to 20

3: 14 to 20

4: 16 to 20

This is due to the fact that Minecraft allows 1 to 80 total tabs, and for each amount, there is only one way the tablist can appear. Minecraft only allows a maximum of 20 tabs in one column, so the tabs will try to fill as few columns as possible will adhering to this rule. For example, if there are 40 tabs, this is satisfied by a 2x20 tablist, but for 41 and 42 you need 3x14. If you specify too few rows for your amount of columns (remember, the amount of columns defaults to 4 if you don’t specify it, which will restrict the amount of rows the most!) the array tablist will instead have the minimum amount of possible rows for that amount of columns.

Next, disabling. Disabling is pretty simple - all of the array tabs will be removed, and all of the player tabs will be shown and returned to their default state as if using the Clear All Player Tab Modifications effect (any simple tabs present before enabling array tablist will not reappear).

This effect adds or removes the specified amount of columns or rows to/from the specified tablist(s). If you are adding columns or rows, you can specify an icon to be set for the new tabs created. This is much more efficient than setting these icons in a loop both in terms of conciseness of code and the amount of packets being sent to/from the server from/to the client.

Now that all of that is covered, we can get into the syntaxes for modifying the components of an array tab!

This is the display name of the specified array tab (the first number expression is the column of the array tab, with the first column being column number 1, and the second number expression being the row of the array tab, numbered similarly) for the specified tablist(s).

This is the score of the specified array tab for the specified tablist(s).

The Config and Issues with Hidden Player Tabs

There’s a small problem with hiding player tabs - if the player tab belonging to player A is hidden in the tablist of player B, then if A was previously not spawned in B’s game but then has to be spawned due to a teleportation, respawn, etc., then A’s skin will appear as Steve/Alex for B. This is because Minecraft uses the tablist information for rendering skins. Fortunately, Tablisknu has a simple solution: just add A’s player tab to B’s tablist when Tablisknu realizes that A is about to spawn for B, then remove it immediately after. However, Tablisknu has to wait a certain amount of time between adding and removing the tabs, and if this time is too short, then A’s skin will not render properly for B. If the time is too long, however, then B will notice A’s player tab in their tablist for a long time when it shouldn’t be there, which defeats the purpose of hiding the tab.

There are two ways to resolve this: the simple way is to just never hide any player tabs. This means not hiding any player tabs directly, and also only using the array tablist with dimensions 4x20 (4 columns and 20 rows) because with those dimensions, the player tabs are not actually hidden, they’re just out of sight to the player (which looks exactly the same). If you 100% want to avoid any issues with this kind of thing, you should opt for this solution.

If you still want to hide player tabs or use array tablist with dimensions other than 4x20, then here’s what you should do to minimize issues relating to skin rendering as a result of this. First, just try it out. Tablisknu’s default values for the delays in adding and removing the tabs have been calibrated to work on my test server, and in most cases they’ll probably work fine for your server as well. If you don’t notice any issues, you can assume that the values are suited for your server.

If not, however, then they can be changed in Tablisknu’s config file (plugins/tablisknu/config.yml). Below I’ve included a copy of the config options which relate to tablists. The explanations you’ll see below are the same ones you’ll see in the config file.

# For reference, 20 ticks = 1 second.
# This is used when a player is hidden in some other player's tablist.
# When a player that is hidden in another player's tablist needs to be spawned for that player,
# (ex. if they are teleporting from faraway to somewhere near that player)
# they need to be temporarily added to that player's tablist.
# However, if they are removed from the tablist too quickly after being temporarily added,
# then their skin will not render properly.
# This option controls the amount of time (in ticks) before re-removing the player from the other player's tablist.
# Generally you want this to be as small as possible
# so that players aren't seeing things in tablist they shouldn't be seeing for too long,
# but you want to make it long enough so that players' skins render properly.
# The 10 ticks default is usually good, but depending on your server you may need to go above 10 ticks.
# Going below 10 ticks will most likely cause skin rendering issues, though you can try if you like.
tablist_remove_tab_delay_spawn: 10
# This is the same as the above option, but for when a player is respawning after dying or switching between worlds,
# and some player is hidden in that player's tablist. In this case those two players could be the same player.
# Here the default ticks is higher (40 ticks) as teleporting between worlds takes more time than teleporting in the same world.
tablist_remove_tab_delay_respawn: 40
# This is the amount of ticks to wait before applying default group tab modifications to a newly joined player.
# Default group tab modifications are the ones that you apply
# when you use tablist syntaxes without specifying a player or tablist group.
# They apply to all players and need to be applied to newly joined players as well.
# However, tablist modifications should not be applied immediately to newly joined players,
# and so there must be some kind of delay. The default delay is 20 ticks.
# If any of your scripts apply tablist modifications to players on join, they should also use a similar delay.
tablist_add_to_default_group_delay: 40

That last one actually doesn’t relate to this issue, but is also very important: if you perform certain tablist actions too soon after a player has joined, then other players’ skins might not render properly for them, their skin might not render properly for other players, or multiple tablists may be messed up. Therefore, you should always employ a delay before using any tablist syntaxes for that player, and you should probably make it the same as the value of the tablist_add_to_default_group_delay option as seen above. This value is the delay that Tablisknu will use internally for the same reason, so it makes sense to use it in your scripts as well.

Header and Footer
This last part of the tablist doesn’t have anything to do with tabs at all - rather, it’s the header and footer of the tablist, which are lines of text which appear above and below the tablist. They generally include information like the URL for your server’s website or similar things, but you can really put anything you want there.

Since the header/footer can be made up of multiple lines, we treat it as a list of strings in Skript. When a player joins a tablist group with a certain header/footer, that player’s header/footer will be increased, if necessary, to at least the size of the group’s header/footer (it will not be decreased in this process). All lines of the group’s header/footer which exist and are not empty will replace the corresponding line in the player’s header/footer (other lines will remain as they were in the player’s header/footer).

This is the amount of lines in the tablist header/footer of the specified tablist, meaning that it’s of type number but will always be a nonnegative integer.

Conclusion

Hopefully reading this helped you to understand Tablisknu’s tablist features. There may still be things you are confused or have questions about, so feel free to comment below or ask questions in the tablisknu channel of the Skript Chat Discord Server. Thanks for reading!