forked from Upstream/Velocitab
Add plugin metrics and update checker (#46)
This commit is contained in:
parent
c48693d865
commit
e422bf0840
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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"));
|
||||||
|
@ -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();
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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() + ")");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user