forked from Upstream/Velocitab
Added API and improved vanish system
This commit is contained in:
parent
3d8bdbea49
commit
dd1ec2120f
@ -28,13 +28,13 @@ import com.velocitypowered.api.plugin.Plugin;
|
|||||||
import com.velocitypowered.api.plugin.PluginContainer;
|
import com.velocitypowered.api.plugin.PluginContainer;
|
||||||
import com.velocitypowered.api.plugin.PluginDescription;
|
import com.velocitypowered.api.plugin.PluginDescription;
|
||||||
import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
||||||
import com.velocitypowered.api.proxy.Player;
|
|
||||||
import com.velocitypowered.api.proxy.ProxyServer;
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
import com.velocitypowered.api.scheduler.ScheduledTask;
|
import com.velocitypowered.api.scheduler.ScheduledTask;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.william278.annotaml.Annotaml;
|
import net.william278.annotaml.Annotaml;
|
||||||
import net.william278.desertwell.util.UpdateChecker;
|
import net.william278.desertwell.util.UpdateChecker;
|
||||||
import net.william278.desertwell.util.Version;
|
import net.william278.desertwell.util.Version;
|
||||||
|
import net.william278.velocitab.api.VelocitabAPI;
|
||||||
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;
|
||||||
@ -77,6 +77,7 @@ public class Velocitab {
|
|||||||
private ScoreboardManager scoreboardManager;
|
private ScoreboardManager scoreboardManager;
|
||||||
@Getter
|
@Getter
|
||||||
private VanishManager vanishManager;
|
private VanishManager vanishManager;
|
||||||
|
private VelocitabAPI velocitabAPI;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public Velocitab(@NotNull ProxyServer server, @NotNull Logger logger, @DataDirectory Path dataDirectory) {
|
public Velocitab(@NotNull ProxyServer server, @NotNull Logger logger, @DataDirectory Path dataDirectory) {
|
||||||
@ -95,6 +96,7 @@ public class Velocitab {
|
|||||||
registerCommands();
|
registerCommands();
|
||||||
registerMetrics();
|
registerMetrics();
|
||||||
checkForUpdates();
|
checkForUpdates();
|
||||||
|
prepareAPI();
|
||||||
logger.info("Successfully enabled Velocitab");
|
logger.info("Successfully enabled Velocitab");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,16 +196,8 @@ public class Velocitab {
|
|||||||
server.getEventManager().register(this, tabList);
|
server.getEventManager().register(this, tabList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
private void prepareAPI() {
|
||||||
public TabPlayer getTabPlayer(@NotNull Player player) {
|
VelocitabAPI.register(this);
|
||||||
return new TabPlayer(player,
|
|
||||||
getLuckPermsHook().map(hook -> hook.getPlayerRole(player)).orElse(Role.DEFAULT_ROLE)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public Optional<TabPlayer> getTabPlayer(String name) {
|
|
||||||
return server.getPlayer(name).map(this::getTabPlayer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCommands() {
|
private void registerCommands() {
|
||||||
|
182
src/main/java/net/william278/velocitab/api/VelocitabAPI.java
Normal file
182
src/main/java/net/william278/velocitab/api/VelocitabAPI.java
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Velocitab, licensed under the Apache License 2.0.
|
||||||
|
*
|
||||||
|
* Copyright (c) William278 <will27528@gmail.com>
|
||||||
|
* 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.api;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
import net.william278.velocitab.Velocitab;
|
||||||
|
import net.william278.velocitab.player.TabPlayer;
|
||||||
|
import net.william278.velocitab.tab.PlayerTabList;
|
||||||
|
import net.william278.velocitab.vanish.VanishIntegration;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Velocitab API class.
|
||||||
|
* </p>
|
||||||
|
* Retrieve an instance of the API class via {@link #getInstance()}.
|
||||||
|
*/
|
||||||
|
public class VelocitabAPI {
|
||||||
|
|
||||||
|
// Instance of the plugin
|
||||||
|
private final Velocitab plugin;
|
||||||
|
private static VelocitabAPI instance;
|
||||||
|
|
||||||
|
@ApiStatus.Internal
|
||||||
|
protected VelocitabAPI(@NotNull Velocitab plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entrypoint to the HuskSync API - returns an instance of the API
|
||||||
|
*
|
||||||
|
* @return instance of the HuskSync API
|
||||||
|
* @since 1.5.2
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static VelocitabAPI getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
throw new NotRegisteredException();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <b>(Internal use only)</b> - Register the API for this platform.
|
||||||
|
*
|
||||||
|
* @param plugin the plugin instance
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
@ApiStatus.Internal
|
||||||
|
public static void register(@NotNull Velocitab plugin) {
|
||||||
|
instance = new VelocitabAPI(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <b>(Internal use only)</b> - Unregister the API for this platform.
|
||||||
|
*/
|
||||||
|
@ApiStatus.Internal
|
||||||
|
public static void unregister() {
|
||||||
|
instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an option of {@link TabPlayer} instance for the given velocity {@link Player}.
|
||||||
|
*
|
||||||
|
* @param player the velocity player to get the {@link TabPlayer} instance for
|
||||||
|
* @return the {@link TabPlayer} instance for the given player or an empty optional if the player is not in a group server
|
||||||
|
* @since 2.0
|
||||||
|
*/
|
||||||
|
public Optional<TabPlayer> getUser(@NotNull Player player) {
|
||||||
|
return plugin.getTabList().getTabPlayer(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the custom name for a player.
|
||||||
|
* This will only be visible in the tab list and not in the nametag.
|
||||||
|
*
|
||||||
|
* @param player The player for whom to set the custom name
|
||||||
|
* @param name The custom name to set
|
||||||
|
*/
|
||||||
|
public void setCustomPlayerName(Player player, String name) {
|
||||||
|
getUser(player).ifPresent(tabPlayer -> {
|
||||||
|
tabPlayer.setCustomName(name);
|
||||||
|
plugin.getTabList().updatePlayerDisplayName(tabPlayer);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the custom name of the TabPlayer, if it has been set.
|
||||||
|
*
|
||||||
|
* @param player The player for whom to get the custom name
|
||||||
|
* @return An Optional object containing the custom name, or empty if no custom name has been set.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public Optional<String> getCustomPlayerName(Player player) {
|
||||||
|
return getUser(player).flatMap(TabPlayer::getCustomName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link PlayerTabList} handles the tab list for all players on the server groups.
|
||||||
|
*
|
||||||
|
* @return the {@link PlayerTabList} global instance.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public PlayerTabList getTabList() {
|
||||||
|
return plugin.getTabList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the VanishIntegration for the VelocitabAPI.
|
||||||
|
*
|
||||||
|
* @param vanishIntegration the VanishIntegration to set
|
||||||
|
*/
|
||||||
|
public void setVanishIntegration(VanishIntegration vanishIntegration) {
|
||||||
|
plugin.getVanishManager().setIntegration(vanishIntegration);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the VanishIntegration associated with the VelocitabAPI instance.
|
||||||
|
* This integration allows checking if a player can see another player and if a player is vanished.
|
||||||
|
*
|
||||||
|
* @return The VanishIntegration instance associated with the VelocitabAPI
|
||||||
|
*/
|
||||||
|
public @NotNull VanishIntegration getVanishIntegration() {
|
||||||
|
return plugin.getVanishManager().getIntegration();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vanishes the player by hiding them from the tab list and scoreboard if enabled.
|
||||||
|
*
|
||||||
|
* @param player The player to vanish
|
||||||
|
*/
|
||||||
|
public void vanishPlayer(Player player) {
|
||||||
|
plugin.getVanishManager().vanishPlayer(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unvanishes the given player by showing them in the tab list and scoreboard if enabled.
|
||||||
|
*
|
||||||
|
* @param player The player to unvanish
|
||||||
|
*/
|
||||||
|
public void unvanishPlayer(Player player) {
|
||||||
|
plugin.getVanishManager().unvanishPlayer(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static final class NotRegisteredException extends IllegalStateException {
|
||||||
|
|
||||||
|
private static final String MESSAGE = """
|
||||||
|
Could not access the Velocitab API as it has not yet been registered. This could be because:
|
||||||
|
1) Velocitab has failed to enable successfully
|
||||||
|
2) You are attempting to access Velocitab on plugin construction/before your plugin has enabled.
|
||||||
|
3) You have shaded Velocitab into your plugin jar and need to fix your maven/gradle/build script
|
||||||
|
to only include Velocitab as a dependency and not as a shaded dependency.""";
|
||||||
|
|
||||||
|
NotRegisteredException() {
|
||||||
|
super(MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -20,13 +20,18 @@
|
|||||||
package net.william278.velocitab.commands;
|
package net.william278.velocitab.commands;
|
||||||
|
|
||||||
import com.mojang.brigadier.Command;
|
import com.mojang.brigadier.Command;
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||||
import com.velocitypowered.api.command.BrigadierCommand;
|
import com.velocitypowered.api.command.BrigadierCommand;
|
||||||
import com.velocitypowered.api.command.CommandSource;
|
import com.velocitypowered.api.command.CommandSource;
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
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.about.AboutMenu;
|
import net.william278.desertwell.about.AboutMenu;
|
||||||
import net.william278.velocitab.Velocitab;
|
import net.william278.velocitab.Velocitab;
|
||||||
|
import net.william278.velocitab.api.VelocitabAPI;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public final class VelocitabCommand {
|
public final class VelocitabCommand {
|
||||||
@ -69,6 +74,21 @@ public final class VelocitabCommand {
|
|||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
.then(LiteralArgumentBuilder.<CommandSource>literal("name")
|
||||||
|
.then(RequiredArgumentBuilder.<CommandSource, String>argument("name", StringArgumentType.word())
|
||||||
|
.executes(ctx -> {
|
||||||
|
|
||||||
|
if (!(ctx.getSource() instanceof Player player)) {
|
||||||
|
ctx.getSource().sendMessage(Component.text("You must be a player to use this command!", MAIN_COLOR));
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
String name = StringArgumentType.getString(ctx, "name");
|
||||||
|
VelocitabAPI.getInstance().setCustomPlayerName(player, name);
|
||||||
|
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 -> {
|
||||||
@ -91,7 +111,7 @@ public final class VelocitabCommand {
|
|||||||
}
|
}
|
||||||
ctx.getSource().sendMessage(Component
|
ctx.getSource().sendMessage(Component
|
||||||
.text("An update for velocitab is available. " +
|
.text("An update for velocitab is available. " +
|
||||||
"Please update to " + checked.getLatestVersion(), MAIN_COLOR));
|
"Please update to " + checked.getLatestVersion(), MAIN_COLOR));
|
||||||
});
|
});
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
})
|
})
|
||||||
|
@ -43,7 +43,7 @@ public enum Placeholder {
|
|||||||
.orElse("")),
|
.orElse("")),
|
||||||
CURRENT_DATE((plugin, player) -> DateTimeFormatter.ofPattern("dd MMM yyyy").format(LocalDateTime.now())),
|
CURRENT_DATE((plugin, player) -> DateTimeFormatter.ofPattern("dd MMM yyyy").format(LocalDateTime.now())),
|
||||||
CURRENT_TIME((plugin, player) -> DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now())),
|
CURRENT_TIME((plugin, player) -> DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now())),
|
||||||
USERNAME((plugin, player) -> plugin.getFormatter().escape(player.getPlayer().getUsername())),
|
USERNAME((plugin, player) -> plugin.getFormatter().escape(player.getCustomName().orElse(player.getPlayer().getUsername()))),
|
||||||
SERVER((plugin, player) -> player.getServerDisplayName(plugin)),
|
SERVER((plugin, player) -> player.getServerDisplayName(plugin)),
|
||||||
PING((plugin, player) -> Long.toString(player.getPlayer().getPing())),
|
PING((plugin, player) -> Long.toString(player.getPlayer().getPing())),
|
||||||
PREFIX((plugin, player) -> player.getRole().getPrefix().orElse("")),
|
PREFIX((plugin, player) -> player.getRole().getPrefix().orElse("")),
|
||||||
|
@ -39,7 +39,6 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
public class LuckPermsHook extends Hook {
|
public class LuckPermsHook extends Hook {
|
||||||
|
|
||||||
private int highestWeight = Role.DEFAULT_WEIGHT;
|
|
||||||
private final LuckPerms api;
|
private final LuckPerms api;
|
||||||
private final EventSubscription<UserDataRecalculateEvent> event;
|
private final EventSubscription<UserDataRecalculateEvent> event;
|
||||||
private final Map<UUID, Long> lastUpdate;
|
private final Map<UUID, Long> lastUpdate;
|
||||||
@ -87,13 +86,9 @@ public class LuckPermsHook extends Hook {
|
|||||||
plugin.getServer().getPlayer(event.getUser().getUniqueId())
|
plugin.getServer().getPlayer(event.getUser().getUniqueId())
|
||||||
.ifPresent(player -> plugin.getServer().getScheduler()
|
.ifPresent(player -> plugin.getServer().getScheduler()
|
||||||
.buildTask(plugin, () -> {
|
.buildTask(plugin, () -> {
|
||||||
final TabPlayer updatedPlayer = new TabPlayer(
|
TabPlayer tabPlayer = tabList.getTabPlayer(player).orElseThrow();
|
||||||
player,
|
tabPlayer.setRole(getRoleFromMetadata(event.getData().getMetaData()));
|
||||||
getRoleFromMetadata(event.getData().getMetaData())
|
tabList.updatePlayerDisplayName(tabPlayer);
|
||||||
);
|
|
||||||
tabList.replacePlayer(updatedPlayer);
|
|
||||||
tabList.updatePlayer(updatedPlayer);
|
|
||||||
tabList.updatePlayerDisplayName(updatedPlayer);
|
|
||||||
})
|
})
|
||||||
.delay(500, TimeUnit.MILLISECONDS)
|
.delay(500, TimeUnit.MILLISECONDS)
|
||||||
.schedule());
|
.schedule());
|
||||||
|
@ -74,6 +74,64 @@ public class ScoreboardManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void vanishPlayer(Player player) {
|
||||||
|
if (!plugin.getSettings().doNametags()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Optional<ServerConnection> optionalServerConnection = player.getCurrentServer();
|
||||||
|
if (optionalServerConnection.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final RegisteredServer serverInfo = optionalServerConnection.get().getServer();
|
||||||
|
final List<RegisteredServer> siblings = plugin.getTabList().getGroupServers(serverInfo.getServerInfo().getName());
|
||||||
|
UpdateTeamsPacket packet = UpdateTeamsPacket.removeTeam(plugin, createdTeams.get(player.getUniqueId()));
|
||||||
|
|
||||||
|
siblings.forEach(server -> server.getPlayersConnected().forEach(connected -> {
|
||||||
|
boolean canSee = !plugin.getVanishManager().isVanished(connected.getUsername())
|
||||||
|
|| plugin.getVanishManager().canSee(player.getUsername(), player.getUsername());
|
||||||
|
|
||||||
|
if (!canSee) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatchPacket(packet, connected);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unvanishPlayer(Player player) {
|
||||||
|
if (!plugin.getSettings().doNametags()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Optional<ServerConnection> optionalServerConnection = player.getCurrentServer();
|
||||||
|
if (optionalServerConnection.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final RegisteredServer serverInfo = optionalServerConnection.get().getServer();
|
||||||
|
final List<RegisteredServer> siblings = plugin.getTabList().getGroupServers(serverInfo.getServerInfo().getName());
|
||||||
|
|
||||||
|
final String role = createdTeams.getOrDefault(player.getUniqueId(), "");
|
||||||
|
if (role.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String nametag = nametags.getOrDefault(role, "");
|
||||||
|
if (nametag.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String[] split = nametag.split(NAMETAG_DELIMITER, 2);
|
||||||
|
final String prefix = split[0];
|
||||||
|
final String suffix = split.length > 1 ? split[1] : "";
|
||||||
|
|
||||||
|
final UpdateTeamsPacket packet = UpdateTeamsPacket.create(plugin, createdTeams.get(player.getUniqueId()), "", prefix, suffix, player.getUsername());
|
||||||
|
|
||||||
|
siblings.forEach(server -> server.getPlayersConnected().forEach(connected -> dispatchPacket(packet, connected)));
|
||||||
|
}
|
||||||
|
|
||||||
public void updateRole(@NotNull Player player, @NotNull String role) {
|
public void updateRole(@NotNull Player player, @NotNull String role) {
|
||||||
if (!player.isActive()) {
|
if (!player.isActive()) {
|
||||||
plugin.getTabList().removeOfflinePlayer(player);
|
plugin.getTabList().removeOfflinePlayer(player);
|
||||||
@ -81,7 +139,7 @@ public class ScoreboardManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final String name = player.getUsername();
|
final String name = player.getUsername();
|
||||||
final TabPlayer tabPlayer = plugin.getTabPlayer(player);
|
final TabPlayer tabPlayer = plugin.getTabList().getTabPlayer(player).orElseThrow();
|
||||||
tabPlayer.getNametag(plugin).thenAccept(nametag -> {
|
tabPlayer.getNametag(plugin).thenAccept(nametag -> {
|
||||||
String[] split = nametag.split(player.getUsername(), 2);
|
String[] split = nametag.split(player.getUsername(), 2);
|
||||||
String prefix = split[0];
|
String prefix = split[0];
|
||||||
|
@ -21,11 +21,13 @@ package net.william278.velocitab.player;
|
|||||||
|
|
||||||
import com.velocitypowered.api.proxy.Player;
|
import com.velocitypowered.api.proxy.Player;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.william278.velocitab.Velocitab;
|
import net.william278.velocitab.Velocitab;
|
||||||
import net.william278.velocitab.config.Placeholder;
|
import net.william278.velocitab.config.Placeholder;
|
||||||
import net.william278.velocitab.tab.PlayerTabList;
|
import net.william278.velocitab.tab.PlayerTabList;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.slf4j.event.Level;
|
import org.slf4j.event.Level;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -33,7 +35,8 @@ import java.util.concurrent.CompletableFuture;
|
|||||||
|
|
||||||
public final class TabPlayer implements Comparable<TabPlayer> {
|
public final class TabPlayer implements Comparable<TabPlayer> {
|
||||||
private final Player player;
|
private final Player player;
|
||||||
private final Role role;
|
@Setter
|
||||||
|
private Role role;
|
||||||
@Getter
|
@Getter
|
||||||
private int headerIndex = 0;
|
private int headerIndex = 0;
|
||||||
@Getter
|
@Getter
|
||||||
@ -41,6 +44,8 @@ public final class TabPlayer implements Comparable<TabPlayer> {
|
|||||||
@Getter
|
@Getter
|
||||||
private Component lastDisplayname;
|
private Component lastDisplayname;
|
||||||
private String teamName;
|
private String teamName;
|
||||||
|
@Nullable
|
||||||
|
private String customName;
|
||||||
|
|
||||||
public TabPlayer(@NotNull Player player, @NotNull Role role) {
|
public TabPlayer(@NotNull Player player, @NotNull Role role) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
@ -165,6 +170,25 @@ public final class TabPlayer implements Comparable<TabPlayer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the custom name of the TabPlayer, if it has been set.
|
||||||
|
*
|
||||||
|
* @return An Optional object containing the custom name, or empty if no custom name has been set.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public Optional<String> getCustomName() {
|
||||||
|
return Optional.ofNullable(customName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the custom name of the TabPlayer.
|
||||||
|
*
|
||||||
|
* @param customName The custom name to set
|
||||||
|
*/
|
||||||
|
public void setCustomName(@NotNull String customName) {
|
||||||
|
this.customName = customName;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(@NotNull TabPlayer o) {
|
public int compareTo(@NotNull TabPlayer o) {
|
||||||
final int roleDifference = role.compareTo(o.role);
|
final int roleDifference = role.compareTo(o.role);
|
||||||
|
@ -33,6 +33,7 @@ import com.velocitypowered.api.scheduler.ScheduledTask;
|
|||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.william278.velocitab.Velocitab;
|
import net.william278.velocitab.Velocitab;
|
||||||
import net.william278.velocitab.config.Placeholder;
|
import net.william278.velocitab.config.Placeholder;
|
||||||
|
import net.william278.velocitab.player.Role;
|
||||||
import net.william278.velocitab.player.TabPlayer;
|
import net.william278.velocitab.player.TabPlayer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@ -63,18 +64,17 @@ public class PlayerTabList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<TabPlayer> getTabPlayer(@NotNull Player player) {
|
||||||
|
return players.stream().filter(tabPlayer -> tabPlayer.getPlayer().getUniqueId().equals(player.getUniqueId())).findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("UnstableApiUsage")
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onPlayerJoin(@NotNull ServerPostConnectEvent event) {
|
public void onPlayerJoin(@NotNull ServerPostConnectEvent event) {
|
||||||
final Player joined = event.getPlayer();
|
final Player joined = event.getPlayer();
|
||||||
plugin.getScoreboardManager().ifPresent(manager -> manager.resetCache(joined));
|
plugin.getScoreboardManager().ifPresent(manager -> manager.resetCache(joined));
|
||||||
|
|
||||||
|
|
||||||
// Remove the player from the tracking list if they are switching servers
|
|
||||||
final RegisteredServer previousServer = event.getPreviousServer();
|
final RegisteredServer previousServer = event.getPreviousServer();
|
||||||
if (previousServer != null) {
|
|
||||||
players.removeIf(player -> player.getPlayer().getUniqueId().equals(joined.getUniqueId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the servers in the group from the joined server name
|
// Get the servers in the group from the joined server name
|
||||||
// If the server is not in a group, use fallback
|
// If the server is not in a group, use fallback
|
||||||
@ -91,8 +91,8 @@ public class PlayerTabList {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the player to the tracking list
|
// Add the player to the tracking list if they are not already listed
|
||||||
final TabPlayer tabPlayer = plugin.getTabPlayer(joined);
|
final TabPlayer tabPlayer = getTabPlayer(joined).orElseGet(() -> createTabPlayer(joined));
|
||||||
players.add(tabPlayer);
|
players.add(tabPlayer);
|
||||||
|
|
||||||
boolean isVanished = plugin.getVanishManager().isVanished(joined.getUsername());
|
boolean isVanished = plugin.getVanishManager().isVanished(joined.getUsername());
|
||||||
@ -134,7 +134,7 @@ public class PlayerTabList {
|
|||||||
|
|
||||||
plugin.getScoreboardManager().ifPresent(s -> {
|
plugin.getScoreboardManager().ifPresent(s -> {
|
||||||
s.resendAllNameTags(joined);
|
s.resendAllNameTags(joined);
|
||||||
plugin.getTabPlayer(joined).getTeamName(plugin).thenAccept(t -> s.updateRole(joined, t));
|
tabPlayer.getTeamName(plugin).thenAccept(t -> s.updateRole(joined, t));
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.delay(500, TimeUnit.MILLISECONDS)
|
.delay(500, TimeUnit.MILLISECONDS)
|
||||||
@ -151,6 +151,16 @@ public class PlayerTabList {
|
|||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private TabListEntry createEntry(@NotNull TabPlayer player, @NotNull TabList tabList, Component displayName) {
|
||||||
|
return TabListEntry.builder()
|
||||||
|
.profile(player.getPlayer().getGameProfile())
|
||||||
|
.displayName(displayName)
|
||||||
|
.latency(0)
|
||||||
|
.tabList(tabList)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
private void addPlayerToTabList(@NotNull TabPlayer player, @NotNull TabPlayer newPlayer) {
|
private void addPlayerToTabList(@NotNull TabPlayer player, @NotNull TabPlayer newPlayer) {
|
||||||
if (newPlayer.getPlayer().getUniqueId().equals(player.getPlayer().getUniqueId())) {
|
if (newPlayer.getPlayer().getUniqueId().equals(player.getPlayer().getUniqueId())) {
|
||||||
return;
|
return;
|
||||||
@ -167,6 +177,20 @@ public class PlayerTabList {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addPlayerToTabList(@NotNull TabPlayer player, @NotNull TabPlayer newPlayer, TabListEntry entry) {
|
||||||
|
if (newPlayer.getPlayer().getUniqueId().equals(player.getPlayer().getUniqueId())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean present = player.getPlayer()
|
||||||
|
.getTabList().getEntries().stream()
|
||||||
|
.noneMatch(e -> e.getProfile().getId().equals(newPlayer.getPlayer().getUniqueId()));
|
||||||
|
|
||||||
|
if (present) {
|
||||||
|
player.getPlayer().getTabList().addEntry(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onPlayerQuit(@NotNull DisconnectEvent event) {
|
public void onPlayerQuit(@NotNull DisconnectEvent event) {
|
||||||
if (event.getLoginStatus() != DisconnectEvent.LoginStatus.SUCCESSFUL_LOGIN) {
|
if (event.getLoginStatus() != DisconnectEvent.LoginStatus.SUCCESSFUL_LOGIN) {
|
||||||
@ -196,10 +220,11 @@ public class PlayerTabList {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace a player in the tab list
|
@NotNull
|
||||||
public void replacePlayer(@NotNull TabPlayer tabPlayer) {
|
public TabPlayer createTabPlayer(@NotNull Player player) {
|
||||||
players.removeIf(player -> player.getPlayer().getUniqueId().equals(tabPlayer.getPlayer().getUniqueId()));
|
return new TabPlayer(player,
|
||||||
players.add(tabPlayer);
|
plugin.getLuckPermsHook().map(hook -> hook.getPlayerRole(player)).orElse(Role.DEFAULT_ROLE)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update a player's name in the tab list
|
// Update a player's name in the tab list
|
||||||
@ -231,7 +256,6 @@ public class PlayerTabList {
|
|||||||
players.forEach(player -> {
|
players.forEach(player -> {
|
||||||
|
|
||||||
if (isVanished && !plugin.getVanishManager().canSee(player.getPlayer().getUsername(), tabPlayer.getPlayer().getUsername())) {
|
if (isVanished && !plugin.getVanishManager().canSee(player.getPlayer().getUsername(), tabPlayer.getPlayer().getUsername())) {
|
||||||
System.out.println("Player " + player.getPlayer().getUsername() + " cannot see " + tabPlayer.getPlayer().getUsername());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,4 +391,33 @@ public class PlayerTabList {
|
|||||||
public void removeOfflinePlayer(@NotNull Player player) {
|
public void removeOfflinePlayer(@NotNull Player player) {
|
||||||
players.removeIf(tabPlayer -> tabPlayer.getPlayer().getUniqueId().equals(player.getUniqueId()));
|
players.removeIf(tabPlayer -> tabPlayer.getPlayer().getUniqueId().equals(player.getUniqueId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void vanishPlayer(TabPlayer tabPlayer) {
|
||||||
|
players.forEach(p -> {
|
||||||
|
if (p.getPlayer().equals(tabPlayer.getPlayer())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!plugin.getVanishManager().canSee(p.getPlayer().getUsername(), tabPlayer.getPlayer().getUsername())) {
|
||||||
|
p.getPlayer().getTabList().removeEntry(tabPlayer.getPlayer().getUniqueId());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unvanishPlayer(TabPlayer tabPlayer) {
|
||||||
|
UUID uuid = tabPlayer.getPlayer().getUniqueId();
|
||||||
|
|
||||||
|
tabPlayer.getDisplayName(plugin).thenAccept(c -> {
|
||||||
|
players.forEach(p -> {
|
||||||
|
if (p.getPlayer().equals(tabPlayer.getPlayer())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!p.getPlayer().getTabList().containsEntry(uuid)) {
|
||||||
|
createEntry(tabPlayer, p.getPlayer().getTabList(), c);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,17 +22,11 @@ package net.william278.velocitab.vanish;
|
|||||||
public class DefaultVanishIntegration implements VanishIntegration {
|
public class DefaultVanishIntegration implements VanishIntegration {
|
||||||
@Override
|
@Override
|
||||||
public boolean canSee(String name, String otherName) {
|
public boolean canSee(String name, String otherName) {
|
||||||
if (otherName.equals("AlexDev_") && name.equals("AlexDalf03")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isVanished(String name) {
|
public boolean isVanished(String name) {
|
||||||
if (name.equals("AlexDev_")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,9 +19,13 @@
|
|||||||
|
|
||||||
package net.william278.velocitab.vanish;
|
package net.william278.velocitab.vanish;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
import net.william278.velocitab.Velocitab;
|
import net.william278.velocitab.Velocitab;
|
||||||
|
import net.william278.velocitab.player.TabPlayer;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class VanishManager {
|
public class VanishManager {
|
||||||
|
|
||||||
@ -30,11 +34,15 @@ public class VanishManager {
|
|||||||
|
|
||||||
public VanishManager(Velocitab plugin) {
|
public VanishManager(Velocitab plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
setIntegration(null);
|
setIntegration(new DefaultVanishIntegration());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIntegration(VanishIntegration integration) {
|
public void setIntegration(@NotNull VanishIntegration integration) {
|
||||||
this.integration = Objects.requireNonNullElseGet(integration, DefaultVanishIntegration::new);
|
this.integration = integration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull VanishIntegration getIntegration() {
|
||||||
|
return integration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canSee(String name, String otherName) {
|
public boolean canSee(String name, String otherName) {
|
||||||
@ -45,12 +53,25 @@ public class VanishManager {
|
|||||||
return integration.isVanished(name);
|
return integration.isVanished(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void vanishPlayer(Player player) {
|
||||||
|
Optional<TabPlayer> tabPlayer = plugin.getTabList().getTabPlayer(player);
|
||||||
|
|
||||||
public void vanish(String name) {
|
if(tabPlayer.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.getTabList().vanishPlayer(tabPlayer.get());
|
||||||
|
plugin.getScoreboardManager().ifPresent(scoreboardManager -> scoreboardManager.vanishPlayer(player));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unvanish(String name) {
|
public void unvanishPlayer(Player player) {
|
||||||
|
Optional<TabPlayer> tabPlayer = plugin.getTabList().getTabPlayer(player);
|
||||||
|
|
||||||
|
if(tabPlayer.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.getTabList().unvanishPlayer(tabPlayer.get());
|
||||||
|
plugin.getScoreboardManager().ifPresent(scoreboardManager -> scoreboardManager.unvanishPlayer(player));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user