diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogManager.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogManager.java index 3261a132..0349184f 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogManager.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogManager.java @@ -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); diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogBuyItemEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogBuyItemEvent.java index fdf052bd..05aee181 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogBuyItemEvent.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogBuyItemEvent.java @@ -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;