Merge pull request #165 from duckietm/dev

🆙 Fix Group Forum buy
This commit is contained in:
DuckieTM
2026-06-10 14:17:32 +02:00
committed by GitHub
2 changed files with 9 additions and 27 deletions
@@ -1247,6 +1247,11 @@ public class CatalogManager {
Guild guild = Emulator.getGameEnvironment().getGuildManager().getGuild(guildId);
if (guild != null && Emulator.getGameEnvironment().getGuildManager().getGuildMember(guild, habbo) != null) {
if (baseItem.getName().equals("guild_forum") && guild.getOwnerId() != habbo.getHabboInfo().getId()) {
habbo.getClient().sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR));
return;
}
InteractionGuildFurni habboItem = (InteractionGuildFurni) Emulator.getGameEnvironment().getItemManager().createItem(habbo.getClient().getHabbo().getHabboInfo().getId(), baseItem, limitedStack, limitedNumber, extradata);
habboItem.setExtradata("");
habboItem.needsUpdate(true);
@@ -14,11 +14,7 @@ import com.eu.habbo.habbohotel.users.HabboBadge;
import com.eu.habbo.habbohotel.users.HabboInventory;
import com.eu.habbo.habbohotel.users.subscriptions.Subscription;
import com.eu.habbo.messages.incoming.MessageHandler;
import com.eu.habbo.messages.outgoing.catalog.AlertPurchaseFailedComposer;
import com.eu.habbo.messages.outgoing.catalog.AlertPurchaseUnavailableComposer;
import com.eu.habbo.messages.outgoing.catalog.BuildersClubFurniCountComposer;
import com.eu.habbo.messages.outgoing.catalog.BuildersClubSubscriptionStatusComposer;
import com.eu.habbo.messages.outgoing.catalog.PurchaseOKComposer;
import com.eu.habbo.messages.outgoing.catalog.*;
import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertComposer;
import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertKeys;
import com.eu.habbo.messages.outgoing.generic.alerts.HotelWillCloseInMinutesComposer;
@@ -52,15 +48,8 @@ public class CatalogBuyItemEvent extends MessageHandler {
int itemId = this.packet.readInt();
String extraData = this.packet.readString();
int count = this.packet.readInt();
// Clamp the client-supplied quantity. Without this the club-offer
// branch accumulates cost in plain ints and a huge count overflows
// to a negative total, bypassing the affordability checks and
// CREDITING the buyer (free currency/subscription exploit).
if (count < 1 || count > 100) {
this.client.sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR).compose());
return;
}
if (count < 1) count = 1;
if (count > 100) count = 100;
try {
if (this.client.getHabbo().getInventory().getItemsComponent().itemCount() > HabboInventory.MAXIMUM_ITEMS) {
@@ -212,12 +201,6 @@ public class CatalogBuyItemEvent extends MessageHandler {
else
item = page.getCatalogItem(itemId);
// Search-results buy sends the catalog offer_id as itemId
// (FurnitureOffer.offerId is derived from furnidata's
// purchaseOfferId, which matches `catalog_items.offer_id`),
// not the `catalog_items.id` primary key that getCatalogItem
// expects. Fall back to scanning the page for the matching
// offer_id so the search → buy flow works.
if (item == null && !(page instanceof RecentPurchasesLayout)) {
for (CatalogItem candidate : page.getCatalogItems().valueCollection()) {
if (candidate != null && candidate.getOfferId() == itemId) {
@@ -226,13 +209,7 @@ public class CatalogBuyItemEvent extends MessageHandler {
}
}
}
// Inventory cap check based on the actual base items the
// purchase will create, not the page layout - bots/pets
// can legitimately live on bundle pages, search results,
// recent-purchases, etc., and the layout-instanceof check
// missed all those paths. Mirrors the bot/pet branches
// inside CatalogManager.purchaseItem (Item.isBot / isPet
// and the same prefix check) so detection stays in sync.
boolean itemHasBot = false;
boolean itemHasPet = false;