forked from Upstream/Velocitab
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
829ab42e2e
11
README.md
11
README.md
@ -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.
|
||||
|
||||

|
||||
|
||||
## 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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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());
|
||||
}));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user