Force clear past vanish states in other plugins
This commit is contained in:
1 parent
d56c34fdd6
commit
34ff8e7443
6 files changed
+145
-3
No files matched your search
@@ -424,6 +424,20 @@ public class SuperVanish extends JavaPlugin implements SuperVanishPlugin {
|
||||
|
||||
public void forceShowAllPlayers() {
|
||||
|
||||
forceShowAllPlayers(false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aggressive when true, also clears legacy (null-plugin-ref) hide state
|
||||
* left behind by plugins using the deprecated
|
||||
* {@code Player#hidePlayer(Player)} API (Essentials is the
|
||||
* common culprit). Only used by {@code /sv cleanup}, which is
|
||||
* the documented escape hatch — normal reload/disable paths
|
||||
* must not touch other plugins' hide state.
|
||||
*/
|
||||
public void forceShowAllPlayers(boolean aggressive) {
|
||||
|
||||
if (visibilityChanger == null) {
|
||||
|
||||
return;
|
||||
@@ -440,7 +454,15 @@ public class SuperVanish extends JavaPlugin implements SuperVanishPlugin {
|
||||
|
||||
}
|
||||
|
||||
BukkitPlayerHidingUtil.showPlayer(subject, viewer, this);
|
||||
if (aggressive) {
|
||||
|
||||
BukkitPlayerHidingUtil.showPlayerAggressive(subject, viewer, this);
|
||||
|
||||
} else {
|
||||
|
||||
BukkitPlayerHidingUtil.showPlayer(subject, viewer, this);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import de.myzelyam.supervanish.SuperVanish;
|
||||
import de.myzelyam.supervanish.commands.CommandAction;
|
||||
@@ -44,16 +45,37 @@ public class Cleanup extends SubCommand {
|
||||
|
||||
}
|
||||
|
||||
// Must run before forceShowAllPlayers: Essentials' setVanished(false)
|
||||
// internally calls the deprecated showPlayer(Player) for every online
|
||||
// user, and we want our aggressive pass to finish after that so nothing
|
||||
// sneaks back in.
|
||||
if (plugin.getPluginHookMgr() != null) {
|
||||
|
||||
plugin.getPluginHookMgr().onCleanup();
|
||||
|
||||
}
|
||||
|
||||
if (plugin.getVisibilityChanger() != null) {
|
||||
|
||||
plugin.forceShowAllPlayers();
|
||||
// Aggressive mode also drops the null-plugin-ref hide that Essentials
|
||||
// and other deprecated-API users leave in CraftPlayer's
|
||||
// invertedVisibilityEntities. Without it, CraftPlayer#canSee still
|
||||
// returns false because the set for the target UUID is non-empty.
|
||||
plugin.forceShowAllPlayers(true);
|
||||
plugin.getVisibilityChanger().getHider().clearHiddenState();
|
||||
|
||||
}
|
||||
|
||||
for (Player online : Bukkit.getOnlinePlayers()) {
|
||||
|
||||
online.removeMetadata("vanished", plugin);
|
||||
for (Plugin other : Bukkit.getPluginManager().getPlugins()) {
|
||||
|
||||
// Each plugin owns its own "vanished" metadata entry; leaving any
|
||||
// of them populated keeps TAB-OG and other consumers treating the
|
||||
// player as vanished even though Vanish-OG has been wiped.
|
||||
online.removeMetadata("vanished", other);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,44 @@ public class EssentialsHook extends PluginHook {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Essentials tracks its own vanish list in {@code getVanishedPlayersNew()} and
|
||||
* re-hides its members from every new joiner via the deprecated
|
||||
* {@code hidePlayer(Player)} API (see EssentialsPlayerListener#onPlayerJoin).
|
||||
* That deprecated call parks a {@code null} plugin ref in CraftPlayer's
|
||||
* invertedVisibilityEntities map, which Vanish-OG's plugin-scoped
|
||||
* {@code showPlayer(Plugin, Player)} cannot clear. So {@code /sv cleanup} must
|
||||
* drive Essentials' state back to "not vanished" on every online user — that's
|
||||
* the only call that removes the entry from Essentials' list *and* fires the
|
||||
* deprecated {@code showPlayer(Player)} that drops the null ref.
|
||||
*/
|
||||
@Override
|
||||
public void onCleanup() {
|
||||
|
||||
if (essentials == null)
|
||||
return;
|
||||
for (Player online : Bukkit.getOnlinePlayers()) {
|
||||
|
||||
try {
|
||||
|
||||
User user = essentials.getUser(online);
|
||||
if (user == null)
|
||||
continue;
|
||||
if (user.isVanished())
|
||||
user.setVanished(false);
|
||||
if (user.isHidden())
|
||||
user.setHidden(false);
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
superVanish.logException(e);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onJoin(PlayerJoinEvent e) {
|
||||
|
||||
|
||||
@@ -36,6 +36,16 @@ public abstract class PluginHook implements Listener {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by {@code /sv cleanup} so hooks can drop any hide state they are
|
||||
* responsible for. Default is a no-op — hooks that keep their own vanish
|
||||
* tracking (Essentials' {@code getVanishedPlayersNew} + deprecated
|
||||
* {@code hidePlayer(Player)} calls) override this to reset it.
|
||||
*/
|
||||
public void onCleanup() {
|
||||
|
||||
}
|
||||
|
||||
public Plugin getPlugin() {
|
||||
|
||||
return plugin;
|
||||
|
||||
@@ -180,4 +180,22 @@ public class PluginHookMgr implements Listener {
|
||||
|
||||
}
|
||||
|
||||
public void onCleanup() {
|
||||
|
||||
for (PluginHook hook : activeHooks) {
|
||||
|
||||
try {
|
||||
|
||||
hook.onCleanup();
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
plugin.logException(e);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -56,6 +56,38 @@ public class BukkitPlayerHidingUtil {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Nuclear show: clears every hide ref that Vanish-OG could plausibly be
|
||||
* responsible for on this (viewer, player) pair. CraftPlayer tracks hides
|
||||
* per-plugin in {@code invertedVisibilityEntities}, and an entity stays hidden
|
||||
* until *all* refs in its set are gone. Essentials'
|
||||
* {@code User#setVanished(true)} and
|
||||
* {@code EssentialsPlayerListener#onPlayerJoin} both call the deprecated
|
||||
* {@code hidePlayer(Player)} form, which registers a {@code null} plugin ref
|
||||
* that Vanish-OG's normal {@code showPlayer(Plugin, Player)} cannot remove — so
|
||||
* {@code /sv cleanup} must also call the deprecated {@code showPlayer(Player)}
|
||||
* to drop it. Without this step, players stay invisible to each other even
|
||||
* after cleanup wipes KeyDB and Vanish-OG's own hide map.
|
||||
*/
|
||||
public static void showPlayerAggressive(Player player, Player viewer, SuperVanish plugin) {
|
||||
|
||||
showPlayer(player, viewer, plugin);
|
||||
if (isNewPlayerHidingAPISupported(plugin)) {
|
||||
|
||||
try {
|
||||
|
||||
Player.class.getMethod("showPlayer", Player.class).invoke(viewer, player);
|
||||
|
||||
} catch (ReflectiveOperationException e) {
|
||||
|
||||
throw new RuntimeException("Failed to legacy-show " + player.getName() + " to " + viewer.getName(), e);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static boolean isNewPlayerHidingAPISupported(SuperVanish plugin) {
|
||||
|
||||
return plugin.getVersionUtil().isOneDotXOrHigher(19);
|
||||
|
||||
Reference in new issue
Block a user