Add plugin metrics and update checker (#46)

This commit is contained in:
William 2023-04-21 00:22:07 +01:00 committed by GitHub
parent c48693d865
commit e422bf0840
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 215 additions and 91 deletions

View File

@ -47,7 +47,7 @@ You can include [placeholders](https://william278.net/docs/velocitab/placeholder
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. 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.
### Command ### Command
You can use the `/velocitab reload` command to reload the plugin config file (permission: `velocitab.command.reload`) You can use the `/velocitab reload` command to reload the plugin config file (permission: `velocitab.command.reload`), and `/velocitab update` to check for updates (permission: `velocitab.command.update`).
## Building ## Building
To build Velocitab, simply run the following in the root of the repository: To build Velocitab, simply run the following in the root of the repository:
@ -64,8 +64,9 @@ Velocitab is licensed under the Apache 2.0 license.
## Links ## Links
* **[Website](https://william278.net/project/velocitab)** — Visit my website! * **[Website](https://william278.net/project/velocitab)** — Visit my website!
* **[Docs](https://william278.net/docs/velocitab)** — Read the plugin docs! * **[Docs](https://william278.net/docs/velocitab)** — Read the plugin docs!
* **[Modrinth](https://modrinth.com/plugin/velocitab)** — View the plugin Modrinth page
* **[Issues](https://github.com/WiIIiam278/Velocitab/issues)** — File a bug report or feature request
* **[Discord](https://discord.com/invite/tVYhJfyDWG)** — Get support, ask questions! * **[Discord](https://discord.com/invite/tVYhJfyDWG)** — Get support, ask questions!
* **[GitHub](https://github.com/WiIIiam278/Velocitab)** — Check out the plugin source code!
--- ---
© [William278](https://william278.net/), 2023. Licensed under the Apache-2.0 License. © [William278](https://william278.net/), 2023. Licensed under the Apache-2.0 License.

View File

@ -38,7 +38,8 @@ dependencies {
implementation 'net.william278:Annotaml:2.0.1' implementation 'net.william278:Annotaml:2.0.1'
implementation 'dev.dejvokep:boosted-yaml:1.3.1' implementation 'dev.dejvokep:boosted-yaml:1.3.1'
implementation 'de.themoep:minedown-adventure:1.7.2-SNAPSHOT' implementation 'de.themoep:minedown-adventure:1.7.2-SNAPSHOT'
implementation 'net.william278:DesertWell:1.1.1' implementation 'net.william278:DesertWell:2.0.2'
implementation 'org.bstats:bstats-velocity:3.0.2'
annotationProcessor 'org.projectlombok:lombok:1.18.26' annotationProcessor 'org.projectlombok:lombok:1.18.26'
} }
@ -70,6 +71,8 @@ shadowJar {
relocate 'dev.dejvokep.boostedyaml', 'net.william278.velocitab.libraries.boostedyaml' relocate 'dev.dejvokep.boostedyaml', 'net.william278.velocitab.libraries.boostedyaml'
relocate 'net.william278.annotaml', 'net.william278.velocitab.libraries.annotaml' relocate 'net.william278.annotaml', 'net.william278.velocitab.libraries.annotaml'
relocate 'net.william278.desertwell', 'net.william278.velocitab.libraries.desertwell' relocate 'net.william278.desertwell', 'net.william278.velocitab.libraries.desertwell'
relocate 'org.json', 'net.william278.velocitab.libraries.json'
relocate 'org.bstats', 'net.william278.velocitab.libraries.bstats'
dependencies { dependencies {
//noinspection GroovyAssignabilityCheck //noinspection GroovyAssignabilityCheck

View File

@ -30,53 +30,64 @@ import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.ProxyServer;
import net.william278.annotaml.Annotaml; import net.william278.annotaml.Annotaml;
import net.william278.desertwell.util.UpdateChecker;
import net.william278.desertwell.util.Version;
import net.william278.velocitab.commands.VelocitabCommand; import net.william278.velocitab.commands.VelocitabCommand;
import net.william278.velocitab.config.Formatter; import net.william278.velocitab.config.Formatter;
import net.william278.velocitab.config.Settings; import net.william278.velocitab.config.Settings;
import net.william278.velocitab.hook.Hook; import net.william278.velocitab.hook.Hook;
import net.william278.velocitab.hook.LuckPermsHook; import net.william278.velocitab.hook.LuckPermsHook;
import net.william278.velocitab.hook.MiniPlaceholdersHook; import net.william278.velocitab.hook.MiniPlaceholdersHook;
import net.william278.velocitab.hook.PapiHook; import net.william278.velocitab.hook.PAPIProxyBridgeHook;
import net.william278.velocitab.packet.ScoreboardManager; import net.william278.velocitab.packet.ScoreboardManager;
import net.william278.velocitab.player.Role; import net.william278.velocitab.player.Role;
import net.william278.velocitab.player.TabPlayer; import net.william278.velocitab.player.TabPlayer;
import net.william278.velocitab.tab.PlayerTabList; import net.william278.velocitab.tab.PlayerTabList;
import org.bstats.charts.SimplePie;
import org.bstats.velocity.Metrics;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.event.Level;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Plugin(id = "velocitab") @Plugin(id = "velocitab")
public class Velocitab { public class Velocitab {
private static final int METRICS_ID = 18247;
private Settings settings; private Settings settings;
private final ProxyServer server; private final ProxyServer server;
private final Logger logger; private final Logger logger;
private final Path dataDirectory; private final Path dataDirectory;
@Inject @Inject
private PluginContainer pluginContainer; private PluginContainer pluginContainer;
@Inject
private Metrics.Factory metricsFactory;
private PlayerTabList tabList; private PlayerTabList tabList;
private List<Hook> hooks; private List<Hook> hooks;
private ScoreboardManager scoreboardManager; private ScoreboardManager scoreboardManager;
@Inject @Inject
public Velocitab(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) { public Velocitab(@NotNull ProxyServer server, @NotNull Logger logger, @DataDirectory Path dataDirectory) {
this.server = server; this.server = server;
this.logger = logger; this.logger = logger;
this.dataDirectory = dataDirectory; this.dataDirectory = dataDirectory;
} }
@Subscribe @Subscribe
public void onProxyInitialization(ProxyInitializeEvent event) { public void onProxyInitialization(@NotNull ProxyInitializeEvent event) {
loadSettings(); loadSettings();
loadHooks(); loadHooks();
prepareScoreboardManager(); prepareScoreboardManager();
prepareTabList(); prepareTabList();
registerCommands(); registerCommands();
registerMetrics();
checkForUpdates();
logger.info("Successfully enabled Velocitab"); logger.info("Successfully enabled Velocitab");
} }
@ -113,12 +124,12 @@ public class Velocitab {
.findFirst(); .findFirst();
} }
public Optional<LuckPermsHook> getLuckPerms() { public Optional<LuckPermsHook> getLuckPermsHook() {
return getHook(LuckPermsHook.class); return getHook(LuckPermsHook.class);
} }
public Optional<PapiHook> getPapiHook() { public Optional<PAPIProxyBridgeHook> getPAPIProxyBridgeHook() {
return getHook(PapiHook.class); return getHook(PAPIProxyBridgeHook.class);
} }
public Optional<MiniPlaceholdersHook> getMiniPlaceholdersHook() { public Optional<MiniPlaceholdersHook> getMiniPlaceholdersHook() {
@ -155,23 +166,11 @@ public class Velocitab {
@NotNull @NotNull
public TabPlayer getTabPlayer(@NotNull Player player) { public TabPlayer getTabPlayer(@NotNull Player player) {
return new TabPlayer(player, return new TabPlayer(player,
getLuckPerms().map(hook -> hook.getPlayerRole(player)) getLuckPermsHook().map(hook -> hook.getPlayerRole(player)).orElse(Role.DEFAULT_ROLE),
.orElse(Role.DEFAULT_ROLE), getLuckPermsHook().map(LuckPermsHook::getHighestWeight).orElse(0)
getLuckPerms().map(LuckPermsHook::getHighestWeight)
.orElse(0));
}
public void log(@NotNull String message, @NotNull Throwable... exceptions) {
Arrays.stream(exceptions).findFirst().ifPresentOrElse(
exception -> logger.error(message, exception),
() -> logger.warn(message)
); );
} }
public PluginDescription getDescription() {
return pluginContainer.getDescription();
}
private void registerCommands() { private void registerCommands() {
final BrigadierCommand command = new VelocitabCommand(this).command(); final BrigadierCommand command = new VelocitabCommand(this).command();
server.getCommandManager().register( server.getCommandManager().register(
@ -179,4 +178,69 @@ public class Velocitab {
command command
); );
} }
@NotNull
public PluginDescription getDescription() {
return pluginContainer.getDescription();
}
@NotNull
public Version getVersion() {
return Version.fromString(getDescription().getVersion().orElseThrow(), "-");
}
private void registerMetrics() {
final Metrics metrics = metricsFactory.make(this, METRICS_ID);
metrics.addCustomChart(new SimplePie("sort_players", () -> settings.isSortPlayers() ? "Enabled" : "Disabled"));
metrics.addCustomChart(new SimplePie("formatter_type", () -> settings.getFormatter().getName()));
metrics.addCustomChart(new SimplePie("using_luckperms", () -> getLuckPermsHook().isPresent() ? "Yes" : "No"));
metrics.addCustomChart(new SimplePie("using_papiproxybridge", () -> getPAPIProxyBridgeHook().isPresent() ? "Yes" : "No"));
metrics.addCustomChart(new SimplePie("using_miniplaceholders", () -> getMiniPlaceholdersHook().isPresent() ? "Yes" : "No"));
}
private void checkForUpdates() {
if (!getSettings().isCheckForUpdates()) {
return;
}
getUpdateChecker().check().thenAccept(checked -> {
if (!checked.isUpToDate()) {
log(Level.WARN, "A new version of Velocitab is available: " + checked.getLatestVersion());
}
});
}
@NotNull
public UpdateChecker getUpdateChecker() {
return UpdateChecker.builder()
.currentVersion(getVersion())
.endpoint(UpdateChecker.Endpoint.MODRINTH)
.resource("velocitab")
.build();
}
public void log(@NotNull Level level, @NotNull String message, @NotNull Throwable... exceptions) {
switch (level) {
case ERROR -> {
if (exceptions.length > 0) {
logger.error(message, exceptions[0]);
} else {
logger.error(message);
}
}
case WARN -> {
if (exceptions.length > 0) {
logger.warn(message, exceptions[0]);
} else {
logger.warn(message);
}
}
case INFO -> logger.info(message);
}
}
public void log(@NotNull String message) {
this.log(Level.INFO, message);
}
} }

View File

@ -25,62 +25,81 @@ import com.velocitypowered.api.command.BrigadierCommand;
import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.CommandSource;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextColor;
import net.william278.desertwell.AboutMenu; import net.william278.desertwell.about.AboutMenu;
import net.william278.desertwell.Version;
import net.william278.velocitab.Velocitab; import net.william278.velocitab.Velocitab;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public final class VelocitabCommand { public final class VelocitabCommand {
private static final TextColor MAIN_COLOR = TextColor.color(0x00FB9A);
private final AboutMenu aboutMenu; private final AboutMenu aboutMenu;
private final Velocitab plugin; private final Velocitab plugin;
public VelocitabCommand(final @NotNull Velocitab plugin) { public VelocitabCommand(final @NotNull Velocitab plugin) {
this.plugin = plugin; this.plugin = plugin;
this.aboutMenu = AboutMenu.create("Velocitab") this.aboutMenu = AboutMenu.builder()
.withDescription(plugin.getDescription().getDescription().orElseThrow()) .title(Component.text("Velocitab"))
.withVersion(Version.fromString(plugin.getDescription().getVersion().orElseThrow(), "-")) .description(Component.text(plugin.getDescription().getDescription().orElseThrow()))
.addAttribution("Author", .version(plugin.getVersion())
AboutMenu.Credit.of("William278").withDescription("Click to visit website").withUrl("https://william278.net")) .credits("Author",
.addAttribution("Contributors", AboutMenu.Credit.of("William278").description("Click to visit website").url("https://william278.net"))
AboutMenu.Credit.of("Ironboundred").withDescription("Coding"), .credits("Contributors",
AboutMenu.Credit.of("Emibergo02").withDescription("Coding"), AboutMenu.Credit.of("Ironboundred").description("Coding"),
AboutMenu.Credit.of("FreeMonoid").withDescription("Coding"), AboutMenu.Credit.of("Emibergo02").description("Coding"),
AboutMenu.Credit.of("4drian3d").withDescription("Coding")) AboutMenu.Credit.of("FreeMonoid").description("Coding"),
.addButtons( AboutMenu.Credit.of("4drian3d").description("Coding"))
AboutMenu.Link.of("https://william278.net/docs/velocitab").withText("Docs").withIcon(""), .buttons(
AboutMenu.Link.of("https://discord.gg/tVYhJfyDWG").withText("Discord").withIcon("").withColor("#6773f5"), AboutMenu.Link.of("https://william278.net/docs/velocitab").text("Docs").icon(""),
AboutMenu.Link.of("https://modrinth.com/plugin/velocitab").withText("Modrinth").withIcon("").withColor("#589143")); AboutMenu.Link.of("https://discord.gg/tVYhJfyDWG").text("Discord").icon("").color(TextColor.color(0x6773f5)),
AboutMenu.Link.of("https://modrinth.com/plugin/velocitab").text("Modrinth").icon("").color(TextColor.color(0x589143)))
.build();
} }
@NotNull
public BrigadierCommand command() { public BrigadierCommand command() {
final LiteralArgumentBuilder<CommandSource> builder = LiteralArgumentBuilder final LiteralArgumentBuilder<CommandSource> builder = LiteralArgumentBuilder
.<CommandSource>literal("velocitab") .<CommandSource>literal("velocitab")
.executes(ctx -> { .executes(ctx -> {
sendAboutInfo(ctx.getSource()); sendAboutInfo(ctx.getSource());
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
}) })
.then(LiteralArgumentBuilder.<CommandSource>literal("about") .then(LiteralArgumentBuilder.<CommandSource>literal("about")
.executes(ctx -> { .executes(ctx -> {
sendAboutInfo(ctx.getSource()); sendAboutInfo(ctx.getSource());
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
}) })
) )
.then(LiteralArgumentBuilder.<CommandSource>literal("reload") .then(LiteralArgumentBuilder.<CommandSource>literal("reload")
.requires(src -> src.hasPermission("velocitab.command.reload")) .requires(src -> src.hasPermission("velocitab.command.reload"))
.executes(ctx -> { .executes(ctx -> {
plugin.loadSettings(); plugin.loadSettings();
plugin.getTabList().reloadUpdate(); plugin.getTabList().reloadUpdate();
ctx.getSource().sendMessage(Component.text( ctx.getSource().sendMessage(Component.text(
"Velocitab has been reloaded!", "Velocitab has been reloaded!",
TextColor.color(255, 199, 31))); MAIN_COLOR));
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
}) })
); )
.then(LiteralArgumentBuilder.<CommandSource>literal("update")
.requires(src -> src.hasPermission("velocitab.command.update"))
.executes(ctx -> {
plugin.getUpdateChecker().check().thenAccept(checked -> {
if (checked.isUpToDate()) {
ctx.getSource().sendMessage(Component
.text("Velocitab is up to date! (Running v" + plugin.getVersion() + ")", MAIN_COLOR));
return;
}
ctx.getSource().sendMessage(Component
.text("An update for velocitab is available. " +
"Please update to " + checked.getLatestVersion(), MAIN_COLOR));
});
return Command.SINGLE_SUCCESS;
})
);
return new BrigadierCommand(builder); return new BrigadierCommand(builder);
} }
private void sendAboutInfo(CommandSource source) { private void sendAboutInfo(@NotNull CommandSource source) {
source.sendMessage(aboutMenu.toMineDown().toComponent()); source.sendMessage(aboutMenu.toComponent());
} }
} }

View File

@ -35,14 +35,28 @@ import java.util.function.Function;
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public enum Formatter { public enum Formatter {
MINEDOWN((text, player, plugin) -> new MineDown(text).toComponent(), MINEDOWN(
(text) -> text.replace("__", "_\\_")), (text, player, plugin) -> new MineDown(text).toComponent(),
MINIMESSAGE((text, player, plugin) -> plugin.getMiniPlaceholdersHook() (text) -> text.replace("__", "_\\_"),
.map(hook -> hook.format(text, player.getPlayer())) "MineDown"
.orElse(MiniMessage.miniMessage().deserialize(text)), ),
(text) -> MiniMessage.miniMessage().escapeTags(text)), MINIMESSAGE(
LEGACY((text, player, plugin) -> LegacyComponentSerializer.legacyAmpersand().deserialize(text), (text, player, plugin) -> plugin.getMiniPlaceholdersHook()
Function.identity()); .map(hook -> hook.format(text, player.getPlayer()))
.orElse(MiniMessage.miniMessage().deserialize(text)),
(text) -> MiniMessage.miniMessage().escapeTags(text),
"MiniMessage"
),
LEGACY(
(text, player, plugin) -> LegacyComponentSerializer.legacyAmpersand().deserialize(text),
Function.identity(),
"Legacy Text"
);
/**
* Name of the formatter
*/
private final String name;
/** /**
* Function to apply formatting to a string * Function to apply formatting to a string
@ -53,9 +67,11 @@ public enum Formatter {
*/ */
private final Function<String, String> escaper; private final Function<String, String> escaper;
Formatter(@NotNull TriFunction<String, TabPlayer, Velocitab, Component> formatter, @NotNull Function<String, String> escaper) { Formatter(@NotNull TriFunction<String, TabPlayer, Velocitab, Component> formatter, @NotNull Function<String, String> escaper,
@NotNull String name) {
this.formatter = formatter; this.formatter = formatter;
this.escaper = escaper; this.escaper = escaper;
this.name = name;
} }
@NotNull @NotNull
@ -68,4 +84,9 @@ public enum Formatter {
return escaper.apply(text); return escaper.apply(text);
} }
@NotNull
public String getName() {
return name;
}
} }

View File

@ -64,8 +64,8 @@ public enum Placeholder {
} }
final String replaced = format; final String replaced = format;
return plugin.getPapiHook() return plugin.getPAPIProxyBridgeHook()
.map(hook -> hook.formatPapiPlaceholders(replaced, player.getPlayer())) .map(hook -> hook.formatPlaceholders(replaced, player.getPlayer()))
.orElse(CompletableFuture.completedFuture(replaced)); .orElse(CompletableFuture.completedFuture(replaced));
} }

View File

@ -36,9 +36,15 @@ import java.util.Map;
Velocitab Config Velocitab Config
Developed by William278 Developed by William278
Placeholders: %players_online%, %max_players_online%, %local_players_online%, %current_date%, %current_time%, %username%, %server%, %ping%, %prefix%, %suffix%, %role%""") Information: https://william278.net/project/velocitab
Documentation: https://william278.net/docs/velocitab""")
public class Settings { public class Settings {
@Getter
@YamlKey("check_for_updates")
@YamlComment("Check for updates on startup")
private boolean checkForUpdates = true;
@YamlKey("headers") @YamlKey("headers")
@YamlComment("Header(s) to display above the TAB list for each server group.\nList multiple headers and set update_rate to the number of ticks between frames for basic animations") @YamlComment("Header(s) to display above the TAB list for each server group.\nList multiple headers and set update_rate to the number of ticks between frames for basic animations")
private Map<String, List<String>> headers = Map.of("default", List.of("&rainbow&Running Velocitab by William278")); private Map<String, List<String>> headers = Map.of("default", List.of("&rainbow&Running Velocitab by William278"));

View File

@ -21,6 +21,7 @@ package net.william278.velocitab.hook;
import net.william278.velocitab.Velocitab; import net.william278.velocitab.Velocitab;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.slf4j.event.Level;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -35,7 +36,7 @@ public abstract class Hook {
plugin.log("Successfully hooked into LuckPerms"); plugin.log("Successfully hooked into LuckPerms");
return Optional.of(new LuckPermsHook(plugin)); return Optional.of(new LuckPermsHook(plugin));
} catch (Exception e) { } catch (Exception e) {
plugin.log("LuckPerms hook was not loaded: " + e.getMessage(), e); plugin.log(Level.WARN, "LuckPerms hook was not loaded: " + e.getMessage(), e);
} }
} }
return Optional.empty(); return Optional.empty();
@ -44,9 +45,9 @@ public abstract class Hook {
if (isPluginAvailable(plugin, "papiproxybridge") && plugin.getSettings().isEnablePapiHook()) { if (isPluginAvailable(plugin, "papiproxybridge") && plugin.getSettings().isEnablePapiHook()) {
try { try {
plugin.log("Successfully hooked into PAPIProxyBridge"); plugin.log("Successfully hooked into PAPIProxyBridge");
return Optional.of(new PapiHook(plugin)); return Optional.of(new PAPIProxyBridgeHook(plugin));
} catch (Exception e) { } catch (Exception e) {
plugin.log("PAPIProxyBridge hook was not loaded: " + e.getMessage(), e); plugin.log(Level.WARN, "PAPIProxyBridge hook was not loaded: " + e.getMessage(), e);
} }
} }
return Optional.empty(); return Optional.empty();
@ -57,7 +58,7 @@ public abstract class Hook {
plugin.log("Successfully hooked into MiniPlaceholders"); plugin.log("Successfully hooked into MiniPlaceholders");
return Optional.of(new MiniPlaceholdersHook(plugin)); return Optional.of(new MiniPlaceholdersHook(plugin));
} catch (Exception e) { } catch (Exception e) {
plugin.log("MiniPlaceholders hook was not loaded: " + e.getMessage(), e); plugin.log(Level.WARN, "MiniPlaceholders hook was not loaded: " + e.getMessage(), e);
} }
} }
return Optional.empty(); return Optional.empty();

View File

@ -26,16 +26,16 @@ import org.jetbrains.annotations.NotNull;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public class PapiHook extends Hook { public class PAPIProxyBridgeHook extends Hook {
private final PlaceholderAPI api; private final PlaceholderAPI api;
public PapiHook(@NotNull Velocitab plugin) { public PAPIProxyBridgeHook(@NotNull Velocitab plugin) {
super(plugin); super(plugin);
this.api = PlaceholderAPI.getInstance(); this.api = PlaceholderAPI.getInstance();
} }
public CompletableFuture<String> formatPapiPlaceholders(@NotNull String input, @NotNull Player player) { public CompletableFuture<String> formatPlaceholders(@NotNull String input, @NotNull Player player) {
return api.formatPlaceholders(input, player.getUniqueId()); return api.formatPlaceholders(input, player.getUniqueId());
} }

View File

@ -25,11 +25,13 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.StateRegistry; import com.velocitypowered.proxy.protocol.StateRegistry;
import net.william278.velocitab.Velocitab; import net.william278.velocitab.Velocitab;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.slf4j.event.Level;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.velocitypowered.api.network.ProtocolVersion.*; import static com.velocitypowered.api.network.ProtocolVersion.*;
public class ScoreboardManager { public class ScoreboardManager {
private final Velocitab plugin; private final Velocitab plugin;
@ -90,7 +92,7 @@ public class ScoreboardManager {
final ConnectedPlayer connectedPlayer = (ConnectedPlayer) player; final ConnectedPlayer connectedPlayer = (ConnectedPlayer) player;
connectedPlayer.getConnection().write(packet); connectedPlayer.getConnection().write(packet);
} catch (Exception e) { } catch (Exception e) {
plugin.log("Failed to dispatch packet (is the client or server modded or using an illegal version?)", e); plugin.log(Level.ERROR, "Failed to dispatch packet (is the client or server modded or using an illegal version?)", e);
} }
} }
@ -109,7 +111,7 @@ public class ScoreboardManager {
.mapping(0x5A, MINECRAFT_1_19_4, false) .mapping(0x5A, MINECRAFT_1_19_4, false)
.register(); .register();
} catch (Throwable e) { } catch (Throwable e) {
plugin.log("Failed to register UpdateTeamsPacket", e); plugin.log(Level.ERROR, "Failed to register UpdateTeamsPacket", e);
} }
} }

View File

@ -226,7 +226,9 @@ public class PlayerTabList {
.schedule(); .schedule();
} }
// Update all players since there was a reload of the config /**
* Update the TAB list for all players when a plugin or proxy reload is performed
*/
public void reloadUpdate() { public void reloadUpdate() {
if (players.isEmpty()) { if (players.isEmpty()) {
return; return;
@ -248,9 +250,10 @@ public class PlayerTabList {
} }
/** /**
* Get the servers in the same group as the given server * Get the servers in the same group as the given server, as an optional
* If the server is not in a group, use fallback * <p>
* If fallback is disabled, return empty * If the server is not in a group, use the fallback group
* If the fallback is disabled, return an empty optional
* *
* @param serverName The server name * @param serverName The server name
* @return The servers in the same group as the given server, empty if the server is not in a group and fallback is disabled * @return The servers in the same group as the given server, empty if the server is not in a group and fallback is disabled
@ -279,8 +282,12 @@ public class PlayerTabList {
plugin.log("Velocitab has been reloaded!"); plugin.log("Velocitab has been reloaded!");
} }
/**
* Remove an offline player from the list of tracked TAB players
*
* @param player The player to remove
*/
public void removeOfflinePlayer(@NotNull Player player) { public void removeOfflinePlayer(@NotNull Player player) {
// Try and remove the player from the list of players
if (!players.removeIf(tabPlayer -> tabPlayer.getPlayer().getUniqueId().equals(player.getUniqueId()))) { if (!players.removeIf(tabPlayer -> tabPlayer.getPlayer().getUniqueId().equals(player.getUniqueId()))) {
plugin.log("Failed to remove offline player " + player.getUsername() + " (UUID: " + player.getUniqueId() + ")"); plugin.log("Failed to remove offline player " + player.getUsername() + " (UUID: " + player.getUniqueId() + ")");
} }