From 0ceeb5ca702e9241c4361ce5a2e85097713c2981 Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Wed, 17 Jun 2026 18:15:08 +0200 Subject: [PATCH] fix(wired): tolerate legacy furni data --- .../wired/WiredLegacyDataGuard.java | 48 +++++++++++++++++++ .../wired/effects/WiredEffectTeleport.java | 10 ++-- .../wired/effects/WiredEffectToggleFurni.java | 10 ++-- .../wired/WiredLegacyDataGuardTest.java | 26 ++++++++++ 4 files changed, 81 insertions(+), 13 deletions(-) create mode 100644 Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/WiredLegacyDataGuard.java create mode 100644 Emulator/src/test/java/com/eu/habbo/habbohotel/items/interactions/wired/WiredLegacyDataGuardTest.java diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/WiredLegacyDataGuard.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/WiredLegacyDataGuard.java new file mode 100644 index 00000000..4ec20d49 --- /dev/null +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/WiredLegacyDataGuard.java @@ -0,0 +1,48 @@ +package com.eu.habbo.habbohotel.items.interactions.wired; + +import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.users.HabboItem; + +import java.util.ArrayList; +import java.util.List; + +public final class WiredLegacyDataGuard { + public static final int DEFAULT_MAX_DELAY = 20; + + private WiredLegacyDataGuard() { + } + + public static int parseDelay(String value) { + try { + int parsed = Integer.parseInt(value == null ? "" : value.trim()); + return Math.max(0, Math.min(parsed, DEFAULT_MAX_DELAY)); + } catch (NumberFormatException e) { + return 0; + } + } + + public static List parseRoomItems(String value, Room room) { + List items = new ArrayList<>(); + if (room == null || value == null || value.isBlank()) { + return items; + } + + for (String part : value.split(";")) { + try { + int itemId = Integer.parseInt(part.trim()); + if (itemId <= 0) { + continue; + } + + HabboItem item = room.getHabboItem(itemId); + if (item != null) { + items.add(item); + } + } catch (NumberFormatException e) { + // Ignore malformed legacy ids and keep loading the remaining items. + } + } + + return items; + } +} diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTeleport.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTeleport.java index 6a5e4b59..3c0207d1 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTeleport.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTeleport.java @@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger; +import com.eu.habbo.habbohotel.items.interactions.wired.WiredLegacyDataGuard; import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings; import com.eu.habbo.habbohotel.pets.RideablePet; import com.eu.habbo.habbohotel.rooms.*; @@ -287,16 +288,11 @@ public class WiredEffectTeleport extends InteractionWiredEffect { String[] wiredDataOld = wiredData.split("\t"); if (wiredDataOld.length >= 1) { - this.setDelay(Integer.parseInt(wiredDataOld[0])); + this.setDelay(WiredLegacyDataGuard.parseDelay(wiredDataOld[0])); } if (wiredDataOld.length == 2) { if (wiredDataOld[1].contains(";")) { - for (String s : wiredDataOld[1].split(";")) { - HabboItem item = room.getHabboItem(Integer.parseInt(s)); - - if (item != null) - this.items.add(item); - } + this.items.addAll(WiredLegacyDataGuard.parseRoomItems(wiredDataOld[1], room)); } } this.fastTeleport = false; diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectToggleFurni.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectToggleFurni.java index 6aa3a078..19d9fd3d 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectToggleFurni.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectToggleFurni.java @@ -15,6 +15,7 @@ import com.eu.habbo.habbohotel.items.interactions.games.freeze.InteractionFreeze import com.eu.habbo.habbohotel.items.interactions.games.tag.InteractionTagField; import com.eu.habbo.habbohotel.items.interactions.games.tag.InteractionTagPole; import com.eu.habbo.habbohotel.items.interactions.pets.*; +import com.eu.habbo.habbohotel.items.interactions.wired.WiredLegacyDataGuard; import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; @@ -274,18 +275,15 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect { String[] wiredDataOld = wiredData.split("\t"); if (wiredDataOld.length >= 1) { - this.setDelay(Integer.parseInt(wiredDataOld[0])); + this.setDelay(WiredLegacyDataGuard.parseDelay(wiredDataOld[0])); } if (wiredDataOld.length == 2) { if (wiredDataOld[1].contains(";")) { - for (String s : wiredDataOld[1].split(";")) { - HabboItem item = room.getHabboItem(Integer.parseInt(s)); - + for (HabboItem item : WiredLegacyDataGuard.parseRoomItems(wiredDataOld[1], room)) { if (item instanceof InteractionFreezeBlock || item instanceof InteractionFreezeTile || item instanceof InteractionCrackable) continue; - if (item != null) - this.items.add(item); + this.items.add(item); } } } diff --git a/Emulator/src/test/java/com/eu/habbo/habbohotel/items/interactions/wired/WiredLegacyDataGuardTest.java b/Emulator/src/test/java/com/eu/habbo/habbohotel/items/interactions/wired/WiredLegacyDataGuardTest.java new file mode 100644 index 00000000..4f939997 --- /dev/null +++ b/Emulator/src/test/java/com/eu/habbo/habbohotel/items/interactions/wired/WiredLegacyDataGuardTest.java @@ -0,0 +1,26 @@ +package com.eu.habbo.habbohotel.items.interactions.wired; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class WiredLegacyDataGuardTest { + + @Test + void malformedDelayFallsBackToZero() { + assertEquals(0, WiredLegacyDataGuard.parseDelay(null)); + assertEquals(0, WiredLegacyDataGuard.parseDelay("nope")); + assertEquals(0, WiredLegacyDataGuard.parseDelay("-5")); + } + + @Test + void oversizedDelayIsClampedThroughWiredInputGuard() { + assertEquals(WiredLegacyDataGuard.DEFAULT_MAX_DELAY, WiredLegacyDataGuard.parseDelay("999999")); + } + + @Test + void nullRoomOrBlankItemsReturnEmptyList() { + assertEquals(0, WiredLegacyDataGuard.parseRoomItems("1;2;bad", null).size()); + assertEquals(0, WiredLegacyDataGuard.parseRoomItems("", null).size()); + } +}