From e7e92cb8c36d051790f4714b6008c7e9a7f7117b Mon Sep 17 00:00:00 2001 From: ehko Date: Thu, 4 Jun 2026 16:49:20 -0400 Subject: [PATCH] add vanish to here --- .../kewwbec/staff/StaffPermissionsNodes.java | 1 + .../java/net/kewwbec/staff/StaffPlugin.java | 12 +++ .../kewwbec/staff/command/VanishCommand.java | 47 +++++++++ .../staff/listener/VanishHudController.java | 95 +++++++++++++++++++ .../net/kewwbec/staff/ui/VanishStatusHud.java | 29 ++++++ .../KweebecNet_Staff/Hud/VanishStatusHud.ui | 12 +++ 6 files changed, 196 insertions(+) create mode 100644 src/main/java/net/kewwbec/staff/command/VanishCommand.java create mode 100644 src/main/java/net/kewwbec/staff/listener/VanishHudController.java create mode 100644 src/main/java/net/kewwbec/staff/ui/VanishStatusHud.java create mode 100644 src/main/resources/Common/UI/Custom/KweebecNet_Staff/Hud/VanishStatusHud.ui diff --git a/src/main/java/net/kewwbec/staff/StaffPermissionsNodes.java b/src/main/java/net/kewwbec/staff/StaffPermissionsNodes.java index 204954a..98f770a 100644 --- a/src/main/java/net/kewwbec/staff/StaffPermissionsNodes.java +++ b/src/main/java/net/kewwbec/staff/StaffPermissionsNodes.java @@ -17,6 +17,7 @@ public final class StaffPermissionsNodes { public static final String LOOKUP = ROOT + ".lookup"; public static final String HISTORY = ROOT + ".history"; public static final String UI = ROOT + ".ui"; + public static final String VANISH = ROOT + ".vanish"; private StaffPermissionsNodes() { } diff --git a/src/main/java/net/kewwbec/staff/StaffPlugin.java b/src/main/java/net/kewwbec/staff/StaffPlugin.java index 9eba801..7424172 100644 --- a/src/main/java/net/kewwbec/staff/StaffPlugin.java +++ b/src/main/java/net/kewwbec/staff/StaffPlugin.java @@ -143,6 +143,18 @@ public final class StaffPlugin extends JavaPlugin { StaffUIContext uiContext = new StaffUIContext(permissions, punishmentService, staffChat, resolver, punishmentRepo, seenRepo); getCommandRegistry().registerCommand(new StaffUICommand(uiContext)); + net.kewwbec.networkcore.api.VanishService vanish = core.getVanishService(); + if (vanish != null) { + getCommandRegistry().registerCommand(new net.kewwbec.staff.command.VanishCommand(vanish)); + net.kewwbec.staff.listener.VanishHudController hudController = + new net.kewwbec.staff.listener.VanishHudController(vanish); + vanish.addListener(hudController::onVanishChanged); + getEventRegistry().registerGlobal(PlayerReadyEvent.class, hudController::onPlayerReady); + getEventRegistry().registerGlobal(PlayerDisconnectEvent.class, hudController::onPlayerDisconnect); + } else { + LOGGER.at(Level.WARNING).log("Staff: NetworkCore VanishService unavailable, skipping /vanish + HUD"); + } + LOGGER.at(Level.INFO).log("Staff started"); } diff --git a/src/main/java/net/kewwbec/staff/command/VanishCommand.java b/src/main/java/net/kewwbec/staff/command/VanishCommand.java new file mode 100644 index 0000000..336aeb0 --- /dev/null +++ b/src/main/java/net/kewwbec/staff/command/VanishCommand.java @@ -0,0 +1,47 @@ +package net.kewwbec.staff.command; + +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.server.core.Message; +import com.hypixel.hytale.server.core.command.system.CommandContext; +import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand; +import com.hypixel.hytale.server.core.universe.PlayerRef; +import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import net.kewwbec.networkcore.api.VanishService; +import net.kewwbec.staff.StaffPermissionsNodes; + +import javax.annotation.Nonnull; +import java.awt.Color; + +/** + * Toggles vanish for the sender. Cross-server via {@link VanishService}'s bus + * channel — if the sender hops to another server, they remain vanished there. + */ +public final class VanishCommand extends AbstractPlayerCommand { + + private final VanishService vanish; + + public VanishCommand(@Nonnull VanishService vanish) { + super("vanish", "Toggle vanish: hide yourself from non-staff players network-wide"); + this.vanish = vanish; + requirePermission(StaffPermissionsNodes.VANISH); + } + + @Override protected boolean canGeneratePermission() { return false; } + + @Override + protected void execute(@Nonnull CommandContext ctx, + @Nonnull Store store, + @Nonnull Ref ref, + @Nonnull PlayerRef sender, + @Nonnull World world) { + boolean now = !vanish.isVanished(sender.getUuid()); + vanish.setVanished(sender.getUuid(), now); + if (now) { + ctx.sendMessage(Message.raw("You are now vanished. Non-staff can't see you.").color(Color.GREEN)); + } else { + ctx.sendMessage(Message.raw("You are no longer vanished.").color(Color.YELLOW)); + } + } +} diff --git a/src/main/java/net/kewwbec/staff/listener/VanishHudController.java b/src/main/java/net/kewwbec/staff/listener/VanishHudController.java new file mode 100644 index 0000000..160b019 --- /dev/null +++ b/src/main/java/net/kewwbec/staff/listener/VanishHudController.java @@ -0,0 +1,95 @@ +package net.kewwbec.staff.listener; + +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.logger.HytaleLogger; +import com.hypixel.hytale.server.core.event.events.player.PlayerDisconnectEvent; +import com.hypixel.hytale.server.core.event.events.player.PlayerReadyEvent; +import com.hypixel.hytale.server.core.universe.PlayerRef; +import com.hypixel.hytale.server.core.universe.Universe; +import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import net.kewwbec.networkcore.api.VanishService; +import net.kewwbec.staff.ui.VanishStatusHud; + +import javax.annotation.Nonnull; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Level; + +/** + * Owns the per-player {@link VanishStatusHud} lifecycle: shows it when the local + * player vanishes (including remote-origin toggles), hides on unvanish or disconnect, + * shows on initial join if already vanished. + */ +public final class VanishHudController { + + private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); + + private final VanishService vanish; + private final ConcurrentMap active = new ConcurrentHashMap<>(); + + public VanishHudController(@Nonnull VanishService vanish) { + this.vanish = vanish; + } + + public void onPlayerReady(@Nonnull PlayerReadyEvent event) { + Ref ref = event.getPlayerRef(); + if (ref == null || !ref.isValid()) return; + Store store = ref.getStore(); + if (store == null) return; + PlayerRef player = store.getComponent(ref, PlayerRef.getComponentType()); + if (player == null) return; + if (vanish.isVanished(player.getUuid())) { + showFor(player); + } + } + + public void onPlayerDisconnect(@Nonnull PlayerDisconnectEvent event) { + PlayerRef ref = event.getPlayerRef(); + if (ref == null) return; + active.remove(ref.getUuid()); + } + + public void onVanishChanged(@Nonnull UUID uuid, @Nonnull Boolean vanishedNow) { + PlayerRef target = findOnline(uuid); + if (target == null) return; + World world = target.getReference() == null + ? null + : target.getReference().getStore().getExternalData().getWorld(); + Runnable apply = () -> { + try { + if (vanishedNow) showFor(target); + else hideFor(target.getUuid()); + } catch (RuntimeException e) { + ((HytaleLogger.Api) LOGGER.at(Level.WARNING).withCause(e)) + .log("VanishHud apply failed for %s", target.getUsername()); + } + }; + if (world != null) world.execute(apply); + else apply.run(); + } + + private void showFor(@Nonnull PlayerRef player) { + active.computeIfAbsent(player.getUuid(), uuid -> { + VanishStatusHud hud = new VanishStatusHud(player); + hud.update(); + return hud; + }); + } + + private void hideFor(@Nonnull UUID uuid) { + VanishStatusHud hud = active.remove(uuid); + if (hud != null) hud.clear(); + } + + private static PlayerRef findOnline(@Nonnull UUID uuid) { + Universe universe = Universe.get(); + if (universe == null) return null; + for (PlayerRef p : universe.getPlayers()) { + if (p.getUuid().equals(uuid)) return p; + } + return null; + } +} diff --git a/src/main/java/net/kewwbec/staff/ui/VanishStatusHud.java b/src/main/java/net/kewwbec/staff/ui/VanishStatusHud.java new file mode 100644 index 0000000..93584fb --- /dev/null +++ b/src/main/java/net/kewwbec/staff/ui/VanishStatusHud.java @@ -0,0 +1,29 @@ +package net.kewwbec.staff.ui; + +import com.hypixel.hytale.server.core.entity.entities.player.hud.CustomUIHud; +import com.hypixel.hytale.server.core.ui.builder.UICommandBuilder; +import com.hypixel.hytale.server.core.universe.PlayerRef; + +import javax.annotation.Nonnull; + +/** + * Persistent bottom-right "VANISHED" indicator shown to the local staff member + * while their vanish state is on. Toggled by {@link net.kewwbec.staff.listener.VanishHudController}. + */ +public final class VanishStatusHud extends CustomUIHud { + + private static final String UI_FILE = "KweebecNet_Staff/Hud/VanishStatusHud.ui"; + + public VanishStatusHud(@Nonnull PlayerRef playerRef) { + super(playerRef, "KweebecNetVanishStatus", 0); + } + + @Override + protected void build(@Nonnull UICommandBuilder ui) { + ui.append(UI_FILE); + } + + public void clear() { + update(true, new UICommandBuilder()); + } +} diff --git a/src/main/resources/Common/UI/Custom/KweebecNet_Staff/Hud/VanishStatusHud.ui b/src/main/resources/Common/UI/Custom/KweebecNet_Staff/Hud/VanishStatusHud.ui new file mode 100644 index 0000000..5c9dd8c --- /dev/null +++ b/src/main/resources/Common/UI/Custom/KweebecNet_Staff/Hud/VanishStatusHud.ui @@ -0,0 +1,12 @@ +Group #VanishStatusHud { + Anchor: (Bottom: 50, Right: 50, Width: 140, Height: 28); + Background: #1A0808; + OutlineColor: #FF4444; + OutlineSize: 1; + + Label #VanishStatusText { + Anchor: (Full: 0); + Style: (FontSize: 12, TextColor: #FF6666, HorizontalAlignment: Center, VerticalAlignment: Center, RenderBold: true); + Text: "VANISHED"; + } +}