From 82d90418cd24970ba578fa710a8105837b04910f Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Tue, 19 May 2026 20:20:08 +0200 Subject: [PATCH] feat(commands): :update_permissions broadcasts refreshed UserPermissionsComposer to every online client MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `PermissionsManager.reload()` rebuilds the rank table from `permission_ranks` + `permission_definitions`, but every Habbo currently online still holds a reference to the OLD `Rank` object on `HabboInfo.rank`. Server-side `hasPermission()` therefore keeps returning stale results, and any Nitro client that reads permission state from the wire keeps gating UI on the map shipped at login — until a relogin or `:give_rank` forces a per-user refresh. Extend the existing `UpdatePermissionsCommand` so after `reload()` it: 1. Iterates the online Habbos via `HabboManager.getOnlineHabbos()`. 2. Re-binds each one's `HabboInfo.rank` to the FRESH `Rank` object returned by `PermissionsManager.getRank(currentRankId)`. Falls back to rank 1 if the admin deleted the rank from `permission_ranks` between sessions, so the user is never left with a null `Rank` reference. 3. Sends a fresh `UserPermissionsComposer` to each client. With the companion composer extension PR also merged, this broadcasts the rank metadata + resolved permission map runtime — the Nitro React-side `useHasPermission(key)` / `useUserRank()` consumers re-render against the freshly-loaded tables without requiring an F5. The whisper feedback now reports how many connected users were refreshed, useful for ops feedback after a large `permission_ranks` edit. Defensive null guards on habbo / habboInfo / client survive transient state during the broadcast (e.g. a user disconnecting mid-iteration). --- .../commands/UpdatePermissionsCommand.java | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/commands/UpdatePermissionsCommand.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/commands/UpdatePermissionsCommand.java index 9f257bdd..b2efc3df 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/commands/UpdatePermissionsCommand.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/commands/UpdatePermissionsCommand.java @@ -2,7 +2,12 @@ package com.eu.habbo.habbohotel.commands; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.gameclients.GameClient; +import com.eu.habbo.habbohotel.permissions.PermissionsManager; +import com.eu.habbo.habbohotel.permissions.Rank; import com.eu.habbo.habbohotel.rooms.RoomChatMessageBubbles; +import com.eu.habbo.habbohotel.users.Habbo; +import com.eu.habbo.habbohotel.users.HabboManager; +import com.eu.habbo.messages.outgoing.users.UserPermissionsComposer; public class UpdatePermissionsCommand extends Command { public UpdatePermissionsCommand() { @@ -13,7 +18,41 @@ public class UpdatePermissionsCommand extends Command { public boolean handle(GameClient gameClient, String[] params) throws Exception { Emulator.getGameEnvironment().getPermissionsManager().reload(); - gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.succes.cmd_update_permissions"), RoomChatMessageBubbles.ALERT); + // PermissionsManager.reload() rebuilt the rank table — each online + // Habbo's HabboInfo still references the OLD Rank object, so + // server-side hasPermission() / wire composers would keep + // reporting stale data until relogin. Re-bind every connected + // user to the freshly-loaded Rank by id, then ship the new + // UserPermissionsComposer (which carries clubLevel, + // securityLevel, isAmbassador, rank metadata and the resolved + // permission_definitions map) so Nitro clients' React-side + // useHasPermission(key) / useUserRank() / useUserPermissions() + // consumers re-render against the updated tables without an F5. + HabboManager habboManager = Emulator.getGameEnvironment().getHabboManager(); + PermissionsManager permissions = Emulator.getGameEnvironment().getPermissionsManager(); + + int refreshed = 0; + + for (Habbo habbo : habboManager.getOnlineHabbos().values()) { + if (habbo == null || habbo.getHabboInfo() == null || habbo.getClient() == null) continue; + + int currentRankId = habbo.getHabboInfo().getRank().getId(); + // Defensive fallback: if the admin deleted the rank from the + // permission_ranks table between sessions, fall back to rank 1 + // (Member) so the user isn't stranded with a null Rank. + Rank freshRank = permissions.rankExists(currentRankId) + ? permissions.getRank(currentRankId) + : permissions.getRank(1); + + habbo.getHabboInfo().setRank(freshRank); + habbo.getClient().sendResponse(new UserPermissionsComposer(habbo)); + refreshed++; + } + + gameClient.getHabbo().whisper( + Emulator.getTexts().getValue("commands.succes.cmd_update_permissions") + " (" + refreshed + " online refreshed)", + RoomChatMessageBubbles.ALERT + ); return true; }