Arcturus-Community/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogManager.java

1179 lines
56 KiB
Java
Raw Normal View History

2018-07-06 15:30:00 +02:00
package com.eu.habbo.habbohotel.catalog;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.achievements.AchievementManager;
import com.eu.habbo.habbohotel.bots.Bot;
2022-03-21 19:51:52 +01:00
import com.eu.habbo.habbohotel.campaign.calendar.CalendarRewardObject;
2018-07-06 15:30:00 +02:00
import com.eu.habbo.habbohotel.catalog.layouts.*;
import com.eu.habbo.habbohotel.gameclients.GameClient;
2019-05-11 00:45:07 +02:00
import com.eu.habbo.habbohotel.guilds.Guild;
2018-07-06 15:30:00 +02:00
import com.eu.habbo.habbohotel.items.FurnitureType;
import com.eu.habbo.habbohotel.items.Item;
import com.eu.habbo.habbohotel.items.SoundTrack;
import com.eu.habbo.habbohotel.items.interactions.*;
import com.eu.habbo.habbohotel.modtool.ScripterManager;
2020-06-05 10:12:49 +02:00
import com.eu.habbo.habbohotel.permissions.Permission;
2018-07-06 15:30:00 +02:00
import com.eu.habbo.habbohotel.pets.Pet;
import com.eu.habbo.habbohotel.users.Habbo;
import com.eu.habbo.habbohotel.users.HabboBadge;
import com.eu.habbo.habbohotel.users.HabboGender;
import com.eu.habbo.habbohotel.users.HabboItem;
import com.eu.habbo.messages.outgoing.catalog.*;
import com.eu.habbo.messages.outgoing.events.calendar.AdventCalendarProductComposer;
import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertComposer;
import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertKeys;
import com.eu.habbo.messages.outgoing.inventory.AddBotComposer;
import com.eu.habbo.messages.outgoing.inventory.AddHabboItemComposer;
import com.eu.habbo.messages.outgoing.inventory.AddPetComposer;
import com.eu.habbo.messages.outgoing.inventory.InventoryRefreshComposer;
2019-07-31 18:01:10 +02:00
import com.eu.habbo.messages.outgoing.modtool.ModToolIssueHandledComposer;
2018-07-06 15:30:00 +02:00
import com.eu.habbo.messages.outgoing.users.AddUserBadgeComposer;
import com.eu.habbo.messages.outgoing.users.UserCreditsComposer;
import com.eu.habbo.messages.outgoing.users.UserPointsComposer;
import com.eu.habbo.plugin.events.emulator.EmulatorLoadCatalogManagerEvent;
import com.eu.habbo.plugin.events.users.catalog.UserCatalogFurnitureBoughtEvent;
import com.eu.habbo.plugin.events.users.catalog.UserCatalogItemPurchasedEvent;
import gnu.trove.TCollections;
import gnu.trove.iterator.TIntObjectIterator;
import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.THashMap;
import gnu.trove.map.hash.TIntIntHashMap;
import gnu.trove.map.hash.TIntObjectHashMap;
import gnu.trove.procedure.TObjectProcedure;
import gnu.trove.set.hash.THashSet;
2020-05-03 01:46:07 +02:00
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
2018-07-06 15:30:00 +02:00
import java.sql.*;
import java.util.*;
import java.util.stream.Collectors;
2018-07-06 15:30:00 +02:00
2019-05-26 20:14:53 +02:00
public class CatalogManager {
2018-07-08 23:32:00 +02:00
2020-05-03 01:46:07 +02:00
private static final Logger LOGGER = LoggerFactory.getLogger(CatalogManager.class);
2019-05-26 20:14:53 +02:00
public static final THashMap<String, Class<? extends CatalogPage>> pageDefinitions = new THashMap<String, Class<? extends CatalogPage>>(CatalogPageLayouts.values().length) {
2018-07-06 15:30:00 +02:00
{
2019-05-26 20:14:53 +02:00
for (CatalogPageLayouts layout : CatalogPageLayouts.values()) {
switch (layout) {
2019-03-18 02:22:00 +01:00
case frontpage:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), FrontpageLayout.class);
break;
2019-03-18 02:22:00 +01:00
case badge_display:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), BadgeDisplayLayout.class);
break;
2019-03-18 02:22:00 +01:00
case spaces_new:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), SpacesLayout.class);
break;
2019-03-18 02:22:00 +01:00
case trophies:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), TrophiesLayout.class);
break;
2019-03-18 02:22:00 +01:00
case bots:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), BotsLayout.class);
break;
2019-03-18 02:22:00 +01:00
case club_buy:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), ClubBuyLayout.class);
break;
2019-03-18 02:22:00 +01:00
case club_gift:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), ClubGiftsLayout.class);
break;
2019-03-18 02:22:00 +01:00
case sold_ltd_items:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), SoldLTDItemsLayout.class);
break;
2019-03-18 02:22:00 +01:00
case single_bundle:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), SingleBundle.class);
break;
2019-03-18 02:22:00 +01:00
case roomads:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), RoomAdsLayout.class);
break;
case recycler:
if (Emulator.getConfig().getBoolean("hotel.ecotron.enabled"))
this.put(layout.name().toLowerCase(), RecyclerLayout.class);
break;
case recycler_info:
if (Emulator.getConfig().getBoolean("hotel.ecotron.enabled"))
this.put(layout.name().toLowerCase(), RecyclerInfoLayout.class);
case recycler_prizes:
if (Emulator.getConfig().getBoolean("hotel.ecotron.enabled"))
this.put(layout.name().toLowerCase(), RecyclerPrizesLayout.class);
break;
case marketplace:
if (Emulator.getConfig().getBoolean("hotel.marketplace.enabled"))
this.put(layout.name().toLowerCase(), MarketplaceLayout.class);
break;
case marketplace_own_items:
if (Emulator.getConfig().getBoolean("hotel.marketplace.enabled"))
this.put(layout.name().toLowerCase(), MarketplaceOwnItems.class);
break;
2019-03-18 02:22:00 +01:00
case info_duckets:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), InfoDucketsLayout.class);
break;
2019-03-18 02:22:00 +01:00
case info_pets:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), InfoPetsLayout.class);
break;
2019-03-18 02:22:00 +01:00
case info_rentables:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), InfoRentablesLayout.class);
break;
2019-03-18 02:22:00 +01:00
case info_loyalty:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), InfoLoyaltyLayout.class);
break;
2019-03-18 02:22:00 +01:00
case loyalty_vip_buy:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), LoyaltyVipBuyLayout.class);
break;
2019-03-18 02:22:00 +01:00
case guilds:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), GuildFrontpageLayout.class);
break;
2019-03-18 02:22:00 +01:00
case guild_furni:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), GuildFurnitureLayout.class);
break;
2019-03-18 02:22:00 +01:00
case guild_forum:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), GuildForumLayout.class);
break;
2019-03-18 02:22:00 +01:00
case pets:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), PetsLayout.class);
break;
2019-03-18 02:22:00 +01:00
case pets2:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), Pets2Layout.class);
break;
2019-03-18 02:22:00 +01:00
case pets3:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), Pets3Layout.class);
break;
2019-03-18 02:22:00 +01:00
case soundmachine:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), TraxLayout.class);
break;
2019-03-18 02:22:00 +01:00
case default_3x3_color_grouping:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), ColorGroupingLayout.class);
break;
2019-03-18 02:22:00 +01:00
case recent_purchases:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), RecentPurchasesLayout.class);
break;
2019-03-18 02:22:00 +01:00
case room_bundle:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), RoomBundleLayout.class);
break;
2019-03-18 02:22:00 +01:00
case petcustomization:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), PetCustomizationLayout.class);
break;
2019-03-18 02:22:00 +01:00
case vip_buy:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), VipBuyLayout.class);
break;
2019-03-18 02:22:00 +01:00
case frontpage_featured:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), FrontPageFeaturedLayout.class);
break;
2019-03-18 02:22:00 +01:00
case builders_club_addons:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), BuildersClubAddonsLayout.class);
break;
2019-03-18 02:22:00 +01:00
case builders_club_frontpage:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), BuildersClubFrontPageLayout.class);
break;
2019-03-18 02:22:00 +01:00
case builders_club_loyalty:
2019-05-26 20:14:53 +02:00
this.put(layout.name().toLowerCase(), BuildersClubLoyaltyLayout.class);
break;
2018-07-06 15:30:00 +02:00
case default_3x3:
2019-03-18 02:22:00 +01:00
default:
2019-05-26 20:14:53 +02:00
this.put("default_3x3", Default_3x3Layout.class);
break;
2018-07-06 15:30:00 +02:00
}
}
}
};
2019-05-26 20:14:53 +02:00
public static int catalogItemAmount;
public static int PURCHASE_COOLDOWN = 1;
public static boolean SORT_USING_ORDERNUM = false;
public final TIntObjectMap<CatalogPage> catalogPages;
public final TIntObjectMap<CatalogFeaturedPage> catalogFeaturedPages;
public final THashMap<Integer, THashSet<Item>> prizes;
public final THashMap<Integer, Integer> giftWrappers;
public final THashMap<Integer, Integer> giftFurnis;
public final THashSet<CatalogItem> clubItems;
public final THashMap<Integer, ClubOffer> clubOffers;
public final THashMap<Integer, TargetOffer> targetOffers;
public final THashMap<Integer, ClothItem> clothing;
public final TIntIntHashMap offerDefs;
public final Item ecotronItem;
public final THashMap<Integer, CatalogLimitedConfiguration> limitedNumbers;
private final List<Voucher> vouchers;
2018-07-06 15:30:00 +02:00
2019-05-26 20:14:53 +02:00
public CatalogManager() {
long millis = System.currentTimeMillis();
this.catalogPages = TCollections.synchronizedMap(new TIntObjectHashMap<>());
this.catalogFeaturedPages = new TIntObjectHashMap<>();
this.prizes = new THashMap<>();
this.giftWrappers = new THashMap<>();
this.giftFurnis = new THashMap<>();
this.clubItems = new THashSet<>();
this.clubOffers = new THashMap<>();
this.targetOffers = new THashMap<>();
this.clothing = new THashMap<>();
this.offerDefs = new TIntIntHashMap();
this.vouchers = new ArrayList<>();
this.limitedNumbers = new THashMap<>();
2018-07-06 15:30:00 +02:00
this.initialize();
this.ecotronItem = Emulator.getGameEnvironment().getItemManager().getItem("ecotron_box");
2020-05-03 01:46:07 +02:00
LOGGER.info("Catalog Manager -> Loaded! (" + (System.currentTimeMillis() - millis) + " MS)");
2018-07-06 15:30:00 +02:00
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
public synchronized void initialize() {
2018-07-06 15:30:00 +02:00
Emulator.getPluginManager().fireEvent(new EmulatorLoadCatalogManagerEvent());
2019-05-24 00:57:22 +02:00
this.loadLimitedNumbers();
this.loadCatalogPages();
this.loadCatalogFeaturedPages();
this.loadCatalogItems();
this.loadClubOffers();
this.loadTargetOffers();
this.loadVouchers();
this.loadClothing();
this.loadRecycler();
this.loadGiftWrappers();
2018-07-06 15:30:00 +02:00
}
2019-05-26 20:14:53 +02:00
private synchronized void loadLimitedNumbers() {
2018-07-06 15:30:00 +02:00
this.limitedNumbers.clear();
2018-09-28 21:25:00 +02:00
THashMap<Integer, LinkedList<Integer>> limiteds = new THashMap<>();
2018-07-06 15:30:00 +02:00
TIntIntHashMap totals = new TIntIntHashMap();
2019-05-26 20:14:53 +02:00
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT * FROM catalog_items_limited")) {
try (ResultSet set = statement.executeQuery()) {
while (set.next()) {
if (!limiteds.containsKey(set.getInt("catalog_item_id"))) {
2018-09-28 21:25:00 +02:00
limiteds.put(set.getInt("catalog_item_id"), new LinkedList<>());
2018-07-06 15:30:00 +02:00
}
totals.adjustOrPutValue(set.getInt("catalog_item_id"), 1, 1);
2019-05-26 20:14:53 +02:00
if (set.getInt("user_id") == 0) {
2018-07-06 15:30:00 +02:00
limiteds.get(set.getInt("catalog_item_id")).push(set.getInt("number"));
}
}
}
2019-05-26 20:14:53 +02:00
} catch (SQLException e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Caught SQL exception", e);
2018-07-06 15:30:00 +02:00
}
2019-05-26 20:14:53 +02:00
for (Map.Entry<Integer, LinkedList<Integer>> set : limiteds.entrySet()) {
2018-07-06 15:30:00 +02:00
this.limitedNumbers.put(set.getKey(), new CatalogLimitedConfiguration(set.getKey(), set.getValue(), totals.get(set.getKey())));
}
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
private synchronized void loadCatalogPages() {
2018-07-06 15:30:00 +02:00
this.catalogPages.clear();
2018-09-28 21:25:00 +02:00
final THashMap<Integer, CatalogPage> pages = new THashMap<>();
2019-05-24 00:57:22 +02:00
pages.put(-1, new CatalogRootLayout());
2019-05-26 20:14:53 +02:00
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT * FROM catalog_pages ORDER BY parent_id, id")) {
try (ResultSet set = statement.executeQuery()) {
while (set.next()) {
2019-03-18 02:22:00 +01:00
Class<? extends CatalogPage> pageClazz = pageDefinitions.get(set.getString("page_layout"));
2019-05-26 20:14:53 +02:00
if (pageClazz == null) {
2020-05-03 01:46:07 +02:00
LOGGER.info("Unknown Page Layout: " + set.getString("page_layout"));
2019-03-18 02:22:00 +01:00
continue;
}
2019-05-26 20:14:53 +02:00
try {
2019-03-18 02:22:00 +01:00
CatalogPage page = pageClazz.getConstructor(ResultSet.class).newInstance(set);
pages.put(page.getId(), page);
2019-05-26 20:14:53 +02:00
} catch (Exception e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Failed to load layout: {}", set.getString("page_layout"));
2019-03-18 02:22:00 +01:00
}
}
}
2019-05-26 20:14:53 +02:00
} catch (SQLException e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Caught SQL exception", e);
2018-07-06 15:30:00 +02:00
}
pages.forEachValue((object) -> {
CatalogPage page = pages.get(object.parentId);
2018-07-06 15:30:00 +02:00
if (page != null) {
if (page.id != object.id) {
page.addChildPage(object);
}
} else {
if (object.parentId != -2) {
2020-05-03 01:46:07 +02:00
LOGGER.info("Parent Page not found for " + object.getPageName() + " (ID: " + object.id + ", parent_id: " + object.parentId + ")");
2018-07-06 15:30:00 +02:00
}
}
return true;
2018-07-06 15:30:00 +02:00
});
this.catalogPages.putAll(pages);
2020-05-03 01:46:07 +02:00
LOGGER.info("Loaded " + this.catalogPages.size() + " Catalog Pages!");
2018-07-06 15:30:00 +02:00
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
private synchronized void loadCatalogFeaturedPages() {
2018-07-06 15:30:00 +02:00
this.catalogFeaturedPages.clear();
2019-05-26 20:14:53 +02:00
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); Statement statement = connection.createStatement(); ResultSet set = statement.executeQuery("SELECT * FROM catalog_featured_pages ORDER BY slot_id ASC")) {
while (set.next()) {
2018-07-06 15:30:00 +02:00
this.catalogFeaturedPages.put(set.getInt("slot_id"), new CatalogFeaturedPage(
set.getInt("slot_id"),
set.getString("caption"),
set.getString("image"),
CatalogFeaturedPage.Type.valueOf(set.getString("type").toUpperCase()),
set.getInt("expire_timestamp"),
set.getString("page_name"),
set.getInt("page_id"),
set.getString("product_name")
2019-05-26 20:14:53 +02:00
));
2018-07-06 15:30:00 +02:00
}
2019-05-26 20:14:53 +02:00
} catch (SQLException e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Caught SQL exception", e);
2018-07-06 15:30:00 +02:00
}
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
private synchronized void loadCatalogItems() {
2018-07-06 15:30:00 +02:00
this.clubItems.clear();
catalogItemAmount = 0;
2019-05-26 20:14:53 +02:00
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); Statement statement = connection.createStatement(); ResultSet set = statement.executeQuery("SELECT * FROM catalog_items")) {
2018-07-06 15:30:00 +02:00
CatalogItem item;
2019-05-26 20:14:53 +02:00
while (set.next()) {
2018-07-06 15:30:00 +02:00
if (set.getString("item_ids").equals("0"))
continue;
2019-05-26 20:14:53 +02:00
if (set.getString("catalog_name").contains("HABBO_CLUB_")) {
2018-07-06 15:30:00 +02:00
this.clubItems.add(new CatalogItem(set));
continue;
}
CatalogPage page = this.catalogPages.get(set.getInt("page_id"));
if (page == null)
continue;
item = page.getCatalogItem(set.getInt("id"));
2019-05-26 20:14:53 +02:00
if (item == null) {
2018-07-06 15:30:00 +02:00
catalogItemAmount++;
item = new CatalogItem(set);
page.addItem(item);
2019-05-26 20:14:53 +02:00
if (item.getOfferId() != -1) {
2018-07-06 15:30:00 +02:00
page.addOfferId(item.getOfferId());
2018-09-28 21:25:00 +02:00
this.offerDefs.put(item.getOfferId(), item.getId());
2018-07-06 15:30:00 +02:00
}
2019-05-26 20:14:53 +02:00
} else
2018-07-06 15:30:00 +02:00
item.update(set);
2019-05-26 20:14:53 +02:00
if (item.isLimited()) {
2018-07-06 15:30:00 +02:00
this.createOrUpdateLimitedConfig(item);
}
}
2019-05-26 20:14:53 +02:00
} catch (SQLException e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Caught SQL exception", e);
2018-07-06 15:30:00 +02:00
}
2019-05-26 20:14:53 +02:00
for (CatalogPage page : this.catalogPages.valueCollection()) {
for (Integer id : page.getIncluded()) {
2018-07-06 15:30:00 +02:00
CatalogPage p = this.catalogPages.get(id);
2019-05-26 20:14:53 +02:00
if (p != null) {
2018-07-06 15:30:00 +02:00
page.getCatalogItems().putAll(p.getCatalogItems());
}
}
}
}
2019-05-26 20:14:53 +02:00
private void loadClubOffers() {
this.clubOffers.clear();
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT * FROM catalog_club_offers WHERE enabled = ?")) {
statement.setString(1, "1");
try (ResultSet set = statement.executeQuery()) {
while (set.next()) {
this.clubOffers.put(set.getInt("id"), new ClubOffer(set));
}
}
} catch (SQLException e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Caught SQL exception", e);
2019-05-24 00:57:22 +02:00
}
2018-07-06 15:30:00 +02:00
}
2019-05-26 20:14:53 +02:00
private void loadTargetOffers() {
synchronized (this.targetOffers) {
2018-10-07 00:28:00 +02:00
this.targetOffers.clear();
2019-05-26 20:14:53 +02:00
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT * FROM catalog_target_offers WHERE end_timestamp > ?")) {
2018-10-07 00:28:00 +02:00
statement.setInt(1, Emulator.getIntUnixTimestamp());
2019-05-26 20:14:53 +02:00
try (ResultSet set = statement.executeQuery()) {
while (set.next()) {
2018-10-07 00:28:00 +02:00
this.targetOffers.put(set.getInt("id"), new TargetOffer(set));
}
}
2019-05-26 20:14:53 +02:00
} catch (SQLException e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Caught SQL exception", e);
2019-05-24 00:57:22 +02:00
}
2018-10-07 00:28:00 +02:00
}
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
private void loadVouchers() {
synchronized (this.vouchers) {
2018-07-06 15:30:00 +02:00
this.vouchers.clear();
2019-05-26 20:14:53 +02:00
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); Statement statement = connection.createStatement(); ResultSet set = statement.executeQuery("SELECT * FROM vouchers")) {
while (set.next()) {
2018-07-06 15:30:00 +02:00
this.vouchers.add(new Voucher(set));
}
2019-05-26 20:14:53 +02:00
} catch (SQLException e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Caught SQL exception", e);
2019-05-24 00:57:22 +02:00
}
2018-07-06 15:30:00 +02:00
}
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
public void loadRecycler() {
synchronized (this.prizes) {
2018-07-06 15:30:00 +02:00
this.prizes.clear();
2019-05-26 20:14:53 +02:00
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); Statement statement = connection.createStatement(); ResultSet set = statement.executeQuery("SELECT * FROM recycler_prizes")) {
while (set.next()) {
2018-07-06 15:30:00 +02:00
Item item = Emulator.getGameEnvironment().getItemManager().getItem(set.getInt("item_id"));
2019-05-26 20:14:53 +02:00
if (item != null) {
if (this.prizes.get(set.getInt("rarity")) == null) {
2018-09-28 21:25:00 +02:00
this.prizes.put(set.getInt("rarity"), new THashSet<>());
2018-07-06 15:30:00 +02:00
}
this.prizes.get(set.getInt("rarity")).add(item);
2019-05-26 20:14:53 +02:00
} else {
2020-05-03 01:46:07 +02:00
LOGGER.error("Cannot load item with ID: {} as recycler reward!", set.getInt("item_id"));
2018-07-06 15:30:00 +02:00
}
}
2019-05-26 20:14:53 +02:00
} catch (SQLException e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Caught SQL exception", e);
2018-07-06 15:30:00 +02:00
}
}
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
public void loadGiftWrappers() {
synchronized (this.giftWrappers) {
synchronized (this.giftFurnis) {
2018-07-06 15:30:00 +02:00
this.giftWrappers.clear();
this.giftFurnis.clear();
2019-05-26 20:14:53 +02:00
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); Statement statement = connection.createStatement(); ResultSet set = statement.executeQuery("SELECT * FROM gift_wrappers ORDER BY sprite_id DESC")) {
while (set.next()) {
switch (set.getString("type")) {
2018-07-06 15:30:00 +02:00
case "wrapper":
this.giftWrappers.put(set.getInt("sprite_id"), set.getInt("item_id"));
break;
case "gift":
this.giftFurnis.put(set.getInt("sprite_id"), set.getInt("item_id"));
break;
}
}
2019-05-26 20:14:53 +02:00
} catch (SQLException e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Caught SQL exception", e);
2018-07-06 15:30:00 +02:00
}
}
}
}
2019-05-26 20:14:53 +02:00
private void loadClothing() {
synchronized (this.clothing) {
2018-07-06 15:30:00 +02:00
this.clothing.clear();
2019-05-26 20:14:53 +02:00
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); Statement statement = connection.createStatement(); ResultSet set = statement.executeQuery("SELECT * FROM catalog_clothing")) {
while (set.next()) {
2018-07-06 15:30:00 +02:00
this.clothing.put(set.getInt("id"), new ClothItem(set));
}
2019-05-26 20:14:53 +02:00
} catch (SQLException e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Caught SQL exception", e);
2018-07-06 15:30:00 +02:00
}
}
}
2019-05-26 20:14:53 +02:00
public ClothItem getClothing(String name) {
for (ClothItem item : this.clothing.values()) {
if (item.name.equalsIgnoreCase(name)) {
2018-07-06 15:30:00 +02:00
return item;
}
}
return null;
}
2019-05-26 20:14:53 +02:00
public Voucher getVoucher(String code) {
synchronized (this.vouchers) {
for (Voucher voucher : this.vouchers) {
if (voucher.code.equals(code)) {
2018-07-06 15:30:00 +02:00
return voucher;
}
}
}
return null;
}
2019-05-26 20:14:53 +02:00
public void redeemVoucher(GameClient client, String voucherCode) {
2022-03-02 23:20:16 +01:00
Habbo habbo = client.getHabbo();
if (habbo == null)
return;
2018-07-06 15:30:00 +02:00
2022-03-02 23:20:16 +01:00
Voucher voucher = Emulator.getGameEnvironment().getCatalogManager().getVoucher(voucherCode);
2019-07-31 18:01:10 +02:00
if (voucher == null) {
client.sendResponse(new RedeemVoucherErrorComposer(RedeemVoucherErrorComposer.INVALID_CODE));
return;
}
2018-07-06 15:30:00 +02:00
2019-07-31 18:01:10 +02:00
if (voucher.isExhausted()) {
2022-03-02 23:20:16 +01:00
client.sendResponse(new RedeemVoucherErrorComposer(Emulator.getGameEnvironment().getCatalogManager().deleteVoucher(voucher) ? RedeemVoucherErrorComposer.INVALID_CODE : RedeemVoucherErrorComposer.TECHNICAL_ERROR));
return;
2019-07-31 18:01:10 +02:00
}
2018-07-06 15:30:00 +02:00
2019-07-31 18:01:10 +02:00
if (voucher.hasUserExhausted(habbo.getHabboInfo().getId())) {
client.sendResponse(new ModToolIssueHandledComposer("You have exceeded the limit for redeeming this voucher."));
return;
}
2018-07-06 15:30:00 +02:00
2019-07-31 18:01:10 +02:00
voucher.addHistoryEntry(habbo.getHabboInfo().getId());
if (voucher.points > 0) {
client.getHabbo().getHabboInfo().addCurrencyAmount(voucher.pointsType, voucher.points);
client.sendResponse(new UserPointsComposer(client.getHabbo().getHabboInfo().getCurrencyAmount(voucher.pointsType), voucher.points, voucher.pointsType));
}
if (voucher.credits > 0) {
client.getHabbo().getHabboInfo().addCredits(voucher.credits);
client.sendResponse(new UserCreditsComposer(client.getHabbo()));
}
2018-07-06 15:30:00 +02:00
2019-07-31 18:01:10 +02:00
if (voucher.catalogItemId > 0) {
CatalogItem item = this.getCatalogItem(voucher.catalogItemId);
if (item != null) {
this.purchaseItem(null, item, client.getHabbo(), 1, "", true);
2018-07-06 15:30:00 +02:00
}
}
2019-07-31 18:01:10 +02:00
client.sendResponse(new RedeemVoucherOKComposer());
2018-07-06 15:30:00 +02:00
}
2019-05-26 20:14:53 +02:00
public boolean deleteVoucher(Voucher voucher) {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("DELETE FROM vouchers WHERE code = ?")) {
2018-07-06 15:30:00 +02:00
statement.setString(1, voucher.code);
2019-05-26 20:14:53 +02:00
synchronized (this.vouchers) {
2018-07-06 15:30:00 +02:00
this.vouchers.remove(voucher);
}
return statement.executeUpdate() >= 1;
2019-05-26 20:14:53 +02:00
} catch (SQLException e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Caught SQL exception", e);
2018-07-06 15:30:00 +02:00
}
return false;
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
public CatalogPage getCatalogPage(int pageId) {
2018-07-06 15:30:00 +02:00
return this.catalogPages.get(pageId);
}
public CatalogPage getCatalogPage(String captionSafe) {
2019-06-16 13:06:04 +02:00
return this.catalogPages.valueCollection().stream()
.filter(p -> p != null && p.getPageName() != null && p.getPageName().equalsIgnoreCase(captionSafe))
.findAny().orElse(null);
2018-07-06 15:30:00 +02:00
}
public CatalogPage getCatalogPageByLayout(String layoutName) {
return this.catalogPages.valueCollection().stream()
.filter(p -> p != null &&
p.isVisible() &&
p.isEnabled() &&
p.getRank() < 2 &&
p.getLayout() != null && p.getLayout().equalsIgnoreCase(layoutName)
)
.findAny().orElse(null);
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
public CatalogItem getCatalogItem(int id) {
2018-07-06 15:30:00 +02:00
final CatalogItem[] item = {null};
2019-05-26 20:14:53 +02:00
synchronized (this.catalogPages) {
this.catalogPages.forEachValue(new TObjectProcedure<CatalogPage>() {
2018-07-06 15:30:00 +02:00
@Override
2019-05-26 20:14:53 +02:00
public boolean execute(CatalogPage object) {
2018-07-06 15:30:00 +02:00
item[0] = object.getCatalogItem(id);
return item[0] == null;
}
});
}
return item[0];
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
public List<CatalogPage> getCatalogPages(int parentId, final Habbo habbo) {
2018-09-28 21:25:00 +02:00
final List<CatalogPage> pages = new ArrayList<>();
2018-07-06 15:30:00 +02:00
2019-05-26 20:14:53 +02:00
this.catalogPages.get(parentId).childPages.forEachValue(new TObjectProcedure<CatalogPage>() {
2018-07-06 15:30:00 +02:00
@Override
2019-05-26 20:14:53 +02:00
public boolean execute(CatalogPage object) {
boolean isVisiblePage = object.visible;
boolean hasRightRank = object.getRank() <= habbo.getHabboInfo().getRank().getId();
boolean clubRightsOkay = true;
if(object.isClubOnly() && !habbo.getHabboInfo().getHabboStats().hasActiveClub()) {
clubRightsOkay = false;
}
if (isVisiblePage && hasRightRank && clubRightsOkay) {
2018-07-06 15:30:00 +02:00
pages.add(object);
}
return true;
}
});
Collections.sort(pages);
return pages;
}
2019-05-26 20:14:53 +02:00
public TIntObjectMap<CatalogFeaturedPage> getCatalogFeaturedPages() {
2018-07-06 15:30:00 +02:00
return this.catalogFeaturedPages;
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
public CatalogItem getClubItem(int itemId) {
synchronized (this.clubItems) {
for (CatalogItem item : this.clubItems) {
2018-07-06 15:30:00 +02:00
if (item.getId() == itemId)
return item;
}
}
return null;
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
public boolean moveCatalogItem(CatalogItem item, int pageId) {
2018-07-06 15:30:00 +02:00
CatalogPage page = this.getCatalogPage(item.getPageId());
2019-05-26 20:14:53 +02:00
if (page == null)
2018-07-06 15:30:00 +02:00
return false;
page.getCatalogItems().remove(item.getId());
page = this.getCatalogPage(pageId);
page.getCatalogItems().put(item.getId(), item);
item.setPageId(pageId);
2019-04-22 01:42:00 +02:00
item.run();
2018-07-06 15:30:00 +02:00
return true;
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
public Item getRandomRecyclerPrize() {
2018-07-06 15:30:00 +02:00
int level = 1;
2019-05-26 20:14:53 +02:00
if (Emulator.getRandom().nextInt(Emulator.getConfig().getInt("hotel.ecotron.rarity.chance.5")) + 1 == Emulator.getConfig().getInt("hotel.ecotron.rarity.chance.5")) {
2018-07-06 15:30:00 +02:00
level = 5;
2019-05-26 20:14:53 +02:00
} else if (Emulator.getRandom().nextInt(Emulator.getConfig().getInt("hotel.ecotron.rarity.chance.4")) + 1 == Emulator.getConfig().getInt("hotel.ecotron.rarity.chance.4")) {
2018-07-06 15:30:00 +02:00
level = 4;
2019-05-26 20:14:53 +02:00
} else if (Emulator.getRandom().nextInt(Emulator.getConfig().getInt("hotel.ecotron.rarity.chance.3")) + 1 == Emulator.getConfig().getInt("hotel.ecotron.rarity.chance.3")) {
2018-07-06 15:30:00 +02:00
level = 3;
2019-05-26 20:14:53 +02:00
} else if (Emulator.getRandom().nextInt(Emulator.getConfig().getInt("hotel.ecotron.rarity.chance.2")) + 1 == Emulator.getConfig().getInt("hotel.ecotron.rarity.chance.2")) {
2018-07-06 15:30:00 +02:00
level = 2;
}
2019-05-26 20:14:53 +02:00
if (this.prizes.containsKey(level) && !this.prizes.get(level).isEmpty()) {
2018-07-06 15:30:00 +02:00
return (Item) this.prizes.get(level).toArray()[Emulator.getRandom().nextInt(this.prizes.get(level).size())];
2019-05-26 20:14:53 +02:00
} else {
2020-05-03 01:46:07 +02:00
LOGGER.error("No rewards specified for rarity level {}", level);
2018-07-06 15:30:00 +02:00
}
return null;
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
public CatalogPage createCatalogPage(String caption, String captionSave, int roomId, int icon, CatalogPageLayouts layout, int minRank, int parentId) {
2018-07-06 15:30:00 +02:00
CatalogPage catalogPage = null;
2019-05-26 20:14:53 +02:00
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("INSERT INTO catalog_pages (parent_id, caption, caption_save, icon_image, visible, enabled, min_rank, page_layout, room_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS)) {
2018-07-06 15:30:00 +02:00
statement.setInt(1, parentId);
statement.setString(2, caption);
statement.setString(3, captionSave);
statement.setInt(4, icon);
statement.setString(5, "1");
statement.setString(6, "1");
statement.setInt(7, minRank);
statement.setString(8, layout.name());
statement.setInt(9, roomId);
statement.execute();
2019-05-26 20:14:53 +02:00
try (ResultSet set = statement.getGeneratedKeys()) {
if (set.next()) {
try (PreparedStatement stmt = connection.prepareStatement("SELECT * FROM catalog_pages WHERE id = ?")) {
2018-07-06 15:30:00 +02:00
stmt.setInt(1, set.getInt(1));
2019-05-26 20:14:53 +02:00
try (ResultSet page = stmt.executeQuery()) {
if (page.next()) {
2018-07-06 15:30:00 +02:00
Class<? extends CatalogPage> pageClazz = pageDefinitions.get(page.getString("page_layout"));
2019-05-26 20:14:53 +02:00
if (pageClazz != null) {
try {
2018-07-06 15:30:00 +02:00
catalogPage = pageClazz.getConstructor(ResultSet.class).newInstance(page);
2019-05-26 20:14:53 +02:00
} catch (Exception e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Caught exception", e);
2018-07-06 15:30:00 +02:00
}
2019-05-26 20:14:53 +02:00
} else {
2020-05-03 01:46:07 +02:00
LOGGER.error("Unknown page layout: {}", page.getString("page_layout"));
2018-07-06 15:30:00 +02:00
}
}
}
}
}
}
2019-05-26 20:14:53 +02:00
} catch (SQLException e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Caught SQL exception", e);
2018-07-06 15:30:00 +02:00
}
2019-05-26 20:14:53 +02:00
if (catalogPage != null) {
2018-07-06 15:30:00 +02:00
this.catalogPages.put(catalogPage.getId(), catalogPage);
}
return catalogPage;
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
public CatalogLimitedConfiguration getLimitedConfig(CatalogItem item) {
synchronized (this.limitedNumbers) {
2018-07-06 15:30:00 +02:00
return this.limitedNumbers.get(item.getId());
}
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
public CatalogLimitedConfiguration createOrUpdateLimitedConfig(CatalogItem item) {
if (item.isLimited()) {
2018-07-06 15:30:00 +02:00
CatalogLimitedConfiguration limitedConfiguration = this.limitedNumbers.get(item.getId());
2019-05-26 20:14:53 +02:00
if (limitedConfiguration == null) {
2018-09-28 21:25:00 +02:00
limitedConfiguration = new CatalogLimitedConfiguration(item.getId(), new LinkedList<>(), 0);
2018-07-06 15:30:00 +02:00
limitedConfiguration.generateNumbers(1, item.limitedStack);
this.limitedNumbers.put(item.getId(), limitedConfiguration);
2019-05-26 20:14:53 +02:00
} else {
if (limitedConfiguration.getTotalSet() != item.limitedStack) {
if (limitedConfiguration.getTotalSet() == 0) {
2018-07-06 15:30:00 +02:00
limitedConfiguration.setTotalSet(item.limitedStack);
2019-05-26 20:14:53 +02:00
} else if (item.limitedStack > limitedConfiguration.getTotalSet()) {
2018-07-06 15:30:00 +02:00
limitedConfiguration.generateNumbers(item.limitedStack + 1, item.limitedStack - limitedConfiguration.getTotalSet());
2019-05-26 20:14:53 +02:00
} else {
2018-07-06 15:30:00 +02:00
item.limitedStack = limitedConfiguration.getTotalSet();
}
}
}
return limitedConfiguration;
}
return null;
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
public void dispose() {
2018-07-06 15:30:00 +02:00
TIntObjectIterator<CatalogPage> pageIterator = this.catalogPages.iterator();
2019-05-26 20:14:53 +02:00
while (pageIterator.hasNext()) {
2018-07-06 15:30:00 +02:00
pageIterator.advance();
2019-05-26 20:14:53 +02:00
for (CatalogItem item : pageIterator.value().getCatalogItems().valueCollection()) {
2018-07-06 15:30:00 +02:00
item.run();
2019-05-26 20:14:53 +02:00
if (item.isLimited()) {
2018-07-06 15:30:00 +02:00
this.limitedNumbers.get(item.getId()).run();
}
}
}
2020-05-03 01:46:07 +02:00
LOGGER.info("Catalog Manager -> Disposed!");
2018-07-06 15:30:00 +02:00
}
2018-07-08 23:32:00 +02:00
2019-05-26 20:14:53 +02:00
public void purchaseItem(CatalogPage page, CatalogItem item, Habbo habbo, int amount, String extradata, boolean free) {
2018-07-06 15:30:00 +02:00
Item cBaseItem = null;
2019-05-26 20:14:53 +02:00
if (item == null || habbo.getHabboStats().isPurchasingFurniture) {
2018-07-06 15:30:00 +02:00
habbo.getClient().sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR).compose());
return;
}
2018-10-07 00:28:00 +02:00
habbo.getHabboStats().isPurchasingFurniture = true;
2018-07-06 15:30:00 +02:00
2019-05-26 20:14:53 +02:00
try {
if (item.isClubOnly() && !habbo.getClient().getHabbo().getHabboStats().hasActiveClub()) {
2018-10-07 00:28:00 +02:00
habbo.getClient().sendResponse(new AlertPurchaseUnavailableComposer(AlertPurchaseUnavailableComposer.REQUIRES_CLUB));
return;
}
2018-09-12 18:45:00 +02:00
2019-05-26 20:14:53 +02:00
if (amount <= 0) {
2018-10-07 00:28:00 +02:00
habbo.getClient().sendResponse(new AlertPurchaseUnavailableComposer(AlertPurchaseUnavailableComposer.ILLEGAL));
return;
}
2019-05-26 20:14:53 +02:00
try {
2018-10-07 00:28:00 +02:00
CatalogLimitedConfiguration limitedConfiguration = null;
int limitedStack = 0;
int limitedNumber = 0;
2019-05-26 20:14:53 +02:00
if (item.isLimited()) {
2018-10-07 00:28:00 +02:00
amount = 1;
2019-05-26 20:14:53 +02:00
if (this.getLimitedConfig(item).available() == 0) {
2018-10-07 00:28:00 +02:00
habbo.getClient().sendResponse(new AlertLimitedSoldOutComposer());
2018-09-12 18:45:00 +02:00
return;
}
2019-05-26 20:14:53 +02:00
if (Emulator.getConfig().getBoolean("hotel.catalog.ltd.limit.enabled")) {
2018-10-07 00:28:00 +02:00
int ltdLimit = Emulator.getConfig().getInt("hotel.purchase.ltd.limit.daily.total");
2019-05-26 20:14:53 +02:00
if (habbo.getHabboStats().totalLtds() >= ltdLimit) {
2018-10-07 00:28:00 +02:00
habbo.alert(Emulator.getTexts().getValue("error.catalog.buy.limited.daily.total").replace("%itemname%", item.getBaseItems().iterator().next().getFullName()).replace("%limit%", ltdLimit + ""));
return;
}
ltdLimit = Emulator.getConfig().getInt("hotel.purchase.ltd.limit.daily.item");
2019-05-26 20:14:53 +02:00
if (habbo.getHabboStats().totalLtds(item.id) >= ltdLimit) {
2018-10-07 00:28:00 +02:00
habbo.alert(Emulator.getTexts().getValue("error.catalog.buy.limited.daily.item").replace("%itemname%", item.getBaseItems().iterator().next().getFullName()).replace("%limit%", ltdLimit + ""));
return;
}
2018-09-12 18:45:00 +02:00
}
}
2018-07-06 15:30:00 +02:00
2019-05-26 20:14:53 +02:00
if (amount > 1) {
if (amount == item.getAmount()) {
2018-10-07 00:28:00 +02:00
amount = 1;
2019-05-26 20:14:53 +02:00
} else {
if (amount * item.getAmount() > 100) {
2019-03-18 02:22:00 +01:00
habbo.alert("Whoops! You tried to buy this " + (amount * item.getAmount()) + " times. This must've been a mistake.");
2018-10-07 00:28:00 +02:00
habbo.getClient().sendResponse(new AlertPurchaseUnavailableComposer(AlertPurchaseUnavailableComposer.ILLEGAL));
return;
}
2018-07-06 15:30:00 +02:00
}
}
2018-10-07 00:28:00 +02:00
THashSet<HabboItem> itemsList = new THashSet<>();
2018-07-06 15:30:00 +02:00
2019-05-26 20:14:53 +02:00
if (amount > 1 && !CatalogItem.haveOffer(item)) {
2018-10-07 00:28:00 +02:00
String message = Emulator.getTexts().getValue("scripter.warning.catalog.amount").replace("%username%", habbo.getHabboInfo().getUsername()).replace("%itemname%", item.getName()).replace("%pagename%", page.getCaption());
ScripterManager.scripterDetected(habbo.getClient(), message);
2020-05-03 01:46:07 +02:00
LOGGER.info(message);
2018-10-07 00:28:00 +02:00
habbo.getClient().sendResponse(new AlertPurchaseUnavailableComposer(AlertPurchaseUnavailableComposer.ILLEGAL));
return;
2018-07-06 15:30:00 +02:00
}
2019-05-26 20:14:53 +02:00
if (item.isLimited()) {
2018-10-07 00:28:00 +02:00
limitedConfiguration = this.getLimitedConfig(item);
2018-07-06 15:30:00 +02:00
2019-05-26 20:14:53 +02:00
if (limitedConfiguration == null) {
2018-10-07 00:28:00 +02:00
limitedConfiguration = this.createOrUpdateLimitedConfig(item);
}
limitedNumber = limitedConfiguration.getNumber();
limitedStack = limitedConfiguration.getTotalSet();
}
2019-05-17 19:56:07 +02:00
int totalCredits = free ? 0 : this.calculateDiscountedPrice(item.getCredits(), amount, item);
int totalPoints = free ? 0 : this.calculateDiscountedPrice(item.getPoints(), amount, item);
if (totalCredits > 0 && habbo.getHabboInfo().getCredits() - totalCredits < 0) return;
2019-05-26 20:14:53 +02:00
if (totalPoints > 0 && habbo.getHabboInfo().getCurrencyAmount(item.getPointsType()) - totalPoints < 0)
return;
2019-05-17 19:56:07 +02:00
2018-10-07 00:28:00 +02:00
List<String> badges = new ArrayList<>();
Map<AddHabboItemComposer.AddHabboItemCategory, List<Integer>> unseenItems = new HashMap<>();
2018-10-07 00:28:00 +02:00
boolean badgeFound = false;
2019-05-17 19:56:07 +02:00
for (int i = 0; i < amount; i++) {
habbo.getHabboStats().addLtdLog(item.getId(), Emulator.getIntUnixTimestamp());
2018-07-06 15:30:00 +02:00
2019-05-17 19:56:07 +02:00
for (Item baseItem : item.getBaseItems()) {
for (int k = 0; k < item.getItemAmount(baseItem.getId()); k++) {
if (baseItem.getName().startsWith("rentable_bot_") || baseItem.getName().startsWith("bot_")) {
String type = item.getName().replace("rentable_bot_", "");
type = type.replace("bot_", "");
type = type.replace("visitor_logger", "visitor_log");
2018-09-12 18:45:00 +02:00
2019-05-17 19:56:07 +02:00
THashMap<String, String> data = new THashMap<>();
2018-07-06 15:30:00 +02:00
2019-05-17 19:56:07 +02:00
for (String s : item.getExtradata().split(";")) {
if (s.contains(":")) {
data.put(s.split(":")[0], s.split(":")[1]);
}
}
2018-07-06 15:30:00 +02:00
2019-05-17 19:56:07 +02:00
Bot bot = Emulator.getGameEnvironment().getBotManager().createBot(data, type);
if (bot != null) {
bot.setOwnerId(habbo.getClient().getHabbo().getHabboInfo().getId());
bot.setOwnerName(habbo.getClient().getHabbo().getHabboInfo().getUsername());
bot.needsUpdate(true);
Emulator.getThreading().run(bot);
habbo.getClient().getHabbo().getInventory().getBotsComponent().addBot(bot);
habbo.getClient().sendResponse(new AddBotComposer(bot));
if (!unseenItems.containsKey(AddHabboItemComposer.AddHabboItemCategory.BOT)) {
unseenItems.put(AddHabboItemComposer.AddHabboItemCategory.BOT, new ArrayList<>());
}
unseenItems.get(AddHabboItemComposer.AddHabboItemCategory.BOT).add(bot.getId());
2019-05-17 19:56:07 +02:00
} else {
throw new Exception("Failed to create bot of type: " + type);
}
} else if (baseItem.getType() == FurnitureType.EFFECT) {
int effectId = baseItem.getEffectM();
2018-07-06 15:30:00 +02:00
2019-05-17 19:56:07 +02:00
if (habbo.getHabboInfo().getGender().equals(HabboGender.F)) {
effectId = baseItem.getEffectF();
}
2018-07-06 15:30:00 +02:00
2019-05-17 19:56:07 +02:00
if (effectId > 0) {
habbo.getInventory().getEffectsComponent().createEffect(effectId);
}
} else if (Item.isPet(baseItem)) {
String[] data = extradata.split("\n");
2018-07-06 15:30:00 +02:00
2019-05-17 19:56:07 +02:00
if (data.length < 3) {
habbo.getClient().sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR));
return;
}
2018-07-06 15:30:00 +02:00
2019-05-17 19:56:07 +02:00
Pet pet = null;
try {
pet = Emulator.getGameEnvironment().getPetManager().createPet(baseItem, data[0], data[1], data[2], habbo.getClient());
} catch (Exception e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Caught exception", e);
2019-05-17 19:56:07 +02:00
habbo.getClient().sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR));
}
2018-07-06 15:30:00 +02:00
2019-05-17 19:56:07 +02:00
if (pet == null) {
habbo.getClient().sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR));
return;
}
2018-07-06 15:30:00 +02:00
2019-05-17 19:56:07 +02:00
habbo.getClient().getHabbo().getInventory().getPetsComponent().addPet(pet);
habbo.getClient().sendResponse(new AddPetComposer(pet));
habbo.getClient().sendResponse(new PetBoughtNotificationComposer(pet, false));
AchievementManager.progressAchievement(habbo.getClient().getHabbo(), Emulator.getGameEnvironment().getAchievementManager().getAchievement("PetLover"));
if (!unseenItems.containsKey(AddHabboItemComposer.AddHabboItemCategory.PET)) {
unseenItems.put(AddHabboItemComposer.AddHabboItemCategory.PET, new ArrayList<>());
}
unseenItems.get(AddHabboItemComposer.AddHabboItemCategory.PET).add(pet.getId());
2019-05-17 19:56:07 +02:00
} else if (baseItem.getType() == FurnitureType.BADGE) {
if (!habbo.getInventory().getBadgesComponent().hasBadge(baseItem.getName())) {
if (!badges.contains(baseItem.getName())) {
badges.add(baseItem.getName());
}
} else {
badgeFound = true;
}
} else {
if (baseItem.getInteractionType().getType() == InteractionTrophy.class || baseItem.getInteractionType().getType() == InteractionBadgeDisplay.class) {
if (baseItem.getInteractionType().getType() == InteractionBadgeDisplay.class && !habbo.getClient().getHabbo().getInventory().getBadgesComponent().hasBadge(extradata)) {
ScripterManager.scripterDetected(habbo.getClient(), Emulator.getTexts().getValue("scripter.warning.catalog.badge_display").replace("%username%", habbo.getClient().getHabbo().getHabboInfo().getUsername()).replace("%badge%", extradata));
extradata = "UMAD";
}
2018-07-06 15:30:00 +02:00
2019-05-17 19:56:07 +02:00
extradata = habbo.getClient().getHabbo().getHabboInfo().getUsername() + (char) 9 + Calendar.getInstance().get(Calendar.DAY_OF_MONTH) + "-" + (Calendar.getInstance().get(Calendar.MONTH) + 1) + "-" + Calendar.getInstance().get(Calendar.YEAR) + (char) 9 + Emulator.getGameEnvironment().getWordFilter().filter(extradata.replace(((char) 9) + "", ""), habbo);
}
2019-05-17 19:56:07 +02:00
if (InteractionTeleport.class.isAssignableFrom(baseItem.getInteractionType().getType())) {
HabboItem teleportOne = Emulator.getGameEnvironment().getItemManager().createItem(habbo.getClient().getHabbo().getHabboInfo().getId(), baseItem, limitedStack, limitedNumber, extradata);
HabboItem teleportTwo = Emulator.getGameEnvironment().getItemManager().createItem(habbo.getClient().getHabbo().getHabboInfo().getId(), baseItem, limitedStack, limitedNumber, extradata);
Emulator.getGameEnvironment().getItemManager().insertTeleportPair(teleportOne.getId(), teleportTwo.getId());
itemsList.add(teleportOne);
itemsList.add(teleportTwo);
} else if (baseItem.getInteractionType().getType() == InteractionHopper.class) {
HabboItem hopper = Emulator.getGameEnvironment().getItemManager().createItem(habbo.getClient().getHabbo().getHabboInfo().getId(), baseItem, limitedStack, limitedNumber, extradata);
Emulator.getGameEnvironment().getItemManager().insertHopper(hopper);
itemsList.add(hopper);
} else if (baseItem.getInteractionType().getType() == InteractionGuildFurni.class || baseItem.getInteractionType().getType() == InteractionGuildGate.class) {
int guildId;
try {
guildId = Integer.parseInt(extradata);
} catch (Exception e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Caught exception", e);
2019-05-17 19:56:07 +02:00
habbo.getClient().sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR));
return;
}
2020-06-07 13:52:07 +02:00
Guild guild = Emulator.getGameEnvironment().getGuildManager().getGuild(guildId);
2019-05-17 19:56:07 +02:00
2020-06-07 13:52:07 +02:00
if (guild != null && Emulator.getGameEnvironment().getGuildManager().getGuildMember(guild, habbo) != null) {
InteractionGuildFurni habboItem = (InteractionGuildFurni) Emulator.getGameEnvironment().getItemManager().createItem(habbo.getClient().getHabbo().getHabboInfo().getId(), baseItem, limitedStack, limitedNumber, extradata);
habboItem.setExtradata("");
habboItem.needsUpdate(true);
2019-05-17 19:56:07 +02:00
2020-06-07 13:52:07 +02:00
Emulator.getThreading().run(habboItem);
Emulator.getGameEnvironment().getGuildManager().setGuild(habboItem, guildId);
itemsList.add(habboItem);
if (baseItem.getName().equals("guild_forum")) {
2019-05-17 19:56:07 +02:00
guild.setForum(true);
guild.needsUpdate = true;
guild.run();
}
2018-07-06 15:30:00 +02:00
}
2019-05-17 19:56:07 +02:00
} else if (baseItem.getInteractionType().getType() == InteractionMusicDisc.class) {
SoundTrack track = Emulator.getGameEnvironment().getItemManager().getSoundTrack(item.getExtradata());
if (track == null) {
habbo.getClient().sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR));
return;
}
InteractionMusicDisc habboItem = (InteractionMusicDisc) Emulator.getGameEnvironment().getItemManager().createItem(habbo.getClient().getHabbo().getHabboInfo().getId(), baseItem, limitedStack, limitedNumber, habbo.getClient().getHabbo().getHabboInfo().getUsername() + "\n" + Calendar.getInstance().get(Calendar.DAY_OF_MONTH) + "\n" + (Calendar.getInstance().get(Calendar.MONTH) + 1) + "\n" + Calendar.getInstance().get(Calendar.YEAR) + "\n" + track.getLength() + "\n" + track.getName() + "\n" + track.getId());
habboItem.needsUpdate(true);
Emulator.getThreading().run(habboItem);
itemsList.add(habboItem);
AchievementManager.progressAchievement(habbo, Emulator.getGameEnvironment().getAchievementManager().getAchievement("MusicCollector"));
} else {
HabboItem habboItem = Emulator.getGameEnvironment().getItemManager().createItem(habbo.getClient().getHabbo().getHabboInfo().getId(), baseItem, limitedStack, limitedNumber, extradata);
itemsList.add(habboItem);
2018-07-06 15:30:00 +02:00
}
}
2018-10-07 00:28:00 +02:00
}
2018-07-06 15:30:00 +02:00
}
}
if (badgeFound && item.getBaseItems().size() == 1) {
2018-10-07 00:28:00 +02:00
habbo.getClient().sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.ALREADY_HAVE_BADGE));
return;
2018-07-06 15:30:00 +02:00
}
UserCatalogItemPurchasedEvent purchasedEvent = new UserCatalogItemPurchasedEvent(habbo, item, itemsList, totalCredits, totalPoints, badges);
Emulator.getPluginManager().fireEvent(purchasedEvent);
2020-06-05 10:12:49 +02:00
if (!free && !habbo.getClient().getHabbo().hasPermission(Permission.ACC_INFINITE_CREDITS)) {
2019-05-26 20:14:53 +02:00
if (purchasedEvent.totalCredits > 0) {
2018-10-07 00:28:00 +02:00
habbo.getClient().getHabbo().getHabboInfo().addCredits(-purchasedEvent.totalCredits);
habbo.getClient().sendResponse(new UserCreditsComposer(habbo.getClient().getHabbo()));
}
2018-07-06 15:30:00 +02:00
}
2020-06-05 10:12:49 +02:00
if (!free && !habbo.getClient().getHabbo().hasPermission(Permission.ACC_INFINITE_POINTS)) {
2019-05-26 20:14:53 +02:00
if (purchasedEvent.totalPoints > 0) {
2018-10-07 00:28:00 +02:00
habbo.getClient().getHabbo().getHabboInfo().addCurrencyAmount(item.getPointsType(), -purchasedEvent.totalPoints);
habbo.getClient().sendResponse(new UserPointsComposer(habbo.getClient().getHabbo().getHabboInfo().getCurrencyAmount(item.getPointsType()), -purchasedEvent.totalPoints, item.getPointsType()));
}
2018-07-06 15:30:00 +02:00
}
2019-05-26 20:14:53 +02:00
if (purchasedEvent.itemsList != null && !purchasedEvent.itemsList.isEmpty()) {
2018-10-07 00:28:00 +02:00
habbo.getClient().getHabbo().getInventory().getItemsComponent().addItems(purchasedEvent.itemsList);
unseenItems.put(AddHabboItemComposer.AddHabboItemCategory.OWNED_FURNI, purchasedEvent.itemsList.stream().map(HabboItem::getId).collect(Collectors.toList()));
2018-07-06 15:30:00 +02:00
2018-10-07 00:28:00 +02:00
Emulator.getPluginManager().fireEvent(new UserCatalogFurnitureBoughtEvent(habbo, item, purchasedEvent.itemsList));
2018-07-06 15:30:00 +02:00
2019-05-26 20:14:53 +02:00
if (limitedConfiguration != null) {
for (HabboItem itm : purchasedEvent.itemsList) {
2018-10-07 00:28:00 +02:00
limitedConfiguration.limitedSold(item.getId(), habbo, itm);
}
2018-07-06 15:30:00 +02:00
}
}
if (!purchasedEvent.badges.isEmpty() && !unseenItems.containsKey(AddHabboItemComposer.AddHabboItemCategory.BADGE)) {
unseenItems.put(AddHabboItemComposer.AddHabboItemCategory.BADGE, new ArrayList<>());
}
2019-05-26 20:14:53 +02:00
for (String b : purchasedEvent.badges) {
2018-10-07 00:28:00 +02:00
HabboBadge badge = new HabboBadge(0, b, 0, habbo);
Emulator.getThreading().run(badge);
habbo.getInventory().getBadgesComponent().addBadge(badge);
habbo.getClient().sendResponse(new AddUserBadgeComposer(badge));
THashMap<String, String> keys = new THashMap<>();
keys.put("display", "BUBBLE");
keys.put("image", "${image.library.url}album1584/" + badge.getCode() + ".gif");
keys.put("message", Emulator.getTexts().getValue("commands.generic.cmd_badge.received"));
habbo.getClient().sendResponse(new BubbleAlertComposer(BubbleAlertKeys.RECEIVED_BADGE.key, keys));
unseenItems.get(AddHabboItemComposer.AddHabboItemCategory.BADGE).add(badge.getId());
2018-10-07 00:28:00 +02:00
}
habbo.getClient().getHabbo().getHabboStats().addPurchase(purchasedEvent.catalogItem);
habbo.getClient().sendResponse(new AddHabboItemComposer(unseenItems));
habbo.getClient().sendResponse(new PurchaseOKComposer(purchasedEvent.catalogItem));
habbo.getClient().sendResponse(new InventoryRefreshComposer());
THashSet<String> itemIds = new THashSet<>();
for(HabboItem ix : purchasedEvent.itemsList) {
itemIds.add(ix.getId() + "");
}
if(!free) {
Emulator.getThreading().run(new CatalogPurchaseLogEntry(
Emulator.getIntUnixTimestamp(),
purchasedEvent.habbo.getHabboInfo().getId(),
purchasedEvent.catalogItem != null ? purchasedEvent.catalogItem.getId() : 0,
String.join(";", itemIds),
purchasedEvent.catalogItem != null ? purchasedEvent.catalogItem.getName() : "",
purchasedEvent.totalCredits,
purchasedEvent.totalPoints,
item != null ? item.getPointsType() : 0,
amount
));
}
2019-05-26 20:14:53 +02:00
} catch (Exception e) {
2020-05-03 01:46:07 +02:00
LOGGER.error("Exception caught", e);
2018-10-07 00:28:00 +02:00
habbo.getClient().sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR));
2018-07-06 15:30:00 +02:00
}
2019-05-26 20:14:53 +02:00
} finally {
2018-10-07 00:28:00 +02:00
habbo.getHabboStats().isPurchasingFurniture = false;
2018-07-06 15:30:00 +02:00
}
}
2019-05-26 20:14:53 +02:00
public List<ClubOffer> getClubOffers() {
2018-07-06 15:30:00 +02:00
List<ClubOffer> offers = new ArrayList<>();
2019-05-26 20:14:53 +02:00
for (Map.Entry<Integer, ClubOffer> entry : this.clubOffers.entrySet()) {
if (!entry.getValue().isDeal()) {
2018-07-06 15:30:00 +02:00
offers.add(entry.getValue());
}
}
return offers;
}
2019-05-26 20:14:53 +02:00
public TargetOffer getTargetOffer(int offerId) {
2018-10-07 00:28:00 +02:00
return this.targetOffers.get(offerId);
}
2019-05-17 19:56:07 +02:00
private int calculateDiscountedPrice(int originalPrice, int amount, CatalogItem item) {
if (!CatalogItem.haveOffer(item)) return originalPrice * amount;
int basicDiscount = amount / DiscountComposer.DISCOUNT_BATCH_SIZE;
int bonusDiscount = 0;
if (basicDiscount >= DiscountComposer.MINIMUM_DISCOUNTS_FOR_BONUS) {
if (amount % DiscountComposer.DISCOUNT_BATCH_SIZE == DiscountComposer.DISCOUNT_BATCH_SIZE - 1) {
bonusDiscount = 1;
}
bonusDiscount += basicDiscount - DiscountComposer.MINIMUM_DISCOUNTS_FOR_BONUS;
}
int additionalDiscounts = 0;
for (int threshold : DiscountComposer.ADDITIONAL_DISCOUNT_THRESHOLDS) {
if (amount >= threshold) additionalDiscounts++;
}
int totalDiscountedItems = (basicDiscount * DiscountComposer.DISCOUNT_AMOUNT_PER_BATCH) + bonusDiscount + additionalDiscounts;
return Math.max(0, originalPrice * (amount - totalDiscountedItems));
}
2018-07-06 15:30:00 +02:00
}