Merge pull request #259 from simoleo89/fix/wired-utility-effect-payloads

fix(wired): bound utility effect payloads
This commit is contained in:
DuckieTM
2026-06-18 12:49:23 +02:00
committed by GitHub
9 changed files with 142 additions and 43 deletions
@@ -93,16 +93,17 @@ public class WiredEffectAdjustClock extends InteractionWiredEffect {
this.items.clear();
String wiredData = set.getString("wired_data");
if (wiredData != null && wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.setDelay(data.delay);
this.operator = this.normalizeOperator(data.operator);
this.furniSource = data.furniSource;
this.minutes = this.normalizeMinutes(data.minutes);
this.halfSecondSteps = this.normalizeHalfSecondSteps(data.halfSecondSteps);
JsonData jsonData = WiredUtilityPayloadGuard.fromJson(wiredData, JsonData.class);
if (jsonData != null) {
this.setDelay(WiredUtilityPayloadGuard.delay(jsonData.delay));
this.operator = this.normalizeOperator(jsonData.operator);
this.furniSource = WiredUtilityPayloadGuard.furniSource(jsonData.furniSource);
this.minutes = this.normalizeMinutes(jsonData.minutes);
this.halfSecondSteps = this.normalizeHalfSecondSteps(jsonData.halfSecondSteps);
if (data.itemIds != null) {
for (Integer id : data.itemIds) {
if (jsonData.itemIds != null) {
for (Integer id : jsonData.itemIds) {
if (id == null) continue;
HabboItem item = room.getHabboItem(id);
if (item != null) {
@@ -298,7 +298,7 @@ public class WiredEffectChangeVariableValue extends InteractionWiredEffect {
String wiredData = set.getString("wired_data");
if (wiredData == null || wiredData.isEmpty() || !wiredData.startsWith("{")) return;
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
JsonData data = WiredUtilityPayloadGuard.fromJson(wiredData, JsonData.class);
if (data == null) return;
this.destinationTargetType = normalizeTargetType(data.destinationTargetType);
@@ -312,7 +312,7 @@ public class WiredEffectChangeVariableValue extends InteractionWiredEffect {
this.destinationFurniSource = normalizeDestinationFurniSource(data.destinationFurniSource);
this.referenceUserSource = normalizeUserSource(data.referenceUserSource);
this.referenceFurniSource = normalizeReferenceFurniSource(data.referenceFurniSource);
this.setDelay(Math.max(0, data.delay));
this.setDelay(WiredUtilityPayloadGuard.delay(data.delay));
if (room != null) {
try {
@@ -260,14 +260,14 @@ public class WiredEffectRemoveVariable extends InteractionWiredEffect {
}
if (wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
JsonData data = WiredUtilityPayloadGuard.fromJson(wiredData, JsonData.class);
if (data != null) {
this.variableItemId = Math.max(0, data.variableItemId);
this.targetType = normalizeTargetType(data.targetType);
this.userSource = normalizeUserSource(data.userSource);
this.furniSource = normalizeFurniSource(data.furniSource);
this.setDelay(Math.max(0, data.delay));
this.setDelay(WiredUtilityPayloadGuard.delay(data.delay));
if (room != null && data.selectedFurniIds != null) {
for (Integer itemId : data.selectedFurniIds) {
@@ -96,19 +96,16 @@ public class WiredEffectResetTimers extends InteractionWiredEffect {
public void loadWiredData(ResultSet set, Room room) throws SQLException {
String wiredData = set.getString("wired_data");
if (wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.delay = data.delay;
JsonData jsonData = WiredUtilityPayloadGuard.fromJson(wiredData, JsonData.class);
if (jsonData != null) {
this.delay = WiredUtilityPayloadGuard.delay(jsonData.delay);
} else {
try {
if (!wiredData.equals("")) {
this.delay = Integer.parseInt(wiredData);
}
} catch (Exception e) {
if (wiredData != null && !wiredData.equals("")) {
this.delay = WiredUtilityPayloadGuard.parseDelay(wiredData);
}
}
this.setDelay(this.delay);
this.setDelay(WiredUtilityPayloadGuard.delay(this.delay));
}
@Override
@@ -350,9 +350,9 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
this.forwardItems = new THashSet<>();
String wiredData = set.getString("wired_data");
if (wiredData != null && wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.setDelay(data.delay);
JsonData data = WiredUtilityPayloadGuard.fromJson(wiredData, JsonData.class);
if (data != null) {
this.setDelay(WiredUtilityPayloadGuard.delay(data.delay));
this.antennaSource = data.antennaSource;
this.furniForward = normalizeSource(data.furniForward);
this.userForward = normalizeSource(data.userForward);
@@ -100,15 +100,16 @@ public class WiredEffectSetAltitude extends InteractionWiredEffect {
this.items.clear();
String wiredData = set.getString("wired_data");
if (wiredData != null && wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.setDelay(data.delay);
this.operator = this.normalizeOperator(data.operator);
this.altitude = this.parseAltitudeOrDefault(data.altitude);
this.furniSource = data.furniSource;
JsonData jsonData = WiredUtilityPayloadGuard.fromJson(wiredData, JsonData.class);
if (jsonData != null) {
this.setDelay(WiredUtilityPayloadGuard.delay(jsonData.delay));
this.operator = this.normalizeOperator(jsonData.operator);
this.altitude = this.parseAltitudeOrDefault(jsonData.altitude);
this.furniSource = WiredUtilityPayloadGuard.furniSource(jsonData.furniSource);
if (data.itemIds != null) {
for (Integer id : data.itemIds) {
if (jsonData.itemIds != null) {
for (Integer id : jsonData.itemIds) {
if (id == null) continue;
HabboItem item = room.getHabboItem(id);
if (item != null) {
@@ -272,22 +272,23 @@ public class WiredEffectWhisper extends InteractionWiredEffect {
public void loadWiredData(ResultSet set, Room room) throws SQLException {
String wiredData = set.getString("wired_data");
if(wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.setDelay(data.delay);
this.message = data.message;
this.userSource = (data.userSource != null) ? data.userSource : WiredSourceUtil.SOURCE_TRIGGER;
this.visibilitySelection = (data.visibilitySelection != null && data.visibilitySelection == VISIBILITY_ALL_ROOM_USERS)
JsonData jsonData = WiredUtilityPayloadGuard.fromJson(wiredData, JsonData.class);
if(jsonData != null) {
this.setDelay(WiredUtilityPayloadGuard.delay(jsonData.delay));
this.message = WiredUtilityPayloadGuard.text(jsonData.message);
this.userSource = (jsonData.userSource != null) ? WiredUtilityPayloadGuard.userSource(jsonData.userSource) : WiredSourceUtil.SOURCE_TRIGGER;
this.visibilitySelection = (jsonData.visibilitySelection != null && jsonData.visibilitySelection == VISIBILITY_ALL_ROOM_USERS)
? VISIBILITY_ALL_ROOM_USERS
: VISIBILITY_SOURCE_USERS;
this.bubbleStyle = (data.bubbleStyle != null) ? data.bubbleStyle : RoomChatMessageBubbles.WIRED.getType();
this.bubbleStyle = (jsonData.bubbleStyle != null) ? jsonData.bubbleStyle : RoomChatMessageBubbles.WIRED.getType();
}
else {
this.message = "";
if (wiredData.split("\t").length >= 2) {
super.setDelay(Integer.parseInt(wiredData.split("\t")[0]));
this.message = wiredData.split("\t")[1];
String[] wiredDataSplit = wiredData != null ? wiredData.split("\t") : new String[0];
if (wiredDataSplit.length >= 2) {
super.setDelay(WiredUtilityPayloadGuard.parseDelay(wiredDataSplit[0]));
this.message = wiredDataSplit[1];
}
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
@@ -0,0 +1,67 @@
package com.eu.habbo.habbohotel.items.interactions.wired.effects;
import com.eu.habbo.habbohotel.wired.core.WiredManager;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
final class WiredUtilityPayloadGuard {
static final int MAX_LOAD_DELAY = 3600;
private WiredUtilityPayloadGuard() {
}
static int delay(int value) {
if (value < 0) {
return 0;
}
return Math.min(value, MAX_LOAD_DELAY);
}
static int parseDelay(String value) {
return delay(parseInt(value, 0));
}
static int parseInt(String value, int fallback) {
if (value == null) {
return fallback;
}
try {
return Integer.parseInt(value.trim());
} catch (RuntimeException e) {
return fallback;
}
}
static int userSource(int value) {
return WiredSourceUtil.isDefaultUserSource(value) ? value : WiredSourceUtil.SOURCE_TRIGGER;
}
static int furniSource(int value) {
switch (value) {
case WiredSourceUtil.SOURCE_TRIGGER:
case WiredSourceUtil.SOURCE_SELECTED:
case WiredSourceUtil.SOURCE_SELECTOR:
case WiredSourceUtil.SOURCE_SIGNAL:
return value;
default:
return WiredSourceUtil.SOURCE_TRIGGER;
}
}
static String text(String value) {
return value == null ? "" : value;
}
static <T> T fromJson(String wiredData, Class<T> type) {
if (wiredData == null || !wiredData.startsWith("{")) {
return null;
}
try {
return WiredManager.getGson().fromJson(wiredData, type);
} catch (RuntimeException e) {
return null;
}
}
}
@@ -0,0 +1,32 @@
package com.eu.habbo.habbohotel.items.interactions.wired.effects;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
class WiredUtilityPayloadGuardTest {
@Test
void clampsDelayAndParsesLegacyNumbers() {
assertEquals(0, WiredUtilityPayloadGuard.delay(-1));
assertEquals(20, WiredUtilityPayloadGuard.parseDelay("20"));
assertEquals(0, WiredUtilityPayloadGuard.parseDelay("bad"));
assertEquals(WiredUtilityPayloadGuard.MAX_LOAD_DELAY, WiredUtilityPayloadGuard.delay(Integer.MAX_VALUE));
}
@Test
void normalizesSourcesAndText() {
assertEquals(WiredSourceUtil.SOURCE_TRIGGER, WiredUtilityPayloadGuard.userSource(999));
assertEquals(WiredSourceUtil.SOURCE_SELECTOR, WiredUtilityPayloadGuard.userSource(WiredSourceUtil.SOURCE_SELECTOR));
assertEquals(WiredSourceUtil.SOURCE_TRIGGER, WiredUtilityPayloadGuard.furniSource(-1));
assertEquals(WiredSourceUtil.SOURCE_SELECTED, WiredUtilityPayloadGuard.furniSource(WiredSourceUtil.SOURCE_SELECTED));
assertEquals("", WiredUtilityPayloadGuard.text(null));
}
@Test
void malformedJsonReturnsNull() {
assertNull(WiredUtilityPayloadGuard.fromJson("{broken", WiredEffectResetTimers.JsonData.class));
assertNull(WiredUtilityPayloadGuard.fromJson(null, WiredEffectResetTimers.JsonData.class));
}
}