fix(catalog): bound target offer purchases

This commit is contained in:
simoleo89
2026-06-17 21:22:03 +02:00
parent 0109c25c80
commit 4ceac0bbc6
3 changed files with 60 additions and 3 deletions
@@ -31,18 +31,21 @@ public class PurchaseTargetOfferEvent extends MessageHandler {
HabboOfferPurchase purchase = HabboOfferPurchase.getOrCreate(this.client.getHabbo(), offerId);
if (purchase != null) {
amount = Math.min(offer.getPurchaseLimit() - purchase.getAmount(), amount);
amount = TargetOfferPurchaseGuard.purchasableAmount(amount, offer.getPurchaseLimit(), purchase.getAmount());
if (amount <= 0) return;
int now = Emulator.getIntUnixTimestamp();
if (offer.getExpirationTime() > now) {
purchase.update(amount, now);
CatalogItem item = Emulator.getGameEnvironment().getCatalogManager().getCatalogItem(offer.getCatalogItem());
if (item == null) return;
if (item.isLimited()) {
amount = 1;
}
purchase.update(amount, now);
Emulator.getGameEnvironment().getCatalogManager().purchaseItem(null, item, this.client.getHabbo(), amount, "", false);
}
}
}
}
}
}
@@ -0,0 +1,19 @@
package com.eu.habbo.messages.incoming.catalog;
final class TargetOfferPurchaseGuard {
private TargetOfferPurchaseGuard() {
}
static int purchasableAmount(int requestedAmount, int purchaseLimit, int alreadyPurchased) {
if (requestedAmount <= 0 || purchaseLimit <= 0) {
return 0;
}
int remaining = purchaseLimit - Math.max(alreadyPurchased, 0);
if (remaining <= 0) {
return 0;
}
return Math.min(requestedAmount, remaining);
}
}
@@ -0,0 +1,35 @@
package com.eu.habbo.messages.incoming.catalog;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class TargetOfferPurchaseGuardTest {
@Test
void rejectsInvalidRequestedAmounts() {
assertEquals(0, TargetOfferPurchaseGuard.purchasableAmount(0, 10, 0));
assertEquals(0, TargetOfferPurchaseGuard.purchasableAmount(-5, 10, 0));
}
@Test
void rejectsOffersWithoutPositiveLimits() {
assertEquals(0, TargetOfferPurchaseGuard.purchasableAmount(1, 0, 0));
assertEquals(0, TargetOfferPurchaseGuard.purchasableAmount(1, -10, 0));
}
@Test
void capsAmountToRemainingLimit() {
assertEquals(3, TargetOfferPurchaseGuard.purchasableAmount(10, 5, 2));
}
@Test
void rejectsWhenLimitIsAlreadyConsumed() {
assertEquals(0, TargetOfferPurchaseGuard.purchasableAmount(1, 5, 5));
assertEquals(0, TargetOfferPurchaseGuard.purchasableAmount(1, 5, 8));
}
@Test
void doesNotLetNegativePurchaseHistoryIncreaseRemainingLimit() {
assertEquals(5, TargetOfferPurchaseGuard.purchasableAmount(10, 5, -4));
}
}