diff --git a/sqlupdates/2_4_0 to 3_0_BETA_1.sql b/sqlupdates/2_4_0 to 3_0_BETA_1.sql index f87aa41e..70294fbb 100644 --- a/sqlupdates/2_4_0 to 3_0_BETA_1.sql +++ b/sqlupdates/2_4_0 to 3_0_BETA_1.sql @@ -126,3 +126,7 @@ INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('commands.description.cmd_ -- Making items.wired_data column bigger since wired data is saved as JSON now ALTER TABLE `items` MODIFY COLUMN `wired_data` varchar(10000); +-- Mute area sqls +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('room.chat.mutearea.allow_whisper', 'false'); + + diff --git a/sqlupdates/3_0_BETA_1 to 3_0_0-RC-1.sql b/sqlupdates/3_0_BETA_1 to 3_0_0-RC-1.sql index dfb1f885..31e6474c 100644 --- a/sqlupdates/3_0_BETA_1 to 3_0_0-RC-1.sql +++ b/sqlupdates/3_0_BETA_1 to 3_0_0-RC-1.sql @@ -4,3 +4,6 @@ INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('wired.variable.roomname', INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('wired.variable.user_count', '%user_count%'); INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('wired.variable.owner', '%owner%'); INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('wired.variable.item_count', '%item_count%'); + +-- Enable bubble alerts +INSERT INTO `emulator_settings` (`key`, `value`) VALUES ('bubblealerts.enabled', '1'); 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 1d2a4f34..6e7908c2 100644 --- a/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogManager.java +++ b/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogManager.java @@ -662,7 +662,6 @@ public class CatalogManager { if (isVisiblePage && hasRightRank && clubRightsOkay) { pages.add(object); } - return true; } }); diff --git a/src/main/java/com/eu/habbo/habbohotel/commands/UpdateNavigatorCommand.java b/src/main/java/com/eu/habbo/habbohotel/commands/UpdateNavigatorCommand.java index c01c2e94..ee3b5f9a 100644 --- a/src/main/java/com/eu/habbo/habbohotel/commands/UpdateNavigatorCommand.java +++ b/src/main/java/com/eu/habbo/habbohotel/commands/UpdateNavigatorCommand.java @@ -13,7 +13,7 @@ public class UpdateNavigatorCommand extends Command { public boolean handle(GameClient gameClient, String[] params) throws Exception { Emulator.getGameEnvironment().getNavigatorManager().loadNavigator(); Emulator.getGameEnvironment().getRoomManager().loadRoomModels(); - Emulator.getGameEnvironment().getRoomManager().loadPublicRooms(); + gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.succes.cmd_update_navigator"), RoomChatMessageBubbles.ALERT); return true; diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/InteractionGameTimer.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/InteractionGameTimer.java index 1f7396e9..bb868c6d 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/InteractionGameTimer.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/InteractionGameTimer.java @@ -14,6 +14,7 @@ import com.eu.habbo.habbohotel.wired.WiredEffectType; import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.habbohotel.wired.WiredTriggerType; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.threading.runnables.games.GameTimer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,7 +64,7 @@ public class InteractionGameTimer extends HabboItem implements Runnable { String[] data = set.getString("extra_data").split("\t"); if (data.length >= 2) { - this.baseTime = Integer.valueOf(data[1]); + this.baseTime = Integer.parseInt(data[1]); this.timeNow = this.baseTime; } @@ -149,33 +150,6 @@ public class InteractionGameTimer extends HabboItem implements Runnable { if (this.needsUpdate() || this.needsDelete()) { super.run(); } - - if (this.getRoomId() == 0) { - this.threadActive = false; - return; - } - - Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); - - if (room == null || !this.isRunning || this.isPaused) { - this.threadActive = false; - return; - } - - this.timeNow--; - if (this.timeNow < 0) this.timeNow = 0; - - if (this.timeNow > 0) { - this.threadActive = true; - Emulator.getThreading().run(this, 1000); - } else { - this.threadActive = false; - this.timeNow = 0; - this.endGame(room); - WiredHandler.handle(WiredTriggerType.GAME_ENDS, null, room, new Object[]{}); - } - - room.updateItem(this); } @Override @@ -248,7 +222,7 @@ public class InteractionGameTimer extends HabboItem implements Runnable { if (!this.threadActive) { this.threadActive = true; - Emulator.getThreading().run(this, 1000); + Emulator.getThreading().run(new GameTimer(this), 1000); } } else if (client != null) { if (!(room.hasRights(client.getHabbo()) || client.getHabbo().hasPermission(Permission.ACC_ANYROOMOWNER))) @@ -271,7 +245,7 @@ public class InteractionGameTimer extends HabboItem implements Runnable { if (!this.threadActive) { this.threadActive = true; - Emulator.getThreading().run(this); + Emulator.getThreading().run(new GameTimer(this)); } } } else { @@ -285,7 +259,7 @@ public class InteractionGameTimer extends HabboItem implements Runnable { if (!this.threadActive) { this.threadActive = true; - Emulator.getThreading().run(this, 1000); + Emulator.getThreading().run(new GameTimer(this), 1000); } } @@ -350,10 +324,30 @@ public class InteractionGameTimer extends HabboItem implements Runnable { } public boolean isRunning() { - return isRunning; + return this.isRunning; } public void setRunning(boolean running) { - isRunning = running; + this.isRunning = running; + } + + public void setThreadActive(boolean threadActive) { + this.threadActive = threadActive; + } + + public boolean isPaused() { + return this.isPaused; + } + + public void reduceTime() { + this.timeNow--; + } + + public int getTimeNow() { + return this.timeNow; + } + + public void setTimeNow(int timeNow) { + this.timeNow = timeNow; } } diff --git a/src/main/java/com/eu/habbo/habbohotel/modtool/ModToolManager.java b/src/main/java/com/eu/habbo/habbohotel/modtool/ModToolManager.java index 9dbd405a..2a65ba4a 100644 --- a/src/main/java/com/eu/habbo/habbohotel/modtool/ModToolManager.java +++ b/src/main/java/com/eu/habbo/habbohotel/modtool/ModToolManager.java @@ -54,7 +54,7 @@ public class ModToolManager { if (userId <= 0) return; - try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT users.*, users_settings.*, permissions.rank_name, permissions.id as rank_id FROM users INNER JOIN users_settings ON users.id = users_settings.user_id INNER JOIN permissions ON permissions.id = users.rank WHERE users.id = ? LIMIT 1")) { + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT users.*, users_settings.*, permissions.rank_name, permissions.acc_hide_mail AS hide_mail, permissions.id AS rank_id FROM users INNER JOIN users_settings ON users.id = users_settings.user_id INNER JOIN permissions ON permissions.id = users.rank WHERE users.id = ? LIMIT 1")) { statement.setInt(1, userId); try (ResultSet set = statement.executeQuery()) { while (set.next()) { @@ -428,6 +428,16 @@ public class ModToolManager { return bans; } + //if machine id is empty, downgrade ban type to IP ban + if( (type == ModToolBanType.MACHINE || type == ModToolBanType.SUPER) && (offlineInfo == null || offlineInfo.getMachineID().isEmpty())) { + type = ModToolBanType.IP; + } + + //if ip address is empty, downgrade ban type to account ban + if( (type == ModToolBanType.IP || type == ModToolBanType.SUPER) && (offlineInfo == null || offlineInfo.getIpLogin().isEmpty())) { + type = ModToolBanType.ACCOUNT; + } + ModToolBan ban = new ModToolBan(targetUserId, offlineInfo != null ? offlineInfo.getIpLogin() : "offline", offlineInfo != null ? offlineInfo.getMachineID() : "offline", moderator.getHabboInfo().getId(), Emulator.getIntUnixTimestamp() + duration, reason, type, cfhTopic); Emulator.getPluginManager().fireEvent(new SupportUserBannedEvent(moderator, target, ban)); Emulator.getThreading().run(ban); diff --git a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomManager.java b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomManager.java index 113736f1..05ddc66a 100644 --- a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomManager.java +++ b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomManager.java @@ -1176,7 +1176,6 @@ public class RoomManager { continue; Habbo friend = Emulator.getGameEnvironment().getHabboManager().getHabbo(buddy.getId()); - if (friend == null || friend.getHabboInfo().getCurrentRoom() == null) continue; @@ -1313,7 +1312,7 @@ public class RoomManager { if (friend == null || friend.getHabboInfo() == null) continue; Room room = friend.getHabboInfo().getCurrentRoom(); - if (room != null) rooms.add(room); + if (room != null && !rooms.contains(room)) rooms.add(room); if (rooms.size() >= limit) break; } 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 f0b1692b..66c3d041 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 @@ -78,16 +78,18 @@ public class SubscriptionHabboClub extends Subscription { progressAchievement(habboInfo); Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(this.getUserId()); - if(habbo != null && habbo.getClient() != null) { + if (habbo != null && habbo.getClient() != null) { - if(habbo.getHabboStats().getRemainingClubGifts() > 0) { + 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 { + 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, SubscriptionHabboClub.HABBO_CLUB, UserClubComposer.RESPONSE_TYPE_NORMAL)); habbo.getClient().sendResponse(new UserPermissionsComposer(habbo)); } @@ -104,9 +106,9 @@ public class SubscriptionHabboClub extends Subscription { public void addDuration(int amount) { super.addDuration(amount); - if(amount < 0) { + if (amount < 0) { Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(this.getUserId()); - if(habbo != null && habbo.getClient() != null) { + 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)); } @@ -125,7 +127,7 @@ public class SubscriptionHabboClub extends Subscription { Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(this.getUserId()); - if(habbo != null && habbo.getClient() != null) { + 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)); } @@ -151,11 +153,11 @@ public class SubscriptionHabboClub extends Subscription { stats.maxRooms = RoomManager.MAXIMUM_ROOMS_USER; Emulator.getThreading().run(stats); - if(habbo != null && ClothingValidationManager.VALIDATE_ON_HC_EXPIRE) { + 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) { + if (habbo.getClient() != null) { habbo.getClient().sendResponse(new UpdateUserLookComposer(habbo)); } @@ -164,7 +166,7 @@ public class SubscriptionHabboClub extends Subscription { } } - if(habbo != null && habbo.getClient() != null) { + 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)); } @@ -172,6 +174,7 @@ public class SubscriptionHabboClub extends Subscription { /** * Calculate's a users upcoming HC Pay day rewards + * * @param habbo User to calculate for * @return ClubCenterDataComposer */ @@ -184,27 +187,27 @@ public class SubscriptionHabboClub extends Subscription { int creditRewardForMonthlySpent = 0; int timeUntilPayday = 0; - for(Subscription sub : habbo.getHabboStats().subscriptions) { - if(sub.getSubscriptionType().equalsIgnoreCase(Subscription.HABBO_CLUB)) { + for (Subscription sub : habbo.getHabboStats().subscriptions) { + if (sub.getSubscriptionType().equalsIgnoreCase(Subscription.HABBO_CLUB)) { - if(firstEverSub == null || sub.getTimestampStart() < firstEverSub.getTimestampStart()) { + if (firstEverSub == null || sub.getTimestampStart() < firstEverSub.getTimestampStart()) { firstEverSub = sub; } - if(sub.isActive()) { + if (sub.isActive()) { activeSub = sub; } } } - if(HC_PAYDAY_ENABLED && activeSub != null) { - currentHcStreak = (int)Math.floor((Emulator.getIntUnixTimestamp() - activeSub.getTimestampStart()) / (60 * 60 * 24.0)); - if(currentHcStreak < 1) { + if (HC_PAYDAY_ENABLED && activeSub != null) { + currentHcStreak = (int) Math.floor((Emulator.getIntUnixTimestamp() - activeSub.getTimestampStart()) / (60 * 60 * 24.0)); + if (currentHcStreak < 1) { currentHcStreak = 0; } - for(Map.Entry set : HC_PAYDAY_STREAK.entrySet()) { - if(currentHcStreak >= set.getKey() && set.getValue() > creditRewardForStreakBonus) { + for (Map.Entry set : HC_PAYDAY_STREAK.entrySet()) { + if (currentHcStreak >= set.getKey() && set.getValue() > creditRewardForStreakBonus) { creditRewardForStreakBonus = set.getValue(); } } @@ -227,21 +230,21 @@ public class SubscriptionHabboClub extends Subscription { SubscriptionManager.LOGGER.error("Caught SQL exception", e); } - creditRewardForMonthlySpent = (int)Math.floor(totalCreditsSpent * HC_PAYDAY_KICKBACK_PERCENTAGE); + creditRewardForMonthlySpent = (int) Math.floor(totalCreditsSpent * HC_PAYDAY_KICKBACK_PERCENTAGE); timeUntilPayday = (HC_PAYDAY_NEXT_DATE - Emulator.getIntUnixTimestamp()) / 60; } return new ClubCenterDataComposer( - currentHcStreak, - (firstEverSub != null ? new SimpleDateFormat("dd-MM-yyyy").format(new Date(firstEverSub.getTimestampStart() * 1000L)) : ""), - HC_PAYDAY_KICKBACK_PERCENTAGE, - 0, - 0, - totalCreditsSpent, - creditRewardForStreakBonus, - creditRewardForMonthlySpent, - timeUntilPayday + currentHcStreak, + (firstEverSub != null ? new SimpleDateFormat("dd-MM-yyyy").format(new Date(firstEverSub.getTimestampStart() * 1000L)) : ""), + HC_PAYDAY_KICKBACK_PERCENTAGE, + 0, + 0, + totalCreditsSpent, + creditRewardForStreakBonus, + creditRewardForMonthlySpent, + timeUntilPayday ); } @@ -265,15 +268,14 @@ public class SubscriptionHabboClub extends Subscription { HabboStats stats = habboInfo.getHabboStats(); ClubCenterDataComposer calculated = calculatePayday(habboInfo); int totalReward = (calculated.creditRewardForMonthlySpent + calculated.creditRewardForStreakBonus); - if(totalReward > 0) { + if (totalReward > 0) { boolean claimed = claimPayDay(Emulator.getGameEnvironment().getHabboManager().getHabbo(userId), totalReward, HC_PAYDAY_CURRENCY); HcPayDayLogEntry le = new HcPayDayLogEntry(timestampNow, userId, calculated.currentHcStreak, calculated.totalCreditsSpent, calculated.creditRewardForMonthlySpent, calculated.creditRewardForStreakBonus, totalReward, HC_PAYDAY_CURRENCY, claimed); Emulator.getThreading().run(le); } stats.lastHCPayday = timestampNow; Emulator.getThreading().run(stats); - } - catch (Exception e) { + } catch (Exception e) { SubscriptionManager.LOGGER.error("Exception processing HC payday for user #" + set.getInt("user_id"), e); } } @@ -281,24 +283,23 @@ public class SubscriptionHabboClub extends Subscription { Date date = new java.util.Date(HC_PAYDAY_NEXT_DATE * 1000L); date = Emulator.modifyDate(date, HC_PAYDAY_INTERVAL); - HC_PAYDAY_NEXT_DATE = (int)(date.getTime() / 1000L); + HC_PAYDAY_NEXT_DATE = (int) (date.getTime() / 1000L); - try(PreparedStatement stm2 = connection.prepareStatement("UPDATE `emulator_settings` SET `value` = ? WHERE `key` = ?")) { + try (PreparedStatement stm2 = connection.prepareStatement("UPDATE `emulator_settings` SET `value` = ? WHERE `key` = ?")) { SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); stm2.setString(1, sdf.format(date)); stm2.setString(2, "subscriptions.hc.payday.next_date"); stm2.execute(); } - try(PreparedStatement stm2 = connection.prepareStatement("UPDATE users_settings SET last_hc_payday = ? WHERE user_id IN (SELECT user_id FROM `users_subscriptions` WHERE subscription_type = '" + Subscription.HABBO_CLUB + "' AND `active` = 1 AND `timestamp_start` < ? AND (`timestamp_start` + `duration`) > ? GROUP BY user_id)")) { + try (PreparedStatement stm2 = connection.prepareStatement("UPDATE users_settings SET last_hc_payday = ? WHERE user_id IN (SELECT user_id FROM `users_subscriptions` WHERE subscription_type = '" + Subscription.HABBO_CLUB + "' AND `active` = 1 AND `timestamp_start` < ? AND (`timestamp_start` + `duration`) > ? GROUP BY user_id)")) { stm2.setInt(1, timestampNow); stm2.setInt(2, timestampNow); stm2.setInt(3, timestampNow); stm2.execute(); } - } - catch (SQLException e) { + } catch (SQLException e) { SubscriptionManager.LOGGER.error("Caught SQL exception", e); } isExecuting = false; @@ -306,13 +307,14 @@ public class SubscriptionHabboClub extends Subscription { /** * Called when a user logs in. Checks for any unclaimed HC Pay day rewards and issues rewards. + * * @param habbo User to process */ public static void processUnclaimed(Habbo habbo) { progressAchievement(habbo.getHabboInfo()); - if(habbo.getHabboStats().getRemainingClubGifts() > 0) { + if (habbo.getHabboStats().getRemainingClubGifts() > 0) { habbo.getClient().sendResponse(new PickMonthlyClubGiftNotificationComposer(habbo.getHabboStats().getRemainingClubGifts())); } @@ -328,25 +330,31 @@ public class SubscriptionHabboClub extends Subscription { int totalPayout = set.getInt("total_payout"); String currency = set.getString("currency"); - if(claimPayDay(habbo, totalPayout, currency)) { - try(PreparedStatement stm2 = connection.prepareStatement("UPDATE logs_hc_payday SET claimed = 1 WHERE id = ?")) { + if (claimPayDay(habbo, totalPayout, currency)) { + try (PreparedStatement stm2 = connection.prepareStatement("UPDATE logs_hc_payday SET claimed = 1 WHERE id = ?")) { stm2.setInt(1, logId); stm2.execute(); } } - } - catch (Exception e) { + } catch (Exception e) { SubscriptionManager.LOGGER.error("Exception processing HC payday for user #" + set.getInt("user_id"), e); } } } - } - catch (SQLException e) { + } catch (SQLException e) { SubscriptionManager.LOGGER.error("Caught SQL exception", e); } } + /** + * + * Seperated these because Beny shouldn't have tied them to Payday. + */ + public static void processClubBadge(Habbo habbo) { + progressAchievement(habbo.getHabboInfo()); + } + /** * Issues rewards to user. * @param habbo User to reward to diff --git a/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogBuyItemAsGiftEvent.java b/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogBuyItemAsGiftEvent.java index 7504c50a..13ffb72a 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogBuyItemAsGiftEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogBuyItemAsGiftEvent.java @@ -336,7 +336,10 @@ public class CatalogBuyItemAsGiftEvent extends MessageHandler { return; } - AchievementManager.progressAchievement(this.client.getHabbo(), Emulator.getGameEnvironment().getAchievementManager().getAchievement("GiftGiver")); + if (this.client.getHabbo().getHabboInfo().getId() != userId) { + AchievementManager.progressAchievement(this.client.getHabbo(), Emulator.getGameEnvironment().getAchievementManager().getAchievement("GiftGiver")); + } + if (habbo != null) { habbo.getClient().sendResponse(new AddHabboItemComposer(gift)); habbo.getClient().getHabbo().getInventory().getItemsComponent().addItem(gift); @@ -351,7 +354,9 @@ public class CatalogBuyItemAsGiftEvent extends MessageHandler { habbo.getClient().sendResponse(new BubbleAlertComposer(BubbleAlertKeys.RECEIVED_BADGE.key, keys)); } - AchievementManager.progressAchievement(userId, Emulator.getGameEnvironment().getAchievementManager().getAchievement("GiftReceiver")); + if (this.client.getHabbo().getHabboInfo().getId() != userId) { + AchievementManager.progressAchievement(userId, Emulator.getGameEnvironment().getAchievementManager().getAchievement("GiftReceiver")); + } if (!this.client.getHabbo().hasPermission(Permission.ACC_INFINITE_CREDITS)) { if (totalCredits > 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 3e13a26a..82ab0bf1 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 @@ -19,7 +19,7 @@ import com.eu.habbo.messages.outgoing.gamecenter.GameCenterGameListComposer; import com.eu.habbo.messages.outgoing.generic.alerts.GenericAlertComposer; import com.eu.habbo.messages.outgoing.generic.alerts.MessagesForYouComposer; import com.eu.habbo.messages.outgoing.habboway.nux.NewUserIdentityComposer; -import com.eu.habbo.messages.outgoing.handshake.DebugConsoleComposer; +import com.eu.habbo.messages.outgoing.handshake.EnableNotificationsComposer; import com.eu.habbo.messages.outgoing.handshake.SecureLoginOKComposer; import com.eu.habbo.messages.outgoing.handshake.AvailabilityStatusMessageComposer; import com.eu.habbo.messages.outgoing.handshake.PingComposer; @@ -122,7 +122,7 @@ public class SecureLoginEvent extends MessageHandler { messages.add(new UserPermissionsComposer(this.client.getHabbo()).compose()); messages.add(new AvailabilityStatusMessageComposer(true, false, true).compose()); messages.add(new PingComposer().compose()); - messages.add(new DebugConsoleComposer(Emulator.debugging).compose()); + messages.add(new EnableNotificationsComposer(Emulator.getConfig().getBoolean("bubblealerts.enabled", true)).compose()); messages.add(new UserAchievementScoreComposer(this.client.getHabbo()).compose()); messages.add(new IsFirstLoginOfDayComposer(true).compose()); messages.add(new UnknownComposer5().compose()); @@ -205,6 +205,8 @@ public class SecureLoginEvent extends MessageHandler { SubscriptionHabboClub.processUnclaimed(habbo); } + SubscriptionHabboClub.processClubBadge(habbo); + Messenger.checkFriendSizeProgress(habbo); if (!habbo.getHabboStats().hasGottenDefaultSavedSearches) { diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MannequinSaveNameEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MannequinSaveNameEvent.java index 7715ffd2..ad09fc3c 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MannequinSaveNameEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MannequinSaveNameEvent.java @@ -9,7 +9,7 @@ public class MannequinSaveNameEvent extends MessageHandler { @Override public void handle() throws Exception { Room room = this.client.getHabbo().getHabboInfo().getCurrentRoom(); - if (room == null || this.client.getHabbo().getHabboInfo().getId() != room.getOwnerId()) + if (room == null || !room.isOwner(this.client.getHabbo())) return; HabboItem item = room.getHabboItem(this.packet.readInt()); diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/pets/BreedMonsterplantsEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/pets/BreedMonsterplantsEvent.java index a297244c..9ce44416 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/pets/BreedMonsterplantsEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/pets/BreedMonsterplantsEvent.java @@ -13,7 +13,7 @@ public class BreedMonsterplantsEvent extends MessageHandler { Pet petOne = this.client.getHabbo().getHabboInfo().getCurrentRoom().getPet(this.packet.readInt()); Pet petTwo = this.client.getHabbo().getHabboInfo().getCurrentRoom().getPet(this.packet.readInt()); - if (petOne == null || petTwo == null) { + if (petOne == null || petTwo == null || petOne == petTwo) { //TODO Add error return; } @@ -23,4 +23,4 @@ public class BreedMonsterplantsEvent extends MessageHandler { } } } -} \ No newline at end of file +} diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/promotions/BuyRoomPromotionEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/promotions/BuyRoomPromotionEvent.java index fdf37650..a157cf15 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/promotions/BuyRoomPromotionEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/promotions/BuyRoomPromotionEvent.java @@ -21,7 +21,7 @@ public class BuyRoomPromotionEvent extends MessageHandler { int itemId = this.packet.readInt(); int roomId = this.packet.readInt(); String title = this.packet.readString(); - boolean unknown1 = this.packet.readBoolean(); + boolean extendedPromotion = this.packet.readBoolean(); String description = this.packet.readString(); int categoryId = this.packet.readInt(); @@ -30,40 +30,41 @@ public class BuyRoomPromotionEvent extends MessageHandler { CatalogPage page = Emulator.getGameEnvironment().getCatalogManager().getCatalogPage(pageId); - if (page != null) { - CatalogItem item = page.getCatalogItem(itemId); - if (item != null) { - if (this.client.getHabbo().getHabboInfo().canBuy(item)) { - Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(roomId); + if (page == null || !page.getLayout().equals("roomads")) + return; - if (!(room.isOwner(this.client.getHabbo()) || room.hasRights(this.client.getHabbo()) || room.getGuildRightLevel(this.client.getHabbo()).equals(RoomRightLevels.GUILD_ADMIN))) { - return; + CatalogItem item = page.getCatalogItem(itemId); + if (item != null) { + if (this.client.getHabbo().getHabboInfo().canBuy(item)) { + Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(roomId); + + if (!(room.isOwner(this.client.getHabbo()) || room.hasRights(this.client.getHabbo()) || room.getGuildRightLevel(this.client.getHabbo()).equals(RoomRightLevels.GUILD_ADMIN))) { + return; + } + + if (room.isPromoted()) { + room.getPromotion().addEndTimestamp(120 * 60); + } else { + room.createPromotion(title, description, categoryId); + } + + if (room.isPromoted()) { + if (!this.client.getHabbo().hasPermission(Permission.ACC_INFINITE_CREDITS)) { + this.client.getHabbo().giveCredits(-item.getCredits()); } - if (room.isPromoted()) { - room.getPromotion().addEndTimestamp(120 * 60); - } else { - room.createPromotion(title, description, categoryId); + if (!this.client.getHabbo().hasPermission(Permission.ACC_INFINITE_POINTS)) { + this.client.getHabbo().givePoints(item.getPointsType(), -item.getPoints()); } - if (room.isPromoted()) { - if (!this.client.getHabbo().hasPermission(Permission.ACC_INFINITE_CREDITS)) { - this.client.getHabbo().giveCredits(-item.getCredits()); - } + this.client.sendResponse(new PurchaseOKComposer()); + room.sendComposer(new RoomPromotionMessageComposer(room, room.getPromotion()).compose()); - if (!this.client.getHabbo().hasPermission(Permission.ACC_INFINITE_POINTS)) { - this.client.getHabbo().givePoints(item.getPointsType(), -item.getPoints()); - } - - this.client.sendResponse(new PurchaseOKComposer()); - room.sendComposer(new RoomPromotionMessageComposer(room, room.getPromotion()).compose()); - - if (!this.client.getHabbo().getInventory().getBadgesComponent().hasBadge(BuyRoomPromotionEvent.ROOM_PROMOTION_BADGE)) { - this.client.getHabbo().addBadge(BuyRoomPromotionEvent.ROOM_PROMOTION_BADGE); - } - } else { - this.client.sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR)); + if (!this.client.getHabbo().getInventory().getBadgesComponent().hasBadge(BuyRoomPromotionEvent.ROOM_PROMOTION_BADGE)) { + this.client.getHabbo().addBadge(BuyRoomPromotionEvent.ROOM_PROMOTION_BADGE); } + } else { + this.client.sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR)); } } } diff --git a/src/main/java/com/eu/habbo/messages/incoming/trading/TradeOfferMultipleItemsEvent.java b/src/main/java/com/eu/habbo/messages/incoming/trading/TradeOfferMultipleItemsEvent.java index 098345e4..231a70c1 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/trading/TradeOfferMultipleItemsEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/trading/TradeOfferMultipleItemsEvent.java @@ -21,7 +21,7 @@ public class TradeOfferMultipleItemsEvent extends MessageHandler { int count = this.packet.readInt(); for (int i = 0; i < count; i++) { HabboItem item = this.client.getHabbo().getInventory().getItemsComponent().getHabboItem(this.packet.readInt()); - if (item != null) { + if (item != null && item.getBaseItem().allowTrade()) { items.add(item); } } diff --git a/src/main/java/com/eu/habbo/messages/incoming/users/SaveWardrobeEvent.java b/src/main/java/com/eu/habbo/messages/incoming/users/SaveWardrobeEvent.java index 1e58686b..94625424 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/users/SaveWardrobeEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/users/SaveWardrobeEvent.java @@ -21,7 +21,9 @@ public class SaveWardrobeEvent extends MessageHandler { wardrobeItem.setNeedsUpdate(true); } else { wardrobeItem = this.client.getHabbo().getInventory().getWardrobeComponent().createLook(this.client.getHabbo(), slotId, look); + wardrobeItem.setGender(HabboGender.valueOf(gender)); wardrobeItem.setNeedsInsert(true); + this.client.getHabbo().getInventory().getWardrobeComponent().getLooks().put(slotId, wardrobeItem); } UserSavedWardrobeEvent wardrobeEvent = new UserSavedWardrobeEvent(this.client.getHabbo(), wardrobeItem); diff --git a/src/main/java/com/eu/habbo/messages/outgoing/Outgoing.java b/src/main/java/com/eu/habbo/messages/outgoing/Outgoing.java index fb84490b..e38663e7 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/Outgoing.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/Outgoing.java @@ -116,7 +116,7 @@ public class Outgoing { public final static int CatalogModeComposer = 3828; // PRODUCTION-201611291003-338511768 public final static int ChangeNameUpdateComposer = 118; // PRODUCTION-201611291003-338511768 public final static int AddFloorItemComposer = 1534; // PRODUCTION-201611291003-338511768 - public final static int DebugConsoleComposer = 3284; // PRODUCTION-201611291003-338511768 + public final static int EnableNotificationsComposer = 3284; // PRODUCTION-201611291003-338511768 public final static int HallOfFameComposer = 3005; // PRODUCTION-201611291003-338511768 public final static int WiredSavedComposer = 1155; // PRODUCTION-201611291003-338511768 public final static int RoomPaintComposer = 2454; // PRODUCTION-201611291003-338511768 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 13e4bfc6..e45b4822 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 @@ -55,7 +55,7 @@ public class ClubGiftsComposer extends MessageComposer { this.response.appendInt(item.getId()); this.response.appendBoolean(item.isClubOnly()); - this.response.appendInt(Math.max(daysRequired - daysAsHc, 0)); + this.response.appendInt(daysRequired); this.response.appendBoolean(daysRequired <= daysAsHc); } } else { diff --git a/src/main/java/com/eu/habbo/messages/outgoing/handshake/DebugConsoleComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/handshake/DebugConsoleComposer.java deleted file mode 100644 index 4ea035af..00000000 --- a/src/main/java/com/eu/habbo/messages/outgoing/handshake/DebugConsoleComposer.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.eu.habbo.messages.outgoing.handshake; - -import com.eu.habbo.messages.ServerMessage; -import com.eu.habbo.messages.outgoing.MessageComposer; -import com.eu.habbo.messages.outgoing.Outgoing; - -public class DebugConsoleComposer extends MessageComposer { - private final boolean debugging; - - public DebugConsoleComposer(boolean debugging) { - this.debugging = debugging; - } - - @Override - protected ServerMessage composeInternal() { - this.response.init(Outgoing.DebugConsoleComposer); - this.response.appendBoolean(this.debugging); - return this.response; - } -} diff --git a/src/main/java/com/eu/habbo/messages/outgoing/handshake/EnableNotificationsComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/handshake/EnableNotificationsComposer.java new file mode 100644 index 00000000..575cd174 --- /dev/null +++ b/src/main/java/com/eu/habbo/messages/outgoing/handshake/EnableNotificationsComposer.java @@ -0,0 +1,20 @@ +package com.eu.habbo.messages.outgoing.handshake; + +import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.outgoing.MessageComposer; +import com.eu.habbo.messages.outgoing.Outgoing; + +public class EnableNotificationsComposer extends MessageComposer { + private final boolean enabled; + + public EnableNotificationsComposer(boolean enabled) { + this.enabled = enabled; + } + + @Override + protected ServerMessage composeInternal() { + this.response.init(Outgoing.EnableNotificationsComposer); + this.response.appendBoolean(this.enabled); + return this.response; + } +} diff --git a/src/main/java/com/eu/habbo/messages/outgoing/modtool/ModToolUserInfoComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/modtool/ModToolUserInfoComposer.java index 74fde87e..41bce32f 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/modtool/ModToolUserInfoComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/modtool/ModToolUserInfoComposer.java @@ -58,7 +58,7 @@ public class ModToolUserInfoComposer extends MessageComposer { this.response.appendString(""); //Last Purchase Timestamp this.response.appendInt(this.set.getInt("user_id")); //Personal Identification # this.response.appendInt(0); // Number of account bans - this.response.appendString(this.set.getString("mail")); + this.response.appendString(this.set.getBoolean("hide_mail") ? "" : this.set.getString("mail")); this.response.appendString("Rank (" + this.set.getInt("rank_id") + "): " + this.set.getString("rank_name")); //user_class_txt ModToolSanctions modToolSanctions = Emulator.getGameEnvironment().getModToolSanctions(); diff --git a/src/main/java/com/eu/habbo/networking/gameserver/GameServer.java b/src/main/java/com/eu/habbo/networking/gameserver/GameServer.java index 3aa20998..98647cc7 100644 --- a/src/main/java/com/eu/habbo/networking/gameserver/GameServer.java +++ b/src/main/java/com/eu/habbo/networking/gameserver/GameServer.java @@ -32,9 +32,6 @@ public class GameServer extends Server { public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast("logger", new LoggingHandler()); - ch.pipeline().addLast("idleStateHandler", new IdleStateHandler(60, 30, 0)); - ch.pipeline().addAfter("idleStateHandler", "idleEventHandler", new IdleTimeoutHandler()); - // Decoders. ch.pipeline().addLast(new GamePolicyDecoder()); ch.pipeline().addLast(new GameByteFrameDecoder()); @@ -43,7 +40,7 @@ public class GameServer extends Server { if (PacketManager.DEBUG_SHOW_PACKETS) { ch.pipeline().addLast(new GameClientMessageLogger()); } - + ch.pipeline().addLast("idleEventHandler", new IdleTimeoutHandler(30, 60)); ch.pipeline().addLast(new GameMessageRateLimit()); ch.pipeline().addLast(new GameMessageHandler()); diff --git a/src/main/java/com/eu/habbo/networking/gameserver/handlers/IdleTimeoutHandler.java b/src/main/java/com/eu/habbo/networking/gameserver/handlers/IdleTimeoutHandler.java index 46bb4c14..26c55666 100644 --- a/src/main/java/com/eu/habbo/networking/gameserver/handlers/IdleTimeoutHandler.java +++ b/src/main/java/com/eu/habbo/networking/gameserver/handlers/IdleTimeoutHandler.java @@ -1,29 +1,136 @@ package com.eu.habbo.networking.gameserver.handlers; import com.eu.habbo.habbohotel.gameclients.GameClient; +import com.eu.habbo.messages.ClientMessage; +import com.eu.habbo.messages.incoming.Incoming; import com.eu.habbo.messages.outgoing.handshake.PingComposer; import com.eu.habbo.networking.gameserver.GameServerAttributes; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.timeout.IdleState; -import io.netty.handler.timeout.IdleStateEvent; + +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; public class IdleTimeoutHandler extends ChannelDuplexHandler { - @Override - public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { - if (evt instanceof IdleStateEvent) { - IdleStateEvent e = (IdleStateEvent) evt; - if (e.state() == IdleState.READER_IDLE) { - ctx.close(); - } else if (e.state() == IdleState.WRITER_IDLE) { - GameClient client = ctx.channel().attr(GameServerAttributes.CLIENT).get(); - if (client != null) { - client.sendResponse(new PingComposer()); - } - } - } else { - super.userEventTriggered(ctx, evt); + private static final long MIN_TIMEOUT_NANOS = TimeUnit.MILLISECONDS.toNanos(1); + + private final long pingScheduleNanos; + private final long pongTimeoutNanos; + + volatile ScheduledFuture pingScheduleFuture; + volatile long lastPongTime;// in nanoseconds + + private volatile int state; // 0 - none, 1 - initialized, 2 - destroyed + + public IdleTimeoutHandler(int pingScheduleSeconds, int pongTimeoutSeconds) { + this.pingScheduleNanos = Math.max(MIN_TIMEOUT_NANOS, TimeUnit.SECONDS.toNanos(pingScheduleSeconds)); + this.pongTimeoutNanos = Math.max(MIN_TIMEOUT_NANOS, TimeUnit.SECONDS.toNanos(pongTimeoutSeconds)); + } + + private void initialize(ChannelHandlerContext ctx) { + // Avoid the case where destroy() is called before scheduling timeouts. + // See: https://github.com/netty/netty/issues/143 + switch (state) { + case 1: + case 2: + return; + } + + state = 1; + + lastPongTime = System.nanoTime(); + if (pingScheduleNanos > 0) { + pingScheduleFuture = ctx.executor().schedule(new PingScheduledTask(ctx), pingScheduleNanos, TimeUnit.NANOSECONDS); } } + private void destroy() { + state = 2; + + if (pingScheduleFuture != null) { + pingScheduleFuture.cancel(false); + pingScheduleFuture = null; + } + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + if (ctx.channel().isActive() && ctx.channel().isRegistered()) { + // channelActvie() event has been fired already, which means this.channelActive() will + // not be invoked. We have to initialize here instead. + initialize(ctx); + } else { + // channelActive() event has not been fired yet. this.channelActive() will be invoked + // and initialization will occur there. + } + } + + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + destroy(); + } + + @Override + public void channelRegistered(ChannelHandlerContext ctx) throws Exception { + // Initialize early if channel is active already. + if (ctx.channel().isActive()) { + initialize(ctx); + } + super.channelRegistered(ctx); + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + // This method will be invoked only if this handler was added + // before channelActive() event is fired. If a user adds this handler + // after the channelActive() event, initialize() will be called by beforeAdd(). + initialize(ctx); + super.channelActive(ctx); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + destroy(); + super.channelInactive(ctx); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // check if its a pong message + if(msg instanceof ClientMessage) { + ClientMessage packet = (ClientMessage) msg; + if(packet.getMessageId() == Incoming.PongEvent) { + this.lastPongTime = System.nanoTime(); + } + } + super.channelRead(ctx, msg); + } + + private final class PingScheduledTask implements Runnable { + private final ChannelHandlerContext ctx; + + public PingScheduledTask(ChannelHandlerContext ctx) { + this.ctx = ctx; + } + + @Override + public void run() { + if (!ctx.channel().isOpen()) { + return; + } + + long currentTime = System.nanoTime(); + if(currentTime - lastPongTime > pongTimeoutNanos) { + ctx.close();// add a promise here ? + return; + } + + GameClient client = ctx.channel().attr(GameServerAttributes.CLIENT).get(); + if (client != null) { + client.sendResponse(new PingComposer()); + } + + pingScheduleFuture = ctx.executor().schedule(this, pingScheduleNanos, TimeUnit.NANOSECONDS); + } + } } diff --git a/src/main/java/com/eu/habbo/threading/runnables/games/GameTimer.java b/src/main/java/com/eu/habbo/threading/runnables/games/GameTimer.java new file mode 100644 index 00000000..f1e903e7 --- /dev/null +++ b/src/main/java/com/eu/habbo/threading/runnables/games/GameTimer.java @@ -0,0 +1,46 @@ +package com.eu.habbo.threading.runnables.games; + +import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.items.interactions.games.InteractionGameTimer; +import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.wired.WiredHandler; +import com.eu.habbo.habbohotel.wired.WiredTriggerType; + +public class GameTimer implements Runnable { + + private final InteractionGameTimer timer; + + public GameTimer(InteractionGameTimer timer) { + this.timer = timer; + } + + @Override + public void run() { + if (timer.getRoomId() == 0) { + timer.setRunning(false); + return; + } + + Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(timer.getRoomId()); + + if (room == null || !timer.isRunning() || timer.isPaused()) { + timer.setThreadActive(false); + return; + } + + timer.reduceTime(); + if (timer.getTimeNow() < 0) timer.setTimeNow(0); + + if (timer.getTimeNow() > 0) { + timer.setThreadActive(true); + Emulator.getThreading().run(this, 1000); + } else { + timer.setThreadActive(false); + timer.setTimeNow(0); + timer.endGame(room); + WiredHandler.handle(WiredTriggerType.GAME_ENDS, null, room, new Object[]{}); + } + + room.updateItem(timer); + } +}