From 4479763f1263b681707108f01b15f0240e331846 Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Wed, 17 Jun 2026 18:32:24 +0200 Subject: [PATCH] fix(wired): bound furni condition inputs --- .../WiredConditionFurniHaveFurni.java | 20 ++--- .../WiredConditionFurniHaveHabbo.java | 23 ++---- .../WiredConditionNotFurniHaveFurni.java | 20 ++--- .../WiredConditionNotFurniHaveHabbo.java | 22 ++---- .../WiredConditionTriggerOnFurni.java | 24 +++--- .../WiredFurniConditionInputGuard.java | 76 +++++++++++++++++++ .../WiredFurniConditionInputGuardTest.java | 41 ++++++++++ 7 files changed, 156 insertions(+), 70 deletions(-) create mode 100644 Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredFurniConditionInputGuard.java create mode 100644 Emulator/src/test/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredFurniConditionInputGuardTest.java diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveFurni.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveFurni.java index 01eae2ad..d83d291b 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveFurni.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveFurni.java @@ -97,9 +97,9 @@ public class WiredConditionFurniHaveFurni extends InteractionWiredCondition { if (wiredData.startsWith("{")) { JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class); this.all = data.all; - this.furniSource = data.furniSource; + this.furniSource = WiredFurniConditionInputGuard.normalizeFurniSource(data.furniSource); - for(int id : data.itemIds) { + for(int id : WiredFurniConditionInputGuard.sanitizeItemIds(data.itemIds, WiredManager.MAXIMUM_FURNI_SELECTION)) { HabboItem item = room.getHabboItem(id); if (item != null) { @@ -114,10 +114,8 @@ public class WiredConditionFurniHaveFurni extends InteractionWiredCondition { this.all = (data[0].equals("1")); if (data.length == 2) { - String[] items = data[1].split(";"); - - for (String s : items) { - HabboItem item = room.getHabboItem(Integer.parseInt(s)); + for (int id : WiredFurniConditionInputGuard.parseLegacyItemIds(data[1], WiredManager.MAXIMUM_FURNI_SELECTION)) { + HabboItem item = room.getHabboItem(id); if (item != null) this.items.add(item); @@ -126,9 +124,7 @@ public class WiredConditionFurniHaveFurni extends InteractionWiredCondition { } this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED; } - if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) { - this.furniSource = WiredSourceUtil.SOURCE_SELECTED; - } + this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, !this.items.isEmpty()); } @Override @@ -172,14 +168,12 @@ public class WiredConditionFurniHaveFurni extends InteractionWiredCondition { int[] params = settings.getIntParams(); this.all = params[0] == 1; - this.furniSource = (params.length > 1) ? params[1] : WiredSourceUtil.SOURCE_TRIGGER; + this.furniSource = (params.length > 1) ? WiredFurniConditionInputGuard.normalizeFurniSource(params[1]) : WiredSourceUtil.SOURCE_TRIGGER; int count = settings.getFurniIds().length; if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false; - if (count > 0 && this.furniSource == WiredSourceUtil.SOURCE_TRIGGER) { - this.furniSource = WiredSourceUtil.SOURCE_SELECTED; - } + this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, count > 0); this.items.clear(); diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveHabbo.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveHabbo.java index 4fb60898..aafd8561 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveHabbo.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveHabbo.java @@ -94,10 +94,10 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition { if (wiredData.startsWith("{")) { JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class); - this.furniSource = data.furniSource; + this.furniSource = WiredFurniConditionInputGuard.normalizeFurniSource(data.furniSource); this.all = data.all; - for(int id : data.itemIds) { + for(int id : WiredFurniConditionInputGuard.sanitizeItemIds(data.itemIds, WiredManager.MAXIMUM_FURNI_SELECTION)) { HabboItem item = room.getHabboItem(id); if (item != null) { @@ -107,12 +107,9 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition { } else { String[] data = wiredData.split(":"); - if (data.length >= 1) { - - String[] items = data[1].split(";"); - - for (String s : items) { - HabboItem item = room.getHabboItem(Integer.parseInt(s)); + if (data.length >= 2) { + for (int id : WiredFurniConditionInputGuard.parseLegacyItemIds(data[1], WiredManager.MAXIMUM_FURNI_SELECTION)) { + HabboItem item = room.getHabboItem(id); if (item != null) this.items.add(item); @@ -121,9 +118,7 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition { this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED; this.all = false; } - if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) { - this.furniSource = WiredSourceUtil.SOURCE_SELECTED; - } + this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, !this.items.isEmpty()); } @Override @@ -162,11 +157,9 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition { int[] params = settings.getIntParams(); this.all = (params.length > 0) && (params[0] == 1); - this.furniSource = (params.length > 1) ? params[1] : ((params.length > 0 && params[0] > 1) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER); + this.furniSource = (params.length > 1) ? WiredFurniConditionInputGuard.normalizeFurniSource(params[1]) : ((params.length > 0 && params[0] > 1) ? WiredFurniConditionInputGuard.normalizeFurniSource(params[0]) : WiredSourceUtil.SOURCE_TRIGGER); - if (count > 0 && this.furniSource == WiredSourceUtil.SOURCE_TRIGGER) { - this.furniSource = WiredSourceUtil.SOURCE_SELECTED; - } + this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, count > 0); this.items.clear(); diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveFurni.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveFurni.java index 41f72077..f76be4bf 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveFurni.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveFurni.java @@ -99,9 +99,9 @@ public class WiredConditionNotFurniHaveFurni extends InteractionWiredCondition { if (wiredData.startsWith("{")) { JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class); this.all = data.all; - this.furniSource = data.furniSource; + this.furniSource = WiredFurniConditionInputGuard.normalizeFurniSource(data.furniSource); - for (int id : data.itemIds) { + for (int id : WiredFurniConditionInputGuard.sanitizeItemIds(data.itemIds, WiredManager.MAXIMUM_FURNI_SELECTION)) { HabboItem item = room.getHabboItem(id); if (item != null) { @@ -115,10 +115,8 @@ public class WiredConditionNotFurniHaveFurni extends InteractionWiredCondition { this.all = (data[0].equals("1")); if (data.length == 2) { - String[] items = data[1].split(";"); - - for (String s : items) { - HabboItem item = room.getHabboItem(Integer.parseInt(s)); + for (int id : WiredFurniConditionInputGuard.parseLegacyItemIds(data[1], WiredManager.MAXIMUM_FURNI_SELECTION)) { + HabboItem item = room.getHabboItem(id); if (item != null) this.items.add(item); @@ -127,9 +125,7 @@ public class WiredConditionNotFurniHaveFurni extends InteractionWiredCondition { } this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED; } - if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) { - this.furniSource = WiredSourceUtil.SOURCE_SELECTED; - } + this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, !this.items.isEmpty()); } @Override @@ -172,14 +168,12 @@ public class WiredConditionNotFurniHaveFurni extends InteractionWiredCondition { if(settings.getIntParams().length < 1) return false; int[] params = settings.getIntParams(); this.all = params[0] == 1; - this.furniSource = (params.length > 1) ? params[1] : WiredSourceUtil.SOURCE_TRIGGER; + this.furniSource = (params.length > 1) ? WiredFurniConditionInputGuard.normalizeFurniSource(params[1]) : WiredSourceUtil.SOURCE_TRIGGER; int count = settings.getFurniIds().length; if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false; - if (count > 0 && this.furniSource == WiredSourceUtil.SOURCE_TRIGGER) { - this.furniSource = WiredSourceUtil.SOURCE_SELECTED; - } + this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, count > 0); this.items.clear(); diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveHabbo.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveHabbo.java index a7d85525..7699bbdd 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveHabbo.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveHabbo.java @@ -95,10 +95,10 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition { if (wiredData.startsWith("{")) { WiredConditionFurniHaveHabbo.JsonData data = WiredManager.getGson().fromJson(wiredData, WiredConditionFurniHaveHabbo.JsonData.class); - this.furniSource = data.furniSource; + this.furniSource = WiredFurniConditionInputGuard.normalizeFurniSource(data.furniSource); this.all = data.all; - for(int id : data.itemIds) { + for(int id : WiredFurniConditionInputGuard.sanitizeItemIds(data.itemIds, WiredManager.MAXIMUM_FURNI_SELECTION)) { HabboItem item = room.getHabboItem(id); if (item != null) { @@ -108,11 +108,9 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition { } else { String[] data = wiredData.split(":"); - if (data.length >= 1) { - String[] items = data[1].split(";"); - - for (String s : items) { - HabboItem item = room.getHabboItem(Integer.parseInt(s)); + if (data.length >= 2) { + for (int id : WiredFurniConditionInputGuard.parseLegacyItemIds(data[1], WiredManager.MAXIMUM_FURNI_SELECTION)) { + HabboItem item = room.getHabboItem(id); if (item != null) this.items.add(item); @@ -121,9 +119,7 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition { this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED; this.all = false; } - if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) { - this.furniSource = WiredSourceUtil.SOURCE_SELECTED; - } + this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, !this.items.isEmpty()); } @Override @@ -161,11 +157,9 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition { int[] params = settings.getIntParams(); this.all = (params.length > 0) && (params[0] == 1); - this.furniSource = (params.length > 1) ? params[1] : ((params.length > 0 && params[0] > 1) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER); + this.furniSource = (params.length > 1) ? WiredFurniConditionInputGuard.normalizeFurniSource(params[1]) : ((params.length > 0 && params[0] > 1) ? WiredFurniConditionInputGuard.normalizeFurniSource(params[0]) : WiredSourceUtil.SOURCE_TRIGGER); - if (count > 0 && this.furniSource == WiredSourceUtil.SOURCE_TRIGGER) { - this.furniSource = WiredSourceUtil.SOURCE_SELECTED; - } + this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, count > 0); this.items.clear(); diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTriggerOnFurni.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTriggerOnFurni.java index 82054911..4c13c669 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTriggerOnFurni.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTriggerOnFurni.java @@ -109,11 +109,11 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition { if (wiredData.startsWith("{")) { JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class); - this.furniSource = data.furniSource; - this.userSource = data.userSource; + this.furniSource = WiredFurniConditionInputGuard.normalizeFurniSource(data.furniSource); + this.userSource = WiredFurniConditionInputGuard.normalizeUserSource(data.userSource); this.quantifier = this.normalizeQuantifier(data.quantifier); - for(int id : data.itemIds) { + for(int id : WiredFurniConditionInputGuard.sanitizeItemIds(data.itemIds, WiredManager.MAXIMUM_FURNI_SELECTION)) { HabboItem item = room.getHabboItem(id); if (item != null) { @@ -121,10 +121,8 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition { } } } else { - String[] data = wiredData.split(";"); - - for (String s : data) { - HabboItem item = room.getHabboItem(Integer.parseInt(s)); + for (int id : WiredFurniConditionInputGuard.parseLegacyItemIds(wiredData, WiredManager.MAXIMUM_FURNI_SELECTION)) { + HabboItem item = room.getHabboItem(id); if (item != null) { this.items.add(item); @@ -134,9 +132,7 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition { this.userSource = WiredSourceUtil.SOURCE_TRIGGER; this.quantifier = QUANTIFIER_ALL; } - if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) { - this.furniSource = WiredSourceUtil.SOURCE_SELECTED; - } + this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, !this.items.isEmpty()); } @Override @@ -182,13 +178,11 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition { if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false; int[] params = settings.getIntParams(); - this.furniSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER; - this.userSource = (params.length > 1) ? params[1] : WiredSourceUtil.SOURCE_TRIGGER; + this.furniSource = (params.length > 0) ? WiredFurniConditionInputGuard.normalizeFurniSource(params[0]) : WiredSourceUtil.SOURCE_TRIGGER; + this.userSource = (params.length > 1) ? WiredFurniConditionInputGuard.normalizeUserSource(params[1]) : WiredSourceUtil.SOURCE_TRIGGER; this.quantifier = (params.length > 2) ? this.normalizeQuantifier(params[2]) : QUANTIFIER_ALL; - if (count > 0 && this.furniSource == WiredSourceUtil.SOURCE_TRIGGER) { - this.furniSource = WiredSourceUtil.SOURCE_SELECTED; - } + this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, count > 0); this.items.clear(); diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredFurniConditionInputGuard.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredFurniConditionInputGuard.java new file mode 100644 index 00000000..dfec95a9 --- /dev/null +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredFurniConditionInputGuard.java @@ -0,0 +1,76 @@ +package com.eu.habbo.habbohotel.items.interactions.wired.conditions; + +import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public final class WiredFurniConditionInputGuard { + private WiredFurniConditionInputGuard() { + } + + public static int normalizeFurniSource(int value) { + switch (value) { + case WiredSourceUtil.SOURCE_SELECTED: + case WiredSourceUtil.SOURCE_SELECTOR: + case WiredSourceUtil.SOURCE_SIGNAL: + case WiredSourceUtil.SOURCE_TRIGGER: + return value; + default: + return WiredSourceUtil.SOURCE_TRIGGER; + } + } + + public static int normalizeUserSource(int value) { + return WiredSourceUtil.isDefaultUserSource(value) ? value : WiredSourceUtil.SOURCE_TRIGGER; + } + + public static int selectedOrNormalizedFurniSource(int value, boolean hasSelectedItems) { + int source = normalizeFurniSource(value); + return (hasSelectedItems && source == WiredSourceUtil.SOURCE_TRIGGER) + ? WiredSourceUtil.SOURCE_SELECTED + : source; + } + + public static List sanitizeItemIds(Collection itemIds, int maxCount) { + List result = new ArrayList<>(); + if (itemIds == null || maxCount < 1) { + return result; + } + + for (Integer itemId : itemIds) { + if (itemId == null || itemId < 1 || result.size() >= maxCount) { + continue; + } + + result.add(itemId); + } + + return result; + } + + public static List parseLegacyItemIds(String value, int maxCount) { + List result = new ArrayList<>(); + if (value == null || value.isBlank() || maxCount < 1) { + return result; + } + + for (String part : value.split("[;,:\\t]")) { + if (result.size() >= maxCount) { + break; + } + + try { + int id = Integer.parseInt(part.trim()); + if (id > 0) { + result.add(id); + } + } catch (NumberFormatException ignored) { + // Ignore malformed legacy item ids. + } + } + + return result; + } +} diff --git a/Emulator/src/test/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredFurniConditionInputGuardTest.java b/Emulator/src/test/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredFurniConditionInputGuardTest.java new file mode 100644 index 00000000..3acc3ec6 --- /dev/null +++ b/Emulator/src/test/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredFurniConditionInputGuardTest.java @@ -0,0 +1,41 @@ +package com.eu.habbo.habbohotel.items.interactions.wired.conditions; + +import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertIterableEquals; + +class WiredFurniConditionInputGuardTest { + + @Test + void furniSourcesFallBackToTriggerWhenUnknown() { + assertEquals(WiredSourceUtil.SOURCE_TRIGGER, WiredFurniConditionInputGuard.normalizeFurniSource(-1)); + assertEquals(WiredSourceUtil.SOURCE_SELECTOR, WiredFurniConditionInputGuard.normalizeFurniSource(WiredSourceUtil.SOURCE_SELECTOR)); + assertEquals(WiredSourceUtil.SOURCE_SELECTED, WiredFurniConditionInputGuard.normalizeFurniSource(WiredSourceUtil.SOURCE_SELECTED)); + } + + @Test + void selectedItemsPromoteTriggerSourceToSelected() { + assertEquals(WiredSourceUtil.SOURCE_SELECTED, + WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(WiredSourceUtil.SOURCE_TRIGGER, true)); + assertEquals(WiredSourceUtil.SOURCE_SELECTOR, + WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(WiredSourceUtil.SOURCE_SELECTOR, true)); + } + + @Test + void itemIdsIgnoreInvalidValuesAndRespectCap() { + assertIterableEquals(Arrays.asList(4, 9), + WiredFurniConditionInputGuard.sanitizeItemIds(Arrays.asList(-1, 4, null, 9, 10), 2)); + } + + @Test + void legacyItemIdsIgnoreMalformedParts() { + assertIterableEquals(Arrays.asList(10, 20, 30), + WiredFurniConditionInputGuard.parseLegacyItemIds("10;bad;-1;20\t30", 5)); + assertIterableEquals(Arrays.asList(10, 20), + WiredFurniConditionInputGuard.parseLegacyItemIds("10;20;30", 2)); + } +}