forked from Upstream/Velocitab
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
4d7ffd75db
@ -27,6 +27,7 @@ repositories {
|
||||
maven { url = 'https://repo.william278.net/velocity/' }
|
||||
maven { url = 'https://repo.papermc.io/repository/maven-public/' }
|
||||
maven { url = 'https://repo.william278.net/releases/' }
|
||||
maven { url = 'https://repo.william278.net/snapshots/' }
|
||||
maven { url = 'https://jitpack.io/' }
|
||||
maven { url = 'https://repo.minebench.de/' }
|
||||
}
|
||||
@ -50,6 +51,7 @@ dependencies {
|
||||
implementation 'de.exlll:configlib-yaml:4.5.0'
|
||||
implementation 'org.apache.commons:commons-jexl3:3.4.0'
|
||||
implementation 'net.jodah:expiringmap:0.5.11'
|
||||
implementation("net.william278:velocityscoreboardapi:1.0.0-b2d9518")
|
||||
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.34'
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ To add additional frames of animation to a header format for a [server group](se
|
||||
|
||||
```yaml
|
||||
headers:
|
||||
- '&rainbow&Running Velocitab by William278'
|
||||
- '&rainbow:10&Running Velocitab by William278'
|
||||
- '&rainbow:20&Running Velocitab by William278'
|
||||
- '<rainbow>Running Velocitab by William278 & AlexDev_</rainbow>'
|
||||
- '<rainbow:10>Running Velocitab by William278 & AlexDev_</rainbow>'
|
||||
- '<rainbow:20>Running Velocitab by William278 & AlexDev_</rainbow>'
|
||||
```
|
||||
</details>
|
||||
|
||||
@ -35,47 +35,47 @@ Wondering how to make something like the above example? Here's how! This example
|
||||
Please note this is not a complete tab_groups file; you will need to add the relevant sections to the correct part in your own Velocitab `tab_groups.yml`.
|
||||
```yaml
|
||||
headers:
|
||||
- '&rainbow&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:2&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:4&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:6&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:8&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:10&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:12&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:14&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:16&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:18&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:20&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:22&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:24&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:26&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:28&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:30&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:32&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:34&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:36&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:38&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:40&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:42&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:44&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:46&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:48&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:50&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:52&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:54&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:56&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:58&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '&rainbow:60&Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
|
||||
- '<rainbow>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:2>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:2>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:2>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:2>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:2>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:2>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:2>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:2>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:18>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:20>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:22>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:24>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:26>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:28>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:30>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:32>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:34>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:36>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:38>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:40>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:42>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:44>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:46>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:48>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:50>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:52>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:54>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:56>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:58>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
- '<rainbow:60>Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n</rainbow>'
|
||||
footers:
|
||||
- |
|
||||
\n&7For Velocity proxy servers:
|
||||
bd96a-#6cffa9&https://modrinth.com/plugin/velocitab
|
||||
bd96a-#6cffa9&https://william278.net/project/veloictab'
|
||||
format: 'ϧ-#fff&[%server%] &f%username%'
|
||||
\n<gray>For Velocity proxy servers:</gray>
|
||||
<gradient:#1bd96a:#6cffa9>https://modrinth.com/plugin/velocitab</gradient>
|
||||
<gradient:#1bd96a:#6cffa9>https://william278.net/project/veloictab</gradient>'
|
||||
format: '<gradient:#999:#fff>[%server%] &f%username%</gradient>'
|
||||
header_footer_update_rate: 200
|
||||
```
|
||||
In config.yml
|
||||
```yaml
|
||||
formatter: MINEDOWN
|
||||
formatter: MINIMESSAGE
|
||||
```
|
||||
</details>
|
||||
|
@ -19,8 +19,8 @@ check_for_updates: true
|
||||
remove_nametags: true
|
||||
# Whether to disable header and footer if they are empty and let backend servers handle them.
|
||||
disable_header_footer_if_empty: true
|
||||
# Which text formatter to use (MINEDOWN, MINIMESSAGE, or LEGACY)
|
||||
formatter: MINEDOWN
|
||||
# Which text formatter to use (MINIMESSAGE, MINEDOWN or LEGACY)
|
||||
formatter: MINIMESSAGE
|
||||
# All servers which are not in other groups will be put in the fallback group.
|
||||
# "false" will exclude them from Velocitab.
|
||||
fallback_enabled: true
|
||||
@ -56,7 +56,7 @@ enable_plugin_message_api: true
|
||||
# • If you supply a url with a 'bug_report' label, it will be shown if the player is disconnected.
|
||||
# • Specify a set of server groups each URL should be sent on. Use '*' to show a URL to all groups.
|
||||
server_links:
|
||||
- label: '�fb9a&About Velocitab'
|
||||
- label: '<#00fb9a>About Velocitab</#00fb9a>'
|
||||
url: 'https://william278.net/project/velocitab'
|
||||
groups:
|
||||
- '*'
|
||||
@ -79,29 +79,30 @@ server_links:
|
||||
# ┗╸ Documentation: https://william278.net/docs/velocitab
|
||||
|
||||
groups:
|
||||
- name: default
|
||||
headers:
|
||||
- '&rainbow&Running Velocitab by William278'
|
||||
footers:
|
||||
- '[There are currently %players_online%/%max_players_online% players online](gray)'
|
||||
format: '&7[%server%] &f%prefix%%username%'
|
||||
nametag:
|
||||
prefix: '&f%prefix%'
|
||||
suffix: '&f%suffix%'
|
||||
servers:
|
||||
- ^lobby[^ ]*
|
||||
- survival
|
||||
- creative
|
||||
- minigames
|
||||
- skyblock
|
||||
- prison
|
||||
sorting_placeholders:
|
||||
- '%role_weight%'
|
||||
- '%username_lower%'
|
||||
collisions: false
|
||||
header_footer_update_rate: 1000
|
||||
placeholder_update_rate: 1000
|
||||
only_list_players_in_same_server: false
|
||||
- name: default
|
||||
headers:
|
||||
- <rainbow:!2>Running Velocitab by William278 & AlexDev_</rainbow>
|
||||
footers:
|
||||
- <gray>There are currently %players_online%/%max_players_online% players online</gray>
|
||||
format: <gray>[%server%] %prefix%%username%</gray>
|
||||
nametag:
|
||||
prefix: <white>%prefix%</white>
|
||||
suffix: <white>%suffix%</white>
|
||||
servers:
|
||||
- skyblock
|
||||
- minigames
|
||||
- survival
|
||||
- lobby
|
||||
- prison
|
||||
- creative
|
||||
- hub
|
||||
sorting_placeholders:
|
||||
- '%role_weight%'
|
||||
- '%username_lower%'
|
||||
collisions: false
|
||||
header_footer_update_rate: 1000
|
||||
placeholder_update_rate: 1000
|
||||
only_list_players_in_same_server: false
|
||||
```
|
||||
|
||||
</details>
|
||||
|
@ -1,12 +1,14 @@
|
||||
Velocitab supports the full range of modern color formatting, including RGB colors and gradients. Both MineDown (_default_), MiniMessage and Legacy formatting are supported. To change which formatter is being used, change the `formatter` value in `config.yml` to `MINEDOWN`, `MINIMESSAGE` or `LEGACY` respectively.
|
||||
Velocitab supports the full range of modern color formatting, including RGB colors and gradients. Both MiniMessage (_default_), MineDown and Legacy formatting are supported. To change which formatter is being used, change the `formatter` value in `config.yml` to `MINEDOWN`, `MINIMESSAGE` or `LEGACY` respectively.
|
||||
|
||||
Formatting is applied on header, footer and player text for each server group, and is applied after [[Placeholders]] have been inserted.
|
||||
|
||||
## MineDown syntax reference
|
||||
MineDown is the default formatter type, enabled by setting `formatter` to `MINEDOWN` in `config.yml`. See the [MineDown Syntax Reference](https://github.com/WiIIiam278/MineDown) on GitHub for the specification of how to format text with it.
|
||||
|
||||
## MiniMessage syntax reference
|
||||
MiniMessage formatting can be enabled by setting `formatter` to `MINIMESSAGE` in `config.yml`. See the [MiniMessage Syntax Reference](https://docs.advntr.dev/minimessage/format.html) on the Adventure Docs for how to format text with it. Using MiniMessage as the formatter also allows compatibility for using MiniPlaceholders in text.
|
||||
MiniMessage is the default formatter type, enabled by setting `formatter` to `MINIMESSAGE` in `config.yml`. See the [MiniMessage Syntax Reference](https://docs.advntr.dev/minimessage/format.html) on the Adventure Docs for how to format text with it. Using MiniMessage as the formatter also allows compatibility for using MiniPlaceholders in text.
|
||||
|
||||
## MineDown syntax reference
|
||||
MineDown formatting can be enabled by setting `formatter` to `MINEDOWN` in `config.yml`. See the [MineDown Syntax Reference](https://github.com/WiIIiam278/MineDown) on GitHub for the specification of how to format text with it.
|
||||
|
||||
|
||||
## Legacy formatting
|
||||
> **Warning:** The option for legacy formatting is provided only for backwards compatibility with other plugins. Please consider using the MineDown or MiniMessage options instead!
|
||||
|
@ -41,3 +41,12 @@ Nametags must adhere to the following restrictions:
|
||||
* Velocitab determines which color to use here based on the last color format used in the configured prefix (displayed before their name), downsampled from RGB if necessary.
|
||||
* To control this, simply set the prefix format to end with a valid [team color](https://wiki.vg/Text_formatting#Colors) you want to use (e.g. `&4` for dark_red in Minedown formatting).
|
||||
* Nametags cannot contain newlines (must be on a single line).
|
||||
|
||||
## Bypassing formatting restrictions
|
||||
UnlimitedNameTags is a spigot plugin that lets you create nametags with unlimited length and lines.
|
||||
You can use rgb colors and gradients in usernames.
|
||||
In order to use this plugin you need to disable the nametag feature in Velocitab by setting `remove_nametags` to `true` in the [`config.yml` file](config-file) and put an empty nametag (empty prefix & suffix) in the [`tab_groups.yml` file](Server-Groups.md).
|
||||
You can find the plugin on [BuiltByBit](https://builtbybit.com/resources/unlimitednametags.46172/?ref=38685) and on [SpigotMC](https://www.spigotmc.org/resources/unlimitednametags.117526/).
|
||||
|
||||

|
||||
|
||||
|
@ -17,9 +17,9 @@ rate to use for the group.
|
||||
|
||||
```yaml
|
||||
headers:
|
||||
- '&rainbow&Running Velocitab by William278'
|
||||
- '<rainbow>Running Velocitab by William278 & AlexDev_</rainbow>'
|
||||
footers:
|
||||
- '[There are currently %players_online%/%max_players_online% players online](gray)'
|
||||
- '<gray>There are currently %players_online%/%max_players_online% players online</gray>'
|
||||
```
|
||||
|
||||
</details>
|
||||
@ -35,7 +35,7 @@ information.
|
||||
<summary>Example of format</summary>
|
||||
|
||||
```yaml
|
||||
format: '&7[%server%] &f%prefix%%username%'
|
||||
format: '<gray>[%server%] %prefix%%username%</gray>'
|
||||
```
|
||||
|
||||
</details>
|
||||
@ -51,8 +51,8 @@ Player formats may only utilize one line.
|
||||
|
||||
```yaml
|
||||
nametag:
|
||||
prefix: '&f%prefix%'
|
||||
suffix: '&f%suffix%'
|
||||
prefix: '<white>%prefix%</white>'
|
||||
suffix: '<white>%suffix%</white>'
|
||||
```
|
||||
|
||||
</details>
|
||||
@ -148,10 +148,10 @@ placeholders in the TAB list will update. The default is 1000 milliseconds (1 se
|
||||
groups:
|
||||
- name: lobbies
|
||||
headers:
|
||||
- '&rainbow&Running Velocitab by William278 on Lobbies!'
|
||||
- '<rainbow:!2>Running Velocitab by William278 & AlexDev_ on Lobbies!</rainbow>'
|
||||
footers:
|
||||
- '[There are currently %players_online%/%max_players_online% players online](gray)'
|
||||
format: '&7[%server%] &f%prefix%%username%'
|
||||
- '<gray>There are currently %players_online%/%max_players_online% players online</gray>'
|
||||
format: '<gray>[%server%] %prefix%%username%</gray>'
|
||||
servers:
|
||||
- lobby
|
||||
- hub
|
||||
@ -165,10 +165,10 @@ groups:
|
||||
placeholder_update_rate: 1000
|
||||
- name: creative
|
||||
headers:
|
||||
- '&rainbow&Running Velocitab by William278 on Creative!'
|
||||
- '<rainbow:!2>Running Velocitab by William278 & AlexDev_ on Creative!</rainbow>'
|
||||
footers:
|
||||
- '[There are currently %players_online%/%max_players_online% players online](gray)'
|
||||
format: '&7[%server%] &f%prefix%%username%'
|
||||
- '<gray>There are currently %players_online%/%max_players_online% players online</gray>'
|
||||
format: '<gray>[%server%] %prefix%%username%</gray>'
|
||||
servers:
|
||||
- creative
|
||||
sorting_placeholders:
|
||||
@ -178,10 +178,10 @@ groups:
|
||||
placeholder_update_rate: 1000
|
||||
- name: survival
|
||||
headers:
|
||||
- '&rainbow&Running Velocitab by William278 on Survival!'
|
||||
- '<rainbow:!2>Running Velocitab by William278 & AlexDev_ on Survival!</rainbow>'
|
||||
footers:
|
||||
- '[There are currently %players_online%/%max_players_online% players online](gray)'
|
||||
format: '&7[%server%] &f%prefix%%username%'
|
||||
- '<gray>There are currently %players_online%/%max_players_online% players online</gray>'
|
||||
format: '<gray>[%server%] %prefix%%username%</gray>'
|
||||
servers:
|
||||
- survival
|
||||
sorting_placeholders:
|
||||
|
@ -114,7 +114,6 @@ public class Velocitab implements ConfigProvider, ScoreboardProvider, LoggerProv
|
||||
|
||||
@Subscribe
|
||||
public void onProxyShutdown(@NotNull ProxyShutdownEvent event) {
|
||||
// server.getScheduler().tasksByPlugin(this).forEach(ScheduledTask::cancel);
|
||||
disableScoreboardManager();
|
||||
getLuckPermsHook().ifPresent(LuckPermsHook::closeEvent);
|
||||
getMiniPlaceholdersHook().ifPresent(MiniPlaceholdersHook::unregisterExpansion);
|
||||
|
@ -48,8 +48,8 @@ public enum Formatter {
|
||||
),
|
||||
MINIMESSAGE(
|
||||
(text, player, viewer, plugin) -> plugin.getMiniPlaceholdersHook()
|
||||
.filter(hook -> viewer != null)
|
||||
.map(hook -> hook.format(text, player.getPlayer(), viewer.getPlayer()))
|
||||
.filter(hook -> player != null)
|
||||
.map(hook -> hook.format(text, player.getPlayer(), viewer == null ? null : viewer.getPlayer()))
|
||||
.orElse(MiniMessage.miniMessage().deserialize(text)),
|
||||
(text) -> MiniMessage.miniMessage().escapeTags(text),
|
||||
"MiniMessage",
|
||||
|
@ -22,8 +22,8 @@ package net.william278.velocitab.config;
|
||||
import com.velocitypowered.api.proxy.ServerConnection;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import it.unimi.dsi.fastutil.Pair;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.william278.velocitab.Velocitab;
|
||||
import net.william278.velocitab.hook.miniconditions.MiniConditionManager;
|
||||
import net.william278.velocitab.player.TabPlayer;
|
||||
import net.william278.velocitab.tab.Nametag;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -114,13 +114,17 @@ public enum Placeholder {
|
||||
.orElse(getPlaceholderFallback(plugin, "%luckperms_meta_" + param + "%")));
|
||||
|
||||
private final static Pattern VELOCITAB_PATTERN = Pattern.compile("<velocitab_.*?>");
|
||||
private final static Pattern TEST = Pattern.compile("<.*?>");
|
||||
private final static Pattern CONDITION_REPLACER = Pattern.compile("<velocitab_rel_condition:[^:]*:");
|
||||
private final static Pattern PLACEHOLDER_PATTERN = Pattern.compile("%.*?%");
|
||||
private final static Pattern CONDITIONAL_PATTERN = Pattern.compile("<velocitab_rel_condition:[^:]*:[^:]*:[^:]*>");
|
||||
private final static String DELIMITER = ":::";
|
||||
private final static String REL_SUBSTITUTE = "-REL-";
|
||||
public final static Map<String, String> SYMBOL_SUBSTITUTES = Map.of(
|
||||
"<", "-COND-1",
|
||||
">", "-COND-2"
|
||||
private final static Map<String, String> SYMBOL_SUBSTITUTES = Map.of(
|
||||
"<", "*LESS*",
|
||||
">", "*GREATER*"
|
||||
);
|
||||
private final static Map<String, String> SYMBOL_SUBSTITUTES_2 = Map.of(
|
||||
"*LESS*", "*LESS2*",
|
||||
"*GREATER*", "*GREATER2*"
|
||||
);
|
||||
|
||||
/**
|
||||
@ -163,44 +167,65 @@ public enum Placeholder {
|
||||
format = result.right();
|
||||
format = replacePlaceholders(format, plugin, player);
|
||||
|
||||
if (result.left()) {
|
||||
format = format.replace(REL_SUBSTITUTE, "%");
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
private static Pair<Boolean, String> processRelationalPlaceholders(@NotNull String format, @NotNull Velocitab plugin) {
|
||||
boolean foundRelational = false;
|
||||
if (format.contains("<vel") && plugin.getFormatter().equals(Formatter.MINIMESSAGE)) {
|
||||
final Matcher velocitabRelationalMatcher = VELOCITAB_PATTERN.matcher(format);
|
||||
while (velocitabRelationalMatcher.find()) {
|
||||
if (velocitabRelationalMatcher.group().contains("rel_condition")) {
|
||||
if (plugin.getFormatter().equals(Formatter.MINIMESSAGE) && format.contains("<vel")) {
|
||||
final Matcher conditionReplacer = CONDITION_REPLACER.matcher(format);
|
||||
while (conditionReplacer.find()) {
|
||||
|
||||
final String search = conditionReplacer.group().split(":")[1];
|
||||
String condition = search;
|
||||
for (Map.Entry<String, String> entry : MiniConditionManager.REPLACE.entrySet()) {
|
||||
condition = condition.replace(entry.getKey(), entry.getValue());
|
||||
}
|
||||
for (Map.Entry<String, String> entry : MiniConditionManager.REPLACE_2.entrySet()) {
|
||||
condition = condition.replace(entry.getValue(), entry.getKey());
|
||||
}
|
||||
format = format.replace(search, condition);
|
||||
}
|
||||
|
||||
final Matcher testMatcher = TEST.matcher(format);
|
||||
while (testMatcher.find()) {
|
||||
if(testMatcher.group().startsWith("<velocitab_rel")) {
|
||||
final Matcher second = TEST.matcher(testMatcher.group().substring(1));
|
||||
while (second.find()) {
|
||||
String s = second.group();
|
||||
for (Map.Entry<String, String> entry : SYMBOL_SUBSTITUTES.entrySet()) {
|
||||
s = s.replace(entry.getKey(), entry.getValue());
|
||||
}
|
||||
format = format.replace(second.group(), s);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
String s = testMatcher.group();
|
||||
for (Map.Entry<String, String> entry : SYMBOL_SUBSTITUTES.entrySet()) {
|
||||
s = s.replace(entry.getKey(), entry.getValue());
|
||||
}
|
||||
format = format.replace(testMatcher.group(), s);
|
||||
}
|
||||
|
||||
final Matcher velocitabRelationalMatcher = VELOCITAB_PATTERN.matcher(format);
|
||||
while (velocitabRelationalMatcher.find()) {
|
||||
foundRelational = true;
|
||||
final String relationalPlaceholder = velocitabRelationalMatcher.group().substring(1, velocitabRelationalMatcher.group().length() - 1);
|
||||
final String fixedString = replaceSymbols(relationalPlaceholder);
|
||||
String fixedString = relationalPlaceholder;
|
||||
for (Map.Entry<String, String> entry : SYMBOL_SUBSTITUTES_2.entrySet()) {
|
||||
fixedString = fixedString.replace(entry.getKey(), entry.getValue());
|
||||
}
|
||||
format = format.replace(relationalPlaceholder, fixedString);
|
||||
}
|
||||
|
||||
format = processConditionalPlaceholders(format);
|
||||
for (Map.Entry<String, String> entry : SYMBOL_SUBSTITUTES.entrySet()) {
|
||||
format = format.replace(entry.getValue(), entry.getKey());
|
||||
}
|
||||
|
||||
}
|
||||
return Pair.of(foundRelational, format);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String processConditionalPlaceholders(@NotNull String format) {
|
||||
final Matcher conditionalMatcher = CONDITIONAL_PATTERN.matcher(format);
|
||||
while (conditionalMatcher.find()) {
|
||||
String conditionalPlaceholder = conditionalMatcher.group();
|
||||
conditionalPlaceholder = conditionalPlaceholder.substring(1, conditionalPlaceholder.length() - 1);
|
||||
final String fixedString = replaceSymbols(conditionalPlaceholder);
|
||||
format = format.replace(conditionalPlaceholder, fixedString);
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String replacePlaceholders(@NotNull String format, @NotNull Velocitab plugin, @Nullable TabPlayer player) {
|
||||
for (Placeholder placeholder : values()) {
|
||||
@ -219,16 +244,6 @@ public enum Placeholder {
|
||||
return format;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String replaceSymbols(@NotNull String input) {
|
||||
String fixedString = input.replace("%", REL_SUBSTITUTE);
|
||||
fixedString = MiniMessage.miniMessage().serialize(Formatter.LEGACY.deserialize(fixedString));
|
||||
for (Map.Entry<String, String> entry : SYMBOL_SUBSTITUTES.entrySet()) {
|
||||
fixedString = fixedString.replace(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return fixedString;
|
||||
}
|
||||
|
||||
public static CompletableFuture<String> replace(@NotNull String format, @NotNull Velocitab plugin,
|
||||
@NotNull TabPlayer player) {
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
package net.william278.velocitab.config;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.velocitypowered.api.util.ServerLink;
|
||||
import net.william278.velocitab.Velocitab;
|
||||
import net.william278.velocitab.player.TabPlayer;
|
||||
|
@ -54,8 +54,8 @@ public class Settings implements ConfigValidator {
|
||||
@Comment("Whether to disable header and footer if they are empty and let backend servers handle them.")
|
||||
private boolean disableHeaderFooterIfEmpty = true;
|
||||
|
||||
@Comment("Which text formatter to use (MINEDOWN, MINIMESSAGE, or LEGACY)")
|
||||
private Formatter formatter = Formatter.MINEDOWN;
|
||||
@Comment("Which text formatter to use (MINIMESSAGE, MINEDOWN or LEGACY)")
|
||||
private Formatter formatter = Formatter.MINIMESSAGE;
|
||||
|
||||
@Comment("All servers which are not in other groups will be put in the fallback group."
|
||||
+ "\n\"false\" will exclude them from Velocitab.")
|
||||
@ -104,7 +104,7 @@ public class Settings implements ConfigValidator {
|
||||
"• Specify a set of server groups each URL should be sent on. Use '*' to show a URL to all groups."})
|
||||
private List<ServerUrl> serverLinks = List.of(
|
||||
new ServerUrl(
|
||||
"�fb9a&About Velocitab",
|
||||
"<#00fb9a>About Velocitab</#00fb9a>",
|
||||
"https://william278.net/project/velocitab"
|
||||
)
|
||||
);
|
||||
|
@ -48,10 +48,10 @@ public class TabGroups implements ConfigValidator {
|
||||
|
||||
private static final Group DEFAULT_GROUP = new Group(
|
||||
"default",
|
||||
List.of("&rainbow&Running Velocitab by William278"),
|
||||
List.of("[There are currently %players_online%/%max_players_online% players online](gray)"),
|
||||
"&7[%server%] &f%prefix%%username%",
|
||||
new Nametag("&f%prefix%", "&f%suffix%"),
|
||||
List.of("<rainbow:!2>Running Velocitab by William278 & AlexDev_</rainbow>"),
|
||||
List.of("<gray>There are currently %players_online%/%max_players_online% players online</gray>"),
|
||||
"<gray>[%server%] %prefix%%username%</gray>",
|
||||
new Nametag("<white>%prefix%</white>", "<white>%suffix%</white>"),
|
||||
Set.of("lobby", "survival", "creative", "minigames", "skyblock", "prison", "hub"),
|
||||
List.of("%role_weight%", "%username_lower%"),
|
||||
false,
|
||||
|
@ -27,15 +27,8 @@ import net.william278.velocitab.Velocitab;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class MiniPlaceholdersHook extends Hook {
|
||||
|
||||
public final static Map<String, String> REPLACE = Map.of(
|
||||
"\"", "-q-",
|
||||
"'", "-a-"
|
||||
);
|
||||
|
||||
private final VelocitabMiniExpansion expansion;
|
||||
|
||||
public MiniPlaceholdersHook(@NotNull Velocitab plugin) {
|
||||
@ -46,9 +39,6 @@ public class MiniPlaceholdersHook extends Hook {
|
||||
|
||||
@NotNull
|
||||
public Component format(@NotNull String text, @NotNull Audience player, @Nullable Audience viewer) {
|
||||
for (Map.Entry<String, String> entry : REPLACE.entrySet()) {
|
||||
text = text.replace(entry.getKey(), entry.getValue());
|
||||
}
|
||||
if (viewer == null) {
|
||||
return MiniMessage.miniMessage().deserialize(text, MiniPlaceholders.getAudienceGlobalPlaceholders(player));
|
||||
}
|
||||
|
@ -26,12 +26,13 @@ import io.github.miniplaceholders.api.utils.TagsUtils;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue;
|
||||
import net.william278.velocitab.Velocitab;
|
||||
import net.william278.velocitab.config.Placeholder;
|
||||
import net.william278.velocitab.hook.miniconditions.MiniConditionManager;
|
||||
import net.william278.velocitab.player.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class VelocitabMiniExpansion {
|
||||
@ -96,11 +97,9 @@ public class VelocitabMiniExpansion {
|
||||
return TagsUtils.EMPTY_TAG;
|
||||
}
|
||||
|
||||
final String value = queue.pop().value();
|
||||
final String value = fixValue(popAll(queue));
|
||||
String replaced = Placeholder.replaceInternal(value, plugin, targetPlayer);
|
||||
for (final Map.Entry<String, String> entry : Placeholder.SYMBOL_SUBSTITUTES.entrySet()) {
|
||||
replaced = replaced.replace(entry.getValue(), entry.getKey());
|
||||
}
|
||||
|
||||
return Tag.selfClosingInserting(MiniMessage.miniMessage().deserialize(replaced, MiniPlaceholders.getAudienceGlobalPlaceholders(audience)));
|
||||
}));
|
||||
builder.relationalPlaceholder("vanish", ((a1, otherAudience, queue, ctx) -> {
|
||||
@ -122,4 +121,23 @@ public class VelocitabMiniExpansion {
|
||||
expansion.unregister();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String popAll(@NotNull ArgumentQueue queue) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
int i = 0;
|
||||
while (queue.hasNext()) {
|
||||
if (i > 0) {
|
||||
builder.append(":");
|
||||
}
|
||||
builder.append(queue.pop().value());
|
||||
i++;
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String fixValue(@NotNull String value) {
|
||||
return value.replace("*LESS2*", "<").replace("*GREATER2*", ">");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue;
|
||||
import net.william278.velocitab.Velocitab;
|
||||
import net.william278.velocitab.config.Placeholder;
|
||||
import net.william278.velocitab.hook.MiniPlaceholdersHook;
|
||||
import net.william278.velocitab.player.TabPlayer;
|
||||
import org.apache.commons.jexl3.JexlBuilder;
|
||||
import org.apache.commons.jexl3.JexlContext;
|
||||
@ -43,6 +42,22 @@ import java.util.regex.Pattern;
|
||||
|
||||
public class MiniConditionManager {
|
||||
|
||||
public final static Map<String, String> REPLACE = Map.of(
|
||||
"\"", "-q-",
|
||||
"'", "-a-"
|
||||
);
|
||||
|
||||
public final static Map<String, String> REPLACE_2 = Map.of(
|
||||
"*LESS3*", "<",
|
||||
"*GREATER3*",">",
|
||||
"*LESS2*", "<",
|
||||
"*GREATER2*", ">"
|
||||
);
|
||||
|
||||
private final static Map<String, String> REPLACE_3 = Map.of(
|
||||
"?dp?", ":"
|
||||
);
|
||||
|
||||
private final Velocitab plugin;
|
||||
private final JexlEngine jexlEngine;
|
||||
private final JexlContext jexlContext;
|
||||
@ -82,6 +97,7 @@ public class MiniConditionManager {
|
||||
return Component.empty();
|
||||
}
|
||||
|
||||
|
||||
String condition = decodeCondition(parameters.get(0));
|
||||
if (parameters.size() < 3) {
|
||||
plugin.getLogger().warn("Invalid condition: Missing true/false values for condition: {}", condition);
|
||||
@ -93,8 +109,9 @@ public class MiniConditionManager {
|
||||
return Component.empty();
|
||||
}
|
||||
|
||||
|
||||
condition = Placeholder.replaceInternal(condition, plugin, tabPlayer.get());
|
||||
String falseValue = processFalseValue(parameters.get(2));
|
||||
final String falseValue = processFalseValue(parameters.get(2));
|
||||
final String expression = buildExpression(condition);
|
||||
return evaluateAndFormatCondition(expression, target, audience, parameters.get(1), falseValue);
|
||||
}
|
||||
@ -103,19 +120,25 @@ public class MiniConditionManager {
|
||||
private List<String> collectParameters(@NotNull ArgumentQueue queue) {
|
||||
final List<String> parameters = Lists.newArrayList();
|
||||
while (queue.hasNext()) {
|
||||
parameters.add(queue.pop().value());
|
||||
String param = queue.pop().value();
|
||||
for (Map.Entry<String, String> entry : REPLACE_2.entrySet()) {
|
||||
param = param.replace(entry.getKey(), entry.getValue());
|
||||
}
|
||||
for (Map.Entry<String, String> entry : REPLACE_3.entrySet()) {
|
||||
param = param.replace(entry.getKey(), entry.getValue());
|
||||
}
|
||||
parameters.add(param);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String decodeCondition(@NotNull String condition) {
|
||||
condition = condition.replace("?lt;", "<").replace("?gt;", ">");
|
||||
for (Map.Entry<String, String> entry : MiniPlaceholdersHook.REPLACE.entrySet()) {
|
||||
for (Map.Entry<String, String> entry : REPLACE.entrySet()) {
|
||||
condition = condition.replace(entry.getValue(), entry.getKey());
|
||||
condition = condition.replace(entry.getKey() + entry.getKey(), entry.getKey());
|
||||
}
|
||||
for (Map.Entry<String, String> entry : Placeholder.SYMBOL_SUBSTITUTES.entrySet()) {
|
||||
for (Map.Entry<String, String> entry : REPLACE_2.entrySet()) {
|
||||
condition = condition.replace(entry.getValue(), entry.getKey());
|
||||
}
|
||||
return condition;
|
||||
|
@ -161,16 +161,7 @@ public final class TabPlayer implements Comparable<TabPlayer> {
|
||||
displayName = displayName.replace(placeholder, value);
|
||||
}
|
||||
|
||||
displayName = displayName.replace("\n", "");
|
||||
final boolean isMiniMessage = plugin.getFormatter().equals(Formatter.MINIMESSAGE);
|
||||
if (isMiniMessage) {
|
||||
displayName = Formatter.LEGACY.serialize(MiniMessage.miniMessage().deserialize(displayName));
|
||||
}
|
||||
displayName = Placeholder.replaceInternal(displayName, plugin, this);
|
||||
if (isMiniMessage) {
|
||||
displayName = MiniMessage.miniMessage().serialize(Formatter.LEGACY.deserialize(displayName))
|
||||
.replace("\\<", "<");
|
||||
}
|
||||
return lastDisplayName = displayName;
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ package net.william278.velocitab.tab;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.william278.velocitab.Velocitab;
|
||||
import net.william278.velocitab.config.Placeholder;
|
||||
import net.william278.velocitab.player.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -31,12 +32,14 @@ public record Nametag(@NotNull String prefix, @NotNull String suffix) {
|
||||
|
||||
@NotNull
|
||||
public Component getPrefixComponent(@NotNull Velocitab plugin, @NotNull TabPlayer tabPlayer, @NotNull TabPlayer target) {
|
||||
return plugin.getFormatter().format(prefix, tabPlayer, target, plugin);
|
||||
final String formatted = Placeholder.replaceInternal(prefix, plugin, tabPlayer);
|
||||
return plugin.getFormatter().format(formatted, tabPlayer, target, plugin);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Component getSuffixComponent(@NotNull Velocitab plugin, @NotNull TabPlayer tabPlayer, @NotNull TabPlayer target) {
|
||||
return plugin.getFormatter().format(suffix, tabPlayer, target, plugin);
|
||||
final String formatted = Placeholder.replaceInternal(suffix, plugin, tabPlayer);
|
||||
return plugin.getFormatter().format(formatted, tabPlayer, target, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -286,6 +286,16 @@ public class PlayerTabList {
|
||||
removePlayer(target, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a player from the tab list
|
||||
* @param uuid
|
||||
*/
|
||||
protected void removeTablistUUID(@NotNull UUID uuid) {
|
||||
getPlayers().forEach((key, value) -> {
|
||||
value.getPlayer().getTabList().getEntry(uuid).ifPresent(entry -> value.getPlayer().getTabList().removeEntry(uuid));
|
||||
});
|
||||
}
|
||||
|
||||
protected void removePlayer(@NotNull Player target, @Nullable RegisteredServer server) {
|
||||
final UUID uuid = target.getUniqueId();
|
||||
plugin.getServer().getAllPlayers().forEach(player -> player.getTabList().removeEntry(uuid));
|
||||
|
@ -168,8 +168,9 @@ public class TabListListener {
|
||||
if (player.getCurrentServer().isPresent()) {
|
||||
return;
|
||||
}
|
||||
tabList.removePlayer(player);
|
||||
}).delay(500, TimeUnit.MILLISECONDS).schedule();
|
||||
|
||||
tabList.removeTablistUUID(event.getPlayer().getUniqueId());
|
||||
}).delay(750, TimeUnit.MILLISECONDS).schedule();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
Loading…
Reference in New Issue
Block a user