fix(wired): bound furni condition inputs

This commit is contained in:
simoleo89
2026-06-17 18:32:24 +02:00
parent 416d0bb088
commit 4479763f12
7 changed files with 156 additions and 70 deletions
@@ -97,9 +97,9 @@ public class WiredConditionFurniHaveFurni extends InteractionWiredCondition {
if (wiredData.startsWith("{")) { if (wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class); JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.all = data.all; 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); HabboItem item = room.getHabboItem(id);
if (item != null) { if (item != null) {
@@ -114,10 +114,8 @@ public class WiredConditionFurniHaveFurni extends InteractionWiredCondition {
this.all = (data[0].equals("1")); this.all = (data[0].equals("1"));
if (data.length == 2) { if (data.length == 2) {
String[] items = data[1].split(";"); for (int id : WiredFurniConditionInputGuard.parseLegacyItemIds(data[1], WiredManager.MAXIMUM_FURNI_SELECTION)) {
HabboItem item = room.getHabboItem(id);
for (String s : items) {
HabboItem item = room.getHabboItem(Integer.parseInt(s));
if (item != null) if (item != null)
this.items.add(item); this.items.add(item);
@@ -126,9 +124,7 @@ public class WiredConditionFurniHaveFurni extends InteractionWiredCondition {
} }
this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED; this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
} }
if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) { this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, !this.items.isEmpty());
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
}
} }
@Override @Override
@@ -172,14 +168,12 @@ public class WiredConditionFurniHaveFurni extends InteractionWiredCondition {
int[] params = settings.getIntParams(); int[] params = settings.getIntParams();
this.all = params[0] == 1; 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; int count = settings.getFurniIds().length;
if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false; if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false;
if (count > 0 && this.furniSource == WiredSourceUtil.SOURCE_TRIGGER) { this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, count > 0);
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
}
this.items.clear(); this.items.clear();
@@ -94,10 +94,10 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition {
if (wiredData.startsWith("{")) { if (wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class); JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.furniSource = data.furniSource; this.furniSource = WiredFurniConditionInputGuard.normalizeFurniSource(data.furniSource);
this.all = data.all; 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); HabboItem item = room.getHabboItem(id);
if (item != null) { if (item != null) {
@@ -107,12 +107,9 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition {
} else { } else {
String[] data = wiredData.split(":"); String[] data = wiredData.split(":");
if (data.length >= 1) { if (data.length >= 2) {
for (int id : WiredFurniConditionInputGuard.parseLegacyItemIds(data[1], WiredManager.MAXIMUM_FURNI_SELECTION)) {
String[] items = data[1].split(";"); HabboItem item = room.getHabboItem(id);
for (String s : items) {
HabboItem item = room.getHabboItem(Integer.parseInt(s));
if (item != null) if (item != null)
this.items.add(item); 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.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
this.all = false; this.all = false;
} }
if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) { this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, !this.items.isEmpty());
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
}
} }
@Override @Override
@@ -162,11 +157,9 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition {
int[] params = settings.getIntParams(); int[] params = settings.getIntParams();
this.all = (params.length > 0) && (params[0] == 1); 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 = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, count > 0);
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
}
this.items.clear(); this.items.clear();
@@ -99,9 +99,9 @@ public class WiredConditionNotFurniHaveFurni extends InteractionWiredCondition {
if (wiredData.startsWith("{")) { if (wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class); JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.all = data.all; 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); HabboItem item = room.getHabboItem(id);
if (item != null) { if (item != null) {
@@ -115,10 +115,8 @@ public class WiredConditionNotFurniHaveFurni extends InteractionWiredCondition {
this.all = (data[0].equals("1")); this.all = (data[0].equals("1"));
if (data.length == 2) { if (data.length == 2) {
String[] items = data[1].split(";"); for (int id : WiredFurniConditionInputGuard.parseLegacyItemIds(data[1], WiredManager.MAXIMUM_FURNI_SELECTION)) {
HabboItem item = room.getHabboItem(id);
for (String s : items) {
HabboItem item = room.getHabboItem(Integer.parseInt(s));
if (item != null) if (item != null)
this.items.add(item); this.items.add(item);
@@ -127,9 +125,7 @@ public class WiredConditionNotFurniHaveFurni extends InteractionWiredCondition {
} }
this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED; this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
} }
if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) { this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, !this.items.isEmpty());
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
}
} }
@Override @Override
@@ -172,14 +168,12 @@ public class WiredConditionNotFurniHaveFurni extends InteractionWiredCondition {
if(settings.getIntParams().length < 1) return false; if(settings.getIntParams().length < 1) return false;
int[] params = settings.getIntParams(); int[] params = settings.getIntParams();
this.all = params[0] == 1; 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; int count = settings.getFurniIds().length;
if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false; if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false;
if (count > 0 && this.furniSource == WiredSourceUtil.SOURCE_TRIGGER) { this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, count > 0);
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
}
this.items.clear(); this.items.clear();
@@ -95,10 +95,10 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition {
if (wiredData.startsWith("{")) { if (wiredData.startsWith("{")) {
WiredConditionFurniHaveHabbo.JsonData data = WiredManager.getGson().fromJson(wiredData, WiredConditionFurniHaveHabbo.JsonData.class); WiredConditionFurniHaveHabbo.JsonData data = WiredManager.getGson().fromJson(wiredData, WiredConditionFurniHaveHabbo.JsonData.class);
this.furniSource = data.furniSource; this.furniSource = WiredFurniConditionInputGuard.normalizeFurniSource(data.furniSource);
this.all = data.all; 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); HabboItem item = room.getHabboItem(id);
if (item != null) { if (item != null) {
@@ -108,11 +108,9 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition {
} else { } else {
String[] data = wiredData.split(":"); String[] data = wiredData.split(":");
if (data.length >= 1) { if (data.length >= 2) {
String[] items = data[1].split(";"); for (int id : WiredFurniConditionInputGuard.parseLegacyItemIds(data[1], WiredManager.MAXIMUM_FURNI_SELECTION)) {
HabboItem item = room.getHabboItem(id);
for (String s : items) {
HabboItem item = room.getHabboItem(Integer.parseInt(s));
if (item != null) if (item != null)
this.items.add(item); 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.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
this.all = false; this.all = false;
} }
if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) { this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, !this.items.isEmpty());
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
}
} }
@Override @Override
@@ -161,11 +157,9 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition {
int[] params = settings.getIntParams(); int[] params = settings.getIntParams();
this.all = (params.length > 0) && (params[0] == 1); 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 = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, count > 0);
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
}
this.items.clear(); this.items.clear();
@@ -109,11 +109,11 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition {
if (wiredData.startsWith("{")) { if (wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class); JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.furniSource = data.furniSource; this.furniSource = WiredFurniConditionInputGuard.normalizeFurniSource(data.furniSource);
this.userSource = data.userSource; this.userSource = WiredFurniConditionInputGuard.normalizeUserSource(data.userSource);
this.quantifier = this.normalizeQuantifier(data.quantifier); 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); HabboItem item = room.getHabboItem(id);
if (item != null) { if (item != null) {
@@ -121,10 +121,8 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition {
} }
} }
} else { } else {
String[] data = wiredData.split(";"); for (int id : WiredFurniConditionInputGuard.parseLegacyItemIds(wiredData, WiredManager.MAXIMUM_FURNI_SELECTION)) {
HabboItem item = room.getHabboItem(id);
for (String s : data) {
HabboItem item = room.getHabboItem(Integer.parseInt(s));
if (item != null) { if (item != null) {
this.items.add(item); this.items.add(item);
@@ -134,9 +132,7 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition {
this.userSource = WiredSourceUtil.SOURCE_TRIGGER; this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
this.quantifier = QUANTIFIER_ALL; this.quantifier = QUANTIFIER_ALL;
} }
if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) { this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, !this.items.isEmpty());
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
}
} }
@Override @Override
@@ -182,13 +178,11 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition {
if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false; if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false;
int[] params = settings.getIntParams(); int[] params = settings.getIntParams();
this.furniSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER; this.furniSource = (params.length > 0) ? WiredFurniConditionInputGuard.normalizeFurniSource(params[0]) : WiredSourceUtil.SOURCE_TRIGGER;
this.userSource = (params.length > 1) ? params[1] : 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; this.quantifier = (params.length > 2) ? this.normalizeQuantifier(params[2]) : QUANTIFIER_ALL;
if (count > 0 && this.furniSource == WiredSourceUtil.SOURCE_TRIGGER) { this.furniSource = WiredFurniConditionInputGuard.selectedOrNormalizedFurniSource(this.furniSource, count > 0);
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
}
this.items.clear(); this.items.clear();
@@ -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<Integer> sanitizeItemIds(Collection<Integer> itemIds, int maxCount) {
List<Integer> 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<Integer> parseLegacyItemIds(String value, int maxCount) {
List<Integer> 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;
}
}
@@ -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));
}
}