Merge pull request #261 from simoleo89/fix/wired-reward-inputs

fix(wired): bound reward inputs
This commit is contained in:
DuckieTM
2026-06-18 12:51:12 +02:00
committed by GitHub
5 changed files with 165 additions and 42 deletions
@@ -202,12 +202,15 @@ public class WiredEffectGiveReward extends InteractionWiredEffect {
int i = 1; int i = 1;
for (String s : items) { for (String s : items) {
String[] d = s.split(","); String[] d = s.split(",", -1);
if (d.length == 3) { if (d.length == 3) {
if (!(d[1].contains(":") || d[1].contains(";"))) { if (!(d[1].contains(":") || d[1].contains(";"))) {
this.rewardItems.add(new WiredGiveRewardItem(i, d[0].equalsIgnoreCase("0"), d[1], Integer.parseInt(d[2]))); try {
continue; this.rewardItems.add(new WiredGiveRewardItem(i, d[0].equalsIgnoreCase("0"), d[1], Integer.parseInt(d[2].trim())));
continue;
} catch (IllegalArgumentException ignored) {
}
} }
} }
@@ -1,6 +1,9 @@
package com.eu.habbo.habbohotel.wired; package com.eu.habbo.habbohotel.wired;
public class WiredGiveRewardItem { public class WiredGiveRewardItem {
private static final int MIN_PROBABILITY = 0;
private static final int MAX_PROBABILITY = 100;
public final int id; public final int id;
public final boolean badge; public final boolean badge;
public final String data; public final String data;
@@ -9,17 +12,20 @@ public class WiredGiveRewardItem {
public WiredGiveRewardItem(int id, boolean badge, String data, int probability) { public WiredGiveRewardItem(int id, boolean badge, String data, int probability) {
this.id = id; this.id = id;
this.badge = badge; this.badge = badge;
this.data = data; this.data = data == null ? "" : data;
this.probability = probability; this.probability = normalizeProbability(probability);
} }
public WiredGiveRewardItem(String dataString) { public WiredGiveRewardItem(String dataString) {
String[] data = dataString.split(","); String[] data = dataString == null ? new String[0] : dataString.split(",", -1);
if (data.length < 4) {
throw new IllegalArgumentException("Invalid wired reward item payload");
}
this.id = Integer.parseInt(data[0]); this.id = parseRequiredInteger(data[0], "id");
this.badge = data[1].equalsIgnoreCase("0"); this.badge = data[1].equalsIgnoreCase("0");
this.data = data[2]; this.data = data[2];
this.probability = Integer.parseInt(data[3]); this.probability = normalizeProbability(parseRequiredInteger(data[3], "probability"));
} }
@Override @Override
@@ -30,4 +36,16 @@ public class WiredGiveRewardItem {
public String wiredString() { public String wiredString() {
return (this.badge ? 0 : 1) + "," + this.data + "," + this.probability; return (this.badge ? 0 : 1) + "," + this.data + "," + this.probability;
} }
private static int parseRequiredInteger(String value, String field) {
try {
return Integer.parseInt(value == null ? "" : value.trim());
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid wired reward item " + field, e);
}
}
private static int normalizeProbability(int probability) {
return Math.max(MIN_PROBABILITY, Math.min(MAX_PROBABILITY, probability));
}
} }
@@ -525,35 +525,55 @@ public class WiredHandler {
if (Emulator.getPluginManager().fireEvent(rewardReceived).isCancelled()) if (Emulator.getPluginManager().fireEvent(rewardReceived).isCancelled())
return false; return false;
if (rewardReceived.value.isEmpty()) String rewardType = rewardReceived.type == null ? "" : rewardReceived.type.trim();
String rewardValue = rewardReceived.value == null ? "" : rewardReceived.value.trim();
if (rewardValue.isEmpty())
return false; return false;
if (rewardReceived.type.equalsIgnoreCase("credits")) { if (rewardType.equalsIgnoreCase("credits")) {
habbo.giveCredits(Integer.parseInt(rewardReceived.value)); Integer amount = parsePositiveRewardInteger(rewardValue);
if (amount == null) return false;
habbo.giveCredits(amount);
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
return true; return true;
} else if (rewardReceived.type.equalsIgnoreCase("diamonds") || rewardReceived.type.equalsIgnoreCase("diamond")) { } else if (rewardType.equalsIgnoreCase("diamonds") || rewardType.equalsIgnoreCase("diamond")) {
habbo.givePoints(5, Integer.parseInt(rewardReceived.value)); Integer amount = parsePositiveRewardInteger(rewardValue);
if (amount == null) return false;
habbo.givePoints(5, amount);
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
return true; return true;
} else if (rewardReceived.type.equalsIgnoreCase("pixels")) { } else if (rewardType.equalsIgnoreCase("pixels")) {
habbo.givePixels(Integer.parseInt(rewardReceived.value)); Integer amount = parsePositiveRewardInteger(rewardValue);
if (amount == null) return false;
habbo.givePixels(amount);
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
return true; return true;
} else if (rewardReceived.type.startsWith("points")) { } else if (rewardType.startsWith("points")) {
int points = Integer.parseInt(rewardReceived.value); Integer points = parsePositiveRewardInteger(rewardValue);
if (points == null) return false;
int type = 5; int type = 5;
try { try {
type = Integer.parseInt(rewardReceived.type.replace("points", "")); int parsedType = Integer.parseInt(rewardType.replace("points", "").trim());
} catch (Exception e) { if (parsedType > 0) {
type = parsedType;
}
} catch (NumberFormatException ignored) {
} }
habbo.givePoints(type, points); habbo.givePoints(type, points);
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
return true; return true;
} else if (rewardReceived.type.equalsIgnoreCase("furni")) { } else if (rewardType.equalsIgnoreCase("furni")) {
Item baseItem = Emulator.getGameEnvironment().getItemManager().getItem(Integer.parseInt(rewardReceived.value)); Integer itemId = parsePositiveRewardInteger(rewardValue);
if (itemId == null) return false;
Item baseItem = Emulator.getGameEnvironment().getItemManager().getItem(itemId);
if (baseItem == null) if (baseItem == null)
return false; return false;
@@ -567,12 +587,18 @@ public class WiredHandler {
habbo.getClient().sendResponse(new InventoryRefreshComposer()); habbo.getClient().sendResponse(new InventoryRefreshComposer());
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
return true; return true;
} else if (rewardReceived.type.equalsIgnoreCase("respect")) { } else if (rewardType.equalsIgnoreCase("respect")) {
habbo.getHabboStats().respectPointsReceived += Integer.parseInt(rewardReceived.value); Integer amount = parsePositiveRewardInteger(rewardValue);
if (amount == null) return false;
habbo.getHabboStats().respectPointsReceived += amount;
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
return true; return true;
} else if (rewardReceived.type.equalsIgnoreCase("cata")) { } else if (rewardType.equalsIgnoreCase("cata")) {
CatalogItem item = Emulator.getGameEnvironment().getCatalogManager().getCatalogItem(Integer.parseInt(rewardReceived.value)); Integer catalogItemId = parsePositiveRewardInteger(rewardValue);
if (catalogItemId == null) return false;
CatalogItem item = Emulator.getGameEnvironment().getCatalogManager().getCatalogItem(catalogItemId);
if (item == null) if (item == null)
return false; return false;
@@ -585,6 +611,15 @@ public class WiredHandler {
return false; return false;
} }
private static Integer parsePositiveRewardInteger(String value) {
try {
int parsed = Integer.parseInt(value == null ? "" : value.trim());
return parsed > 0 ? parsed : null;
} catch (NumberFormatException ignored) {
return null;
}
}
public static boolean getReward(Habbo habbo, WiredEffectGiveReward wiredBox) { public static boolean getReward(Habbo habbo, WiredEffectGiveReward wiredBox) {
if (wiredBox.limit > 0) { if (wiredBox.limit > 0) {
if (wiredBox.limit - wiredBox.getGiven() == 0) { if (wiredBox.limit - wiredBox.getGiven() == 0) {
@@ -1165,35 +1165,52 @@ public final class WiredManager {
return false; return false;
} }
if (rewardReceived.value.isEmpty()) { String rewardType = rewardReceived.type == null ? "" : rewardReceived.type.trim();
String rewardValue = rewardReceived.value == null ? "" : rewardReceived.value.trim();
if (rewardValue.isEmpty()) {
return false; return false;
} }
if (rewardReceived.type.equalsIgnoreCase("credits")) { if (rewardType.equalsIgnoreCase("credits")) {
habbo.giveCredits(Integer.parseInt(rewardReceived.value)); Integer amount = parsePositiveRewardInteger(rewardValue);
if (amount == null) return false;
habbo.giveCredits(amount);
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
return true; return true;
} }
if (rewardReceived.type.equalsIgnoreCase("diamonds") || rewardReceived.type.equalsIgnoreCase("diamond")) { if (rewardType.equalsIgnoreCase("diamonds") || rewardType.equalsIgnoreCase("diamond")) {
habbo.givePoints(5, Integer.parseInt(rewardReceived.value)); Integer amount = parsePositiveRewardInteger(rewardValue);
if (amount == null) return false;
habbo.givePoints(5, amount);
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
return true; return true;
} }
if (rewardReceived.type.equalsIgnoreCase("pixels")) { if (rewardType.equalsIgnoreCase("pixels")) {
habbo.givePixels(Integer.parseInt(rewardReceived.value)); Integer amount = parsePositiveRewardInteger(rewardValue);
if (amount == null) return false;
habbo.givePixels(amount);
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
return true; return true;
} }
if (rewardReceived.type.startsWith("points")) { if (rewardType.startsWith("points")) {
int points = Integer.parseInt(rewardReceived.value); Integer points = parsePositiveRewardInteger(rewardValue);
if (points == null) return false;
int type = 5; int type = 5;
try { try {
type = Integer.parseInt(rewardReceived.type.replace("points", "")); int parsedType = Integer.parseInt(rewardType.replace("points", "").trim());
} catch (Exception e) { if (parsedType > 0) {
type = parsedType;
}
} catch (NumberFormatException ignored) {
} }
habbo.givePoints(type, points); habbo.givePoints(type, points);
@@ -1201,8 +1218,11 @@ public final class WiredManager {
return true; return true;
} }
if (rewardReceived.type.equalsIgnoreCase("furni")) { if (rewardType.equalsIgnoreCase("furni")) {
Item baseItem = Emulator.getGameEnvironment().getItemManager().getItem(Integer.parseInt(rewardReceived.value)); Integer itemId = parsePositiveRewardInteger(rewardValue);
if (itemId == null) return false;
Item baseItem = Emulator.getGameEnvironment().getItemManager().getItem(itemId);
if (baseItem == null) { if (baseItem == null) {
return false; return false;
} }
@@ -1220,14 +1240,20 @@ public final class WiredManager {
return true; return true;
} }
if (rewardReceived.type.equalsIgnoreCase("respect")) { if (rewardType.equalsIgnoreCase("respect")) {
habbo.getHabboStats().respectPointsReceived += Integer.parseInt(rewardReceived.value); Integer amount = parsePositiveRewardInteger(rewardValue);
if (amount == null) return false;
habbo.getHabboStats().respectPointsReceived += amount;
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
return true; return true;
} }
if (rewardReceived.type.equalsIgnoreCase("cata")) { if (rewardType.equalsIgnoreCase("cata")) {
CatalogItem item = Emulator.getGameEnvironment().getCatalogManager().getCatalogItem(Integer.parseInt(rewardReceived.value)); Integer catalogItemId = parsePositiveRewardInteger(rewardValue);
if (catalogItemId == null) return false;
CatalogItem item = Emulator.getGameEnvironment().getCatalogManager().getCatalogItem(catalogItemId);
if (item == null) { if (item == null) {
return false; return false;
} }
@@ -1240,6 +1266,15 @@ public final class WiredManager {
return false; return false;
} }
private static Integer parsePositiveRewardInteger(String value) {
try {
int parsed = Integer.parseInt(value == null ? "" : value.trim());
return parsed > 0 ? parsed : null;
} catch (NumberFormatException ignored) {
return null;
}
}
public static boolean getReward(Habbo habbo, WiredEffectGiveReward wiredBox) { public static boolean getReward(Habbo habbo, WiredEffectGiveReward wiredBox) {
synchronized (wiredBox) { synchronized (wiredBox) {
if (wiredBox.getLimit() > 0) { if (wiredBox.getLimit() > 0) {
@@ -0,0 +1,32 @@
package com.eu.habbo.habbohotel.wired;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
class WiredGiveRewardItemTest {
@Test
void parsesLegacyRewardPayload() {
WiredGiveRewardItem item = new WiredGiveRewardItem("7,1,credits#25,40");
assertEquals(7, item.id);
assertEquals(false, item.badge);
assertEquals("credits#25", item.data);
assertEquals(40, item.probability);
}
@Test
void rejectsMalformedRewardPayloads() {
assertThrows(IllegalArgumentException.class, () -> new WiredGiveRewardItem("7,1,credits#25"));
assertThrows(IllegalArgumentException.class, () -> new WiredGiveRewardItem("abc,1,credits#25,40"));
assertThrows(IllegalArgumentException.class, () -> new WiredGiveRewardItem("7,1,credits#25,nope"));
}
@Test
void clampsRewardProbability() {
assertEquals(100, new WiredGiveRewardItem(1, false, "credits#25", 200).probability);
assertEquals(0, new WiredGiveRewardItem(1, false, "credits#25", -20).probability);
assertEquals(100, new WiredGiveRewardItem("1,1,credits#25,200").probability);
}
}