You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-20 15:36:17 +00:00
feat(housekeeping): ban-user with arbitrary duration + ack composer
Adds two new packets: * Incoming 9102 HousekeepingBanUserEvent — reads (userId, reason, hours). Unlike ModToolSanctionBanEvent which only accepts the four fixed Habbo-protocol banType buckets (18h / 7d / 30d / 100y), this one converts the hours arg straight to seconds and feeds them into ModToolManager.ban with ModToolBanType.ACCOUNT and cfhTopic=0. Duration is clamped to 100 years to keep it inside `int` range. * Outgoing 9201 HousekeepingActionResultComposer — generic ack for any HK action (ban / mute / kick / give-credits / room-close / …). Wire shape is (actionKey, ok, actionId, message). The actionKey lets the client filter multiple in-flight actions to the right Promise via `accept`, so concurrent admin operations don't cross-resolve. actionId here is the target user id because ModToolBan doesn't expose the `bans` autoinc id on the object — there's a TODO to swap this for a dedicated housekeeping_log row id once that table goes in. Same ACC_HOUSEKEEPING permission gate as the find-user packets, so operators only need to grant the permission once. `mvn compile` clean.
This commit is contained in:
@@ -720,5 +720,6 @@ public class PacketManager {
|
|||||||
// Housekeeping (in-client admin panel)
|
// Housekeeping (in-client admin panel)
|
||||||
this.registerHandler(Incoming.HousekeepingFindUserByNameEvent, com.eu.habbo.messages.incoming.housekeeping.HousekeepingFindUserByNameEvent.class);
|
this.registerHandler(Incoming.HousekeepingFindUserByNameEvent, com.eu.habbo.messages.incoming.housekeeping.HousekeepingFindUserByNameEvent.class);
|
||||||
this.registerHandler(Incoming.HousekeepingFindUserByIdEvent, com.eu.habbo.messages.incoming.housekeeping.HousekeepingFindUserByIdEvent.class);
|
this.registerHandler(Incoming.HousekeepingFindUserByIdEvent, com.eu.habbo.messages.incoming.housekeeping.HousekeepingFindUserByIdEvent.class);
|
||||||
|
this.registerHandler(Incoming.HousekeepingBanUserEvent, com.eu.habbo.messages.incoming.housekeeping.HousekeepingBanUserEvent.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -464,4 +464,5 @@ public class Incoming {
|
|||||||
// Housekeeping (in-client admin panel) — IDs 9100..9199 reserved
|
// Housekeeping (in-client admin panel) — IDs 9100..9199 reserved
|
||||||
public static final int HousekeepingFindUserByNameEvent = 9100;
|
public static final int HousekeepingFindUserByNameEvent = 9100;
|
||||||
public static final int HousekeepingFindUserByIdEvent = 9101;
|
public static final int HousekeepingFindUserByIdEvent = 9101;
|
||||||
|
public static final int HousekeepingBanUserEvent = 9102;
|
||||||
}
|
}
|
||||||
|
|||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
package com.eu.habbo.messages.incoming.housekeeping;
|
||||||
|
|
||||||
|
import com.eu.habbo.Emulator;
|
||||||
|
import com.eu.habbo.habbohotel.modtool.ModToolBan;
|
||||||
|
import com.eu.habbo.habbohotel.modtool.ModToolBanType;
|
||||||
|
import com.eu.habbo.habbohotel.permissions.Permission;
|
||||||
|
import com.eu.habbo.messages.incoming.MessageHandler;
|
||||||
|
import com.eu.habbo.messages.outgoing.housekeeping.HousekeepingActionResultComposer;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply an arbitrary-duration account ban. Duration is taken in hours
|
||||||
|
* from the wire and converted to seconds for ModToolManager.ban —
|
||||||
|
* unlike ModToolSanctionBanEvent which only accepts the four fixed
|
||||||
|
* Habbo-protocol banType buckets.
|
||||||
|
*/
|
||||||
|
public class HousekeepingBanUserEvent extends MessageHandler {
|
||||||
|
private static final String ACTION_KEY = "user.ban";
|
||||||
|
private static final int SECONDS_IN_HOUR = 3600;
|
||||||
|
// 100-year ceiling, matches ModToolSanctionBanEvent's permanent ban.
|
||||||
|
private static final int MAX_DURATION_SECONDS = 100 * 365 * 24 * 3600;
|
||||||
|
|
||||||
|
@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 hours = this.packet.readInt();
|
||||||
|
|
||||||
|
if (userId <= 0 || hours <= 0) {
|
||||||
|
this.client.sendResponse(new HousekeepingActionResultComposer(ACTION_KEY, false, 0, "invalid_input"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long durationLong = (long) hours * SECONDS_IN_HOUR;
|
||||||
|
int duration = durationLong > MAX_DURATION_SECONDS ? MAX_DURATION_SECONDS : (int) durationLong;
|
||||||
|
|
||||||
|
List<ModToolBan> bans = Emulator.getGameEnvironment().getModToolManager()
|
||||||
|
.ban(userId, this.client.getHabbo(), reason != null ? reason : "", duration, ModToolBanType.ACCOUNT, 0);
|
||||||
|
|
||||||
|
if (bans == null || bans.isEmpty()) {
|
||||||
|
this.client.sendResponse(new HousekeepingActionResultComposer(ACTION_KEY, false, 0, "ban_failed"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModToolBan doesn't expose the `bans` table autoinc id on the
|
||||||
|
// object, so we return the target user id as the actionId — it's
|
||||||
|
// the only stable handle the client can use until a dedicated
|
||||||
|
// housekeeping_log row id supersedes it.
|
||||||
|
this.client.sendResponse(new HousekeepingActionResultComposer(ACTION_KEY, true, userId, ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -588,5 +588,6 @@ public class Outgoing {
|
|||||||
|
|
||||||
// Housekeeping (in-client admin panel) — IDs 9200..9299 reserved
|
// Housekeeping (in-client admin panel) — IDs 9200..9299 reserved
|
||||||
public static final int HousekeepingUserDetailComposer = 9200;
|
public static final int HousekeepingUserDetailComposer = 9200;
|
||||||
|
public static final int HousekeepingActionResultComposer = 9201;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
package com.eu.habbo.messages.outgoing.housekeeping;
|
||||||
|
|
||||||
|
import com.eu.habbo.messages.ServerMessage;
|
||||||
|
import com.eu.habbo.messages.outgoing.MessageComposer;
|
||||||
|
import com.eu.habbo.messages.outgoing.Outgoing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic ack for any housekeeping action (ban, mute, kick, give-credits,
|
||||||
|
* room-close, …). The client matches it back to the originating call via
|
||||||
|
* the `actionKey` field, which lets multiple in-flight actions share the
|
||||||
|
* same event stream without ordering bugs.
|
||||||
|
*/
|
||||||
|
public class HousekeepingActionResultComposer extends MessageComposer {
|
||||||
|
private final String actionKey;
|
||||||
|
private final boolean ok;
|
||||||
|
private final int actionId;
|
||||||
|
private final String message;
|
||||||
|
|
||||||
|
public HousekeepingActionResultComposer(String actionKey, boolean ok, int actionId, String message) {
|
||||||
|
this.actionKey = actionKey != null ? actionKey : "";
|
||||||
|
this.ok = ok;
|
||||||
|
this.actionId = actionId;
|
||||||
|
this.message = message != null ? message : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ServerMessage composeInternal() {
|
||||||
|
this.response.init(Outgoing.HousekeepingActionResultComposer);
|
||||||
|
this.response.appendString(this.actionKey);
|
||||||
|
this.response.appendBoolean(this.ok);
|
||||||
|
this.response.appendInt(this.actionId);
|
||||||
|
this.response.appendString(this.message);
|
||||||
|
|
||||||
|
return this.response;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user