diff --git a/src/main/java/net/william278/velocitab/Velocitab.java b/src/main/java/net/william278/velocitab/Velocitab.java index 5743471..ca1066f 100644 --- a/src/main/java/net/william278/velocitab/Velocitab.java +++ b/src/main/java/net/william278/velocitab/Velocitab.java @@ -28,6 +28,7 @@ import com.velocitypowered.api.plugin.Plugin; import com.velocitypowered.api.plugin.PluginContainer; import com.velocitypowered.api.plugin.PluginDescription; import com.velocitypowered.api.plugin.annotation.DataDirectory; +import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.scheduler.ScheduledTask; import lombok.Getter; @@ -45,6 +46,7 @@ import net.william278.velocitab.hook.PAPIProxyBridgeHook; import net.william278.velocitab.packet.ScoreboardManager; import net.william278.velocitab.player.Role; import net.william278.velocitab.player.TabPlayer; +import net.william278.velocitab.sorting.SortingManager; import net.william278.velocitab.tab.PlayerTabList; import net.william278.velocitab.vanish.VanishManager; import org.bstats.charts.SimplePie; @@ -75,6 +77,7 @@ public class Velocitab { private PlayerTabList tabList; private List hooks; private ScoreboardManager scoreboardManager; + private SortingManager sortingManager; @Getter private VanishManager vanishManager; @@ -91,6 +94,7 @@ public class Velocitab { loadHooks(); prepareScoreboardManager(); prepareTabList(); + prepareSortingManager(); prepareVanishManager(); registerCommands(); registerMetrics(); @@ -181,6 +185,15 @@ public class Velocitab { this.vanishManager = new VanishManager(this); } + private void prepareSortingManager() { + this.sortingManager = new SortingManager(this); + } + + @NotNull + public SortingManager getSortingManager() { + return sortingManager; + } + @NotNull public Optional getScoreboardManager() { return Optional.ofNullable(scoreboardManager); diff --git a/src/main/java/net/william278/velocitab/player/Role.java b/src/main/java/net/william278/velocitab/player/Role.java index dde0d2b..f88ece7 100644 --- a/src/main/java/net/william278/velocitab/player/Role.java +++ b/src/main/java/net/william278/velocitab/player/Role.java @@ -23,10 +23,7 @@ import lombok.Getter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; public class Role implements Comparable { public static final int DEFAULT_WEIGHT = 0; @@ -73,29 +70,9 @@ public class Role implements Comparable { @NotNull protected String getWeightString() { - return compressNumber(Integer.MAX_VALUE / 4d - weight); + return Integer.toString(weight); } - public String compressNumber(double number) { - int wholePart = (int) number; - final char decimalChar = (char) ((number - wholePart) * Character.MAX_VALUE); - - final List charList = new ArrayList<>(); - - while (wholePart > 0) { - char digit = (char) (wholePart % Character.MAX_VALUE); - - charList.add(0, digit); - - wholePart /= Character.MAX_VALUE; - } - - if (charList.isEmpty()) { - charList.add((char) 0); - } - - return charList.stream().map(String::valueOf).collect(Collectors.joining()) + decimalChar; - } } diff --git a/src/main/java/net/william278/velocitab/player/TabPlayer.java b/src/main/java/net/william278/velocitab/player/TabPlayer.java index 8a7148f..c6ad001 100644 --- a/src/main/java/net/william278/velocitab/player/TabPlayer.java +++ b/src/main/java/net/william278/velocitab/player/TabPlayer.java @@ -27,8 +27,6 @@ import net.william278.velocitab.Velocitab; import net.william278.velocitab.config.Placeholder; import net.william278.velocitab.tab.PlayerTabList; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.slf4j.event.Level; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -131,19 +129,8 @@ public final class TabPlayer implements Comparable { @NotNull public CompletableFuture getTeamName(@NotNull Velocitab plugin) { - if (!plugin.getSettings().isSortPlayers()) { - return CompletableFuture.completedFuture(""); - } - - final String sortingFormat = String.join("", plugin.getSettings().getSortingElements()); - return Placeholder.replace(sortingFormat, plugin, this) // Replace placeholders - .thenApply(formatted -> formatted.length() > 12 ? formatted.substring(0, 12) : formatted) // Truncate - .thenApply(truncated -> truncated + getPlayer().getUniqueId().toString().substring(0, 4)) // Make unique - .thenApply(teamName -> this.teamName = teamName) - .exceptionally(e -> { - plugin.log(Level.ERROR, "Failed to get team name for " + player.getUsername(), e); - return ""; - }); + return plugin.getSortingManager().getTeamName(this) + .thenApply(teamName -> this.teamName = teamName); } public Optional getLastTeamName() { diff --git a/src/main/java/net/william278/velocitab/sorting/SortingManager.java b/src/main/java/net/william278/velocitab/sorting/SortingManager.java new file mode 100644 index 0000000..1dc7a85 --- /dev/null +++ b/src/main/java/net/william278/velocitab/sorting/SortingManager.java @@ -0,0 +1,103 @@ +/* + * This file is part of Velocitab, licensed under the Apache License 2.0. + * + * Copyright (c) William278 + * Copyright (c) contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.william278.velocitab.sorting; + +import net.william278.velocitab.Velocitab; +import net.william278.velocitab.config.Placeholder; +import net.william278.velocitab.player.TabPlayer; +import org.slf4j.event.Level; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +public class SortingManager { + + private final Velocitab plugin; + private static final String DELIMITER = ":::"; + + public SortingManager(Velocitab plugin) { + this.plugin = plugin; + } + + public CompletableFuture getTeamName(TabPlayer player) { + if (!plugin.getSettings().isSortPlayers()) { + return CompletableFuture.completedFuture(""); + } + + return Placeholder.replace(String.join(DELIMITER, plugin.getSettings().getSortingElements()), plugin, player) + .thenApply(s -> Arrays.asList(s.split(DELIMITER))) + .thenApply(v -> v.stream().map(this::adaptValue).collect(Collectors.toList())) + .thenApply(v -> handleList(player, v)); + } + + private String handleList(TabPlayer player, List values) { + String result = String.join("", values); + + if (result.length() > 12) { + result = result.substring(0, 12); + plugin.log(Level.WARN, "Sorting element list is too long, truncating to 16 characters"); + } + + result += player.getPlayer().getUniqueId().toString().substring(0, 4); // Make unique + + return result; + } + + private String adaptValue(String value) { + if (value.isEmpty()) { + return ""; + } + + if (value.matches("[0-9]+")) { + double parsed = Double.parseDouble(value); + return compressNumber(Integer.MAX_VALUE / 4d - parsed); + } + + if (value.length() > 6) { + return value.substring(0, 4); + } + + return value; + } + + public String compressNumber(double number) { + int wholePart = (int) number; + final char decimalChar = (char) ((number - wholePart) * Character.MAX_VALUE); + final List charList = new ArrayList<>(); + + while (wholePart > 0) { + char digit = (char) (wholePart % Character.MAX_VALUE); + + charList.add(0, digit); + + wholePart /= Character.MAX_VALUE; + } + + if (charList.isEmpty()) { + charList.add((char) 0); + } + + return charList.stream().map(String::valueOf).collect(Collectors.joining()) + decimalChar; + } +} +