Merge remote-tracking branch 'origin/master'

This commit is contained in:
William 2023-03-15 17:15:18 +00:00
commit 829ab42e2e
No known key found for this signature in database
5 changed files with 55 additions and 12 deletions

View File

@ -11,23 +11,24 @@
</a>
</p>
<br/>
**Velocitab** is a super-simple Velocity TAB menu plugin that uses scoreboard team client-bound packets to actually sort player lists without the need for a backend plugin.
![showcase.png](images/showcase.png)
## Setup
Requires [Protocolize](https://github.com/Exceptionflug/protocolize) v2.2.5 to be installed on your proxy. [LuckPerms](https://luckperms.net) is also strongly recommended for prefix/suffix/role (and sorting) support.
Requires [Protocolize](https://www.spigotmc.org/resources/protocolize-protocollib-for-bungeecord-waterfall-velocity.63778/) v2.2.5 to be installed on your proxy. [LuckPerms](https://luckperms.net) is also strongly recommended for prefix/suffix/role (and sorting) support.
Simply download the latest release and place it in your Velocity plugins folder (along with Protocolize).
## Configuration
Velocitab has a simple config file that lets you define a header, footer and format for the player list, as well as a set of servers you do not want to have the custom player list appear on (i.e. if you want certain backend servers to manage the tab list instead of the proxy).
Velocitab has a simple config file that lets you define a header, footer and format for the player list. You can additionally configure [groups of servers](https://william278.net/docs/velocitab/server-groups) to display different formats in the TAB menu depending on which server the player is viewing it from.
### Formatting
Formatting is handled through [MineDown](https://github.com/Phoenix616/MineDown), supporting the full range of RGB colors and gradients. If you use my other plugin using MineDown, HuskChat, you'll feel right at home.
Velocitab [supports](https://william278.net/docs/velocitab/formatting) the full range of RGB colors and gradients, with options to use either MineDown (_default_) or MiniMessage formatting.
### Placeholders
You can include placeholders in the header, footer and player name format of the TAB list. The following placeholders are supported:
You can include [placeholders](https://william278.net/docs/velocitab/placeholders) in the header, footer and player name format of the TAB list. The following placeholders are supported:
| Placeholder | Description | Example |
|--------------------------|-----------------------------------------------|--------------------|
@ -44,6 +45,8 @@ You can include placeholders in the header, footer and player name format of the
| `%role%` | The player's primary LuckPerms group | `admin` |
| `%debug_team_name%` | Internal team value, used for list sorting | `1_alpha_William2` |
PlaceholderAPI placeholders are also supported. To use them, just install [PAPIProxyBridge](https://modrinth.com/plugin/papiproxybridge) on your Velocity proxy and backend Spigot servers. Additionally, a hook for MiniPlaceholders is supported for servers using the MiniMessage formatter.
## Building
To build Velocitab, simply run the following in the root of the repository:
```bash

View File

@ -28,7 +28,7 @@ public enum Placeholder {
PREFIX((plugin, player) -> player.getRole().getPrefix().orElse("")),
SUFFIX((plugin, player) -> player.getRole().getSuffix().orElse("")),
ROLE((plugin, player) -> player.getRole().getName().orElse("")),
DEBUG_TEAM_NAME((plugin, player) -> plugin.getFormatter().escape(player.getTeamName()));
DEBUG_TEAM_NAME((plugin, player) -> plugin.getFormatter().escape(player.getTeamName(plugin)));
/**
* Function to replace placeholders with a real value

View File

@ -1,11 +1,11 @@
package net.william278.velocitab.config;
import lombok.Getter;
import net.william278.annotaml.YamlComment;
import net.william278.annotaml.YamlFile;
import net.william278.annotaml.YamlKey;
import net.william278.velocitab.Velocitab;
import net.william278.velocitab.player.TabPlayer;
import org.apache.commons.text.StringEscapeUtils;
import org.jetbrains.annotations.NotNull;
@ -56,6 +56,13 @@ public class Settings {
@YamlComment("If you are using MINIMESSAGE formatting, enable this to support MiniPlaceholders in formatting.")
private boolean enableMiniPlaceholdersHook = true;
@YamlKey("sort_players_by")
@YamlComment("Ordered list of elements by which players should be sorted. (ROLE_WEIGHT, ROLE_NAME and SERVER are supported)")
private List<TabPlayer.SortableElement> sortPlayersBy = List.of(
TabPlayer.SortableElement.ROLE_WEIGHT,
TabPlayer.SortableElement.ROLE_NAME
);
@YamlKey("update_rate")
@YamlComment("How often to periodically update the TAB list, including header and footer, for all users.\nWill only update on player join/leave if set to 0.")
private int updateRate = 0;
@ -109,6 +116,11 @@ public class Settings {
return enableMiniPlaceholdersHook;
}
@NotNull
public List<TabPlayer.SortableElement> getSortingElementList() {
return sortPlayersBy;
}
public int getUpdateRate() {
return updateRate;
}

View File

@ -8,6 +8,8 @@ import net.william278.velocitab.tab.PlayerTabList;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
public final class TabPlayer implements Comparable<TabPlayer> {
private final Player player;
@ -34,7 +36,7 @@ public final class TabPlayer implements Comparable<TabPlayer> {
public String getServerName() {
return player.getCurrentServer()
.map(serverConnection -> serverConnection.getServerInfo().getName())
.orElse("Unknown");
.orElse("unknown");
}
@NotNull
@ -46,8 +48,10 @@ public final class TabPlayer implements Comparable<TabPlayer> {
}
@NotNull
public String getTeamName() {
return role.getWeightString(highestWeight) + role.getName().map(name -> "-" + name).orElse("");
public String getTeamName(@NotNull Velocitab plugin) {
return plugin.getSettings().getSortingElementList().stream()
.map(element -> element.resolve(this, plugin))
.collect(Collectors.joining("-"));
}
public void sendHeaderAndFooter(@NotNull PlayerTabList tabList) {
@ -68,4 +72,28 @@ public final class TabPlayer implements Comparable<TabPlayer> {
public boolean equals(Object obj) {
return obj instanceof TabPlayer other && player.getUniqueId().equals(other.player.getUniqueId());
}
/**
* Elements for sorting players
*/
@SuppressWarnings("unused")
public enum SortableElement {
ROLE_WEIGHT((player, plugin) -> player.getRole().getWeightString(player.highestWeight)),
ROLE_NAME((player, plugin) -> player.getRole().getName()
.map(name -> name.length() > 3 ? name.substring(0, 3) : name)
.orElse("")),
SERVER_NAME((player, plugin) -> player.getServerName());
private final BiFunction<TabPlayer, Velocitab, String> elementResolver;
SortableElement(@NotNull BiFunction<TabPlayer, Velocitab, String> elementResolver) {
this.elementResolver = elementResolver;
}
@NotNull
private String resolve(@NotNull TabPlayer tabPlayer, @NotNull Velocitab plugin) {
return elementResolver.apply(tabPlayer, plugin);
}
}
}

View File

@ -76,7 +76,7 @@ public class PlayerTabList {
if (serversInGroup.isPresent() && !serversInGroup.get().contains(player.getServerName())) {
continue; // Skip players on other servers
}
playerRoles.put(player.getPlayer().getUsername(), player.getTeamName());
playerRoles.put(player.getPlayer().getUsername(), player.getTeamName(plugin));
tabList.getEntries().stream()
.filter(e -> e.getProfile().getId().equals(player.getPlayer().getUniqueId())).findFirst()
.ifPresentOrElse(
@ -118,7 +118,7 @@ public class PlayerTabList {
);
plugin.getScoreboardManager().updateRoles(
player.getPlayer(),
newPlayer.getTeamName(),
newPlayer.getTeamName(plugin),
newPlayer.getPlayer().getUsername()
);
}
@ -147,7 +147,7 @@ public class PlayerTabList {
.filter(e -> e.getProfile().getId().equals(tabPlayer.getPlayer().getUniqueId())).findFirst()
.ifPresent(entry -> entry.setDisplayName(displayName));
plugin.getScoreboardManager().updateRoles(player.getPlayer(),
tabPlayer.getTeamName(), tabPlayer.getPlayer().getUsername());
tabPlayer.getTeamName(plugin), tabPlayer.getPlayer().getUsername());
}));
}