diff --git a/Emulator/src/main/java/com/eu/habbo/messages/PacketManager.java b/Emulator/src/main/java/com/eu/habbo/messages/PacketManager.java index f5dfafa9..971101e6 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/PacketManager.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/PacketManager.java @@ -722,5 +722,7 @@ public class PacketManager { this.registerHandler(Incoming.HousekeepingFindUserByIdEvent, com.eu.habbo.messages.incoming.housekeeping.HousekeepingFindUserByIdEvent.class); this.registerHandler(Incoming.HousekeepingBanUserEvent, com.eu.habbo.messages.incoming.housekeeping.HousekeepingBanUserEvent.class); this.registerHandler(Incoming.HousekeepingUnbanUserEvent, com.eu.habbo.messages.incoming.housekeeping.HousekeepingUnbanUserEvent.class); + this.registerHandler(Incoming.HousekeepingMuteUserEvent, com.eu.habbo.messages.incoming.housekeeping.HousekeepingMuteUserEvent.class); + this.registerHandler(Incoming.HousekeepingKickUserEvent, com.eu.habbo.messages.incoming.housekeeping.HousekeepingKickUserEvent.class); } } diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/Incoming.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/Incoming.java index aaafcf87..194bb517 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/Incoming.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/Incoming.java @@ -466,4 +466,6 @@ public class Incoming { public static final int HousekeepingFindUserByIdEvent = 9101; public static final int HousekeepingBanUserEvent = 9102; public static final int HousekeepingUnbanUserEvent = 9103; + public static final int HousekeepingMuteUserEvent = 9104; + public static final int HousekeepingKickUserEvent = 9105; } diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingKickUserEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingKickUserEvent.java new file mode 100644 index 00000000..acc5d96c --- /dev/null +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingKickUserEvent.java @@ -0,0 +1,60 @@ +package com.eu.habbo.messages.incoming.housekeeping; + +import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.permissions.Permission; +import com.eu.habbo.habbohotel.users.Habbo; +import com.eu.habbo.messages.incoming.MessageHandler; +import com.eu.habbo.messages.outgoing.housekeeping.HousekeepingActionResultComposer; + +/** + * Kick a user out of their current room. Mirrors ModToolManager.kick + * (leave room + alert), but the legacy method gates on ACC_SUPPORTTOOL, + * which would force HK operators to also hold the support-tool permission. + * Replicating the few lines locally keeps the HK module self-gated on + * ACC_HOUSEKEEPING. + */ +public class HousekeepingKickUserEvent extends MessageHandler { + private static final String ACTION_KEY = "user.kick"; + + @Override + public int getRatelimit() { + return 1000; + } + + @Override + public void handle() throws Exception { + if (!this.client.getHabbo().hasPermission(Permission.ACC_HOUSEKEEPING)) { + return; + } + + int userId = this.packet.readInt(); + String reason = this.packet.readString(); + + if (userId <= 0) { + this.client.sendResponse(new HousekeepingActionResultComposer(ACTION_KEY, false, 0, "invalid_input")); + return; + } + + Habbo target = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId); + + if (target == null) { + this.client.sendResponse(new HousekeepingActionResultComposer(ACTION_KEY, false, 0, "user_offline")); + return; + } + + if (target.hasPermission(Permission.ACC_UNKICKABLE)) { + this.client.sendResponse(new HousekeepingActionResultComposer(ACTION_KEY, false, 0, "target_unkickable")); + return; + } + + if (target.getHabboInfo().getCurrentRoom() != null) { + Emulator.getGameEnvironment().getRoomManager().leaveRoom(target, target.getHabboInfo().getCurrentRoom()); + } + + if (reason != null && !reason.isEmpty()) { + target.alert(reason); + } + + this.client.sendResponse(new HousekeepingActionResultComposer(ACTION_KEY, true, userId, "")); + } +} diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingMuteUserEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingMuteUserEvent.java new file mode 100644 index 00000000..ad6cba32 --- /dev/null +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingMuteUserEvent.java @@ -0,0 +1,55 @@ +package com.eu.habbo.messages.incoming.housekeeping; + +import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.permissions.Permission; +import com.eu.habbo.habbohotel.users.Habbo; +import com.eu.habbo.messages.incoming.MessageHandler; +import com.eu.habbo.messages.outgoing.housekeeping.HousekeepingActionResultComposer; + +/** + * Apply an arbitrary-duration in-room mute. Habbo.mute is a session-only + * mute (it stores remaining seconds on the live Habbo object), so the + * target must be online for the action to take effect — when the target + * isn't online the handler returns ok=false with `user_offline` so the + * UI can fall back to ModToolSanctionMute or surface a clear error. + */ +public class HousekeepingMuteUserEvent extends MessageHandler { + private static final String ACTION_KEY = "user.mute"; + private static final int SECONDS_IN_MINUTE = 60; + + @Override + public int getRatelimit() { + return 1000; + } + + @Override + public void handle() throws Exception { + if (!this.client.getHabbo().hasPermission(Permission.ACC_HOUSEKEEPING)) { + return; + } + + int userId = this.packet.readInt(); + String reason = this.packet.readString(); + int minutes = this.packet.readInt(); + + if (userId <= 0 || minutes <= 0) { + this.client.sendResponse(new HousekeepingActionResultComposer(ACTION_KEY, false, 0, "invalid_input")); + return; + } + + Habbo target = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId); + + if (target == null) { + this.client.sendResponse(new HousekeepingActionResultComposer(ACTION_KEY, false, 0, "user_offline")); + return; + } + + target.mute(minutes * SECONDS_IN_MINUTE, false); + + if (reason != null && !reason.isEmpty()) { + target.alert(reason); + } + + this.client.sendResponse(new HousekeepingActionResultComposer(ACTION_KEY, true, userId, "")); + } +}