fix(wired): bound movement effect payloads

This commit is contained in:
simoleo89
2026-06-17 20:28:11 +02:00
parent 416d0bb088
commit a2d75ea487
6 changed files with 150 additions and 42 deletions
@@ -268,31 +268,35 @@ public class WiredEffectTeleport extends InteractionWiredEffect {
this.items = new ArrayList<>();
String wiredData = set.getString("wired_data");
if (wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.setDelay(data.delay);
this.fastTeleport = data.fastTeleport;
this.furniSource = data.furniSource;
this.userSource = data.userSource;
for (Integer id: data.itemIds) {
HabboItem item = room.getHabboItem(id);
if (item != null) {
this.items.add(item);
JsonData jsonData = WiredMovementPayloadGuard.fromJson(wiredData, JsonData.class);
if (jsonData != null) {
this.setDelay(WiredMovementPayloadGuard.delay(jsonData.delay));
this.fastTeleport = jsonData.fastTeleport;
this.furniSource = WiredMovementPayloadGuard.furniSource(jsonData.furniSource);
this.userSource = WiredMovementPayloadGuard.userSource(jsonData.userSource);
if (jsonData.itemIds != null) {
for (Integer id: jsonData.itemIds) {
if (id == null) continue;
HabboItem item = room.getHabboItem(id);
if (item != null) {
this.items.add(item);
}
}
}
if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) {
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
}
} else {
String[] wiredDataOld = wiredData.split("\t");
String[] wiredDataOld = wiredData != null ? wiredData.split("\t") : new String[0];
if (wiredDataOld.length >= 1) {
this.setDelay(Integer.parseInt(wiredDataOld[0]));
this.setDelay(WiredMovementPayloadGuard.parseDelay(wiredDataOld[0]));
}
if (wiredDataOld.length == 2) {
if (wiredDataOld[1].contains(";")) {
for (String s : wiredDataOld[1].split(";")) {
HabboItem item = room.getHabboItem(Integer.parseInt(s));
int itemId = WiredMovementPayloadGuard.parseInt(s, 0);
HabboItem item = itemId > 0 ? room.getHabboItem(itemId) : null;
if (item != null)
this.items.add(item);
@@ -251,12 +251,13 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect {
this.items.clear();
String wiredData = set.getString("wired_data");
if (wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.setDelay(data.delay);
this.toggleType = normalizeToggleType(data.toggleType);
this.furniSource = data.furniSource;
for (Integer id: data.itemIds) {
JsonData jsonData = WiredMovementPayloadGuard.fromJson(wiredData, JsonData.class);
if (jsonData != null) {
this.setDelay(WiredMovementPayloadGuard.delay(jsonData.delay));
this.toggleType = normalizeToggleType(jsonData.toggleType);
this.furniSource = WiredMovementPayloadGuard.furniSource(jsonData.furniSource);
if (jsonData.itemIds != null) for (Integer id: jsonData.itemIds) {
if (id == null) continue;
HabboItem item = room.getHabboItem(id);
if (item instanceof InteractionFreezeBlock || item instanceof InteractionFreezeTile || item instanceof InteractionCrackable) {
@@ -271,15 +272,16 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect {
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
}
} else {
String[] wiredDataOld = wiredData.split("\t");
String[] wiredDataOld = wiredData != null ? wiredData.split("\t") : new String[0];
if (wiredDataOld.length >= 1) {
this.setDelay(Integer.parseInt(wiredDataOld[0]));
this.setDelay(WiredMovementPayloadGuard.parseDelay(wiredDataOld[0]));
}
if (wiredDataOld.length == 2) {
if (wiredDataOld[1].contains(";")) {
for (String s : wiredDataOld[1].split(";")) {
HabboItem item = room.getHabboItem(Integer.parseInt(s));
int itemId = WiredMovementPayloadGuard.parseInt(s, 0);
HabboItem item = itemId > 0 ? room.getHabboItem(itemId) : null;
if (item instanceof InteractionFreezeBlock || item instanceof InteractionFreezeTile || item instanceof InteractionCrackable)
continue;
@@ -230,13 +230,14 @@ public class WiredEffectToggleRandom extends InteractionWiredEffect {
this.items.clear();
String wiredData = set.getString("wired_data");
if (wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.setDelay(data.delay);
this.furniSource = data.furniSource;
for (Integer id: data.itemIds) {
JsonData jsonData = WiredMovementPayloadGuard.fromJson(wiredData, JsonData.class);
if (jsonData != null) {
this.setDelay(WiredMovementPayloadGuard.delay(jsonData.delay));
this.furniSource = WiredMovementPayloadGuard.furniSource(jsonData.furniSource);
if (jsonData.itemIds != null) for (Integer id: jsonData.itemIds) {
if (id == null) continue;
HabboItem item = room.getHabboItem(id);
if (item instanceof InteractionFreezeBlock || item instanceof InteractionGameTimer || item instanceof InteractionCrackable)
continue;
@@ -247,15 +248,16 @@ public class WiredEffectToggleRandom extends InteractionWiredEffect {
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
}
} else {
String[] wiredDataOld = wiredData.split("\t");
String[] wiredDataOld = wiredData != null ? wiredData.split("\t") : new String[0];
if (wiredDataOld.length >= 1) {
this.setDelay(Integer.parseInt(wiredDataOld[0]));
this.setDelay(WiredMovementPayloadGuard.parseDelay(wiredDataOld[0]));
}
if (wiredDataOld.length == 2) {
if (wiredDataOld[1].contains(";")) {
for (String s : wiredDataOld[1].split(";")) {
HabboItem item = room.getHabboItem(Integer.parseInt(s));
int itemId = WiredMovementPayloadGuard.parseInt(s, 0);
HabboItem item = itemId > 0 ? room.getHabboItem(itemId) : null;
if (item instanceof InteractionFreezeBlock || item instanceof InteractionGameTimer || item instanceof InteractionCrackable)
continue;
@@ -178,29 +178,33 @@ public class WiredEffectTriggerStacks extends InteractionWiredEffect {
this.items = new THashSet<>();
String wiredData = set.getString("wired_data");
if (wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.setDelay(data.delay);
this.furniSource = data.furniSource;
for (Integer id: data.itemIds) {
HabboItem item = room.getHabboItem(id);
if (item != null) {
this.items.add(item);
JsonData jsonData = WiredMovementPayloadGuard.fromJson(wiredData, JsonData.class);
if (jsonData != null) {
this.setDelay(WiredMovementPayloadGuard.delay(jsonData.delay));
this.furniSource = WiredMovementPayloadGuard.furniSource(jsonData.furniSource);
if (jsonData.itemIds != null) {
for (Integer id: jsonData.itemIds) {
if (id == null) continue;
HabboItem item = room.getHabboItem(id);
if (item != null) {
this.items.add(item);
}
}
}
if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) {
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
}
} else {
String[] wiredDataOld = wiredData.split("\t");
String[] wiredDataOld = wiredData != null ? wiredData.split("\t") : new String[0];
if (wiredDataOld.length >= 1) {
this.setDelay(Integer.parseInt(wiredDataOld[0]));
this.setDelay(WiredMovementPayloadGuard.parseDelay(wiredDataOld[0]));
}
if (wiredDataOld.length == 2) {
if (wiredDataOld[1].contains(";")) {
for (String s : wiredDataOld[1].split(";")) {
HabboItem item = room.getHabboItem(Integer.parseInt(s));
int itemId = WiredMovementPayloadGuard.parseInt(s, 0);
HabboItem item = itemId > 0 ? room.getHabboItem(itemId) : null;
if (item != null)
this.items.add(item);
@@ -0,0 +1,63 @@
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 WiredMovementPayloadGuard {
static final int MAX_LOAD_DELAY = 3600;
private WiredMovementPayloadGuard() {
}
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 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 int userSource(int value) {
return WiredSourceUtil.isDefaultUserSource(value) ? value : WiredSourceUtil.SOURCE_TRIGGER;
}
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,33 @@
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 WiredMovementPayloadGuardTest {
@Test
void delayAndIntegersAreBounded() {
assertEquals(0, WiredMovementPayloadGuard.delay(-100));
assertEquals(25, WiredMovementPayloadGuard.parseDelay("25"));
assertEquals(0, WiredMovementPayloadGuard.parseDelay("bad"));
assertEquals(WiredMovementPayloadGuard.MAX_LOAD_DELAY, WiredMovementPayloadGuard.delay(Integer.MAX_VALUE));
assertEquals(7, WiredMovementPayloadGuard.parseInt(" 7 ", 0));
assertEquals(3, WiredMovementPayloadGuard.parseInt("oops", 3));
}
@Test
void sourceValuesFallbackToTriggerWhenInvalid() {
assertEquals(WiredSourceUtil.SOURCE_TRIGGER, WiredMovementPayloadGuard.furniSource(-1));
assertEquals(WiredSourceUtil.SOURCE_SELECTED, WiredMovementPayloadGuard.furniSource(WiredSourceUtil.SOURCE_SELECTED));
assertEquals(WiredSourceUtil.SOURCE_TRIGGER, WiredMovementPayloadGuard.userSource(999));
assertEquals(WiredSourceUtil.SOURCE_SELECTOR, WiredMovementPayloadGuard.userSource(WiredSourceUtil.SOURCE_SELECTOR));
}
@Test
void malformedJsonDoesNotThrow() {
assertNull(WiredMovementPayloadGuard.fromJson("{broken", WiredEffectTeleport.JsonData.class));
assertNull(WiredMovementPayloadGuard.fromJson(null, WiredEffectTeleport.JsonData.class));
}
}