diff --git a/Emulator/pom.xml b/Emulator/pom.xml
index 88b0e6a3..17628061 100644
--- a/Emulator/pom.xml
+++ b/Emulator/pom.xml
@@ -6,7 +6,7 @@
com.eu.habbo
Habbo
- 4.2.25
+ 4.2.26
UTF-8
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomChatMessageBubbles.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomChatMessageBubbles.java
index d38133e4..fef00f33 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomChatMessageBubbles.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/rooms/RoomChatMessageBubbles.java
@@ -134,7 +134,18 @@ public class RoomChatMessageBubbles {
}
public static RoomChatMessageBubbles getBubble(int id) {
- return BUBBLES.getOrDefault(id, NORMAL);
+ RoomChatMessageBubbles bubble = BUBBLES.get(id);
+ if (bubble != null) return bubble;
+
+ // Custom chat bubbles (client-side only, e.g. ids 253+) are not registered
+ // above. Instead of falling back to NORMAL (which made them render as the
+ // default bubble), pass the id through so the server relays it as-is and
+ // the client renders its own .bubble- style. Capped to avoid abuse.
+ if (id > 0 && id <= 1000) {
+ return new RoomChatMessageBubbles(id, "CUSTOM_" + id, "", true, false);
+ }
+
+ return NORMAL;
}
private static void registerBubble(RoomChatMessageBubbles bubble) {
diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/handshake/MachineIDEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/handshake/MachineIDEvent.java
index 477fc3c6..64696bf7 100644
--- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/handshake/MachineIDEvent.java
+++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/handshake/MachineIDEvent.java
@@ -1,5 +1,6 @@
package com.eu.habbo.messages.incoming.handshake;
+import com.eu.habbo.Emulator;
import com.eu.habbo.messages.NoAuthMessage;
import com.eu.habbo.messages.incoming.MessageHandler;
import org.slf4j.Logger;
@@ -24,6 +25,15 @@ public class MachineIDEvent extends MessageHandler {
this.client.setMachineId(storedMachineId);
+ // Persist the machine fingerprint onto the user so machine/super bans can
+ // target it (createOfflineUserBan copies users.machine_id). The Nitro client
+ // sends this UniqueID packet right after the SSO ticket, so the Habbo is
+ // normally already loaded by the time we get here.
+ if (!storedMachineId.isEmpty() && this.client.getHabbo() != null && this.client.getHabbo().getHabboInfo() != null) {
+ this.client.getHabbo().getHabboInfo().setMachineID(storedMachineId);
+ Emulator.getThreading().run(this.client.getHabbo());
+ }
+
LOGGER.debug("Setting client MachineId to {}", storedMachineId);
}
}
\ No newline at end of file
diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/handshake/SecureLoginEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/handshake/SecureLoginEvent.java
index 7c7dcf3c..cdebe27d 100644
--- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/handshake/SecureLoginEvent.java
+++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/handshake/SecureLoginEvent.java
@@ -161,6 +161,12 @@ public class SecureLoginEvent extends MessageHandler {
throw new NullPointerException(habbo.getHabboInfo().getUsername() + " has a NON EXISTING RANK!");
}
+ // If the machine fingerprint already arrived (UniqueID before login),
+ // persist it so machine/super bans can target this user.
+ if (this.client.getMachineId() != null && !this.client.getMachineId().isEmpty()) {
+ this.client.getHabbo().getHabboInfo().setMachineID(this.client.getMachineId());
+ }
+
Emulator.getThreading().run(habbo);
Emulator.getGameEnvironment().getHabboManager().addHabbo(habbo);
} catch (Exception e) {