diff --git a/sqlupdates/DEV_TO_SUBSCRIPTION-REVAMP.sql b/sqlupdates/DEV_TO_SUBSCRIPTION-REVAMP.sql index a1686879..5003f7fa 100644 --- a/sqlupdates/DEV_TO_SUBSCRIPTION-REVAMP.sql +++ b/sqlupdates/DEV_TO_SUBSCRIPTION-REVAMP.sql @@ -53,7 +53,9 @@ INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('subscriptions.hc.payday INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('subscriptions.hc.payday.currency', 'credits'); INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('subscriptions.hc.payday.percentage', '10'); INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('subscriptions.hc.payday.creditsspent_reset_on_expire', '1'); -INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('subscriptions.hc.payday.message', 'Woohoo HC Payday has arrived! You have received %amount% credits to your purse. Enjoy!') +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('subscriptions.hc.achievement', 'VipHC'); +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('subscriptions.hc.discount.enabled', '1'); +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('subscriptions.hc.discount.days_before_end', '7'); INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('subscriptions.scheduler.enabled', '1'); INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('subscriptions.scheduler.interval', '10'); @@ -71,18 +73,31 @@ INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('hotel.users.max.friends INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('hotel.users.max.rooms', '50'); INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('hotel.users.max.rooms.hc', '75'); -DELETE FROM `emulator_settings` WHERE `key` = 'hotel.max.rooms.per.user'; -DELETE FROM `emulator_settings` WHERE `key` = 'hotel.max.rooms.user'; -DELETE FROM `emulator_settings` WHERE `key` = 'hotel.max.rooms.vip'; +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('hotel.auto.pixels.hc_modifier', '1'); +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('hotel.auto.points.hc_modifier', '1'); +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('hotel.auto.credits.hc_modifier', '1'); +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('hotel.auto.gotwpoints.hc_modifier', '1'); -DELETE FROM `emulator_settings` WHERE `key` = 'max.friends'; -DELETE FROM `emulator_settings` WHERE `key` = 'max.friends'; +DELETE FROM `emulator_settings` WHERE `key` IN ('hotel.max.rooms.per.user', 'hotel.max.rooms.user', 'hotel.max.rooms.vip', 'max.friends', 'hotel.max.friends', 'max.friends.hc', 'hotel.max.friends.hc'); ALTER TABLE `users_settings` ADD COLUMN `max_friends` int(10) NULL DEFAULT 300 AFTER `has_gotten_default_saved_searches`; ALTER TABLE `users_settings` ADD COLUMN `max_rooms` int(10) NULL DEFAULT 50 AFTER `has_gotten_default_saved_searches`; ALTER TABLE `users_settings` ADD COLUMN `last_hc_payday` int(10) NULL DEFAULT 0 AFTER `has_gotten_default_saved_searches`; +ALTER TABLE `users_settings` ADD COLUMN `hc_gifts_claimed` int(10) NULL DEFAULT 0 AFTER `has_gotten_default_saved_searches`; ALTER TABLE `permissions` ADD COLUMN `cmd_subscription` enum('0','1') NULL DEFAULT '0' AFTER `cmd_credits`; INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('commands.keys.cmd_subscription', 'subscription;sub'); +INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('commands.error.cmd_subscription.invalid_action', 'Invalid action specified. Must be add, +, remove or -'); +INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('commands.error.cmd_subscription.type_not_found', '%subscription% is not a valid subscription type'); +INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('commands.error.cmd_subscription.invalid_params_time', 'Invalid time span, try: x minutes/days/weeks/months'); +INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('commands.error.cmd_subscription.success_add_time', 'Successfully added %time% seconds to %subscription% on %user%'); +INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('commands.error.cmd_subscription.user_not_have', '%user% does not have the %subscription% subscription'); +INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('commands.error.cmd_subscription.success_remove_time', 'Successfully removed %time% seconds from %subscription% on %user%'); +INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('commands.error.cmd_subscription.success_remove_sub', 'Successfully removed %subscription% sub from %user%'); +INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('commands.error.cmd_subscription.user_not_found', '%user% was not found'); +INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('commands.error.cmd_subscription.invalid_params', 'Invalid command format'); -INSERT INTO users_subscriptions SELECT NULL, user_id, 'HABBO_CLUB' as `subscription_type`, UNIX_TIMESTAMP() AS `timestamp_start`, (club_expire_timestamp - UNIX_TIMESTAMP()) AS `duration`, 1 AS `active` FROM users_settings WHERE club_expire_timestamp > UNIX_TIMESTAMP(); +INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('subscriptions.hc.payday.message', 'Woohoo HC Payday has arrived! You have received %amount% credits to your purse. Enjoy!'); + +-- OPTIONAL HC MIGRATION +-- INSERT INTO users_subscriptions SELECT NULL, user_id, 'HABBO_CLUB' as `subscription_type`, UNIX_TIMESTAMP() AS `timestamp_start`, (club_expire_timestamp - UNIX_TIMESTAMP()) AS `duration`, 1 AS `active` FROM users_settings WHERE club_expire_timestamp > UNIX_TIMESTAMP(); diff --git a/src/main/java/com/eu/habbo/core/CreditsScheduler.java b/src/main/java/com/eu/habbo/core/CreditsScheduler.java index d5442bbf..db5e74fb 100644 --- a/src/main/java/com/eu/habbo/core/CreditsScheduler.java +++ b/src/main/java/com/eu/habbo/core/CreditsScheduler.java @@ -13,6 +13,7 @@ public class CreditsScheduler extends Scheduler { public static boolean IGNORE_HOTEL_VIEW; public static boolean IGNORE_IDLED; + public static double HC_MODIFIER; public CreditsScheduler() { @@ -24,6 +25,8 @@ public class CreditsScheduler extends Scheduler { if (Emulator.getConfig().getBoolean("hotel.auto.credits.enabled")) { IGNORE_HOTEL_VIEW = Emulator.getConfig().getBoolean("hotel.auto.credits.ignore.hotelview"); IGNORE_IDLED = Emulator.getConfig().getBoolean("hotel.auto.credits.ignore.idled"); + HC_MODIFIER = Emulator.getConfig().getDouble("hotel.auto.credits.hc_modifier", 1.0); + if (this.disposed) { this.disposed = false; this.run(); @@ -49,7 +52,7 @@ public class CreditsScheduler extends Scheduler { if (habbo.getRoomUnit().isIdle() && IGNORE_IDLED) continue; - habbo.giveCredits(habbo.getHabboInfo().getRank().getCreditsTimerAmount()); + habbo.giveCredits((int)(habbo.getHabboInfo().getRank().getCreditsTimerAmount() * (habbo.getHabboStats().hasActiveClub() ? HC_MODIFIER : 1.0))); } } catch (Exception e) { LOGGER.error("Caught exception", e); diff --git a/src/main/java/com/eu/habbo/core/GotwPointsScheduler.java b/src/main/java/com/eu/habbo/core/GotwPointsScheduler.java index 58b3acc7..58350a95 100644 --- a/src/main/java/com/eu/habbo/core/GotwPointsScheduler.java +++ b/src/main/java/com/eu/habbo/core/GotwPointsScheduler.java @@ -14,6 +14,7 @@ public class GotwPointsScheduler extends Scheduler { public static boolean IGNORE_HOTEL_VIEW; public static boolean IGNORE_IDLED; public static String GOTW_POINTS_NAME; + public static double HC_MODIFIER; public GotwPointsScheduler() { //TODO MOVE TO A PLUGIN. IS NOT PART OF OFFICIAL HABBO. @@ -25,6 +26,7 @@ public class GotwPointsScheduler extends Scheduler { if (Emulator.getConfig().getBoolean("hotel.auto.gotwpoints.enabled")) { IGNORE_HOTEL_VIEW = Emulator.getConfig().getBoolean("hotel.auto.gotwpoints.ignore.hotelview"); IGNORE_IDLED = Emulator.getConfig().getBoolean("hotel.auto.gotwpoints.ignore.idled"); + HC_MODIFIER = Emulator.getConfig().getDouble("hotel.auto.gotwpoints.hc_modifier", 1.0); GOTW_POINTS_NAME = Emulator.getConfig().getValue("hotel.auto.gotwpoints.name"); if (this.disposed) { @@ -62,8 +64,7 @@ public class GotwPointsScheduler extends Scheduler { } type = Emulator.getConfig().getInt("seasonal.currency." + GOTW_POINTS_NAME, -1); if (found || type != -1) { - - habbo.givePoints(type, habbo.getHabboInfo().getRank().getGotwTimerAmount()); + habbo.givePoints(type, (int)(habbo.getHabboInfo().getRank().getGotwTimerAmount() * (habbo.getHabboStats().hasActiveClub() ? HC_MODIFIER : 1.0))); } } } catch (Exception e) { diff --git a/src/main/java/com/eu/habbo/core/PixelScheduler.java b/src/main/java/com/eu/habbo/core/PixelScheduler.java index cadf07ea..2b0bddd5 100644 --- a/src/main/java/com/eu/habbo/core/PixelScheduler.java +++ b/src/main/java/com/eu/habbo/core/PixelScheduler.java @@ -13,6 +13,7 @@ public class PixelScheduler extends Scheduler { public static boolean IGNORE_HOTEL_VIEW; public static boolean IGNORE_IDLED; + public static double HC_MODIFIER; public PixelScheduler() { super(Emulator.getConfig().getInt("hotel.auto.pixels.interval")); @@ -23,6 +24,7 @@ public class PixelScheduler extends Scheduler { if (Emulator.getConfig().getBoolean("hotel.auto.pixels.enabled")) { IGNORE_HOTEL_VIEW = Emulator.getConfig().getBoolean("hotel.auto.pixels.ignore.hotelview"); IGNORE_IDLED = Emulator.getConfig().getBoolean("hotel.auto.pixels.ignore.idled"); + HC_MODIFIER = Emulator.getConfig().getDouble("hotel.auto.pixels.hc_modifier", 1.0); if (this.disposed) { this.disposed = false; this.run(); @@ -47,7 +49,7 @@ public class PixelScheduler extends Scheduler { if (habbo.getRoomUnit().isIdle() && IGNORE_IDLED) continue; - habbo.givePixels(habbo.getHabboInfo().getRank().getPixelsTimerAmount()); + habbo.givePixels((int)(habbo.getHabboInfo().getRank().getPixelsTimerAmount() * (habbo.getHabboStats().hasActiveClub() ? HC_MODIFIER : 1.0))); } } catch (Exception e) { LOGGER.error("Caught exception", e); diff --git a/src/main/java/com/eu/habbo/core/PointsScheduler.java b/src/main/java/com/eu/habbo/core/PointsScheduler.java index d30abc6a..ca863cb8 100644 --- a/src/main/java/com/eu/habbo/core/PointsScheduler.java +++ b/src/main/java/com/eu/habbo/core/PointsScheduler.java @@ -13,6 +13,7 @@ public class PointsScheduler extends Scheduler { public static boolean IGNORE_HOTEL_VIEW; public static boolean IGNORE_IDLED; + public static double HC_MODIFIER; public PointsScheduler() { @@ -24,6 +25,7 @@ public class PointsScheduler extends Scheduler { if (Emulator.getConfig().getBoolean("hotel.auto.points.enabled")) { IGNORE_HOTEL_VIEW = Emulator.getConfig().getBoolean("hotel.auto.points.ignore.hotelview"); IGNORE_IDLED = Emulator.getConfig().getBoolean("hotel.auto.points.ignore.idled"); + HC_MODIFIER = Emulator.getConfig().getDouble("hotel.auto.points.hc_modifier", 1.0); if (this.disposed) { this.disposed = false; this.run(); @@ -50,7 +52,7 @@ public class PointsScheduler extends Scheduler { continue; //habbo.givePoints(POINTS); - habbo.givePoints(habbo.getHabboInfo().getRank().getDiamondsTimerAmount()); + habbo.givePoints((int)(habbo.getHabboInfo().getRank().getDiamondsTimerAmount() * (habbo.getHabboStats().hasActiveClub() ? HC_MODIFIER : 1.0))); } } catch (Exception e) { LOGGER.error("Caught exception", e); diff --git a/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogManager.java b/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogManager.java index 87649d94..34a24e3d 100644 --- a/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogManager.java +++ b/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogManager.java @@ -615,6 +615,16 @@ public class CatalogManager { .findAny().orElse(null); } + 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); + } public CatalogItem getCatalogItem(int id) { final CatalogItem[] item = {null}; diff --git a/src/main/java/com/eu/habbo/habbohotel/catalog/ClubOffer.java b/src/main/java/com/eu/habbo/habbohotel/catalog/ClubOffer.java index 4ba103ba..de40e8ef 100644 --- a/src/main/java/com/eu/habbo/habbohotel/catalog/ClubOffer.java +++ b/src/main/java/com/eu/habbo/habbohotel/catalog/ClubOffer.java @@ -1,9 +1,14 @@ package com.eu.habbo.habbohotel.catalog; +import com.eu.habbo.Emulator; +import com.eu.habbo.messages.ISerialize; +import com.eu.habbo.messages.ServerMessage; + import java.sql.ResultSet; import java.sql.SQLException; +import java.util.Calendar; -public class ClubOffer { +public class ClubOffer implements ISerialize { private final int id; @@ -70,4 +75,46 @@ public class ClubOffer { public boolean isDeal() { return this.deal; } + + @Override + public void serialize(ServerMessage message) { + serialize(message, Emulator.getIntUnixTimestamp()); + } + + public void serialize(ServerMessage message, int hcExpireTimestamp) { + hcExpireTimestamp = Math.min(Emulator.getIntUnixTimestamp(), hcExpireTimestamp); + message.appendInt(this.id); + message.appendString(this.name); + message.appendBoolean(false); //unused + message.appendInt(this.credits); + message.appendInt(this.points); + message.appendInt(this.pointsType); + message.appendBoolean(this.vip); + + long seconds = this.days * 86400L; + + long secondsTotal = seconds; + + int totalYears = (int) Math.floor((int) seconds / 86400 * 31 * 12); + seconds -= totalYears * 86400 * 31 * 12; + + int totalMonths = (int) Math.floor((int) seconds / 86400 * 31); + seconds -= totalMonths * 86400 * 31; + + int totalDays = (int) Math.floor((int) seconds / 86400); + seconds -= totalDays * 86400; + + message.appendInt((int) secondsTotal / 86400 / 31); + message.appendInt((int) seconds); + message.appendBoolean(false); //giftable + message.appendInt((int) seconds); + + hcExpireTimestamp += secondsTotal; + + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(hcExpireTimestamp * 1000L); + message.appendInt(cal.get(Calendar.YEAR)); + message.appendInt(cal.get(Calendar.MONTH)); + message.appendInt(cal.get(Calendar.DAY_OF_MONTH)); + } } \ No newline at end of file diff --git a/src/main/java/com/eu/habbo/habbohotel/commands/SubscriptionCommand.java b/src/main/java/com/eu/habbo/habbohotel/commands/SubscriptionCommand.java index fbf32b54..25f8b758 100644 --- a/src/main/java/com/eu/habbo/habbohotel/commands/SubscriptionCommand.java +++ b/src/main/java/com/eu/habbo/habbohotel/commands/SubscriptionCommand.java @@ -63,14 +63,13 @@ public class SubscriptionCommand extends Command { int timeToAdd = Emulator.timeStringToSeconds(message.toString()); if(timeToAdd < 1) { - gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_subscription.invalid_params", "Invalid time span, try: x minutes/days/weeks/months"), RoomChatMessageBubbles.ALERT); + gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_subscription.invalid_params_time", "Invalid time span, try: x minutes/days/weeks/months"), RoomChatMessageBubbles.ALERT); return true; } habbo.getHabboStats().createSubscription(subscription, timeToAdd); gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_subscription.success_add_time", "Successfully added %time% seconds to %subscription% on %user%").replace("%time%", timeToAdd + "").replace("%user%", params[1]).replace("%subscription%", subscription), RoomChatMessageBubbles.ALERT); } - else if(action.equalsIgnoreCase("remove") || action.equalsIgnoreCase("-") || action.equalsIgnoreCase("r")) { Subscription s = habbo.getHabboStats().getSubscription(subscription); @@ -83,11 +82,11 @@ public class SubscriptionCommand extends Command { int timeToRemove = Emulator.timeStringToSeconds(message.toString()); if (timeToRemove < 1) { - gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_subscription.invalid_params", "Invalid time span, try: x minutes/days/weeks/months"), RoomChatMessageBubbles.ALERT); + gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_subscription.invalid_params_time", "Invalid time span, try: x minutes/days/weeks/months"), RoomChatMessageBubbles.ALERT); return true; } - s.addDuration(timeToRemove); + s.addDuration(-timeToRemove); gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_subscription.success_remove_time", "Successfully removed %time% seconds from %subscription% on %user%").replace("%time%", timeToRemove + "").replace("%user%", params[1]).replace("%subscription%", subscription), RoomChatMessageBubbles.ALERT); } else { @@ -95,6 +94,9 @@ public class SubscriptionCommand extends Command { gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_subscription.success_remove_sub", "Successfully removed %subscription% sub from %user%").replace("%user%", params[1]).replace("%subscription%", subscription), RoomChatMessageBubbles.ALERT); } } + else { + gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_subscription.invalid_action", "Invalid action specified. Must be add, +, remove or -"), RoomChatMessageBubbles.ALERT); + } } else { gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_subscription.user_not_found", "%user% was not found").replace("%user%", params[1]), RoomChatMessageBubbles.ALERT); diff --git a/src/main/java/com/eu/habbo/habbohotel/items/Item.java b/src/main/java/com/eu/habbo/habbohotel/items/Item.java index eb7316ff..97e1a435 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/Item.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/Item.java @@ -3,12 +3,14 @@ package com.eu.habbo.habbohotel.items; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.items.interactions.InteractionMultiHeight; import com.eu.habbo.habbohotel.users.HabboItem; +import com.eu.habbo.messages.ISerialize; +import com.eu.habbo.messages.ServerMessage; import gnu.trove.list.array.TIntArrayList; import java.sql.ResultSet; import java.sql.SQLException; -public class Item { +public class Item implements ISerialize { private int id; private int spriteId; @@ -220,4 +222,30 @@ public class Item { } public String getClothingOnWalk() { return clothingOnWalk; } + + @Override + public void serialize(ServerMessage message) { + message.appendString(this.type.code.toLowerCase()); + + if (type == FurnitureType.BADGE) { + message.appendString(this.customParams); + } else { + message.appendInt(this.spriteId); + + if (this.getName().contains("wallpaper_single") || this.getName().contains("floor_single") || this.getName().contains("landscape_single")) { + message.appendString(this.name.split("_")[2]); + } else if (type == FurnitureType.ROBOT) { + message.appendString(this.customParams); + } else if (name.equalsIgnoreCase("poster")) { + message.appendString(this.customParams); + } else if (name.startsWith("SONG ")) { + message.appendString(this.customParams); + } else { + message.appendString(""); + } + + message.appendInt(1); // productCount + message.appendBoolean(false); + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/ItemManager.java b/src/main/java/com/eu/habbo/habbohotel/items/ItemManager.java index 7fdc0202..3da8125f 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/ItemManager.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/ItemManager.java @@ -685,13 +685,14 @@ public class ItemManager { } public HabboItem createGift(String username, Item item, String extraData, int limitedStack, int limitedSells) { - HabboItem gift = null; - int userId = 0; Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(username); + int userId = 0; + if (habbo != null) { userId = habbo.getHabboInfo().getId(); - } else { + } + else { try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT id FROM users WHERE username = ?")) { statement.setString(1, username); try (ResultSet set = statement.executeQuery()) { @@ -704,6 +705,14 @@ public class ItemManager { } } + if(userId > 0) { + return createGift(userId, item, extraData, limitedStack, limitedSells); + } + + return null; + } + + public HabboItem createGift(int userId, Item item, String extraData, int limitedStack, int limitedSells) { if (userId == 0) return null; @@ -712,26 +721,12 @@ public class ItemManager { extraData = extraData.substring(0, 1000); } - try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("INSERT INTO items (user_id, item_id, extra_data, limited_data) VALUES (?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS)) { - statement.setInt(1, userId); - statement.setInt(2, item.getId()); - statement.setString(3, extraData); - statement.setString(4, limitedStack + ":" + limitedSells); - statement.execute(); - - try (ResultSet set = statement.getGeneratedKeys()) { - if (set.next()) { - gift = new InteractionGift(set.getInt(1), userId, item, extraData, limitedStack, limitedSells); - } - } - } catch (SQLException e) { - LOGGER.error("Caught SQL exception", e); - } + HabboItem gift = this.createItem(userId, item, limitedStack, limitedSells, extraData); if (gift != null) { + Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId); if (habbo != null) { habbo.getInventory().getItemsComponent().addItem(gift); - habbo.getClient().sendResponse(new AddHabboItemComposer(gift)); } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionCrackable.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionCrackable.java index 70869154..af65156c 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionCrackable.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionCrackable.java @@ -10,6 +10,7 @@ import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboGender; import com.eu.habbo.habbohotel.users.HabboItem; +import com.eu.habbo.habbohotel.users.subscriptions.SubscriptionHabboClub; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.outgoing.users.UserClubComposer; import com.eu.habbo.messages.outgoing.users.UserPermissionsComposer; @@ -120,16 +121,10 @@ public class InteractionCrackable extends HabboItem { // subscriptions are given immediately upon cracking switch (rewardData.subscriptionType) { case HABBO_CLUB: - if (habbo.getHabboStats().getClubExpireTimestamp() <= Emulator.getIntUnixTimestamp()) - habbo.getHabboStats().setClubExpireTimestamp(Emulator.getIntUnixTimestamp()); - - habbo.getHabboStats().setClubExpireTimestamp(habbo.getHabboStats().getClubExpireTimestamp() + (rewardData.subscriptionDuration * 86400)); - habbo.getClient().sendResponse(new UserPermissionsComposer(habbo)); - habbo.getClient().sendResponse(new UserClubComposer(habbo)); - habbo.getHabboStats().run(); + habbo.getHabboStats().createSubscription(SubscriptionHabboClub.HABBO_CLUB, rewardData.subscriptionDuration * 86400); break; case BUILDERS_CLUB: - habbo.alert("Builders club has not been implemented yet. Sorry!"); + habbo.getHabboStats().createSubscription("BUILDERS_CLUB", rewardData.subscriptionDuration * 86400); break; } } diff --git a/src/main/java/com/eu/habbo/habbohotel/users/HabboStats.java b/src/main/java/com/eu/habbo/habbohotel/users/HabboStats.java index edf706a4..8f8f1382 100644 --- a/src/main/java/com/eu/habbo/habbohotel/users/HabboStats.java +++ b/src/main/java/com/eu/habbo/habbohotel/users/HabboStats.java @@ -10,7 +10,6 @@ import com.eu.habbo.habbohotel.rooms.RoomChatMessageBubbles; import com.eu.habbo.habbohotel.rooms.RoomTrade; import com.eu.habbo.habbohotel.users.cache.HabboOfferPurchase; import com.eu.habbo.habbohotel.users.subscriptions.Subscription; -import com.eu.habbo.habbohotel.users.subscriptions.SubscriptionManager; import com.eu.habbo.plugin.events.users.subscriptions.UserSubscriptionCreatedEvent; import com.eu.habbo.plugin.events.users.subscriptions.UserSubscriptionExtendedEvent; import gnu.trove.list.array.TIntArrayList; @@ -96,6 +95,7 @@ public class HabboStats implements Runnable { public int maxFriends; public int maxRooms; public int lastHCPayday; + public int hcGiftsClaimed; public int hcMessageLastModified = Emulator.getIntUnixTimestamp(); public THashSet subscriptions; @@ -150,6 +150,7 @@ public class HabboStats implements Runnable { this.maxFriends = set.getInt("max_friends"); this.maxRooms = set.getInt("max_rooms"); this.lastHCPayday = set.getInt("last_hc_payday"); + this.hcGiftsClaimed = set.getInt("hc_gifts_claimed"); this.nuxReward = this.nux; @@ -316,7 +317,7 @@ public class HabboStats implements Runnable { int onlineTime = Emulator.getIntUnixTimestamp() - onlineTimeLast; try (Connection connection = Emulator.getDatabase().getDataSource().getConnection()) { - try (PreparedStatement statement = connection.prepareStatement("UPDATE users_settings SET achievement_score = ?, respects_received = ?, respects_given = ?, daily_respect_points = ?, block_following = ?, block_friendrequests = ?, online_time = online_time + ?, guild_id = ?, daily_pet_respect_points = ?, club_expire_timestamp = ?, login_streak = ?, rent_space_id = ?, rent_space_endtime = ?, volume_system = ?, volume_furni = ?, volume_trax = ?, block_roominvites = ?, old_chat = ?, block_camera_follow = ?, chat_color = ?, hof_points = ?, block_alerts = ?, talent_track_citizenship_level = ?, talent_track_helpers_level = ?, ignore_bots = ?, ignore_pets = ?, nux = ?, mute_end_timestamp = ?, allow_name_change = ?, perk_trade = ?, can_trade = ?, `forums_post_count` = ?, ui_flags = ?, has_gotten_default_saved_searches = ?, max_friends = ?, max_rooms = ?, last_hc_payday = ? WHERE user_id = ? LIMIT 1")) { + try (PreparedStatement statement = connection.prepareStatement("UPDATE users_settings SET achievement_score = ?, respects_received = ?, respects_given = ?, daily_respect_points = ?, block_following = ?, block_friendrequests = ?, online_time = online_time + ?, guild_id = ?, daily_pet_respect_points = ?, club_expire_timestamp = ?, login_streak = ?, rent_space_id = ?, rent_space_endtime = ?, volume_system = ?, volume_furni = ?, volume_trax = ?, block_roominvites = ?, old_chat = ?, block_camera_follow = ?, chat_color = ?, hof_points = ?, block_alerts = ?, talent_track_citizenship_level = ?, talent_track_helpers_level = ?, ignore_bots = ?, ignore_pets = ?, nux = ?, mute_end_timestamp = ?, allow_name_change = ?, perk_trade = ?, can_trade = ?, `forums_post_count` = ?, ui_flags = ?, has_gotten_default_saved_searches = ?, max_friends = ?, max_rooms = ?, last_hc_payday = ?, hc_gifts_claimed = ? WHERE user_id = ? LIMIT 1")) { statement.setInt(1, this.achievementScore); statement.setInt(2, this.respectPointsReceived); statement.setInt(3, this.respectPointsGiven); @@ -354,7 +355,8 @@ public class HabboStats implements Runnable { statement.setInt(35, this.maxFriends); statement.setInt(36, this.maxRooms); statement.setInt(37, this.lastHCPayday); - statement.setInt(38, this.habboInfo.getId()); + statement.setInt(38, this.hcGiftsClaimed); + statement.setInt(39, this.habboInfo.getId()); statement.executeUpdate(); } @@ -542,6 +544,27 @@ public class HabboStats implements Runnable { return hasSubscription(Subscription.HABBO_CLUB); } + public int getPastTimeAsClub() { + int pastTimeAsHC = 0; + for(Subscription subs : this.subscriptions) { + if(subs.getSubscriptionType().equalsIgnoreCase(Subscription.HABBO_CLUB)) { + pastTimeAsHC += subs.getDuration() - (Math.max(subs.getRemaining(), 0)); + } + } + return pastTimeAsHC; + } + + public int getTimeTillNextClubGift() { + int pastTimeAsClub = getPastTimeAsClub(); + int totalGifts = (int)Math.ceil(pastTimeAsClub / 2678400.0); + return (totalGifts * 2678400) - pastTimeAsClub; + } + + public int getRemainingClubGifts() { + int totalGifts = (int)Math.ceil(getPastTimeAsClub() / 2678400.0); + return totalGifts - this.hcGiftsClaimed; + } + public THashMap getAchievementProgress() { return this.achievementProgress; } diff --git a/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/FiguredataPalette.java b/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/FiguredataPalette.java index b569d83f..841fd5d4 100644 --- a/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/FiguredataPalette.java +++ b/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/FiguredataPalette.java @@ -1,11 +1,10 @@ package com.eu.habbo.habbohotel.users.clothingvalidation; -import java.util.Map; import java.util.TreeMap; public class FiguredataPalette { public int id; - public Map colors; + public TreeMap colors; public FiguredataPalette(int id) { this.id = id; @@ -20,11 +19,8 @@ public class FiguredataPalette { return this.colors.get(colorId); } - /** - * @return First non-club and selectable color - */ public FiguredataPaletteColor getFirstNonHCColor() { - for(FiguredataPaletteColor color : this.colors.values()) { + for(FiguredataPaletteColor color : this.colors.descendingMap().values()) { if(!color.club && color.selectable) return color; } diff --git a/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/FiguredataSettype.java b/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/FiguredataSettype.java index dfe6366d..e3698815 100644 --- a/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/FiguredataSettype.java +++ b/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/FiguredataSettype.java @@ -10,7 +10,7 @@ public class FiguredataSettype { public boolean mandatoryFemale0; public boolean mandatoryMale1; public boolean mandatoryFemale1; - public Map sets; + public TreeMap sets; public FiguredataSettype(String type, int paletteId, boolean mandatoryMale0, boolean mandatoryFemale0, boolean mandatoryMale1, boolean mandatoryFemale1) { this.type = type; @@ -35,13 +35,13 @@ public class FiguredataSettype { * @return First non-sellable and selectable set for given gender */ public FiguredataSettypeSet getFirstSetForGender(String gender) { - for(FiguredataSettypeSet set : this.sets.values()) { - if(set.gender.equalsIgnoreCase(gender) && !set.sellable && set.selectable) { + for(FiguredataSettypeSet set : this.sets.descendingMap().values()) { + if((set.gender.equalsIgnoreCase(gender) || set.gender.equalsIgnoreCase("u")) && !set.sellable && set.selectable) { return set; } } - return this.sets.size() > 0 ? this.sets.entrySet().iterator().next().getValue() : null; + return this.sets.size() > 0 ? this.sets.descendingMap().entrySet().iterator().next().getValue() : null; } /** @@ -49,8 +49,8 @@ public class FiguredataSettype { * @return First non-club, non-sellable and selectable set for given gender */ public FiguredataSettypeSet getFirstNonHCSetForGender(String gender) { - for(FiguredataSettypeSet set : this.sets.values()) { - if(set.gender.equalsIgnoreCase(gender) && !set.club && !set.sellable && set.selectable) { + for(FiguredataSettypeSet set : this.sets.descendingMap().values()) { + if((set.gender.equalsIgnoreCase(gender) || set.gender.equalsIgnoreCase("u")) && !set.club && !set.sellable && set.selectable) { return set; } } diff --git a/src/main/java/com/eu/habbo/habbohotel/users/subscriptions/SubscriptionHabboClub.java b/src/main/java/com/eu/habbo/habbohotel/users/subscriptions/SubscriptionHabboClub.java index 32e04120..f0b1692b 100644 --- a/src/main/java/com/eu/habbo/habbohotel/users/subscriptions/SubscriptionHabboClub.java +++ b/src/main/java/com/eu/habbo/habbohotel/users/subscriptions/SubscriptionHabboClub.java @@ -2,12 +2,16 @@ package com.eu.habbo.habbohotel.users.subscriptions; import com.eu.habbo.Emulator; import com.eu.habbo.database.Database; +import com.eu.habbo.habbohotel.achievements.Achievement; +import com.eu.habbo.habbohotel.achievements.AchievementManager; import com.eu.habbo.habbohotel.messenger.Messenger; import com.eu.habbo.habbohotel.rooms.RoomManager; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboInfo; +import com.eu.habbo.habbohotel.users.HabboStats; import com.eu.habbo.habbohotel.users.clothingvalidation.ClothingValidationManager; import com.eu.habbo.messages.outgoing.catalog.ClubCenterDataComposer; +import com.eu.habbo.messages.outgoing.generic.PickMonthlyClubGiftNotificationComposer; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDataComposer; import com.eu.habbo.messages.outgoing.users.*; import gnu.trove.map.hash.THashMap; @@ -33,6 +37,9 @@ public class SubscriptionHabboClub extends Subscription { public static TreeMap HC_PAYDAY_STREAK = new TreeMap<>(); public static String HC_PAYDAY_CURRENCY = ""; public static Double HC_PAYDAY_KICKBACK_PERCENTAGE = 0.1; + public static String ACHIEVEMENT_NAME = ""; + public static boolean DISCOUNT_ENABLED = false; + public static int DISCOUNT_DAYS_BEFORE_END = 7; /** * When true "coins spent" will be calculated from the timestamp the user joins HC instead of from the last HC pay day execution timestamp @@ -60,19 +67,28 @@ public class SubscriptionHabboClub extends Subscription { public void onCreated() { super.onCreated(); - Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(this.getUserId()); - habbo.getHabboStats().maxFriends = Messenger.MAXIMUM_FRIENDS_HC; - habbo.getHabboStats().maxRooms = RoomManager.MAXIMUM_ROOMS_HC; - habbo.getHabboStats().lastHCPayday = HC_PAYDAY_COINSSPENT_RESET_ON_EXPIRE ? Emulator.getIntUnixTimestamp() : HC_PAYDAY_NEXT_DATE - Emulator.timeStringToSeconds(HC_PAYDAY_INTERVAL); - Emulator.getThreading().run(habbo.getHabboStats()); + HabboInfo habboInfo = Emulator.getGameEnvironment().getHabboManager().getHabboInfo(this.getUserId()); + HabboStats stats = habboInfo.getHabboStats(); - if(habbo.getClient() != null) { + stats.maxFriends = Messenger.MAXIMUM_FRIENDS_HC; + stats.maxRooms = RoomManager.MAXIMUM_ROOMS_HC; + stats.lastHCPayday = HC_PAYDAY_COINSSPENT_RESET_ON_EXPIRE ? Emulator.getIntUnixTimestamp() : HC_PAYDAY_NEXT_DATE - Emulator.timeStringToSeconds(HC_PAYDAY_INTERVAL); + Emulator.getThreading().run(stats); + + progressAchievement(habboInfo); + + Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(this.getUserId()); + if(habbo != null && habbo.getClient() != null) { + + if(habbo.getHabboStats().getRemainingClubGifts() > 0) { + habbo.getClient().sendResponse(new PickMonthlyClubGiftNotificationComposer(habbo.getHabboStats().getRemainingClubGifts())); + } if((Emulator.getIntUnixTimestamp() - habbo.getHabboStats().hcMessageLastModified) < 60) { Emulator.getThreading().run(() -> { habbo.getClient().sendResponse(new UserClubComposer(habbo)); habbo.getClient().sendResponse(new UserPermissionsComposer(habbo)); }, (Emulator.getIntUnixTimestamp() - habbo.getHabboStats().hcMessageLastModified)); } else { - habbo.getClient().sendResponse(new UserClubComposer(habbo)); + habbo.getClient().sendResponse(new UserClubComposer(habbo, SubscriptionHabboClub.HABBO_CLUB, UserClubComposer.RESPONSE_TYPE_NORMAL)); habbo.getClient().sendResponse(new UserPermissionsComposer(habbo)); } } @@ -91,7 +107,7 @@ public class SubscriptionHabboClub extends Subscription { if(amount < 0) { Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(this.getUserId()); if(habbo != null && habbo.getClient() != null) { - habbo.getClient().sendResponse(new UserClubComposer(habbo)); + habbo.getClient().sendResponse(new UserClubComposer(habbo, SubscriptionHabboClub.HABBO_CLUB, UserClubComposer.RESPONSE_TYPE_NORMAL)); habbo.getClient().sendResponse(new UserPermissionsComposer(habbo)); } } @@ -109,8 +125,8 @@ public class SubscriptionHabboClub extends Subscription { Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(this.getUserId()); - if(habbo.getClient() != null) { - habbo.getClient().sendResponse(new UserClubComposer(habbo)); + if(habbo != null && habbo.getClient() != null) { + habbo.getClient().sendResponse(new UserClubComposer(habbo, SubscriptionHabboClub.HABBO_CLUB, UserClubComposer.RESPONSE_TYPE_NORMAL)); habbo.getClient().sendResponse(new UserPermissionsComposer(habbo)); } } @@ -128,12 +144,15 @@ public class SubscriptionHabboClub extends Subscription { super.onExpired(); Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(this.getUserId()); - habbo.getHabboStats().maxFriends = Messenger.MAXIMUM_FRIENDS; - habbo.getHabboStats().maxRooms = RoomManager.MAXIMUM_ROOMS_USER; - Emulator.getThreading().run(habbo.getHabboStats()); + HabboInfo habboInfo = Emulator.getGameEnvironment().getHabboManager().getHabboInfo(this.getUserId()); + HabboStats stats = habboInfo.getHabboStats(); - if(ClothingValidationManager.VALIDATE_ON_HC_EXPIRE) { - habbo.getHabboInfo().setLook(ClothingValidationManager.validateLook(habbo, habbo.getHabboInfo().getLook(), habbo.getHabboInfo().getGender().name())); + stats.maxFriends = Messenger.MAXIMUM_FRIENDS; + stats.maxRooms = RoomManager.MAXIMUM_ROOMS_USER; + Emulator.getThreading().run(stats); + + if(habbo != null && ClothingValidationManager.VALIDATE_ON_HC_EXPIRE) { + habboInfo.setLook(ClothingValidationManager.validateLook(habbo, habboInfo.getLook(), habboInfo.getGender().name())); Emulator.getThreading().run(habbo.getHabboInfo()); if(habbo.getClient() != null) { @@ -145,8 +164,8 @@ public class SubscriptionHabboClub extends Subscription { } } - if(habbo.getClient() != null) { - habbo.getClient().sendResponse(new UserClubComposer(habbo)); + if(habbo != null && habbo.getClient() != null) { + habbo.getClient().sendResponse(new UserClubComposer(habbo, SubscriptionHabboClub.HABBO_CLUB, UserClubComposer.RESPONSE_TYPE_NORMAL)); habbo.getClient().sendResponse(new UserPermissionsComposer(habbo)); } } @@ -243,6 +262,7 @@ public class SubscriptionHabboClub extends Subscription { try { int userId = set.getInt("user_id"); HabboInfo habboInfo = Emulator.getGameEnvironment().getHabboManager().getHabboInfo(userId); + HabboStats stats = habboInfo.getHabboStats(); ClubCenterDataComposer calculated = calculatePayday(habboInfo); int totalReward = (calculated.creditRewardForMonthlySpent + calculated.creditRewardForStreakBonus); if(totalReward > 0) { @@ -250,7 +270,8 @@ public class SubscriptionHabboClub extends Subscription { HcPayDayLogEntry le = new HcPayDayLogEntry(timestampNow, userId, calculated.currentHcStreak, calculated.totalCreditsSpent, calculated.creditRewardForMonthlySpent, calculated.creditRewardForStreakBonus, totalReward, HC_PAYDAY_CURRENCY, claimed); Emulator.getThreading().run(le); } - habboInfo.getHabboStats().lastHCPayday = timestampNow; + stats.lastHCPayday = timestampNow; + Emulator.getThreading().run(stats); } catch (Exception e) { SubscriptionManager.LOGGER.error("Exception processing HC payday for user #" + set.getInt("user_id"), e); @@ -288,6 +309,13 @@ public class SubscriptionHabboClub extends Subscription { * @param habbo User to process */ public static void processUnclaimed(Habbo habbo) { + + progressAchievement(habbo.getHabboInfo()); + + if(habbo.getHabboStats().getRemainingClubGifts() > 0) { + habbo.getClient().sendResponse(new PickMonthlyClubGiftNotificationComposer(habbo.getHabboStats().getRemainingClubGifts())); + } + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT * FROM `logs_hc_payday` WHERE user_id = ? AND claimed = 0")) { statement.setInt(1, habbo.getHabboInfo().getId()); @@ -368,4 +396,22 @@ public class SubscriptionHabboClub extends Subscription { return true; } + private static void progressAchievement(HabboInfo habboInfo) { + HabboStats stats = habboInfo.getHabboStats(); + Achievement achievement = Emulator.getGameEnvironment().getAchievementManager().getAchievement(ACHIEVEMENT_NAME); + if(achievement != null) { + int currentProgress = stats.getAchievementProgress(achievement); + if(currentProgress == -1) { + currentProgress = 0; + } + + int progressToSet = (int)Math.ceil(stats.getPastTimeAsClub() / 2678400.0); + int toIncrease = Math.max(progressToSet - currentProgress, 0); + + if(toIncrease > 0) { + AchievementManager.progressAchievement(habboInfo.getId(), achievement, toIncrease); + } + } + } + } diff --git a/src/main/java/com/eu/habbo/messages/PacketManager.java b/src/main/java/com/eu/habbo/messages/PacketManager.java index 36c6e2c9..00cdb987 100644 --- a/src/main/java/com/eu/habbo/messages/PacketManager.java +++ b/src/main/java/com/eu/habbo/messages/PacketManager.java @@ -255,6 +255,10 @@ public class PacketManager { this.registerHandler(Incoming.CatalogSearchedItemEvent, CatalogSearchedItemEvent.class); this.registerHandler(Incoming.PurchaseTargetOfferEvent, PurchaseTargetOfferEvent.class); this.registerHandler(Incoming.TargetOfferStateEvent, TargetOfferStateEvent.class); + this.registerHandler(Incoming.CatalogSelectClubGiftEvent, CatalogSelectClubGiftEvent.class); + this.registerHandler(Incoming.RequestClubCenterEvent, RequestClubCenterEvent.class); + this.registerHandler(Incoming.CatalogRequestClubDiscountEvent, CatalogRequestClubDiscountEvent.class); + this.registerHandler(Incoming.CatalogBuyClubDiscountEvent, CatalogBuyClubDiscountEvent.class); } private void registerEvent() throws Exception { diff --git a/src/main/java/com/eu/habbo/messages/incoming/Incoming.java b/src/main/java/com/eu/habbo/messages/incoming/Incoming.java index 2f2bfc1d..53a76eeb 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/Incoming.java +++ b/src/main/java/com/eu/habbo/messages/incoming/Incoming.java @@ -40,6 +40,9 @@ public class Incoming { public static final int RequestHeightmapEvent = 3898; public static final int TradeCloseEvent = 2551; public static final int CatalogBuyItemEvent = 3492; + public static final int CatalogSelectClubGiftEvent = 2276; + public static final int CatalogRequestClubDiscountEvent = 2462; + public static final int CatalogBuyClubDiscountEvent = 3407; public static final int RequestGuildMembersEvent = 312; public static final int RequestPetInformationEvent = 2934; public static final int RoomUserWhisperEvent = 1543; @@ -72,6 +75,7 @@ public class Incoming { public static final int RequestPromotedRoomsEvent = 2908; public static final int GuildSetAdminEvent = 2894; public static final int GetClubDataEvent = 3285; + public static final int RequestClubCenterEvent = 869; public static final int RequestMeMenuSettingsEvent = 2388; public static final int MannequinSaveNameEvent = 2850; public static final int SellItemEvent = 3447; diff --git a/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogBuyClubDiscountEvent.java b/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogBuyClubDiscountEvent.java new file mode 100644 index 00000000..45567242 --- /dev/null +++ b/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogBuyClubDiscountEvent.java @@ -0,0 +1,88 @@ +package com.eu.habbo.messages.incoming.catalog; + +import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.catalog.ClubOffer; +import com.eu.habbo.habbohotel.permissions.Permission; +import com.eu.habbo.habbohotel.users.subscriptions.Subscription; +import com.eu.habbo.habbohotel.users.subscriptions.SubscriptionHabboClub; +import com.eu.habbo.messages.incoming.MessageHandler; +import com.eu.habbo.messages.outgoing.catalog.AlertPurchaseFailedComposer; +import com.eu.habbo.messages.outgoing.catalog.PurchaseOKComposer; +import com.eu.habbo.messages.outgoing.inventory.InventoryRefreshComposer; +import com.eu.habbo.messages.outgoing.unknown.ExtendClubMessageComposer; +import com.eu.habbo.messages.outgoing.users.UserClubComposer; +import com.eu.habbo.messages.outgoing.users.UserCreditsComposer; +import com.eu.habbo.messages.outgoing.users.UserCurrencyComposer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CatalogBuyClubDiscountEvent extends MessageHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(CatalogBuyClubDiscountEvent.class); + + @Override + public void handle() throws Exception { + + Subscription subscription = this.client.getHabbo().getHabboStats().getSubscription(SubscriptionHabboClub.HABBO_CLUB); + + int days = 0; + int minutes = 0; + int timeRemaining = 0; + + if(subscription != null) { + timeRemaining = subscription.getRemaining(); + days = (int) Math.floor(timeRemaining / 86400.0); + minutes = (int) Math.ceil(timeRemaining / 60.0); + + if(days < 1 && minutes > 0) { + days = 1; + } + } + + if(timeRemaining > 0 && SubscriptionHabboClub.DISCOUNT_ENABLED && days <= SubscriptionHabboClub.DISCOUNT_DAYS_BEFORE_END) { + ClubOffer deal = Emulator.getGameEnvironment().getCatalogManager().clubOffers.values().stream().filter(ClubOffer::isDeal).findAny().orElse(null); + + if(deal != null) { + ClubOffer regular = Emulator.getGameEnvironment().getCatalogManager().getClubOffers().stream().filter(x -> x.getDays() == deal.getDays()).findAny().orElse(null); + if(regular != null) { + + int totalDays = deal.getDays(); + int totalCredits = deal.getCredits(); + int totalDuckets = deal.getPoints(); + + if (totalDays > 0) { + if (this.client.getHabbo().getHabboInfo().getCurrencyAmount(deal.getPointsType()) < totalDuckets) + return; + + if (this.client.getHabbo().getHabboInfo().getCredits() < totalCredits) + return; + + if (!this.client.getHabbo().hasPermission(Permission.ACC_INFINITE_CREDITS)) + this.client.getHabbo().getHabboInfo().addCredits(-totalCredits); + + if (!this.client.getHabbo().hasPermission(Permission.ACC_INFINITE_POINTS)) + this.client.getHabbo().getHabboInfo().addCurrencyAmount(deal.getPointsType(), -totalDuckets); + + + if(this.client.getHabbo().getHabboStats().createSubscription(Subscription.HABBO_CLUB, (totalDays * 86400)) == null) { + this.client.sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR).compose()); + throw new Exception("Unable to create or extend subscription"); + } + + if (totalCredits > 0) + this.client.sendResponse(new UserCreditsComposer(this.client.getHabbo())); + + if (totalDuckets > 0) + this.client.sendResponse(new UserCurrencyComposer(this.client.getHabbo())); + + this.client.sendResponse(new PurchaseOKComposer(null)); + this.client.sendResponse(new InventoryRefreshComposer()); + + this.client.getHabbo().getHabboStats().run(); + } + } + } + } + + } +} diff --git a/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogBuyItemEvent.java b/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogBuyItemEvent.java index 17915caf..b0264ace 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogBuyItemEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogBuyItemEvent.java @@ -2,10 +2,7 @@ package com.eu.habbo.messages.incoming.catalog; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.bots.BotManager; -import com.eu.habbo.habbohotel.catalog.CatalogItem; -import com.eu.habbo.habbohotel.catalog.CatalogManager; -import com.eu.habbo.habbohotel.catalog.CatalogPage; -import com.eu.habbo.habbohotel.catalog.ClubOffer; +import com.eu.habbo.habbohotel.catalog.*; import com.eu.habbo.habbohotel.catalog.layouts.*; import com.eu.habbo.habbohotel.items.FurnitureType; import com.eu.habbo.habbohotel.permissions.Permission; @@ -66,10 +63,12 @@ public class CatalogBuyItemEvent extends MessageHandler { if (searchedItem.getOfferId() > 0) { page = Emulator.getGameEnvironment().getCatalogManager().getCatalogPage(searchedItem.getPageId()); - if (page.getCatalogItem(itemId).getOfferId() <= 0) { - page = null; - } else { - if (page.getRank() > this.client.getHabbo().getHabboInfo().getRank().getId()) { + if(page != null) { + if (page.getCatalogItem(itemId).getOfferId() <= 0) { + page = null; + } else if (page.getRank() > this.client.getHabbo().getHabboInfo().getRank().getId()) { + page = null; + } else if (page.getLayout() != null && page.getLayout().equalsIgnoreCase(CatalogPageLayouts.club_gift.name())) { page = null; } } @@ -77,6 +76,10 @@ public class CatalogBuyItemEvent extends MessageHandler { } else { page = Emulator.getGameEnvironment().getCatalogManager().catalogPages.get(pageId); + if(page != null && page.getLayout() != null && page.getLayout().equalsIgnoreCase(CatalogPageLayouts.club_gift.name())) { + page = null; + } + if (page instanceof RoomBundleLayout) { final CatalogItem[] item = new CatalogItem[1]; page.getCatalogItems().forEachValue(new TObjectProcedure() { diff --git a/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogRequestClubDiscountEvent.java b/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogRequestClubDiscountEvent.java new file mode 100644 index 00000000..1d5bc5c6 --- /dev/null +++ b/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogRequestClubDiscountEvent.java @@ -0,0 +1,54 @@ +package com.eu.habbo.messages.incoming.catalog; + +import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.catalog.CatalogItem; +import com.eu.habbo.habbohotel.catalog.CatalogPage; +import com.eu.habbo.habbohotel.catalog.CatalogPageLayouts; +import com.eu.habbo.habbohotel.catalog.ClubOffer; +import com.eu.habbo.habbohotel.items.Item; +import com.eu.habbo.habbohotel.users.subscriptions.Subscription; +import com.eu.habbo.habbohotel.users.subscriptions.SubscriptionHabboClub; +import com.eu.habbo.messages.incoming.MessageHandler; +import com.eu.habbo.messages.outgoing.catalog.AlertPurchaseFailedComposer; +import com.eu.habbo.messages.outgoing.unknown.ExtendClubMessageComposer; +import com.eu.habbo.messages.outgoing.users.ClubGiftReceivedComposer; +import gnu.trove.set.hash.THashSet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CatalogRequestClubDiscountEvent extends MessageHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(CatalogRequestClubDiscountEvent.class); + + @Override + public void handle() throws Exception { + + Subscription subscription = this.client.getHabbo().getHabboStats().getSubscription(SubscriptionHabboClub.HABBO_CLUB); + + int days = 0; + int minutes = 0; + int timeRemaining = 0; + + if(subscription != null) { + timeRemaining = subscription.getRemaining(); + days = (int) Math.floor(timeRemaining / 86400.0); + minutes = (int) Math.ceil(timeRemaining / 60.0); + + if(days < 1 && minutes > 0) { + days = 1; + } + } + + if(timeRemaining > 0 && SubscriptionHabboClub.DISCOUNT_ENABLED && days <= SubscriptionHabboClub.DISCOUNT_DAYS_BEFORE_END) { + ClubOffer deal = Emulator.getGameEnvironment().getCatalogManager().clubOffers.values().stream().filter(ClubOffer::isDeal).findAny().orElse(null); + + if(deal != null) { + ClubOffer regular = Emulator.getGameEnvironment().getCatalogManager().getClubOffers().stream().filter(x -> x.getDays() == deal.getDays()).findAny().orElse(null); + if(regular != null) { + this.client.sendResponse(new ExtendClubMessageComposer(this.client.getHabbo(), deal, regular.getCredits(), regular.getPoints(), regular.getPointsType(), Math.max(0, days))); + } + } + } + + } +} diff --git a/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogSelectClubGiftEvent.java b/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogSelectClubGiftEvent.java new file mode 100644 index 00000000..e4d6794d --- /dev/null +++ b/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogSelectClubGiftEvent.java @@ -0,0 +1,77 @@ +package com.eu.habbo.messages.incoming.catalog; + +import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.catalog.CatalogItem; +import com.eu.habbo.habbohotel.catalog.CatalogPage; +import com.eu.habbo.habbohotel.catalog.CatalogPageLayouts; +import com.eu.habbo.habbohotel.items.Item; +import com.eu.habbo.messages.incoming.MessageHandler; +import com.eu.habbo.messages.outgoing.catalog.*; +import com.eu.habbo.messages.outgoing.users.ClubGiftReceivedComposer; +import gnu.trove.set.hash.THashSet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CatalogSelectClubGiftEvent extends MessageHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(CatalogSelectClubGiftEvent.class); + + @Override + public void handle() throws Exception { + + String itemName = this.packet.readString(); + + if(itemName.isEmpty()) { + LOGGER.error("itemName is empty"); + this.client.sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR)); + return; + } + + if(this.client.getHabbo().getHabboStats().getRemainingClubGifts() < 1) { + LOGGER.error("User has no remaining club gifts"); + this.client.sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR)); + return; + } + + CatalogPage page = Emulator.getGameEnvironment().getCatalogManager().getCatalogPageByLayout(CatalogPageLayouts.club_gift.name().toLowerCase()); + + if(page == null) { + LOGGER.error("Catalog page not found"); + this.client.sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR)); + return; + } + + CatalogItem catalogItem = page.getCatalogItems().valueCollection().stream().filter(x -> x.getName().equalsIgnoreCase(itemName)).findAny().orElse(null); + + if(catalogItem == null) { + LOGGER.error("Catalog item not found"); + this.client.sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR)); + return; + } + + int daysRequired = 0; + try { + daysRequired = Integer.parseInt(catalogItem.getExtradata()); + } + catch (NumberFormatException ignored) { } + + if(daysRequired > (int) Math.floor(this.client.getHabbo().getHabboStats().getPastTimeAsClub() / 86400.0)) { + LOGGER.error("Not been member for long enough"); + this.client.sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR)); + return; + } + + THashSet itemsGiven = new THashSet<>(); + for(Item item : catalogItem.getBaseItems()) { + if(Emulator.getGameEnvironment().getItemManager().createGift(this.client.getHabbo().getHabboInfo().getId(), item, "", 0, 0) != null) { + itemsGiven.add(item); + } + } + + this.client.getHabbo().getHabboStats().hcGiftsClaimed++; + Emulator.getThreading().run(this.client.getHabbo().getHabboStats()); + + this.client.sendResponse(new ClubGiftReceivedComposer(itemName, itemsGiven)); + + } +} diff --git a/src/main/java/com/eu/habbo/messages/incoming/catalog/RequestClubDataEvent.java b/src/main/java/com/eu/habbo/messages/incoming/catalog/RequestClubDataEvent.java index 79eb7525..6085e1eb 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/catalog/RequestClubDataEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/catalog/RequestClubDataEvent.java @@ -9,6 +9,5 @@ public class RequestClubDataEvent extends MessageHandler { @Override public void handle() throws Exception { this.client.sendResponse(new ClubDataComposer(this.client.getHabbo(), this.packet.readInt())); - this.client.sendResponse(SubscriptionHabboClub.calculatePayday(this.client.getHabbo().getHabboInfo())); } } diff --git a/src/main/java/com/eu/habbo/messages/incoming/catalog/RequestClubGiftsEvent.java b/src/main/java/com/eu/habbo/messages/incoming/catalog/RequestClubGiftsEvent.java index 98bc8014..777e65fd 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/catalog/RequestClubGiftsEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/catalog/RequestClubGiftsEvent.java @@ -6,6 +6,10 @@ import com.eu.habbo.messages.outgoing.catalog.ClubGiftsComposer; public class RequestClubGiftsEvent extends MessageHandler { @Override public void handle() throws Exception { - this.client.sendResponse(new ClubGiftsComposer()); + this.client.sendResponse(new ClubGiftsComposer( + (int) Math.floor(this.client.getHabbo().getHabboStats().getTimeTillNextClubGift() / 86400.0), + this.client.getHabbo().getHabboStats().getRemainingClubGifts(), + (int) Math.floor(this.client.getHabbo().getHabboStats().getPastTimeAsClub() / 86400.0) + )); } } diff --git a/src/main/java/com/eu/habbo/messages/incoming/handshake/SecureLoginEvent.java b/src/main/java/com/eu/habbo/messages/incoming/handshake/SecureLoginEvent.java index f28c9758..89ca6250 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/handshake/SecureLoginEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/handshake/SecureLoginEvent.java @@ -138,7 +138,7 @@ public class SecureLoginEvent extends MessageHandler { //messages.add(new MessengerInitComposer(this.client.getHabbo()).compose()); //messages.add(new FriendsComposer(this.client.getHabbo()).compose()); - messages.add(new UserClubComposer(this.client.getHabbo()).compose()); + messages.add(new UserClubComposer(this.client.getHabbo(), SubscriptionHabboClub.HABBO_CLUB, UserClubComposer.RESPONSE_TYPE_LOGIN).compose()); if (this.client.getHabbo().hasPermission(Permission.ACC_SUPPORTTOOL)) { messages.add(new ModToolComposer(this.client.getHabbo()).compose()); diff --git a/src/main/java/com/eu/habbo/messages/incoming/users/RequestClubCenterEvent.java b/src/main/java/com/eu/habbo/messages/incoming/users/RequestClubCenterEvent.java new file mode 100644 index 00000000..80dede05 --- /dev/null +++ b/src/main/java/com/eu/habbo/messages/incoming/users/RequestClubCenterEvent.java @@ -0,0 +1,12 @@ +package com.eu.habbo.messages.incoming.users; + +import com.eu.habbo.habbohotel.users.subscriptions.SubscriptionHabboClub; +import com.eu.habbo.messages.incoming.MessageHandler; +import com.eu.habbo.messages.outgoing.users.UserClubComposer; + +public class RequestClubCenterEvent extends MessageHandler { + @Override + public void handle() throws Exception { + this.client.sendResponse(SubscriptionHabboClub.calculatePayday(this.client.getHabbo().getHabboInfo())); + } +} diff --git a/src/main/java/com/eu/habbo/messages/incoming/users/RequestUserClubEvent.java b/src/main/java/com/eu/habbo/messages/incoming/users/RequestUserClubEvent.java index c560fbb1..34fb4905 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/users/RequestUserClubEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/users/RequestUserClubEvent.java @@ -6,6 +6,7 @@ import com.eu.habbo.messages.outgoing.users.UserClubComposer; public class RequestUserClubEvent extends MessageHandler { @Override public void handle() throws Exception { - this.client.sendResponse(new UserClubComposer(this.client.getHabbo())); + String subscriptionType = this.packet.readString(); + this.client.sendResponse(new UserClubComposer(this.client.getHabbo(), subscriptionType)); } } diff --git a/src/main/java/com/eu/habbo/messages/outgoing/catalog/ClubDataComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/catalog/ClubDataComposer.java index 6d44e75d..96188ad2 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/catalog/ClubDataComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/catalog/ClubDataComposer.java @@ -28,45 +28,7 @@ public class ClubDataComposer extends MessageComposer { //TODO Change this to a seperate table. for (ClubOffer offer : offers) { - this.response.appendInt(offer.getId()); - this.response.appendString(offer.getName()); - this.response.appendBoolean(false); //unused - this.response.appendInt(offer.getCredits()); - this.response.appendInt(offer.getPoints()); - this.response.appendInt(offer.getPointsType()); - this.response.appendBoolean(offer.isVip()); - - long seconds = offer.getDays() * 86400L; - - long secondsTotal = seconds; - - int totalYears = (int) Math.floor((int) seconds / 86400 * 31 * 12); - seconds -= totalYears * 86400 * 31 * 12; - - int totalMonths = (int) Math.floor((int) seconds / 86400 * 31); - seconds -= totalMonths * 86400 * 31; - - int totalDays = (int) Math.floor((int) seconds / 86400); - seconds -= totalDays * 86400; - - this.response.appendInt((int) secondsTotal / 86400 / 31); - this.response.appendInt((int) seconds); - this.response.appendBoolean(false); //giftable - this.response.appendInt((int) seconds); - - int endTimestamp = this.habbo.getHabboStats().getClubExpireTimestamp(); - - if (endTimestamp < Emulator.getIntUnixTimestamp()) { - endTimestamp = Emulator.getIntUnixTimestamp(); - } - - endTimestamp += secondsTotal; - - Calendar cal = Calendar.getInstance(); - cal.setTimeInMillis(endTimestamp * 1000L); - this.response.appendInt(cal.get(Calendar.YEAR)); - this.response.appendInt(cal.get(Calendar.MONTH) + 1); - this.response.appendInt(cal.get(Calendar.DAY_OF_MONTH)); + offer.serialize(this.response, this.habbo.getHabboStats().getClubExpireTimestamp()); } this.response.appendInt(this.windowId); diff --git a/src/main/java/com/eu/habbo/messages/outgoing/catalog/ClubGiftsComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/catalog/ClubGiftsComposer.java index f4e1161d..13e4bfc6 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/catalog/ClubGiftsComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/catalog/ClubGiftsComposer.java @@ -3,63 +3,60 @@ package com.eu.habbo.messages.outgoing.catalog; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.catalog.CatalogItem; import com.eu.habbo.habbohotel.catalog.CatalogPage; +import com.eu.habbo.habbohotel.catalog.CatalogPageLayouts; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.outgoing.MessageComposer; import com.eu.habbo.messages.outgoing.Outgoing; import gnu.trove.iterator.TIntObjectIterator; +import gnu.trove.procedure.TObjectProcedure; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.NoSuchElementException; public class ClubGiftsComposer extends MessageComposer { + + private final int daysTillNextGift; + private final int availableGifts; + private final int daysAsHc; + + public ClubGiftsComposer(int daysTillNextGift, int availableGifts, int daysAsHc) { + this.daysTillNextGift = daysTillNextGift; + this.availableGifts = availableGifts; + this.daysAsHc = daysAsHc; + } + @Override protected ServerMessage composeInternal() { this.response.init(Outgoing.ClubGiftsComposer); - this.response.appendInt(0); //Days Until Next Gift - this.response.appendInt(1); //Gift Selectable + this.response.appendInt(this.daysTillNextGift); //Days Until Next Gift + this.response.appendInt(this.availableGifts); //Gift Selectable - CatalogPage page = Emulator.getGameEnvironment().getCatalogManager().getCatalogPage(Emulator.getConfig().getInt("catalog.page.vipgifts")); + CatalogPage page = Emulator.getGameEnvironment().getCatalogManager().getCatalogPageByLayout(CatalogPageLayouts.club_gift.name().toLowerCase()); if (page != null) { - this.response.appendInt(page.getCatalogItems().size()); + final List items = new ArrayList<>(page.getCatalogItems().valueCollection()); + Collections.sort(items); - TIntObjectIterator iterator = page.getCatalogItems().iterator(); - for (int i = page.getCatalogItems().size(); i-- > 0; ) { - try { - iterator.advance(); - - CatalogItem item = iterator.value(); - - if (item != null) { - item.serialize(this.response); - } - } catch (NoSuchElementException e) { - break; - } + this.response.appendInt(items.size()); + for(CatalogItem item : items) { + item.serialize(this.response); } - this.response.appendInt(page.getCatalogItems().size()); - iterator = page.getCatalogItems().iterator(); - for (int i = page.getCatalogItems().size(); i-- > 0; ) { + this.response.appendInt(items.size()); + for(CatalogItem item : items) { + int daysRequired = 0; try { - iterator.advance(); - - CatalogItem item = iterator.value(); - - if (item != null) { - this.response.appendInt(item.getId()); - this.response.appendBoolean(true); - this.response.appendInt(i); - this.response.appendBoolean(true); - } else { - this.response.appendInt(-100); - this.response.appendBoolean(false); - this.response.appendInt(-100); - this.response.appendBoolean(false); - } - } catch (NoSuchElementException e) { - break; + daysRequired = Integer.parseInt(item.getExtradata()); } + catch (NumberFormatException ignored) { } + + this.response.appendInt(item.getId()); + this.response.appendBoolean(item.isClubOnly()); + this.response.appendInt(Math.max(daysRequired - daysAsHc, 0)); + this.response.appendBoolean(daysRequired <= daysAsHc); } } else { this.response.appendInt(0); diff --git a/src/main/java/com/eu/habbo/messages/outgoing/unknown/ExtendClubMessageComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/unknown/ExtendClubMessageComposer.java index ec7cf3a1..8225c519 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/unknown/ExtendClubMessageComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/unknown/ExtendClubMessageComposer.java @@ -1,88 +1,37 @@ package com.eu.habbo.messages.outgoing.unknown; -import com.eu.habbo.Emulator; -import com.eu.habbo.habbohotel.catalog.CatalogItem; +import com.eu.habbo.habbohotel.catalog.ClubOffer; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.outgoing.MessageComposer; import com.eu.habbo.messages.outgoing.Outgoing; -import java.util.Calendar; - public class ExtendClubMessageComposer extends MessageComposer { private final Habbo habbo; - private final CatalogItem item; - private final int unknownInt1; - private final int unknownInt2; - private final int unknownInt3; - private final int unknownInt4; + private final ClubOffer offer; + private final int normalCreditCost; + private final int normalPointsCost; + private final int pointsType; + private final int daysRemaining; - public ExtendClubMessageComposer(Habbo habbo, CatalogItem item, int unknownInt1, int unknownInt2, int unknownInt3, int unknownInt4) { + public ExtendClubMessageComposer(Habbo habbo, ClubOffer offer, int normalCreditCost, int normalPointsCost, int pointsType, int daysRemaining) { this.habbo = habbo; - this.item = item; - this.unknownInt1 = unknownInt1; - this.unknownInt2 = unknownInt2; - this.unknownInt3 = unknownInt3; - this.unknownInt4 = unknownInt4; + this.offer = offer; + this.normalCreditCost = normalCreditCost; + this.normalPointsCost = normalPointsCost; + this.pointsType = pointsType; + this.daysRemaining = daysRemaining; } @Override protected ServerMessage composeInternal() { this.response.init(Outgoing.ExtendClubMessageComposer); - this.response.appendInt(this.item.getId()); - this.response.appendString(this.item.getName()); - this.response.appendBoolean(false); //unused - this.response.appendInt(this.item.getCredits()); - this.response.appendInt(this.item.getPoints()); - this.response.appendInt(this.item.getPointsType()); - this.response.appendBoolean(this.item.getName().contains("_VIP_")); + this.offer.serialize(this.response, this.habbo.getHabboStats().getClubExpireTimestamp()); - String[] data = this.item.getName().replace("_VIP_", "_").toLowerCase().split("_"); - - long seconds = 0; - - if (data[3].toLowerCase().startsWith("day")) { - seconds = 86400 * Integer.valueOf(data[2]); - } else if (data[3].toLowerCase().startsWith("month")) { - seconds = 86400 * 31 * Integer.valueOf(data[2]); - } else if (data[3].toLowerCase().startsWith("year")) { - seconds = 86400 * 31 * 12 * Integer.valueOf(data[2]); - } - - long secondsTotal = seconds; - - int totalYears = (int) Math.floor((int) seconds / 86400 * 31 * 12); - seconds -= totalYears * 86400 * 31 * 12; - - int totalMonths = (int) Math.floor((int) seconds / 86400 * 31); - seconds -= totalMonths * 86400 * 31; - - int totalDays = (int) Math.floor((int) seconds / 86400); - seconds -= totalDays * 86400; - - this.response.appendInt((int) secondsTotal / 86400 / 31); - this.response.appendInt((int) seconds); - this.response.appendBoolean(false); //giftable - this.response.appendInt((int) seconds); - - int endTimestamp = this.habbo.getHabboStats().getClubExpireTimestamp(); - - if (endTimestamp < Emulator.getIntUnixTimestamp()) { - endTimestamp = Emulator.getIntUnixTimestamp(); - } - - endTimestamp += secondsTotal; - - Calendar cal = Calendar.getInstance(); - cal.setTimeInMillis(endTimestamp * 1000L); - this.response.appendInt(cal.get(Calendar.YEAR)); - this.response.appendInt(cal.get(Calendar.MONTH) + 1); - this.response.appendInt(cal.get(Calendar.DAY_OF_MONTH)); - - this.response.appendInt(this.unknownInt1); - this.response.appendInt(this.unknownInt2); - this.response.appendInt(this.unknownInt3); - this.response.appendInt(this.unknownInt4); + this.response.appendInt(this.normalCreditCost); + this.response.appendInt(this.normalPointsCost); + this.response.appendInt(this.pointsType); + this.response.appendInt(this.daysRemaining); return this.response; } } \ No newline at end of file diff --git a/src/main/java/com/eu/habbo/messages/outgoing/users/ClubGiftReceivedComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/users/ClubGiftReceivedComposer.java index b67608bd..de0755f4 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/users/ClubGiftReceivedComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/users/ClubGiftReceivedComposer.java @@ -1,6 +1,6 @@ package com.eu.habbo.messages.outgoing.users; -import com.eu.habbo.habbohotel.users.HabboItem; +import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.outgoing.MessageComposer; import com.eu.habbo.messages.outgoing.Outgoing; @@ -8,23 +8,23 @@ import gnu.trove.set.hash.THashSet; public class ClubGiftReceivedComposer extends MessageComposer { //:test 735 s:t i:1 s:s i:230 s:throne i:1 b:1 i:1 i:10; - private final THashSet items; + private final String name; + private final THashSet items; - public ClubGiftReceivedComposer(THashSet items) { + public ClubGiftReceivedComposer(String name, THashSet items) { + this.name = name; this.items = items; } @Override protected ServerMessage composeInternal() { this.response.init(Outgoing.ClubGiftReceivedComposer); + + this.response.appendString(this.name); this.response.appendInt(this.items.size()); - for (HabboItem item : this.items) { - this.response.appendString(item.getBaseItem().getType().code); - this.response.appendInt(item.getBaseItem().getId()); - this.response.appendString(item.getBaseItem().getName()); - this.response.appendInt(0); - this.response.appendBoolean(false); + for (Item item : this.items) { + item.serialize(this.response); } return this.response; diff --git a/src/main/java/com/eu/habbo/messages/outgoing/users/UserClubComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/users/UserClubComposer.java index 6bcb5f65..695561d2 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/users/UserClubComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/users/UserClubComposer.java @@ -3,6 +3,8 @@ package com.eu.habbo.messages.outgoing.users; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.subscriptions.Subscription; +import com.eu.habbo.habbohotel.users.subscriptions.SubscriptionHabboClub; +import com.eu.habbo.habbohotel.users.subscriptions.SubscriptionManager; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.outgoing.MessageComposer; import com.eu.habbo.messages.outgoing.Outgoing; @@ -13,22 +15,59 @@ import java.util.concurrent.TimeUnit; public class UserClubComposer extends MessageComposer { private final Habbo habbo; + private final String subscriptionType; + private final int responseType; + + public static int RESPONSE_TYPE_NORMAL = 0; + public static int RESPONSE_TYPE_LOGIN = 1; + public static int RESPONSE_TYPE_PURCHASE = 2; // closes the catalog after buying + public static int RESPONSE_TYPE_DISCOUNT_AVAILABLE = 3; + public static int RESPONSE_TYPE_CITIZENSHIP_DISCOUNT = 4; public UserClubComposer(Habbo habbo) { this.habbo = habbo; + this.subscriptionType = SubscriptionHabboClub.HABBO_CLUB.toLowerCase(); + this.responseType = 0; + } + + public UserClubComposer(Habbo habbo, String subscriptionType) { + this.habbo = habbo; + this.subscriptionType = subscriptionType; + this.responseType = 0; + } + + public UserClubComposer(Habbo habbo, String subscriptionType, int responseType) { + this.habbo = habbo; + this.subscriptionType = subscriptionType; + this.responseType = responseType; } @Override protected ServerMessage composeInternal() { this.response.init(Outgoing.UserClubComposer); - this.response.appendString("club_habbo"); + this.response.appendString(this.subscriptionType.toLowerCase()); - Subscription subscription = this.habbo.getHabboStats().getSubscription(Subscription.HABBO_CLUB); + if(Emulator.getGameEnvironment().getSubscriptionManager().getSubscriptionClass(this.subscriptionType.toUpperCase()) == null) { + this.response.appendInt(0); // daysToPeriodEnd + this.response.appendInt(0); // memberPeriods + this.response.appendInt(0); // periodsSubscribedAhead + this.response.appendInt(0); // responseType + this.response.appendBoolean(false); // hasEverBeenMember + this.response.appendBoolean(false); // isVIP + this.response.appendInt(0); // pastClubDays + this.response.appendInt(0); // pastVIPdays + this.response.appendInt(0); // minutesTillExpiration + this.response.appendInt(0); // minutesSinceLastModified + return this.response; + } + + Subscription subscription = this.habbo.getHabboStats().getSubscription(this.subscriptionType); int days = 0; int minutes = 0; int timeRemaining = 0; + int pastTimeAsHC = this.habbo.getHabboStats().getPastTimeAsClub(); if(subscription != null) { timeRemaining = subscription.getRemaining(); @@ -40,14 +79,16 @@ public class UserClubComposer extends MessageComposer { } } + int responseType = ((this.responseType <= RESPONSE_TYPE_LOGIN) && timeRemaining > 0 && SubscriptionHabboClub.DISCOUNT_ENABLED && days <= SubscriptionHabboClub.DISCOUNT_DAYS_BEFORE_END) ? RESPONSE_TYPE_DISCOUNT_AVAILABLE : this.responseType; + this.response.appendInt(days); // daysToPeriodEnd this.response.appendInt(0); // memberPeriods this.response.appendInt(0); // periodsSubscribedAhead - this.response.appendInt(0); // responseType - this.response.appendBoolean(true); // hasEverBeenMember + this.response.appendInt(responseType); // responseType + this.response.appendBoolean(pastTimeAsHC > 0); // hasEverBeenMember this.response.appendBoolean(true); // isVIP this.response.appendInt(0); // pastClubDays - this.response.appendInt(0); // pastVIPdays + this.response.appendInt((int) Math.floor(pastTimeAsHC / 86400.0)); // pastVIPdays this.response.appendInt(minutes); // minutesTillExpiration this.response.appendInt((Emulator.getIntUnixTimestamp() - this.habbo.getHabboStats().hcMessageLastModified) / 60); // minutesSinceLastModified this.habbo.getHabboStats().hcMessageLastModified = Emulator.getIntUnixTimestamp(); @@ -63,6 +104,14 @@ public class UserClubComposer extends MessageComposer { // int - minutesTillExpiration // (optional) int - minutesSinceLastModified + /* + responseType: + 1 = RESPONSE_TYPE_LOGIN + 2 = RESPONSE_TYPE_PURCHASE + 3 = RESPONSE_TYPE_DISCOUNT_AVAILABLE + 4 = RESPONSE_TYPE_CITIZENSHIP_DISCOUNT + */ + /* int endTimestamp = this.habbo.getHabboStats().getClubExpireTimestamp(); diff --git a/src/main/java/com/eu/habbo/messages/rcon/ModifyUserSubscription.java b/src/main/java/com/eu/habbo/messages/rcon/ModifyUserSubscription.java new file mode 100644 index 00000000..8ec3e2ea --- /dev/null +++ b/src/main/java/com/eu/habbo/messages/rcon/ModifyUserSubscription.java @@ -0,0 +1,108 @@ +package com.eu.habbo.messages.rcon; + +import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.rooms.RoomChatMessageBubbles; +import com.eu.habbo.habbohotel.users.Habbo; +import com.eu.habbo.habbohotel.users.HabboInfo; +import com.eu.habbo.habbohotel.users.subscriptions.Subscription; +import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDataComposer; +import com.eu.habbo.messages.outgoing.users.MeMenuSettingsComposer; +import com.eu.habbo.messages.outgoing.users.UpdateUserLookComposer; +import com.google.gson.Gson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +public class ModifyUserSubscription extends RCONMessage { + private static final Logger LOGGER = LoggerFactory.getLogger(ModifyUserSubscription.class); + + public ModifyUserSubscription() { + super(ModifyUserSubscription.JSON.class); + } + + @Override + public void handle(Gson gson, JSON json) { + try { + + if(json.user_id <= 0) { + this.status = RCONMessage.HABBO_NOT_FOUND; + this.message = "User not found"; + return; + } + + if (!Emulator.getGameEnvironment().getSubscriptionManager().types.containsKey(json.type)) { + this.status = RCONMessage.STATUS_ERROR; + this.message = "%subscription% is not a valid subscription type".replace("%subscription%", json.type); + return; + } + + HabboInfo habbo = Emulator.getGameEnvironment().getHabboManager().getHabboInfo(json.user_id); + + if (habbo == null) { + this.status = RCONMessage.HABBO_NOT_FOUND; + this.message = "User not found"; + return; + } + + if (json.action.equalsIgnoreCase("add") || json.action.equalsIgnoreCase("+") || json.action.equalsIgnoreCase("a")) { + if (json.duration < 1) { + this.status = RCONMessage.STATUS_ERROR; + this.message = "duration must be > 0"; + return; + } + + habbo.getHabboStats().createSubscription(json.type, json.duration); + this.status = RCONMessage.STATUS_OK; + this.message = "Successfully added %time% seconds to %subscription% on %user%".replace("%time%", json.duration + "").replace("%user%", habbo.getUsername()).replace("%subscription%", json.type); + } else if (json.action.equalsIgnoreCase("remove") || json.action.equalsIgnoreCase("-") || json.action.equalsIgnoreCase("r")) { + Subscription s = habbo.getHabboStats().getSubscription(json.type); + + if (s == null) { + this.status = RCONMessage.STATUS_ERROR; + this.message = "%user% does not have the %subscription% subscription".replace("%user%", habbo.getUsername()).replace("%subscription%", json.type); + return; + } + + if (json.duration != -1) { + if (json.duration < 1) { + this.status = RCONMessage.STATUS_ERROR; + this.message = "duration must be > 0 or -1 to remove all time"; + return; + } + + s.addDuration(-json.duration); + this.status = RCONMessage.STATUS_OK; + this.message = "Successfully removed %time% seconds from %subscription% on %user%".replace("%time%", json.duration + "").replace("%user%", habbo.getUsername()).replace("%subscription%", json.type); + } else { + s.addDuration(-s.getRemaining()); + this.status = RCONMessage.STATUS_OK; + this.message = "Successfully removed %subscription% sub from %user%".replace("%user%", habbo.getUsername()).replace("%subscription%", json.type); + } + } + else { + this.status = RCONMessage.STATUS_ERROR; + this.message = "Invalid action specified. Must be add, +, remove or -"; + } + } + catch (Exception e) { + this.status = RCONMessage.SYSTEM_ERROR; + this.message = "Exception occurred"; + LOGGER.error("Exception occurred", e); + } + } + + static class JSON { + + public int user_id; + + public String type = ""; // Subscription type e.g. HABBO_CLUB + + public String action = ""; // Can be add or remove + + public int duration = -1; // Time to add/remove in seconds. -1 means remove subscription entirely + + } +} \ No newline at end of file diff --git a/src/main/java/com/eu/habbo/networking/rconserver/RCONServer.java b/src/main/java/com/eu/habbo/networking/rconserver/RCONServer.java index ebc225f5..7bbd9f05 100644 --- a/src/main/java/com/eu/habbo/networking/rconserver/RCONServer.java +++ b/src/main/java/com/eu/habbo/networking/rconserver/RCONServer.java @@ -61,6 +61,7 @@ public class RCONServer extends Server { this.addRCONMessage("ignoreuser", IgnoreUser.class); this.addRCONMessage("setmotto", SetMotto.class); this.addRCONMessage("giveuserclothing", GiveUserClothing.class); + this.addRCONMessage("modifysubscription", ModifyUserSubscription.class); Collections.addAll(this.allowedAdresses, Emulator.getConfig().getValue("rcon.allowed", "127.0.0.1").split(";")); } diff --git a/src/main/java/com/eu/habbo/plugin/PluginManager.java b/src/main/java/com/eu/habbo/plugin/PluginManager.java index 041f835d..eff47754 100644 --- a/src/main/java/com/eu/habbo/plugin/PluginManager.java +++ b/src/main/java/com/eu/habbo/plugin/PluginManager.java @@ -178,6 +178,9 @@ public class PluginManager { SubscriptionHabboClub.HC_PAYDAY_CURRENCY = Emulator.getConfig().getValue("subscriptions.hc.payday.currency"); SubscriptionHabboClub.HC_PAYDAY_KICKBACK_PERCENTAGE = Emulator.getConfig().getInt("subscriptions.hc.payday.percentage", 10) / 100.0; SubscriptionHabboClub.HC_PAYDAY_COINSSPENT_RESET_ON_EXPIRE = Emulator.getConfig().getBoolean("subscriptions.hc.payday.creditsspent_reset_on_expire", false); + SubscriptionHabboClub.ACHIEVEMENT_NAME = Emulator.getConfig().getValue("subscriptions.hc.achievement", "VipHC"); + SubscriptionHabboClub.DISCOUNT_ENABLED = Emulator.getConfig().getBoolean("subscriptions.hc.discount.enabled", false); + SubscriptionHabboClub.DISCOUNT_DAYS_BEFORE_END = Emulator.getConfig().getInt("subscriptions.hc.discount.days_before_end", 7); SubscriptionHabboClub.HC_PAYDAY_STREAK.clear(); for (String streak : Emulator.getConfig().getValue("subscriptions.hc.payday.streak", "7=5;30=10;60=15;90=20;180=25;365=30").split(Pattern.quote(";"))) {