diff --git a/build.gradle b/build.gradle
index d677eaa..6a8a967 100644
--- a/build.gradle
+++ b/build.gradle
@@ -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'
}
diff --git a/docs/Animations.md b/docs/Animations.md
index 7afb23f..caf9e43 100644
--- a/docs/Animations.md
+++ b/docs/Animations.md
@@ -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'
+ - 'Running Velocitab by William278 & AlexDev_'
+ - 'Running Velocitab by William278 & AlexDev_'
+ - 'Running Velocitab by William278 & AlexDev_'
```
@@ -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'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
+ - 'Velocitab ⭐ A super-simple (sorted!) Velocity TAB menu plugin\n'
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%'
+ \nFor Velocity proxy servers:
+ https://modrinth.com/plugin/velocitab
+ https://william278.net/project/veloictab'
+format: '[%server%] &f%username%'
header_footer_update_rate: 200
```
In config.yml
```yaml
-formatter: MINEDOWN
+formatter: MINIMESSAGE
```
diff --git a/docs/Config-File.md b/docs/Config-File.md
index 6a5e8d7..de47b82 100644
--- a/docs/Config-File.md
+++ b/docs/Config-File.md
@@ -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:
+ - Running Velocitab by William278 & AlexDev_
+ footers:
+ - There are currently %players_online%/%max_players_online% players online
+ format: [%server%] %prefix%%username%
+ nametag:
+ prefix: %prefix%
+ suffix: %suffix%
+ 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
```
diff --git a/docs/Formatting.md b/docs/Formatting.md
index ca0d106..9425af8 100644
--- a/docs/Formatting.md
+++ b/docs/Formatting.md
@@ -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!
diff --git a/docs/Nametags.md b/docs/Nametags.md
index 590d221..01d183b 100644
--- a/docs/Nametags.md
+++ b/docs/Nametags.md
@@ -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/).
+
+
+
diff --git a/docs/Server-Groups.md b/docs/Server-Groups.md
index 1088993..73c2c28 100644
--- a/docs/Server-Groups.md
+++ b/docs/Server-Groups.md
@@ -17,9 +17,9 @@ rate to use for the group.
```yaml
headers:
- - '&rainbow&Running Velocitab by William278'
+ - 'Running Velocitab by William278 & AlexDev_'
footers:
- - '[There are currently %players_online%/%max_players_online% players online](gray)'
+ - 'There are currently %players_online%/%max_players_online% players online'
```
@@ -35,7 +35,7 @@ information.
Example of format
```yaml
- format: '&7[%server%] &f%prefix%%username%'
+ format: '[%server%] %prefix%%username%'
```
@@ -51,8 +51,8 @@ Player formats may only utilize one line.
```yaml
nametag:
- prefix: '&f%prefix%'
- suffix: '&f%suffix%'
+ prefix: '%prefix%'
+ suffix: '%suffix%'
```
@@ -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!'
+ - 'Running Velocitab by William278 & AlexDev_ on Lobbies!'
footers:
- - '[There are currently %players_online%/%max_players_online% players online](gray)'
- format: '&7[%server%] &f%prefix%%username%'
+ - 'There are currently %players_online%/%max_players_online% players online'
+ format: '[%server%] %prefix%%username%'
servers:
- lobby
- hub
@@ -165,10 +165,10 @@ groups:
placeholder_update_rate: 1000
- name: creative
headers:
- - '&rainbow&Running Velocitab by William278 on Creative!'
+ - 'Running Velocitab by William278 & AlexDev_ on Creative!'
footers:
- - '[There are currently %players_online%/%max_players_online% players online](gray)'
- format: '&7[%server%] &f%prefix%%username%'
+ - 'There are currently %players_online%/%max_players_online% players online'
+ format: '[%server%] %prefix%%username%'
servers:
- creative
sorting_placeholders:
@@ -178,10 +178,10 @@ groups:
placeholder_update_rate: 1000
- name: survival
headers:
- - '&rainbow&Running Velocitab by William278 on Survival!'
+ - 'Running Velocitab by William278 & AlexDev_ on Survival!'
footers:
- - '[There are currently %players_online%/%max_players_online% players online](gray)'
- format: '&7[%server%] &f%prefix%%username%'
+ - 'There are currently %players_online%/%max_players_online% players online'
+ format: '[%server%] %prefix%%username%'
servers:
- survival
sorting_placeholders:
diff --git a/src/main/java/net/william278/velocitab/Velocitab.java b/src/main/java/net/william278/velocitab/Velocitab.java
index b9b12ea..74bba41 100644
--- a/src/main/java/net/william278/velocitab/Velocitab.java
+++ b/src/main/java/net/william278/velocitab/Velocitab.java
@@ -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);
diff --git a/src/main/java/net/william278/velocitab/config/Formatter.java b/src/main/java/net/william278/velocitab/config/Formatter.java
index 6d93121..9948cdb 100644
--- a/src/main/java/net/william278/velocitab/config/Formatter.java
+++ b/src/main/java/net/william278/velocitab/config/Formatter.java
@@ -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",
diff --git a/src/main/java/net/william278/velocitab/config/Placeholder.java b/src/main/java/net/william278/velocitab/config/Placeholder.java
index b01571b..1fb3321 100644
--- a/src/main/java/net/william278/velocitab/config/Placeholder.java
+++ b/src/main/java/net/william278/velocitab/config/Placeholder.java
@@ -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("");
+ private final static Pattern TEST = Pattern.compile("<.*?>");
+ private final static Pattern CONDITION_REPLACER = Pattern.compile("");
private final static String DELIMITER = ":::";
- private final static String REL_SUBSTITUTE = "-REL-";
- public final static Map SYMBOL_SUBSTITUTES = Map.of(
- "<", "-COND-1",
- ">", "-COND-2"
+ private final static Map SYMBOL_SUBSTITUTES = Map.of(
+ "<", "*LESS*",
+ ">", "*GREATER*"
+ );
+ private final static Map 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 processRelationalPlaceholders(@NotNull String format, @NotNull Velocitab plugin) {
boolean foundRelational = false;
- if (format.contains(" entry : MiniConditionManager.REPLACE.entrySet()) {
+ condition = condition.replace(entry.getKey(), entry.getValue());
+ }
+ for (Map.Entry 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(" 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 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 entry : SYMBOL_SUBSTITUTES_2.entrySet()) {
+ fixedString = fixedString.replace(entry.getKey(), entry.getValue());
+ }
format = format.replace(relationalPlaceholder, fixedString);
}
- format = processConditionalPlaceholders(format);
+ for (Map.Entry 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 entry : SYMBOL_SUBSTITUTES.entrySet()) {
- fixedString = fixedString.replace(entry.getKey(), entry.getValue());
- }
- return fixedString;
- }
-
public static CompletableFuture replace(@NotNull String format, @NotNull Velocitab plugin,
@NotNull TabPlayer player) {
diff --git a/src/main/java/net/william278/velocitab/config/ServerUrl.java b/src/main/java/net/william278/velocitab/config/ServerUrl.java
index c4274a3..b4c519f 100644
--- a/src/main/java/net/william278/velocitab/config/ServerUrl.java
+++ b/src/main/java/net/william278/velocitab/config/ServerUrl.java
@@ -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;
diff --git a/src/main/java/net/william278/velocitab/config/Settings.java b/src/main/java/net/william278/velocitab/config/Settings.java
index 7fb0587..3e11c17 100644
--- a/src/main/java/net/william278/velocitab/config/Settings.java
+++ b/src/main/java/net/william278/velocitab/config/Settings.java
@@ -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 serverLinks = List.of(
new ServerUrl(
- "fb9a&About Velocitab",
+ "<#00fb9a>About Velocitab#00fb9a>",
"https://william278.net/project/velocitab"
)
);
diff --git a/src/main/java/net/william278/velocitab/config/TabGroups.java b/src/main/java/net/william278/velocitab/config/TabGroups.java
index 0ea7a39..6a65239 100644
--- a/src/main/java/net/william278/velocitab/config/TabGroups.java
+++ b/src/main/java/net/william278/velocitab/config/TabGroups.java
@@ -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("Running Velocitab by William278 & AlexDev_"),
+ List.of("There are currently %players_online%/%max_players_online% players online"),
+ "[%server%] %prefix%%username%",
+ new Nametag("%prefix%", "%suffix%"),
Set.of("lobby", "survival", "creative", "minigames", "skyblock", "prison", "hub"),
List.of("%role_weight%", "%username_lower%"),
false,
diff --git a/src/main/java/net/william278/velocitab/hook/MiniPlaceholdersHook.java b/src/main/java/net/william278/velocitab/hook/MiniPlaceholdersHook.java
index 323af75..3b3c61e 100644
--- a/src/main/java/net/william278/velocitab/hook/MiniPlaceholdersHook.java
+++ b/src/main/java/net/william278/velocitab/hook/MiniPlaceholdersHook.java
@@ -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 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 entry : REPLACE.entrySet()) {
- text = text.replace(entry.getKey(), entry.getValue());
- }
if (viewer == null) {
return MiniMessage.miniMessage().deserialize(text, MiniPlaceholders.getAudienceGlobalPlaceholders(player));
}
diff --git a/src/main/java/net/william278/velocitab/hook/VelocitabMiniExpansion.java b/src/main/java/net/william278/velocitab/hook/VelocitabMiniExpansion.java
index 7e25748..8b767d6 100644
--- a/src/main/java/net/william278/velocitab/hook/VelocitabMiniExpansion.java
+++ b/src/main/java/net/william278/velocitab/hook/VelocitabMiniExpansion.java
@@ -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 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*", ">");
+ }
+
}
diff --git a/src/main/java/net/william278/velocitab/hook/miniconditions/MiniConditionManager.java b/src/main/java/net/william278/velocitab/hook/miniconditions/MiniConditionManager.java
index b55c011..dee4a22 100644
--- a/src/main/java/net/william278/velocitab/hook/miniconditions/MiniConditionManager.java
+++ b/src/main/java/net/william278/velocitab/hook/miniconditions/MiniConditionManager.java
@@ -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 REPLACE = Map.of(
+ "\"", "-q-",
+ "'", "-a-"
+ );
+
+ public final static Map REPLACE_2 = Map.of(
+ "*LESS3*", "<",
+ "*GREATER3*",">",
+ "*LESS2*", "<",
+ "*GREATER2*", ">"
+ );
+
+ private final static Map 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 collectParameters(@NotNull ArgumentQueue queue) {
final List parameters = Lists.newArrayList();
while (queue.hasNext()) {
- parameters.add(queue.pop().value());
+ String param = queue.pop().value();
+ for (Map.Entry entry : REPLACE_2.entrySet()) {
+ param = param.replace(entry.getKey(), entry.getValue());
+ }
+ for (Map.Entry 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 entry : MiniPlaceholdersHook.REPLACE.entrySet()) {
+ for (Map.Entry entry : REPLACE.entrySet()) {
condition = condition.replace(entry.getValue(), entry.getKey());
condition = condition.replace(entry.getKey() + entry.getKey(), entry.getKey());
}
- for (Map.Entry entry : Placeholder.SYMBOL_SUBSTITUTES.entrySet()) {
+ for (Map.Entry entry : REPLACE_2.entrySet()) {
condition = condition.replace(entry.getValue(), entry.getKey());
}
return condition;
diff --git a/src/main/java/net/william278/velocitab/player/TabPlayer.java b/src/main/java/net/william278/velocitab/player/TabPlayer.java
index c7e8e69..5fb521b 100644
--- a/src/main/java/net/william278/velocitab/player/TabPlayer.java
+++ b/src/main/java/net/william278/velocitab/player/TabPlayer.java
@@ -161,16 +161,7 @@ public final class TabPlayer implements Comparable {
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;
}
diff --git a/src/main/java/net/william278/velocitab/tab/Nametag.java b/src/main/java/net/william278/velocitab/tab/Nametag.java
index 2d80a38..cd29b25 100644
--- a/src/main/java/net/william278/velocitab/tab/Nametag.java
+++ b/src/main/java/net/william278/velocitab/tab/Nametag.java
@@ -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
diff --git a/src/main/java/net/william278/velocitab/tab/PlayerTabList.java b/src/main/java/net/william278/velocitab/tab/PlayerTabList.java
index d96fbaa..e61de01 100644
--- a/src/main/java/net/william278/velocitab/tab/PlayerTabList.java
+++ b/src/main/java/net/william278/velocitab/tab/PlayerTabList.java
@@ -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));
diff --git a/src/main/java/net/william278/velocitab/tab/TabListListener.java b/src/main/java/net/william278/velocitab/tab/TabListListener.java
index 70a2345..083e263 100644
--- a/src/main/java/net/william278/velocitab/tab/TabListListener.java
+++ b/src/main/java/net/william278/velocitab/tab/TabListListener.java
@@ -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