diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..e045ce45 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM maven:latest AS builder + +# Copy the Emulator sources to the container +COPY . . +# Package it +RUN mvn package && mv /target/Habbo*-with-dependencies.jar /target/Habbo.jar + +# Use Java 8 for running +FROM java:8 AS runner + +# Copy the generated source +COPY --from=builder /target/Habbo.jar / + +# Save the script to wait for the database, among running the Arcturus Emulator +RUN echo "#!/bin/bash \n java -Dfile.encoding=UTF-8 -jar /Habbo.jar" > /entrypoint.sh +RUN chmod +x /entrypoint.sh + +# Run the Emulator with Java +ENTRYPOINT ["/entrypoint.sh"] diff --git a/README.md b/README.md index 364c2985..bff62d04 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,11 @@ TheGeneral's own words were "dont like it then dont use it". We did not like wha Arcturus Morningstar is released under the [GNU General Public License v3](https://www.gnu.org/licenses/gpl-3.0.txt). ## Versions ## -![image](https://img.shields.io/badge/VERSION-2.4.0-success.svg?style=for-the-badge&logo=appveyor) -![image](https://img.shields.io/badge/STATUS-STABLE-blue.svg?style=for-the-badge&logo=appveyor) +[![image](https://img.shields.io/badge/VERSION-3.0.0-success.svg?style=for-the-badge&logo=appveyor)](#) +[![image](https://img.shields.io/badge/STATUS-STABLE-blue.svg?style=for-the-badge&logo=appveyor)](#) +[![image](https://img.shields.io/discord/557240155040251905?style=for-the-badge&logo=discord&color=7289DA&label=DISCORD&logoColor=fff)](https://discord.gg/BzfFsTp) -Compiled Download: https://git.krews.org/morningstar/Arcturus-Community/releases +Compiled Download: https://git.krews.org/morningstar/Arcturus-Community/-/releases Client build: **PRODUCTION-201611291003-338511768** @@ -24,17 +25,36 @@ When making an bug report or a feature request use the template we provide so th ## Credits ## - TheGeneral -- Capheus (Decompilation.) -- Harmonic - Beny -- Claudio - Alejandro -- Harmony -- Quadral (Pathfinder) +- Capheus - Skeletor -- z -- ArpyAge +- Harmonic - Mike +- Remco +- zGrav +- Quadral +- Harmony +- Swirny +- ArpyAge +- Mikkel +- Rodolfo +- Rasmus +- Kitt Mustang +- Snaiker +- nttzx +- necmi +- Dome +- Jose Flores +- Cam +- Oliver +- Narzo +- Tenshie +- MartenM +- Ridge +- SenpaiDipper +- Snaiker +- Thijmen ## Discord ## diff --git a/pom.xml b/pom.xml index 35de71dc..419c9bea 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.eu.habbo Habbo - 2.4.0 + 3.0.0 UTF-8 diff --git a/sqlupdates/2_4_0 to 3_0_BETA_1.sql b/sqlupdates/2_4_0 to 3_0_BETA_1.sql new file mode 100644 index 00000000..70294fbb --- /dev/null +++ b/sqlupdates/2_4_0 to 3_0_BETA_1.sql @@ -0,0 +1,132 @@ +CREATE TABLE `users_subscriptions` ( + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `user_id` int(10) UNSIGNED NULL, + `subscription_type` varchar(255) NULL, + `timestamp_start` int(10) UNSIGNED NULL, + `duration` int(10) UNSIGNED NULL, + `active` tinyint(1) NULL DEFAULT 1, + PRIMARY KEY (`id`), + INDEX `user_id`(`user_id`), + INDEX `subscription_type`(`subscription_type`), + INDEX `timestamp_start`(`timestamp_start`), + INDEX `active`(`active`) +); + +CREATE TABLE `logs_shop_purchases` ( + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `timestamp` int(10) UNSIGNED NULL, + `user_id` int(10) UNSIGNED NULL, + `catalog_item_id` int(10) UNSIGNED NULL, + `item_ids` text DEFAULT NULL, + `catalog_name` varchar(255) NULL, + `cost_credits` int(10) NULL, + `cost_points` int(10) NULL, + `points_type` int(10) NULL, + `amount` int(10) NULL, + PRIMARY KEY (`id`), + INDEX `timestamp`(`timestamp`), + INDEX `user_id`(`user_id`) +); + +CREATE TABLE `logs_hc_payday` ( + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `timestamp` int(10) UNSIGNED NULL, + `user_id` int(10) UNSIGNED NULL, + `hc_streak` int(10) UNSIGNED NULL, + `total_coins_spent` int(10) UNSIGNED NULL, + `reward_coins_spent` int(10) UNSIGNED NULL, + `reward_streak` int(10) UNSIGNED NULL, + `total_payout` int(10) UNSIGNED NULL, + `currency` varchar(255) NULL, + `claimed` tinyint(1) DEFAULT 0 NULL, + PRIMARY KEY (`id`), + INDEX `timestamp`(`timestamp`), + INDEX `user_id`(`user_id`) +); + +ALTER TABLE `emulator_settings` MODIFY COLUMN `value` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL AFTER `key`; +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('subscriptions.hc.payday.enabled', '1'); +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('subscriptions.hc.payday.next_date', '2020-10-15 00:00:00'); +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('subscriptions.hc.payday.interval', '1 month'); +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('subscriptions.hc.payday.query', 'SELECT SUM(cost_credits) AS `amount_spent` FROM `logs_shop_purchases` WHERE `user_id` = @user_id AND `timestamp` > @timestamp_start AND `timestamp` <= @timestamp_end AND `catalog_name` NOT LIKE \'CF_%\' AND `catalog_name` NOT LIKE \'CFC_%\';'); +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('subscriptions.hc.payday.streak', '7=5;30=10;60=15;90=20;180=25;365=30'); +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_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'); + +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('hotel.users.clothingvalidation.onhcexpired', '0'); +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('hotel.users.clothingvalidation.onlogin', '0'); +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('hotel.users.clothingvalidation.onchangelooks', '0'); +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('hotel.users.clothingvalidation.onmimic', '0'); +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('hotel.users.clothingvalidation.onmannequin', '0'); +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('hotel.users.clothingvalidation.onfballgate', '0'); +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('gamedata.figuredata.url', 'https://habbo.com/gamedata/figuredata/0'); + +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('hotel.users.max.friends', '300'); +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('hotel.users.max.friends.hc', '1100'); +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'); + +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'); + +INSERT INTO `emulator_settings`(`key`, `value`) VALUES ('room.chat.mutearea.allow_whisper', '1'); + +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 `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 ('hotel.roomuser.idle.not_dancing.ignore.wired_idle', '0'); + +-- 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(); + +INSERT INTO `emulator_settings` (`key`, `value`) VALUES ('hotel.rooms.deco_hosting', '1'); + +INSERT INTO `emulator_settings` (`key`, `value`) VALUES ('easter_eggs.enabled', '1'); + +ALTER TABLE `bots` +ADD COLUMN `bubble_id` int(3) NULL DEFAULT 31 AFTER `effect`; + +-- Permissions to see tent chat +ALTER TABLE `permissions` ADD `acc_see_tentchat` ENUM('0', '1') NOT NULL DEFAULT '0' AFTER `acc_see_whispers`; +INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('hotel.room.tent.prefix', 'Tent'); + +-- Roombadge command +ALTER TABLE `permissions` ADD `cmd_roombadge` ENUM('0', '1') NOT NULL DEFAULT '0' AFTER `cmd_massbadge`; +INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('commands.error.cmd_roombadge.no_badge', 'No badge specified!'); +INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('commands.keys.cmd_roombadge', 'roombadge'); +INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('commands.description.cmd_roombadge', ':roombadge '); + +-- 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/2_4_0-RC-2 to 2_4_0-RC-3.sql b/sqlupdates/2_4_0-RC-2 to 2_4_0-RC-3.sql new file mode 100644 index 00000000..4e5a5206 --- /dev/null +++ b/sqlupdates/2_4_0-RC-2 to 2_4_0-RC-3.sql @@ -0,0 +1,2 @@ +-- Recycler value fix +INSERT INTO `emulator_settings` (`key`, `value`) VALUES ('recycler.value', '8'); diff --git a/sqlupdates/3_0_BETA_1 to 3_0_0.sql b/sqlupdates/3_0_BETA_1 to 3_0_0.sql new file mode 100644 index 00000000..31e6474c --- /dev/null +++ b/sqlupdates/3_0_BETA_1 to 3_0_0.sql @@ -0,0 +1,9 @@ +-- Wired variables for bots +INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('wired.variable.name', '%name%'); +INSERT INTO `emulator_texts` (`key`, `value`) VALUES ('wired.variable.roomname', '%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/Emulator.java b/src/main/java/com/eu/habbo/Emulator.java index 9954c318..33a46886 100644 --- a/src/main/java/com/eu/habbo/Emulator.java +++ b/src/main/java/com/eu/habbo/Emulator.java @@ -24,10 +24,10 @@ import java.io.*; import java.security.MessageDigest; import java.sql.Timestamp; import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.Random; +import java.util.*; import java.util.concurrent.ThreadLocalRandom; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public final class Emulator { @@ -35,13 +35,12 @@ public final class Emulator { private static final String OS_NAME = System.getProperty("os.name"); private static final String CLASS_PATH = System.getProperty("java.class.path"); - public final static int MAJOR = 2; - public final static int MINOR = 4; + public final static int MAJOR = 3; + public final static int MINOR = 0; public final static int BUILD = 0; - public final static String PREVIEW = ""; - public static final String version = "Arcturus Morningstar" + " " + MAJOR + "." + MINOR + "." + BUILD; + public static final String version = "Arcturus Morningstar" + " " + MAJOR + "." + MINOR + "." + BUILD + " " + PREVIEW; private static final String logo = "\n" + "███╗ ███╗ ██████╗ ██████╗ ███╗ ██╗██╗███╗ ██╗ ██████╗ ███████╗████████╗ █████╗ ██████╗ \n" + @@ -49,8 +48,8 @@ public final class Emulator { "██╔████╔██║██║ ██║██████╔╝██╔██╗ ██║██║██╔██╗ ██║██║ ███╗███████╗ ██║ ███████║██████╔╝\n" + "██║╚██╔╝██║██║ ██║██╔══██╗██║╚██╗██║██║██║╚██╗██║██║ ██║╚════██║ ██║ ██╔══██║██╔══██╗\n" + "██║ ╚═╝ ██║╚██████╔╝██║ ██║██║ ╚████║██║██║ ╚████║╚██████╔╝███████║ ██║ ██║ ██║██║ ██║\n" + - "╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝\n" + - " "; + "╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝\n" ; + public static String build = ""; public static boolean isReady = false; @@ -83,6 +82,13 @@ public final class Emulator { Runtime.getRuntime().addShutdownHook(hook); } + public static void promptEnterKey(){ + System.out.println("\n"); + System.out.println("Press \"ENTER\" if you agree to the terms stated above..."); + Scanner scanner = new Scanner(System.in); + scanner.nextLine(); + } + public static void main(String[] args) throws Exception { try { // Check if running on Windows and not in IntelliJ. @@ -104,6 +110,12 @@ public final class Emulator { System.out.println(logo); + // Checks if this is a BETA build before allowing them to continue. + if (PREVIEW.toLowerCase().contains("beta")) { + System.out.println("Warning, this is a beta build, this means that there may be unintended consequences so make sure you take regular backups while using this build. If you notice any issues you should make an issue on the Krews Git."); + promptEnterKey(); + } + LOGGER.info("This project is for educational purposes only. This Emulator is an open-source fork of Arcturus created by TheGeneral."); LOGGER.info("Version: {}", version); LOGGER.info("Build: {}", build); @@ -141,7 +153,7 @@ public final class Emulator { Emulator.rconServer.connect(); Emulator.badgeImager = new BadgeImager(); - LOGGER.info("Arcturus Morningstar has succesfully loaded."); + LOGGER.info("Arcturus Morningstar has successfully loaded."); LOGGER.info("System launched in: {}ms. Using {} threads!", (System.nanoTime() - startTime) / 1e6, Runtime.getRuntime().availableProcessors() * 2); LOGGER.info("Memory: {}/{}MB", (runtime.totalMemory() - runtime.freeMemory()) / (1024 * 1024), (runtime.freeMemory()) / (1024 * 1024)); @@ -368,6 +380,65 @@ public final class Emulator { System.exit(0); } + public static int timeStringToSeconds(String timeString) { + int totalSeconds = 0; + + Matcher m = Pattern.compile("(([0-9]*) (second|minute|hour|day|week|month|year))").matcher(timeString); + Map map = new HashMap() { + { + put("second", 1); + put("minute", 60); + put("hour", 3600); + put("day", 86400); + put("week", 604800); + put("month", 2628000); + put("year", 31536000); + } + }; + + while (m.find()) { + try { + int amount = Integer.parseInt(m.group(2)); + String what = m.group(3); + totalSeconds += amount * map.get(what); + } + catch (Exception ignored) { } + } + + return totalSeconds; + } + + public static Date modifyDate(Date date, String timeString) { + int totalSeconds = 0; + + Calendar c = Calendar.getInstance(); + c.setTime(date); + + Matcher m = Pattern.compile("(([0-9]*) (second|minute|hour|day|week|month|year))").matcher(timeString); + Map map = new HashMap() { + { + put("second", Calendar.SECOND); + put("minute", Calendar.MINUTE); + put("hour", Calendar.HOUR); + put("day", Calendar.DAY_OF_MONTH); + put("week", Calendar.WEEK_OF_MONTH); + put("month", Calendar.MONTH); + put("year", Calendar.YEAR); + } + }; + + while (m.find()) { + try { + int amount = Integer.parseInt(m.group(2)); + String what = m.group(3); + c.add(map.get(what), amount); + } + catch (Exception ignored) { } + } + + return c.getTime(); + } + private static String dateToUnixTimestamp(Date date) { String res = ""; Date aux = stringToDate("1970-01-01 00:00:00"); @@ -378,7 +449,7 @@ public final class Emulator { return res + seconds; } - private static Date stringToDate(String date) { + public static Date stringToDate(String date) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date res = null; try { diff --git a/src/main/java/com/eu/habbo/core/CleanerThread.java b/src/main/java/com/eu/habbo/core/CleanerThread.java index b9a721dc..10dcc784 100644 --- a/src/main/java/com/eu/habbo/core/CleanerThread.java +++ b/src/main/java/com/eu/habbo/core/CleanerThread.java @@ -144,8 +144,8 @@ public class CleanerThread implements Runnable { if (Emulator.isReady) { for (Habbo habbo : Emulator.getGameEnvironment().getHabboManager().getOnlineHabbos().values()) { - habbo.getHabboStats().petRespectPointsToGive = Emulator.getConfig().getInt("hotel.daily.respect"); - habbo.getHabboStats().respectPointsToGive = Emulator.getConfig().getInt("hotel.daily.respect.pets"); + habbo.getHabboStats().respectPointsToGive = Emulator.getConfig().getInt("hotel.daily.respect"); + habbo.getHabboStats().petRespectPointsToGive = Emulator.getConfig().getInt("hotel.daily.respect.pets"); } } } diff --git a/src/main/java/com/eu/habbo/core/ConfigurationManager.java b/src/main/java/com/eu/habbo/core/ConfigurationManager.java index 29e50f73..19b442fe 100644 --- a/src/main/java/com/eu/habbo/core/ConfigurationManager.java +++ b/src/main/java/com/eu/habbo/core/ConfigurationManager.java @@ -23,7 +23,7 @@ public class ConfigurationManager { public boolean loaded = false; public boolean isLoading = false; - public ConfigurationManager(String configurationPath) throws Exception { + public ConfigurationManager(String configurationPath) { this.properties = new Properties(); this.configurationPath = configurationPath; this.reload(); @@ -37,7 +37,12 @@ public class ConfigurationManager { String envDbHostname = System.getenv("DB_HOSTNAME"); - boolean useEnvVarsForDbConnection = envDbHostname != null && envDbHostname.length() > 1; + boolean useEnvVarsForDbConnection = false; + + if(envDbHostname != null) + { + useEnvVarsForDbConnection = envDbHostname.length() > 1; + } if (!useEnvVarsForDbConnection) { try { 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/Easter.java b/src/main/java/com/eu/habbo/core/Easter.java index ea643841..f358dbc8 100644 --- a/src/main/java/com/eu/habbo/core/Easter.java +++ b/src/main/java/com/eu/habbo/core/Easter.java @@ -1,5 +1,6 @@ package com.eu.habbo.core; +import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomChatMessage; import com.eu.habbo.habbohotel.rooms.RoomChatMessageBubbles; @@ -11,7 +12,7 @@ import com.eu.habbo.plugin.events.users.UserSavedMottoEvent; public class Easter { @EventHandler public static void onUserChangeMotto(UserSavedMottoEvent event) { - if (event.newMotto.equalsIgnoreCase("crickey!")) { + if (Emulator.getConfig().getBoolean("easter_eggs.enabled") && event.newMotto.equalsIgnoreCase("crickey!")) { event.habbo.getClient().sendResponse(new RoomUserWhisperComposer(new RoomChatMessage(event.newMotto, event.habbo, event.habbo, RoomChatMessageBubbles.ALERT))); Room room = event.habbo.getHabboInfo().getCurrentRoom(); 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/core/TextsManager.java b/src/main/java/com/eu/habbo/core/TextsManager.java index 90c6520a..4b0bf66e 100644 --- a/src/main/java/com/eu/habbo/core/TextsManager.java +++ b/src/main/java/com/eu/habbo/core/TextsManager.java @@ -72,7 +72,7 @@ public class TextsManager { public int getInt(String key, Integer defaultValue) { try { return Integer.parseInt(this.getValue(key, defaultValue.toString())); - } catch (Exception e) { + } catch (NumberFormatException e) { LOGGER.error("Caught exception", e); } return defaultValue; diff --git a/src/main/java/com/eu/habbo/database/Database.java b/src/main/java/com/eu/habbo/database/Database.java index c37a524a..00be0fee 100644 --- a/src/main/java/com/eu/habbo/database/Database.java +++ b/src/main/java/com/eu/habbo/database/Database.java @@ -3,9 +3,18 @@ package com.eu.habbo.database; import com.eu.habbo.Emulator; import com.eu.habbo.core.ConfigurationManager; import com.zaxxer.hikari.HikariDataSource; +import gnu.trove.map.hash.THashMap; +import gnu.trove.set.hash.THashSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class Database { private static final Logger LOGGER = LoggerFactory.getLogger(Database.class); @@ -53,4 +62,52 @@ public class Database { public DatabasePool getDatabasePool() { return this.databasePool; } + + public static PreparedStatement preparedStatementWithParams(Connection connection, String query, THashMap queryParams) throws SQLException { + THashMap params = new THashMap(); + THashSet quotedParams = new THashSet<>(); + + for(String key : queryParams.keySet()) { + quotedParams.add(Pattern.quote(key)); + } + + String regex = "(" + String.join("|", quotedParams) + ")"; + + Matcher m = Pattern.compile(regex).matcher(query); + + int i = 1; + + while (m.find()) { + try { + params.put(i, queryParams.get(m.group(1))); + i++; + } + catch (Exception ignored) { } + } + + PreparedStatement statement = connection.prepareStatement(query.replaceAll(regex, "?")); + + for(Map.Entry set : params.entrySet()) { + if(set.getValue().getClass() == String.class) { + statement.setString(set.getKey(), (String)set.getValue()); + } + else if(set.getValue().getClass() == Integer.class) { + statement.setInt(set.getKey(), (Integer)set.getValue()); + } + else if(set.getValue().getClass() == Double.class) { + statement.setDouble(set.getKey(), (Double)set.getValue()); + } + else if(set.getValue().getClass() == Float.class) { + statement.setFloat(set.getKey(), (Float)set.getValue()); + } + else if(set.getValue().getClass() == Long.class) { + statement.setLong(set.getKey(), (Long)set.getValue()); + } + else { + statement.setObject(set.getKey(), set.getValue()); + } + } + + return statement; + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/GameEnvironment.java b/src/main/java/com/eu/habbo/habbohotel/GameEnvironment.java index 63a956bb..a614cb05 100644 --- a/src/main/java/com/eu/habbo/habbohotel/GameEnvironment.java +++ b/src/main/java/com/eu/habbo/habbohotel/GameEnvironment.java @@ -20,6 +20,8 @@ import com.eu.habbo.habbohotel.pets.PetManager; import com.eu.habbo.habbohotel.polls.PollManager; import com.eu.habbo.habbohotel.rooms.RoomManager; import com.eu.habbo.habbohotel.users.HabboManager; +import com.eu.habbo.habbohotel.users.subscriptions.SubscriptionManager; +import com.eu.habbo.habbohotel.users.subscriptions.SubscriptionScheduler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,6 +33,8 @@ public class GameEnvironment { public PixelScheduler pixelScheduler; public PointsScheduler pointsScheduler; public GotwPointsScheduler gotwPointsScheduler; + public SubscriptionScheduler subscriptionScheduler; + private HabboManager habboManager; private NavigatorManager navigatorManager; private GuildManager guildManager; @@ -49,6 +53,7 @@ public class GameEnvironment { private WordFilter wordFilter; private CraftingManager craftingManager; private PollManager pollManager; + private SubscriptionManager subscriptionManager; public void load() throws Exception { LOGGER.info("GameEnvironment -> Loading..."); @@ -86,6 +91,11 @@ public class GameEnvironment { this.gotwPointsScheduler = new GotwPointsScheduler(); Emulator.getThreading().run(this.gotwPointsScheduler); + this.subscriptionManager = new SubscriptionManager(); + this.subscriptionManager.init(); + + this.subscriptionScheduler = new SubscriptionScheduler(); + Emulator.getThreading().run(this.subscriptionScheduler); LOGGER.info("GameEnvironment -> Loaded!"); } @@ -103,6 +113,7 @@ public class GameEnvironment { this.roomManager.dispose(); this.itemManager.dispose(); this.hotelViewManager.dispose(); + this.subscriptionManager.dispose(); LOGGER.info("GameEnvironment -> Disposed!"); } @@ -191,4 +202,8 @@ public class GameEnvironment { public GotwPointsScheduler getGotwPointsScheduler() { return this.gotwPointsScheduler; } + + public SubscriptionManager getSubscriptionManager() { + return this.subscriptionManager; + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/bots/Bot.java b/src/main/java/com/eu/habbo/habbohotel/bots/Bot.java index 8cedc5ff..b1149aa9 100644 --- a/src/main/java/com/eu/habbo/habbohotel/bots/Bot.java +++ b/src/main/java/com/eu/habbo/habbohotel/bots/Bot.java @@ -44,6 +44,7 @@ public class Bot implements Runnable { private int chatTimeOut; private int chatTimestamp; private short lastChatIndex; + private int bubble; private String type; @@ -73,6 +74,7 @@ public class Bot implements Runnable { this.chatLines = new ArrayList<>(); this.type = "generic_bot"; this.room = null; + this.bubble = RoomChatMessageBubbles.BOT_RENTABLE.getType(); } public Bot(ResultSet set) throws SQLException { @@ -94,6 +96,7 @@ public class Bot implements Runnable { this.roomUnit = null; this.chatTimeOut = Emulator.getIntUnixTimestamp() + this.chatDelay; this.needsUpdate = false; + this.bubble = set.getInt("bubble_id"); } public Bot(Bot bot) { @@ -110,6 +113,7 @@ public class Bot implements Runnable { this.chatLines = new ArrayList<>(Arrays.asList("Default Message :D")); this.type = bot.getType(); this.effect = bot.getEffect(); + this.bubble = bot.getBubbleId(); this.needsUpdate = false; } @@ -133,7 +137,7 @@ public class Bot implements Runnable { @Override public void run() { if (this.needsUpdate) { - try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("UPDATE bots SET name = ?, motto = ?, figure = ?, gender = ?, user_id = ?, room_id = ?, x = ?, y = ?, z = ?, rot = ?, dance = ?, freeroam = ?, chat_lines = ?, chat_auto = ?, chat_random = ?, chat_delay = ?, effect = ? WHERE id = ?")) { + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("UPDATE bots SET name = ?, motto = ?, figure = ?, gender = ?, user_id = ?, room_id = ?, x = ?, y = ?, z = ?, rot = ?, dance = ?, freeroam = ?, chat_lines = ?, chat_auto = ?, chat_random = ?, chat_delay = ?, effect = ?, bubble_id = ? WHERE id = ?")) { statement.setString(1, this.name); statement.setString(2, this.motto); statement.setString(3, this.figure); @@ -155,7 +159,8 @@ public class Bot implements Runnable { statement.setString(15, this.chatRandom ? "1" : "0"); statement.setInt(16, this.chatDelay); statement.setInt(17, this.effect); - statement.setInt(18, this.id); + statement.setInt(18, this.bubble); + statement.setInt(19, this.id); statement.execute(); this.needsUpdate = false; } catch (SQLException e) { @@ -173,11 +178,11 @@ public class Bot implements Runnable { int timeOut = Emulator.getRandom().nextInt(20) * 2; this.roomUnit.setWalkTimeOut((timeOut < 10 ? 5 : timeOut) + Emulator.getIntUnixTimestamp()); } - } else { + }/* else { for (RoomTile t : this.room.getLayout().getTilesAround(this.room.getLayout().getTile(this.getRoomUnit().getX(), this.getRoomUnit().getY()))) { WiredHandler.handle(WiredTriggerType.BOT_REACHED_STF, this.roomUnit, this.room, this.room.getItemsAt(t).toArray()); } - } + }*/ } if (!this.chatLines.isEmpty() && this.chatTimeOut <= Emulator.getIntUnixTimestamp() && this.chatAuto) { @@ -188,12 +193,16 @@ public class Bot implements Runnable { this.lastChatIndex = 0; } - this.talk(this.chatLines.get(this.lastChatIndex) - .replace("%owner%", this.room.getOwnerName()) - .replace("%item_count%", this.room.itemCount() + "") - .replace("%name%", this.name) - .replace("%roomname%", this.room.getName()) - .replace("%user_count%", this.room.getUserCount() + "")); + String message = this.chatLines.get(this.lastChatIndex) + .replace(Emulator.getTexts().getValue("wired.variable.owner", "%owner%"), this.room.getOwnerName()) + .replace(Emulator.getTexts().getValue("wired.variable.item_count", "%item_count%"), this.room.itemCount() + "") + .replace(Emulator.getTexts().getValue("wired.variable.name", "%name%"), this.name) + .replace(Emulator.getTexts().getValue("wired.variable.roomname", "%roomname%"), this.room.getName()) + .replace(Emulator.getTexts().getValue("wired.variable.user_count", "%user_count%"), this.room.getUserCount() + ""); + + if(!WiredHandler.handle(WiredTriggerType.SAY_SOMETHING, this.getRoomUnit(), room, new Object[]{ message })) { + this.talk(message); + } this.chatTimeOut = Emulator.getIntUnixTimestamp() + this.chatDelay; } @@ -208,7 +217,7 @@ public class Bot implements Runnable { return; this.chatTimestamp = Emulator.getIntUnixTimestamp(); - this.room.botChat(new RoomUserTalkComposer(new RoomChatMessage(event.message, this.roomUnit, RoomChatMessageBubbles.BOT_RENTABLE)).compose()); + this.room.botChat(new RoomUserTalkComposer(new RoomChatMessage(event.message, this.roomUnit, RoomChatMessageBubbles.getBubble(this.getBubbleId()))).compose()); if (message.equals("o/") || message.equals("_o/")) { this.room.sendComposer(new RoomUserActionComposer(this.roomUnit, RoomUserAction.WAVE).compose()); @@ -223,7 +232,7 @@ public class Bot implements Runnable { return; this.chatTimestamp = Emulator.getIntUnixTimestamp(); - this.room.botChat(new RoomUserShoutComposer(new RoomChatMessage(event.message, this.roomUnit, RoomChatMessageBubbles.BOT_RENTABLE)).compose()); + this.room.botChat(new RoomUserShoutComposer(new RoomChatMessage(event.message, this.roomUnit, RoomChatMessageBubbles.getBubble(this.getBubbleId()))).compose()); if (message.equals("o/") || message.equals("_o/")) { this.room.sendComposer(new RoomUserActionComposer(this.roomUnit, RoomUserAction.WAVE).compose()); @@ -238,7 +247,7 @@ public class Bot implements Runnable { return; this.chatTimestamp = Emulator.getIntUnixTimestamp(); - event.target.getClient().sendResponse(new RoomUserWhisperComposer(new RoomChatMessage(event.message, this.roomUnit, RoomChatMessageBubbles.BOT_RENTABLE))); + event.target.getClient().sendResponse(new RoomUserWhisperComposer(new RoomChatMessage(event.message, this.roomUnit, RoomChatMessageBubbles.getBubble(this.getBubbleId())))); } } @@ -247,7 +256,12 @@ public class Bot implements Runnable { room.giveEffect(this.roomUnit, this.effect, -1); } - this.talk(PLACEMENT_MESSAGES[Emulator.getRandom().nextInt(PLACEMENT_MESSAGES.length)]); + if(PLACEMENT_MESSAGES.length > 0) { + String message = PLACEMENT_MESSAGES[Emulator.getRandom().nextInt(PLACEMENT_MESSAGES.length)]; + if (!WiredHandler.handle(WiredTriggerType.SAY_SOMETHING, this.getRoomUnit(), room, new Object[]{message})) { + this.talk(message); + } + } } public void onPickUp(Habbo habbo, Room room) { @@ -270,6 +284,10 @@ public class Bot implements Runnable { return this.name; } + public int getBubbleId() { + return bubble; + } + public void setName(String name) { this.name = name; this.needsUpdate = true; diff --git a/src/main/java/com/eu/habbo/habbohotel/bots/BotManager.java b/src/main/java/com/eu/habbo/habbohotel/bots/BotManager.java index 1f93888c..9a8129ae 100644 --- a/src/main/java/com/eu/habbo/habbohotel/bots/BotManager.java +++ b/src/main/java/com/eu/habbo/habbohotel/bots/BotManager.java @@ -12,6 +12,7 @@ import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertComposer; import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertKeys; import com.eu.habbo.messages.outgoing.inventory.AddBotComposer; import com.eu.habbo.messages.outgoing.inventory.RemoveBotComposer; +import com.eu.habbo.messages.outgoing.rooms.users.RoomUserStatusComposer; import com.eu.habbo.messages.outgoing.rooms.users.RoomUsersComposer; import com.eu.habbo.plugin.events.bots.BotPickUpEvent; import com.eu.habbo.plugin.events.bots.BotPlacedEvent; @@ -48,13 +49,8 @@ public class BotManager { } public static void addBotDefinition(String type, Class botClazz) throws Exception { - if (botClazz.getDeclaredConstructor(ResultSet.class) == null) { - throw new Exception("Missing Bot(ResultSet) constructor!"); - } else { - botClazz.getDeclaredConstructor(ResultSet.class).setAccessible(true); - - botDefenitions.put(type, botClazz); - } + botClazz.getDeclaredConstructor(ResultSet.class).setAccessible(true); + botDefenitions.put(type, botClazz); } public boolean reload() { @@ -144,6 +140,7 @@ public class BotManager { room.addBot(bot); Emulator.getThreading().run(bot); room.sendComposer(new RoomUsersComposer(bot).compose()); + room.sendComposer(new RoomUserStatusComposer(bot.getRoomUnit()).compose()); habbo.getInventory().getBotsComponent().removeBot(bot); habbo.getClient().sendResponse(new RemoveBotComposer(bot)); bot.onPlace(habbo, room); diff --git a/src/main/java/com/eu/habbo/habbohotel/bots/ButlerBot.java b/src/main/java/com/eu/habbo/habbohotel/bots/ButlerBot.java index d776bee9..b5acb9f2 100644 --- a/src/main/java/com/eu/habbo/habbohotel/bots/ButlerBot.java +++ b/src/main/java/com/eu/habbo/habbohotel/bots/ButlerBot.java @@ -3,6 +3,8 @@ package com.eu.habbo.habbohotel.bots; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.rooms.RoomChatMessage; import com.eu.habbo.habbohotel.rooms.RoomUnitStatus; +import com.eu.habbo.habbohotel.wired.WiredHandler; +import com.eu.habbo.habbohotel.wired.WiredTriggerType; import com.eu.habbo.plugin.events.bots.BotServerItemEvent; import com.eu.habbo.threading.runnables.RoomUnitGiveHanditem; import com.eu.habbo.threading.runnables.RoomUnitWalkToRoomUnit; @@ -56,54 +58,86 @@ public class ButlerBot extends Bot { @Override public void onUserSay(final RoomChatMessage message) { - if (this.getRoomUnit().hasStatus(RoomUnitStatus.MOVE)) + if (this.getRoomUnit().hasStatus(RoomUnitStatus.MOVE) || this.getRoom() == null) { return; + } + + double distanceBetweenBotAndHabbo = this.getRoomUnit().getCurrentLocation().distance(message.getHabbo().getRoomUnit().getCurrentLocation()); + + if (distanceBetweenBotAndHabbo <= Emulator.getConfig().getInt("hotel.bot.butler.commanddistance")) { - if (this.getRoomUnit().getCurrentLocation().distance(message.getHabbo().getRoomUnit().getCurrentLocation()) <= Emulator.getConfig().getInt("hotel.bot.butler.commanddistance")) if (message.getUnfilteredMessage() != null) { for (Map.Entry, Integer> set : serveItems.entrySet()) { - for (String s : set.getKey()) { - if (message.getUnfilteredMessage().toLowerCase().contains(s)) { + for (String keyword : set.getKey()) { + + // Check if the string contains a certain keyword using a regex. + // If keyword = tea, teapot wouldn't trigger it. + if (message.getUnfilteredMessage().toLowerCase().matches("\\b" + keyword + "\\b")) { + + // Enable plugins to cancel this event BotServerItemEvent serveEvent = new BotServerItemEvent(this, message.getHabbo(), set.getValue()); if (Emulator.getPluginManager().fireEvent(serveEvent).isCancelled()) { return; } + // Start give handitem process if (this.getRoomUnit().canWalk()) { - final String key = s; - final Bot b = this; - b.lookAt(serveEvent.habbo); + final String key = keyword; + final Bot bot = this; - final List tasks = new ArrayList(); + // Step 1: Look at Habbo + bot.lookAt(serveEvent.habbo); + + // Step 2: Prepare tasks for when the Bot (carrying the handitem) reaches the Habbo + final List tasks = new ArrayList<>(); tasks.add(new RoomUnitGiveHanditem(serveEvent.habbo.getRoomUnit(), serveEvent.habbo.getHabboInfo().getCurrentRoom(), serveEvent.itemId)); tasks.add(new RoomUnitGiveHanditem(this.getRoomUnit(), serveEvent.habbo.getHabboInfo().getCurrentRoom(), 0)); - tasks.add(() -> b.talk(Emulator.getTexts().getValue("bots.butler.given").replace("%key%", key).replace("%username%", serveEvent.habbo.getHabboInfo().getUsername()))); + tasks.add(() -> { + if(this.getRoom() != null) { + String botMessage = Emulator.getTexts() + .getValue("bots.butler.given") + .replace("%key%", key) + .replace("%username%", serveEvent.habbo.getHabboInfo().getUsername()); - List failedReached = new ArrayList(); - failedReached.add(() -> { - if (b.getRoomUnit().getCurrentLocation().distance(serveEvent.habbo.getRoomUnit().getCurrentLocation()) <= Emulator.getConfig().getInt("hotel.bot.butler.servedistance", 8)) { - for (Runnable t : tasks) { - t.run(); + if (!WiredHandler.handle(WiredTriggerType.SAY_SOMETHING, this.getRoomUnit(), this.getRoom(), new Object[]{ botMessage })) { + bot.talk(botMessage); } } }); + List failedReached = new ArrayList<>(); + failedReached.add(() -> { + if (distanceBetweenBotAndHabbo <= Emulator.getConfig().getInt("hotel.bot.butler.servedistance", 8)) { + for (Runnable task : tasks) { + task.run(); + } + } + }); + + // Give bot the handitem that it's going to give the Habbo Emulator.getThreading().run(new RoomUnitGiveHanditem(this.getRoomUnit(), serveEvent.habbo.getHabboInfo().getCurrentRoom(), serveEvent.itemId)); - if (b.getRoomUnit().getCurrentLocation().distance(serveEvent.habbo.getRoomUnit().getCurrentLocation()) > Emulator.getConfig().getInt("hotel.bot.butler.reachdistance", 3)) { + if (distanceBetweenBotAndHabbo > Emulator.getConfig().getInt("hotel.bot.butler.reachdistance", 3)) { Emulator.getThreading().run(new RoomUnitWalkToRoomUnit(this.getRoomUnit(), serveEvent.habbo.getRoomUnit(), serveEvent.habbo.getHabboInfo().getCurrentRoom(), tasks, failedReached, Emulator.getConfig().getInt("hotel.bot.butler.reachdistance", 3))); } else { Emulator.getThreading().run(failedReached.get(0), 1000); } } else { - this.getRoom().giveHandItem(serveEvent.habbo, serveEvent.itemId); - this.talk(Emulator.getTexts().getValue("bots.butler.given").replace("%key%", s).replace("%username%", serveEvent.habbo.getHabboInfo().getUsername())); + if(this.getRoom() != null) { + this.getRoom().giveHandItem(serveEvent.habbo, serveEvent.itemId); + + String msg = Emulator.getTexts().getValue("bots.butler.given").replace("%key%", keyword).replace("%username%", serveEvent.habbo.getHabboInfo().getUsername()); + if (!WiredHandler.handle(WiredTriggerType.SAY_SOMETHING, this.getRoomUnit(), this.getRoom(), new Object[]{msg})) { + this.talk(msg); + } + } } return; } } } } + } } } 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 255031af..6e7908c2 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}; @@ -639,10 +649,19 @@ public class CatalogManager { this.catalogPages.get(parentId).childPages.forEachValue(new TObjectProcedure() { @Override public boolean execute(CatalogPage object) { - if (object.getRank() <= habbo.getHabboInfo().getRank().getId() && object.visible) { - pages.add(object); + + boolean isVisiblePage = object.visible; + boolean hasRightRank = object.getRank() <= habbo.getHabboInfo().getRank().getId(); + + boolean clubRightsOkay = true; + + if(object.isClubOnly() && !habbo.getHabboInfo().getHabboStats().hasActiveClub()) { + clubRightsOkay = false; } + if (isVisiblePage && hasRightRank && clubRightsOkay) { + pages.add(object); + } return true; } }); @@ -1060,9 +1079,6 @@ public class CatalogManager { } } - UserCatalogItemPurchasedEvent purchasedEvent = new UserCatalogItemPurchasedEvent(habbo, item, itemsList, totalCredits, totalPoints, badges); - Emulator.getPluginManager().fireEvent(purchasedEvent); - if (badgeFound) { habbo.getClient().sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.ALREADY_HAVE_BADGE)); @@ -1071,6 +1087,9 @@ public class CatalogManager { } } + UserCatalogItemPurchasedEvent purchasedEvent = new UserCatalogItemPurchasedEvent(habbo, item, itemsList, totalCredits, totalPoints, badges); + Emulator.getPluginManager().fireEvent(purchasedEvent); + if (!free && !habbo.getClient().getHabbo().hasPermission(Permission.ACC_INFINITE_CREDITS)) { if (purchasedEvent.totalCredits > 0) { habbo.getClient().getHabbo().getHabboInfo().addCredits(-purchasedEvent.totalCredits); @@ -1121,6 +1140,26 @@ public class CatalogManager { habbo.getClient().sendResponse(new PurchaseOKComposer(purchasedEvent.catalogItem)); habbo.getClient().sendResponse(new InventoryRefreshComposer()); + THashSet itemIds = new THashSet<>(); + + for(HabboItem ix : purchasedEvent.itemsList) { + itemIds.add(ix.getId() + ""); + } + + if(!free) { + Emulator.getThreading().run(new CatalogPurchaseLogEntry( + Emulator.getIntUnixTimestamp(), + purchasedEvent.habbo.getHabboInfo().getId(), + purchasedEvent.catalogItem != null ? purchasedEvent.catalogItem.getId() : 0, + String.join(";", itemIds), + purchasedEvent.catalogItem != null ? purchasedEvent.catalogItem.getName() : "", + purchasedEvent.totalCredits, + purchasedEvent.totalPoints, + item != null ? item.getPointsType() : 0, + amount + )); + } + } catch (Exception e) { LOGGER.error("Exception caught", e); habbo.getClient().sendResponse(new AlertPurchaseFailedComposer(AlertPurchaseFailedComposer.SERVER_ERROR)); diff --git a/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogPurchaseLogEntry.java b/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogPurchaseLogEntry.java new file mode 100644 index 00000000..5f6febd7 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogPurchaseLogEntry.java @@ -0,0 +1,61 @@ +package com.eu.habbo.habbohotel.catalog; + +import com.eu.habbo.Emulator; +import com.eu.habbo.core.DatabaseLoggable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +public class CatalogPurchaseLogEntry implements Runnable, DatabaseLoggable { + + private static final Logger LOGGER = LoggerFactory.getLogger(CatalogPurchaseLogEntry.class); + private static final String QUERY = "INSERT INTO `logs_shop_purchases` (timestamp, user_id, catalog_item_id, item_ids, catalog_name, cost_credits, cost_points, points_type, amount) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + private final int timestamp; + private final int userId; + private final int catalogItemId; + private final String itemIds; + private final String catalogName; + private final int costCredits; + private final int costPoints; + private final int pointsType; + private final int amount; + + public CatalogPurchaseLogEntry(int timestamp, int userId, int catalogItemId, String itemIds, String catalogName, int costCredits, int costPoints, int pointsType, int amount) { + this.timestamp = timestamp; + this.userId = userId; + this.catalogItemId = catalogItemId; + this.itemIds = itemIds; + this.catalogName = catalogName; + this.costCredits = costCredits; + this.costPoints = costPoints; + this.pointsType = pointsType; + this.amount = amount; + } + + @Override + public String getQuery() { + return QUERY; + } + + @Override + public void log(PreparedStatement statement) throws SQLException { + statement.setInt(1, this.timestamp); + statement.setInt(2, this.userId); + statement.setInt(3, this.catalogItemId); + statement.setString(4, this.itemIds); + statement.setString(5, this.catalogName); + statement.setInt(6, this.costCredits); + statement.setInt(7, this.costPoints); + statement.setInt(8, this.pointsType); + statement.setInt(9, this.amount); + statement.addBatch(); + } + + @Override + public void run() { + Emulator.getDatabaseLogger().store(this); + } +} 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..3be967be 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,15 @@ 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; +import java.util.TimeZone; -public class ClubOffer { +public class ClubOffer implements ISerialize { private final int id; @@ -70,4 +76,47 @@ 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.max(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 * 86400; + + long secondsTotal = seconds; + + int totalYears = (int) Math.floor((int) seconds / (86400.0 * 31 * 12)); + seconds -= totalYears * (86400 * 31 * 12); + + int totalMonths = (int) Math.floor((int) seconds / (86400.0 * 31)); + seconds -= totalMonths * (86400 * 31); + + int totalDays = (int) Math.floor((int) seconds / 86400.0); + 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.setTimeZone(TimeZone.getTimeZone("UTC")); + cal.setTimeInMillis(hcExpireTimestamp * 1000L); + message.appendInt(cal.get(Calendar.YEAR)); + message.appendInt(cal.get(Calendar.MONTH) + 1); + message.appendInt(cal.get(Calendar.DAY_OF_MONTH)); + } } \ No newline at end of file diff --git a/src/main/java/com/eu/habbo/habbohotel/catalog/layouts/RoomBundleLayout.java b/src/main/java/com/eu/habbo/habbohotel/catalog/layouts/RoomBundleLayout.java index 680d3e9b..d283ada6 100644 --- a/src/main/java/com/eu/habbo/habbohotel/catalog/layouts/RoomBundleLayout.java +++ b/src/main/java/com/eu/habbo/habbohotel/catalog/layouts/RoomBundleLayout.java @@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.bots.Bot; import com.eu.habbo.habbohotel.catalog.CatalogItem; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.rooms.RoomManager; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertComposer; @@ -133,7 +134,7 @@ public class RoomBundleLayout extends SingleBundle { if (habbo != null) { int count = Emulator.getGameEnvironment().getRoomManager().getRoomsForHabbo(habbo).size(); - int max = habbo.getHabboStats().hasActiveClub() ? Emulator.getConfig().getInt("hotel.max.rooms.vip") : Emulator.getConfig().getInt("hotel.max.rooms.user"); + int max = habbo.getHabboStats().hasActiveClub() ? RoomManager.MAXIMUM_ROOMS_HC : RoomManager.MAXIMUM_ROOMS_USER; if (count >= max) { habbo.getClient().sendResponse(new CanCreateRoomComposer(count, max)); diff --git a/src/main/java/com/eu/habbo/habbohotel/commands/AboutCommand.java b/src/main/java/com/eu/habbo/habbohotel/commands/AboutCommand.java index ab4ece28..b3a111a9 100644 --- a/src/main/java/com/eu/habbo/habbohotel/commands/AboutCommand.java +++ b/src/main/java/com/eu/habbo/habbohotel/commands/AboutCommand.java @@ -3,7 +3,10 @@ package com.eu.habbo.habbohotel.commands; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.catalog.CatalogManager; import com.eu.habbo.habbohotel.gameclients.GameClient; +import com.eu.habbo.habbohotel.users.HabboManager; +import com.eu.habbo.messages.outgoing.generic.alerts.MessagesForYouComposer; +import java.util.Collections; import java.util.concurrent.TimeUnit; @@ -11,9 +14,12 @@ public class AboutCommand extends Command { public AboutCommand() { super(null, new String[]{"about", "info", "online", "server"}); } - + public static String credits = "Arcturus Morningstar is an opensource project based on Arcturus By TheGeneral \n" + + "The Following people have all contributed to this emulator:\n" + + " TheGeneral\n Beny\n Alejandro\n Capheus\n Skeletor\n Harmonic\n Mike\n Remco\n zGrav \n Quadral \n Harmony\n Swirny\n ArpyAge\n Mikkel\n Rodolfo\n Rasmus\n Kitt Mustang\n Snaiker\n nttzx\n necmi\n Dome\n Jose Flores\n Cam\n Oliver\n Narzo\n Tenshie\n MartenM\n Ridge\n SenpaiDipper\n Snaiker\n Thijmen"; @Override public boolean handle(GameClient gameClient, String[] params) { + Emulator.getRuntime().gc(); int seconds = Emulator.getIntUnixTimestamp() - Emulator.getTimeStarted(); @@ -42,9 +48,8 @@ public class AboutCommand extends Command { "Thanks for using Arcturus. Report issues on the forums. http://arcturus.wf \r\r" + " - The General"; - gameClient.getHabbo().alert(message); - + gameClient.sendResponse(new MessagesForYouComposer(Collections.singletonList(credits))); return true; } } diff --git a/src/main/java/com/eu/habbo/habbohotel/commands/CommandHandler.java b/src/main/java/com/eu/habbo/habbohotel/commands/CommandHandler.java index 16d2c5c9..a37d9482 100644 --- a/src/main/java/com/eu/habbo/habbohotel/commands/CommandHandler.java +++ b/src/main/java/com/eu/habbo/habbohotel/commands/CommandHandler.java @@ -10,6 +10,7 @@ import com.eu.habbo.habbohotel.pets.PetCommand; import com.eu.habbo.habbohotel.pets.PetVocalsType; import com.eu.habbo.habbohotel.pets.RideablePet; import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.rooms.RoomRightLevels; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserTypingComposer; import com.eu.habbo.plugin.events.users.UserCommandEvent; import com.eu.habbo.plugin.events.users.UserExecuteCommandEvent; @@ -72,9 +73,14 @@ public class CommandHandler { for (String s : command.keys) { if (s.toLowerCase().equals(parts[0].toLowerCase())) { boolean succes = false; - if (command.permission == null || gameClient.getHabbo().hasPermission(command.permission, gameClient.getHabbo().getHabboInfo().getCurrentRoom() != null && (gameClient.getHabbo().getHabboInfo().getCurrentRoom().hasRights(gameClient.getHabbo())) || gameClient.getHabbo().hasPermission(Permission.ACC_PLACEFURNI) || (gameClient.getHabbo().getHabboInfo().getCurrentRoom() != null && gameClient.getHabbo().getHabboInfo().getCurrentRoom().getGuildId() > 0 && gameClient.getHabbo().getHabboInfo().getCurrentRoom().guildRightLevel(gameClient.getHabbo()) >= 2))) { + if (command.permission == null || gameClient.getHabbo().hasPermission(command.permission, gameClient.getHabbo().getHabboInfo().getCurrentRoom() != null && (gameClient.getHabbo().getHabboInfo().getCurrentRoom().hasRights(gameClient.getHabbo())) || gameClient.getHabbo().hasPermission(Permission.ACC_PLACEFURNI) || (gameClient.getHabbo().getHabboInfo().getCurrentRoom() != null && gameClient.getHabbo().getHabboInfo().getCurrentRoom().getGuildId() > 0 && gameClient.getHabbo().getHabboInfo().getCurrentRoom().getGuildRightLevel(gameClient.getHabbo()).isEqualOrGreaterThan(RoomRightLevels.GUILD_RIGHTS)))) { try { - Emulator.getPluginManager().fireEvent(new UserExecuteCommandEvent(gameClient.getHabbo(), command, parts)); + UserExecuteCommandEvent userExecuteCommandEvent = new UserExecuteCommandEvent(gameClient.getHabbo(), command, parts); + Emulator.getPluginManager().fireEvent(userExecuteCommandEvent); + + if(userExecuteCommandEvent.isCancelled()) { + return userExecuteCommandEvent.isSuccess(); + } if (gameClient.getHabbo().getHabboInfo().getCurrentRoom() != null) gameClient.getHabbo().getHabboInfo().getCurrentRoom().sendComposer(new RoomUserTypingComposer(gameClient.getHabbo().getRoomUnit(), false).compose()); @@ -211,6 +217,7 @@ public class CommandHandler { addCommand(new LayCommand()); addCommand(new MachineBanCommand()); addCommand(new MassBadgeCommand()); + addCommand(new RoomBadgeCommand()); addCommand(new MassCreditsCommand()); addCommand(new MassGiftCommand()); addCommand(new MassPixelsCommand()); @@ -285,6 +292,7 @@ public class CommandHandler { addCommand(new UpdateYoutubePlaylistsCommand()); addCommand(new AddYoutubePlaylistCommand()); addCommand(new SoftKickCommand()); + addCommand(new SubscriptionCommand()); addCommand(new TestCommand()); } @@ -313,4 +321,4 @@ public class CommandHandler { commands.clear(); LOGGER.info("Command Handler -> Disposed!"); } -} \ No newline at end of file +} diff --git a/src/main/java/com/eu/habbo/habbohotel/commands/EjectAllCommand.java b/src/main/java/com/eu/habbo/habbohotel/commands/EjectAllCommand.java index 8e5ab590..51fa9589 100644 --- a/src/main/java/com/eu/habbo/habbohotel/commands/EjectAllCommand.java +++ b/src/main/java/com/eu/habbo/habbohotel/commands/EjectAllCommand.java @@ -3,6 +3,7 @@ package com.eu.habbo.habbohotel.commands; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.rooms.RoomRightLevels; public class EjectAllCommand extends Command { public EjectAllCommand() { @@ -14,7 +15,7 @@ public class EjectAllCommand extends Command { Room room = gameClient.getHabbo().getHabboInfo().getCurrentRoom(); if (room != null) { - if (room.isOwner(gameClient.getHabbo()) || (room.hasGuild() && room.guildRightLevel(gameClient.getHabbo()) == 3)) { + if (room.isOwner(gameClient.getHabbo()) || (room.hasGuild() && room.getGuildRightLevel(gameClient.getHabbo()).equals(RoomRightLevels.GUILD_ADMIN))) { room.ejectAll(gameClient.getHabbo()); } } diff --git a/src/main/java/com/eu/habbo/habbohotel/commands/MimicCommand.java b/src/main/java/com/eu/habbo/habbohotel/commands/MimicCommand.java index 123f1db4..13d72c30 100644 --- a/src/main/java/com/eu/habbo/habbohotel/commands/MimicCommand.java +++ b/src/main/java/com/eu/habbo/habbohotel/commands/MimicCommand.java @@ -6,6 +6,7 @@ import com.eu.habbo.habbohotel.permissions.Permission; import com.eu.habbo.habbohotel.rooms.RoomChatMessageBubbles; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboGender; +import com.eu.habbo.habbohotel.users.clothingvalidation.ClothingValidationManager; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDataComposer; import com.eu.habbo.messages.outgoing.users.UserDataComposer; import com.eu.habbo.util.figure.FigureUtil; @@ -35,7 +36,7 @@ public class MimicCommand extends Command { gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_mimic.forbidden_clothing"), RoomChatMessageBubbles.ALERT); return true; } else { - gameClient.getHabbo().getHabboInfo().setLook(habbo.getHabboInfo().getLook()); + gameClient.getHabbo().getHabboInfo().setLook(ClothingValidationManager.VALIDATE_ON_MIMIC ? ClothingValidationManager.validateLook(gameClient.getHabbo(), habbo.getHabboInfo().getLook(), habbo.getHabboInfo().getGender().name()) : habbo.getHabboInfo().getLook()); gameClient.getHabbo().getHabboInfo().setGender(habbo.getHabboInfo().getGender()); gameClient.sendResponse(new UserDataComposer(gameClient.getHabbo())); gameClient.getHabbo().getHabboInfo().getCurrentRoom().sendComposer(new RoomUserDataComposer(gameClient.getHabbo()).compose()); diff --git a/src/main/java/com/eu/habbo/habbohotel/commands/RoomBadgeCommand.java b/src/main/java/com/eu/habbo/habbohotel/commands/RoomBadgeCommand.java new file mode 100644 index 00000000..a2693217 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/commands/RoomBadgeCommand.java @@ -0,0 +1,54 @@ +package com.eu.habbo.habbohotel.commands; + +import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.gameclients.GameClient; +import com.eu.habbo.habbohotel.rooms.RoomChatMessageBubbles; +import com.eu.habbo.habbohotel.users.Habbo; +import com.eu.habbo.habbohotel.users.HabboBadge; +import com.eu.habbo.habbohotel.users.inventory.BadgesComponent; +import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertComposer; +import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertKeys; +import com.eu.habbo.messages.outgoing.users.AddUserBadgeComposer; +import gnu.trove.map.hash.THashMap; + +public class RoomBadgeCommand extends Command { + public RoomBadgeCommand() { + super("cmd_roombadge", Emulator.getTexts().getValue("commands.keys.cmd_roombadge").split(";")); + } + + @Override + public boolean handle(GameClient gameClient, String[] params) throws Exception { + if (gameClient == null) + return true; + + if (params.length == 2) { + String badge; + + badge = params[1]; + + if (!badge.isEmpty()) { + THashMap keys = new THashMap<>(); + keys.put("display", "BUBBLE"); + keys.put("image", "${image.library.url}album1584/" + badge + ".gif"); + keys.put("message", Emulator.getTexts().getValue("commands.generic.cmd_badge.received")); + ServerMessage message = new BubbleAlertComposer(BubbleAlertKeys.RECEIVED_BADGE.key, keys).compose(); + + for (Habbo habbo : gameClient.getHabbo().getRoomUnit().getRoom().getHabbos()) { + if (habbo.isOnline()) { + if (habbo.getInventory() != null && habbo.getInventory().getBadgesComponent() != null && !habbo.getInventory().getBadgesComponent().hasBadge(badge)) { + HabboBadge b = BadgesComponent.createBadge(badge, habbo); + + habbo.getClient().sendResponse(new AddUserBadgeComposer(b)); + habbo.getClient().sendResponse(message); + } + } + } + } + return true; + } + + gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_roombadge.no_badge"), RoomChatMessageBubbles.ALERT); + return true; + } +} diff --git a/src/main/java/com/eu/habbo/habbohotel/commands/SubscriptionCommand.java b/src/main/java/com/eu/habbo/habbohotel/commands/SubscriptionCommand.java new file mode 100644 index 00000000..25f8b758 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/commands/SubscriptionCommand.java @@ -0,0 +1,109 @@ +package com.eu.habbo.habbohotel.commands; + +import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.gameclients.GameClient; +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.HabboManager; +import com.eu.habbo.habbohotel.users.subscriptions.Subscription; + +/** + * @author Beny + */ +public class SubscriptionCommand extends Command { + public SubscriptionCommand() { + super("cmd_subscription", Emulator.getTexts().getValue("commands.keys.cmd_subscription").split(";")); + } + + /** + * Allows you to give/extend/remove subscription on a given user. + * + * Parameters: + * [username] = Username of user to execute command on + * [type] = Subscription type (e.g. HABBO_CLUB) + * [add|remove] = Use add or remove to increase/decrease sub duration + * [time] = Time string e.g. "1 week", "18 days", "4 minutes". Can be complex e.g. "1 month 5 days 2 minutes" + * + * Examples: + * :sub Beny habbo_club add 1 month - adds 1 month of HABBO_CLUB subscription duration on the user Beny + * :sub Beny builders_club add 1 month - adds 1 month of BUILDERS_CLUB subscription duration on the user Beny + * :sub Beny habbo_club remove 3 days - removes 3 days of HABBO_CLUB subscription duration on the user Beny + * :sub Beny habbo_club remove - removes all remaining time from the HABBO_CLUB subscription (expires it) on the user Beny + * + * @param gameClient Client that executed the command + * @param params Command parameters + * @return Boolean indicating success + * @throws Exception Exception + */ + @Override + public boolean handle(GameClient gameClient, String[] params) throws Exception { + if (params.length >= 4) { + HabboInfo info = HabboManager.getOfflineHabboInfo(params[1]); + + if (info != null) { + Habbo habbo = Emulator.getGameServer().getGameClientManager().getHabbo(params[1]); + + String subscription = params[2].toUpperCase(); + String action = params[3]; + + StringBuilder message = new StringBuilder(); + if (params.length > 4) { + for (int i = 4; i < params.length; i++) { + message.append(params[i]).append(" "); + } + } + + if(!Emulator.getGameEnvironment().getSubscriptionManager().types.containsKey(subscription)) { + gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_subscription.type_not_found", "%subscription% is not a valid subscription type").replace("%subscription%", subscription), RoomChatMessageBubbles.ALERT); + return true; + } + + if(action.equalsIgnoreCase("add") || action.equalsIgnoreCase("+") || action.equalsIgnoreCase("a")) { + int timeToAdd = Emulator.timeStringToSeconds(message.toString()); + + if(timeToAdd < 1) { + 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); + + if (s == null) { + gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_subscription.user_not_have", "%user% does not have the %subscription% subscription").replace("%user%", params[1]).replace("%subscription%", subscription), RoomChatMessageBubbles.ALERT); + return true; + } + + if(message.length() != 0) { + int timeToRemove = Emulator.timeStringToSeconds(message.toString()); + + if (timeToRemove < 1) { + 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); + 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 { + s.addDuration(-s.getRemaining()); + 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); + } + } else { + gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_subscription.invalid_params", "Invalid command format"), RoomChatMessageBubbles.ALERT); + } + 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/commands/UserInfoCommand.java b/src/main/java/com/eu/habbo/habbohotel/commands/UserInfoCommand.java index fdd621c8..b4a3ca78 100644 --- a/src/main/java/com/eu/habbo/habbohotel/commands/UserInfoCommand.java +++ b/src/main/java/com/eu/habbo/habbohotel/commands/UserInfoCommand.java @@ -45,7 +45,7 @@ public class UserInfoCommand extends Command { Emulator.getTexts().getValue("command.cmd_userinfo.online") + ": " + (onlineHabbo == null ? Emulator.getTexts().getValue("generic.no") : Emulator.getTexts().getValue("generic.yes")) + "\r" + ((habbo.getRank().hasPermission(Permission.ACC_HIDE_MAIL, true)) ? "" : Emulator.getTexts().getValue("command.cmd_userinfo.email") + ": " + habbo.getMail() + "\r") + ((habbo.getRank().hasPermission(Permission.ACC_HIDE_IP, true)) ? "" : Emulator.getTexts().getValue("command.cmd_userinfo.ip_register") + ": " + habbo.getIpRegister() + "\r") + - ((habbo.getRank().hasPermission(Permission.ACC_HIDE_IP, true)) || onlineHabbo == null ? "" : Emulator.getTexts().getValue("command.cmd_userinfo.ip_current") + ": " + onlineHabbo.getClient().getChannel().remoteAddress().toString() + "\r") + + ((habbo.getRank().hasPermission(Permission.ACC_HIDE_IP, true)) || onlineHabbo == null ? "" : Emulator.getTexts().getValue("command.cmd_userinfo.ip_current") + ": " + onlineHabbo.getHabboInfo().getIpLogin() + "\r") + (onlineHabbo != null ? Emulator.getTexts().getValue("command.cmd_userinfo.achievement_score") + ": " + onlineHabbo.getHabboStats().achievementScore + "\r" : "")); ModToolBan ban = Emulator.getGameEnvironment().getModToolManager().checkForBan(habbo.getId()); diff --git a/src/main/java/com/eu/habbo/habbohotel/commands/WordQuizCommand.java b/src/main/java/com/eu/habbo/habbohotel/commands/WordQuizCommand.java index 09a6c4dc..ba74d5d2 100644 --- a/src/main/java/com/eu/habbo/habbohotel/commands/WordQuizCommand.java +++ b/src/main/java/com/eu/habbo/habbohotel/commands/WordQuizCommand.java @@ -2,6 +2,9 @@ package com.eu.habbo.habbohotel.commands; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.gameclients.GameClient; +import com.eu.habbo.habbohotel.rooms.RoomChatMessageBubbles; + +import java.util.Arrays; public class WordQuizCommand extends Command { public WordQuizCommand() { @@ -11,21 +14,21 @@ public class WordQuizCommand extends Command { @Override public boolean handle(GameClient gameClient, String[] params) throws Exception { if (!gameClient.getHabbo().getHabboInfo().getCurrentRoom().hasActiveWordQuiz()) { + if(params.length == 1) { + gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.description.cmd_word_quiz"), RoomChatMessageBubbles.ALERT); + return true; + } StringBuilder question = new StringBuilder(); int duration = 60; - if (params.length > 2) { - for (int i = 1; i < params.length - 1; i++) { - question.append(" ").append(params[i]); - } + try { + duration = Integer.parseInt(params[params.length-1]); + params = Arrays.copyOf(params, params.length-1); + } + catch (Exception e) {} - try { - duration = Integer.valueOf(params[params.length - 1]); - } catch (Exception e) { - question.append(" ").append(params[params.length - 1]); - } - } else { - question = new StringBuilder(params[1]); + for (int i = 1; i < params.length; i++) { + question.append(" ").append(params[i]); } gameClient.getHabbo().getHabboInfo().getCurrentRoom().startWordQuiz(question.toString(), duration * 1000); diff --git a/src/main/java/com/eu/habbo/habbohotel/games/Game.java b/src/main/java/com/eu/habbo/habbohotel/games/Game.java index 16783eb7..24a8051d 100644 --- a/src/main/java/com/eu/habbo/habbohotel/games/Game.java +++ b/src/main/java/com/eu/habbo/habbohotel/games/Game.java @@ -95,7 +95,9 @@ public abstract class Game implements Runnable { if (team != null && team.isMember(habbo)) { if (habbo.getHabboInfo().getGamePlayer() != null) { team.removeMember(habbo.getHabboInfo().getGamePlayer()); - habbo.getHabboInfo().getGamePlayer().reset(); + if (habbo.getHabboInfo().getGamePlayer() != null) { + habbo.getHabboInfo().getGamePlayer().reset(); + } } habbo.getHabboInfo().setCurrentGame(null); @@ -238,7 +240,10 @@ public abstract class Game implements Runnable { if (this.room == null) return; - for (Map.Entry teamEntry : this.teams.entrySet()) { + THashMap teamsCopy = new THashMap<>(); + teamsCopy.putAll(this.teams); + + for (Map.Entry teamEntry : teamsCopy.entrySet()) { Emulator.getThreading().run(new SaveScoreForTeam(teamEntry.getValue(), this)); } } diff --git a/src/main/java/com/eu/habbo/habbohotel/games/GamePlayer.java b/src/main/java/com/eu/habbo/habbohotel/games/GamePlayer.java index 1950c917..bfd82a59 100644 --- a/src/main/java/com/eu/habbo/habbohotel/games/GamePlayer.java +++ b/src/main/java/com/eu/habbo/habbohotel/games/GamePlayer.java @@ -13,6 +13,7 @@ public class GamePlayer { private int score; + private int wiredScore; public GamePlayer(Habbo habbo, GameTeamColors teamColor) { @@ -23,15 +24,23 @@ public class GamePlayer { public void reset() { this.score = 0; + this.wiredScore = 0; } - public synchronized void addScore(int amount) { + addScore(amount, false); + } + + public synchronized void addScore(int amount, boolean isWired) { if (habbo.getHabboInfo().getGamePlayer() != null && this.habbo.getHabboInfo().getCurrentGame() != null && this.habbo.getHabboInfo().getCurrentRoom().getGame(this.habbo.getHabboInfo().getCurrentGame()).getTeamForHabbo(this.habbo) != null) { this.score += amount; if (this.score < 0) this.score = 0; + if(isWired && this.score > 0) { + this.wiredScore += amount; + } + WiredHandler.handle(WiredTriggerType.SCORE_ACHIEVED, this.habbo.getRoomUnit(), this.habbo.getHabboInfo().getCurrentRoom(), new Object[]{this.habbo.getHabboInfo().getCurrentRoom().getGame(this.habbo.getHabboInfo().getCurrentGame()).getTeamForHabbo(this.habbo).getTotalScore(), amount}); } } @@ -49,4 +58,8 @@ public class GamePlayer { public int getScore() { return this.score; } + + public int getScoreAchievementValue() { + return this.score - this.wiredScore; + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/games/battlebanzai/BattleBanzaiGame.java b/src/main/java/com/eu/habbo/habbohotel/games/battlebanzai/BattleBanzaiGame.java index 31a561b5..b2ee6dcf 100644 --- a/src/main/java/com/eu/habbo/habbohotel/games/battlebanzai/BattleBanzaiGame.java +++ b/src/main/java/com/eu/habbo/habbohotel/games/battlebanzai/BattleBanzaiGame.java @@ -44,6 +44,7 @@ public class BattleBanzaiGame extends Game { private final THashMap gameTiles; private int tileCount; private int countDown; + private int countDown2; public BattleBanzaiGame(Room room) { super(BattleBanzaiGameTeam.class, BattleBanzaiGamePlayer.class, room, true); @@ -58,8 +59,12 @@ public class BattleBanzaiGame extends Game { public void initialise() { if (!this.state.equals(GameState.IDLE)) return; - + + /* The first countdown is activated for the first two seconds emitting only the blue light (second interaction), + the second, after another two seconds, completely activates the sphere (third interaction). + */ this.countDown = 3; + this.countDown2 = 2; this.resetMap(); @@ -105,8 +110,15 @@ public class BattleBanzaiGame extends Game { if (this.countDown == 0) { for (HabboItem item : this.room.getRoomSpecialTypes().getItemsOfType(InteractionBattleBanzaiSphere.class)) { - item.setExtradata("2"); + item.setExtradata("1"); this.room.updateItemState(item); + if(this.countDown2 > 0) { + this.countDown2--; + if(this.countDown2 == 0) { + item.setExtradata("2"); + this.room.updateItemState(item); + } + } } } @@ -166,7 +178,7 @@ public class BattleBanzaiGame extends Game { for (GameTeam team : this.teams.values()) { if (!singleTeamGame) { for (GamePlayer player : team.getMembers()) { - if (player.getScore() > 0) { + if (player.getScoreAchievementValue() > 0) { AchievementManager.progressAchievement(player.getHabbo(), Emulator.getGameEnvironment().getAchievementManager().getAchievement("BattleBallPlayer")); } } @@ -180,7 +192,7 @@ public class BattleBanzaiGame extends Game { if (winningTeam != null) { if (!singleTeamGame) { for (GamePlayer player : winningTeam.getMembers()) { - if (player.getScore() > 0) { + if (player.getScoreAchievementValue() > 0) { this.room.sendComposer(new RoomUserActionComposer(player.getHabbo().getRoomUnit(), RoomUserAction.WAVE).compose()); AchievementManager.progressAchievement(player.getHabbo(), Emulator.getGameEnvironment().getAchievementManager().getAchievement("BattleBallWinner")); } diff --git a/src/main/java/com/eu/habbo/habbohotel/games/freeze/FreezeGame.java b/src/main/java/com/eu/habbo/habbohotel/games/freeze/FreezeGame.java index eb625350..642564d1 100644 --- a/src/main/java/com/eu/habbo/habbohotel/games/freeze/FreezeGame.java +++ b/src/main/java/com/eu/habbo/habbohotel/games/freeze/FreezeGame.java @@ -287,9 +287,9 @@ public class FreezeGame extends Game { players.addAll(team.getMembers()); for (GamePlayer p : players) { - if (p.getScore() > 0) { + if (p.getScoreAchievementValue() > 0) { if (team.equals(winningTeam)) { - AchievementManager.progressAchievement(p.getHabbo(), Emulator.getGameEnvironment().getAchievementManager().getAchievement("FreezeWinner"), p.getScore()); + AchievementManager.progressAchievement(p.getHabbo(), Emulator.getGameEnvironment().getAchievementManager().getAchievement("FreezeWinner"), p.getScoreAchievementValue()); this.room.sendComposer(new RoomUserActionComposer(p.getHabbo().getRoomUnit(), RoomUserAction.WAVE).compose()); } 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..11d19294 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; @@ -36,6 +38,7 @@ public class Item { private String clothingOnWalk; private ItemInteraction interactionType; + private int rotations; public Item(ResultSet set) throws SQLException { this.load(set); @@ -117,6 +120,13 @@ public class Item { this.multiHeights = new double[0]; } } + + this.rotations = 4; + + try { + this.rotations = set.getInt("rotations"); + } + catch (SQLException ignored) { } } public int getId() { @@ -220,4 +230,34 @@ public class Item { } public String getClothingOnWalk() { return clothingOnWalk; } + + public int getRotations() { + return rotations; + } + + @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..f702d68c 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/ItemManager.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/ItemManager.java @@ -141,6 +141,7 @@ public class ItemManager { this.interactionsList.add(new ItemInteraction("puzzle_box", InteractionPuzzleBox.class)); this.interactionsList.add(new ItemInteraction("hopper", InteractionHopper.class)); this.interactionsList.add(new ItemInteraction("costume_hopper", InteractionCostumeHopper.class)); + this.interactionsList.add(new ItemInteraction("effect_gate", InteractionEffectGate.class)); this.interactionsList.add(new ItemInteraction("club_hopper", InteractionHabboClubHopper.class)); this.interactionsList.add(new ItemInteraction("club_gate", InteractionHabboClubGate.class)); this.interactionsList.add(new ItemInteraction("club_teleporttile", InteractionHabboClubTeleportTile.class)); @@ -685,13 +686,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 +706,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 +722,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/InteractionBackgroundToner.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionBackgroundToner.java index 813ce782..ab6bf36e 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionBackgroundToner.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionBackgroundToner.java @@ -52,7 +52,7 @@ public class InteractionBackgroundToner extends HabboItem { @Override public boolean isWalkable() { - return false; + return this.getBaseItem().allowWalk(); } @Override 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/items/interactions/InteractionCustomValues.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionCustomValues.java index d25a3cc8..9ef005bc 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionCustomValues.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionCustomValues.java @@ -1,5 +1,6 @@ package com.eu.habbo.habbohotel.items.interactions; +import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; @@ -78,4 +79,8 @@ public abstract class InteractionCustomValues extends HabboItem { super.serializeExtradata(serverMessage); } + + public void onCustomValuesSaved(Room room, GameClient client) { + + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionDefault.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionDefault.java index 1db3a1d2..4860d0ff 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionDefault.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionDefault.java @@ -48,15 +48,17 @@ public class InteractionDefault extends HabboItem { public void onMove(Room room, RoomTile oldLocation, RoomTile newLocation) { super.onMove(room, oldLocation, newLocation); - for (RoomUnit unit : room.getRoomUnits()) { - if (!oldLocation.unitIsOnFurniOnTile(unit, this.getBaseItem())) - continue; // If the unit was previously on the furni... - if (newLocation.unitIsOnFurniOnTile(unit, this.getBaseItem())) continue; // but is not anymore... + if(room.getItemsAt(oldLocation).stream().noneMatch(item -> item.getClass().isAssignableFrom(InteractionRoller.class))) { + for (RoomUnit unit : room.getRoomUnits()) { + if (!oldLocation.unitIsOnFurniOnTile(unit, this.getBaseItem())) + continue; // If the unit was previously on the furni... + if (newLocation.unitIsOnFurniOnTile(unit, this.getBaseItem())) continue; // but is not anymore... - try { - this.onWalkOff(unit, room, new Object[]{}); // the unit walked off! - } catch (Exception ignored) { + try { + this.onWalkOff(unit, room, new Object[]{oldLocation, newLocation}); // the unit walked off! + } catch (Exception ignored) { + } } } } @@ -137,14 +139,22 @@ public class InteractionDefault extends HabboItem { if (roomUnit != null) { if (this.getBaseItem().getEffectF() > 0 || this.getBaseItem().getEffectM() > 0) { + int nextEffectM = 0; + int nextEffectF = 0; + if (objects != null && objects.length == 2) { if (objects[0] instanceof RoomTile && objects[1] instanceof RoomTile) { - RoomTile goalTile = (RoomTile) objects[1]; - HabboItem topItem = room.getTopItemAt(goalTile.x, goalTile.y); + RoomTile goalTile = (RoomTile) objects[0]; + HabboItem topItem = room.getTopItemAt(goalTile.x, goalTile.y, (objects[0] != objects[1]) ? this : null); if (topItem != null && (topItem.getBaseItem().getEffectM() == this.getBaseItem().getEffectM() || topItem.getBaseItem().getEffectF() == this.getBaseItem().getEffectF())) { return; } + + if(topItem != null) { + nextEffectM = topItem.getBaseItem().getEffectM(); + nextEffectF = topItem.getBaseItem().getEffectF(); + } } } @@ -154,12 +164,12 @@ public class InteractionDefault extends HabboItem { if (habbo != null) { if (habbo.getHabboInfo().getGender().equals(HabboGender.M) && this.getBaseItem().getEffectM() > 0) { - room.giveEffect(habbo, 0, -1); + room.giveEffect(habbo, nextEffectM, -1); return; } if (habbo.getHabboInfo().getGender().equals(HabboGender.F) && this.getBaseItem().getEffectF() > 0) { - room.giveEffect(habbo, 0, -1); + room.giveEffect(habbo, nextEffectF, -1); } } } else if (roomUnit.getRoomUnitType().equals(RoomUnitType.BOT)) { @@ -167,12 +177,12 @@ public class InteractionDefault extends HabboItem { if (bot != null) { if (bot.getGender().equals(HabboGender.M) && this.getBaseItem().getEffectM() > 0) { - room.giveEffect(roomUnit, 0, -1); + room.giveEffect(roomUnit, nextEffectM, -1); return; } if (bot.getGender().equals(HabboGender.F) && this.getBaseItem().getEffectF() > 0) { - room.giveEffect(roomUnit, 0, -1); + room.giveEffect(roomUnit, nextEffectF, -1); } } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionEffectGate.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionEffectGate.java new file mode 100644 index 00000000..0e6ad5d7 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionEffectGate.java @@ -0,0 +1,85 @@ +package com.eu.habbo.habbohotel.items.interactions; + +import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.gameclients.GameClient; +import com.eu.habbo.habbohotel.items.Item; +import com.eu.habbo.habbohotel.items.interactions.interfaces.ConditionalGate; +import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.rooms.RoomUnit; +import com.eu.habbo.threading.runnables.CloseGate; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class InteractionEffectGate extends InteractionDefault implements ConditionalGate { + + // List of Habboween costumes according to http://www.habboxwiki.com/Costumes + private static final List defaultAllowedEnables = new ArrayList<>(Arrays.asList( + 114, // Strong Arms + 115, // Ringmaster Costume + 116, // Fly Head + 117, // Executioner Hood + 118, // Evil Clown Paint + 135 // Marionette + )); + + public InteractionEffectGate(ResultSet set, Item baseItem) throws SQLException { + super(set, baseItem); + this.setExtradata("0"); + } + + public InteractionEffectGate(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) { + super(id, userId, item, extradata, limitedStack, limitedSells); + this.setExtradata("0"); + } + + @Override + public boolean isWalkable() { + return true; + } + + @Override + public boolean canWalkOn(RoomUnit roomUnit, Room room, Object[] objects) { + if (roomUnit == null || room == null) + return false; + + String customparams = this.getBaseItem().getCustomParams().trim(); + + if (!customparams.isEmpty()) { + return Arrays.asList(customparams.split(";")) + .contains(Integer.valueOf(roomUnit.getEffectId()).toString()); + } + + return defaultAllowedEnables.contains(roomUnit.getEffectId()); + } + + @Override + public void onWalkOn(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { + super.onWalkOn(roomUnit, room, objects); + + if (this.canWalkOn(roomUnit, room, objects)) { + this.setExtradata("1"); + room.updateItemState(this); + } + } + + @Override + public void onClick(GameClient client, Room room, Object[] objects) throws Exception { + super.onClick(client, room, objects); + } + + @Override + public void onWalkOff(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { + super.onWalkOff(roomUnit, room, objects); + + Emulator.getThreading().run(new CloseGate(this, room), 1000); + } + + @Override + public void onRejected(RoomUnit roomUnit, Room room, Object[] objects) { + + } +} diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionEffectTile.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionEffectTile.java index cb8eb2ab..ac10dcc7 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionEffectTile.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionEffectTile.java @@ -1,5 +1,6 @@ package com.eu.habbo.habbohotel.items.interactions; +import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.bots.Bot; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.rooms.Room; @@ -7,6 +8,8 @@ import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.rooms.RoomUnitType; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboGender; +import com.eu.habbo.habbohotel.wired.WiredHandler; +import com.eu.habbo.habbohotel.wired.WiredTriggerType; import java.sql.ResultSet; import java.sql.SQLException; @@ -32,7 +35,11 @@ public class InteractionEffectTile extends InteractionPressurePlate { @Override public void onWalkOff(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - super.onWalkOff(roomUnit, room, objects); + Emulator.getThreading().run(() -> updateState(room), 100); + + if(objects != null && objects.length > 0) { + WiredHandler.handle(WiredTriggerType.WALKS_OFF_FURNI, roomUnit, room, new Object[]{this}); + } } @Override diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionFireworks.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionFireworks.java index 645c0d4e..b2255e2f 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionFireworks.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionFireworks.java @@ -5,14 +5,28 @@ import com.eu.habbo.habbohotel.achievements.AchievementManager; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.rooms.RoomLayout; +import com.eu.habbo.habbohotel.rooms.RoomTile; import com.eu.habbo.habbohotel.rooms.RoomUnit; -import com.eu.habbo.habbohotel.users.HabboItem; -import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.habbohotel.users.Habbo; +import com.eu.habbo.habbohotel.wired.WiredEffectType; +import com.eu.habbo.threading.runnables.RoomUnitWalkToLocation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +public class InteractionFireworks extends InteractionDefault { + + private static final Logger LOGGER = LoggerFactory.getLogger(InteractionFireworks.class); + + private static final String STATE_EMPTY = "0"; // Not used since the removal of pixels + private static final String STATE_CHARGED = "1"; + private static final String STATE_EXPLOSION = "2"; -public class InteractionFireworks extends HabboItem { public InteractionFireworks(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); } @@ -26,35 +40,103 @@ public class InteractionFireworks extends HabboItem { return false; } - @Override - public boolean isWalkable() { - return this.getBaseItem().allowWalk(); - } - - @Override - public void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - - } - - @Override - public void serializeExtradata(ServerMessage serverMessage) { - serverMessage.appendInt((this.isLimited() ? 256 : 0)); - serverMessage.appendString(this.getExtradata()); - super.serializeExtradata(serverMessage); //Design flaw ;( - } - + /** + * Checked in Habbo on 2021-01-03 + * - Fireworks should be charged to be able to detonate them + * - Habbos with Rights can detonate fireworks from anywhere in a room + * - Habbos without rights have to walk to an adjecent tile to be able to detonate (see Interaction Switch) + * - Wired can always detonate fireworks + */ @Override public void onClick(GameClient client, Room room, Object[] objects) throws Exception { - super.onClick(client, room, objects); + if (room == null) + return; - if (client != null && this.getExtradata().equalsIgnoreCase("2")) //2 explodes I think (0 = empty, 1 = charged, 2 = effect) - { - AchievementManager.progressAchievement(client.getHabbo(), Emulator.getGameEnvironment().getAchievementManager().getAchievement("FireworksCharger")); + // Wireds can always detonate fireworks if charged + if (objects.length >= 2 && objects[1] instanceof WiredEffectType && objects[1] == WiredEffectType.TOGGLE_STATE) { + if (this.getExtradata().equalsIgnoreCase(STATE_CHARGED)) { + super.onClick(client, room, objects); + + if (this.getExtradata().equalsIgnoreCase(STATE_EXPLOSION)) { + this.reCharge(room); + } + } + + return; + } + + if (client == null) + return; + + // Habbos without rights have to walk to an adjecent tile to be able to detonate the fireworks + if (!this.canToggle(client.getHabbo(), room)) { + RoomTile closestTile = null; + for (RoomTile tile : room.getLayout().getTilesAround(room.getLayout().getTile(this.getX(), this.getY()))) { + if (tile.isWalkable() && (closestTile == null || closestTile.distance(client.getHabbo().getRoomUnit().getCurrentLocation()) > tile.distance(client.getHabbo().getRoomUnit().getCurrentLocation()))) { + closestTile = tile; + } + } + + if (closestTile != null && !closestTile.equals(client.getHabbo().getRoomUnit().getCurrentLocation())) { + List onSuccess = new ArrayList<>(); + onSuccess.add(() -> { + try { + this.onClick(client, room, objects); + } catch (Exception e) { + e.printStackTrace(); + } + }); + + client.getHabbo().getRoomUnit().setGoalLocation(closestTile); + Emulator.getThreading().run(new RoomUnitWalkToLocation(client.getHabbo().getRoomUnit(), closestTile, room, onSuccess, new ArrayList<>())); + } + } + + if (this.getExtradata().equalsIgnoreCase(STATE_CHARGED)) { + super.onClick(client, room, objects); + + if (this.getExtradata().equalsIgnoreCase(STATE_EXPLOSION)) + { + this.reCharge(room); + AchievementManager.progressAchievement(client.getHabbo(), Emulator.getGameEnvironment().getAchievementManager().getAchievement("FireworksCharger")); + } } } @Override public boolean allowWiredResetState() { - return true; + return false; + } + + @Override + public void onPlace(Room room) { + super.onPlace(room); + this.setExtradata(STATE_CHARGED); + } + + @Override + public boolean canToggle(Habbo habbo, Room room) { + return room.hasRights(habbo) || RoomLayout.tilesAdjecent( + room.getLayout().getTile(this.getX(), this.getY()), + habbo.getRoomUnit().getCurrentLocation() + ); + } + + private void reCharge(Room room) { + // Default = 5000, Nuclear Firework should have 10000 in its custom params according to Habbo + int explodeDuration = 5000; + if (!this.getBaseItem().getCustomParams().isEmpty()) { + try { + explodeDuration = Integer.parseInt(this.getBaseItem().getCustomParams()); + } catch (NumberFormatException e) { + LOGGER.error("Incorrect customparams (" + this.getBaseItem().getCustomParams() + ") for base item ID (" + this.getBaseItem().getId() + ") of type (" + this.getBaseItem().getName() + ")"); + } + } + + Emulator.getThreading().run(() -> { + this.setExtradata(STATE_CHARGED); + this.needsUpdate(true); + room.updateItemState(this); + }, explodeDuration); } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionGate.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionGate.java index 5c0b3422..f7ceb0e3 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionGate.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionGate.java @@ -3,6 +3,7 @@ package com.eu.habbo.habbohotel.items.interactions; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.rooms.RoomTile; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.habbohotel.wired.WiredEffectType; @@ -38,17 +39,21 @@ public class InteractionGate extends HabboItem { @Override public void onClick(GameClient client, Room room, Object[] objects) throws Exception { - boolean isWired = (objects.length >= 2 && objects[1] instanceof WiredEffectType && objects[1] == WiredEffectType.TOGGLE_STATE); - if (client != null && !room.hasRights(client.getHabbo()) && !isWired) + boolean executedByWired = (objects.length >= 2 && objects[1] instanceof WiredEffectType && objects[1] == WiredEffectType.TOGGLE_STATE); + + if (client != null && !room.hasRights(client.getHabbo()) && !executedByWired) return; - if (!isWired && !room.getHabbosAt(this.getX(), this.getY()).isEmpty()) - return; + // If a Habbo is standing on a tile occupied by the gate, the gate shouldn't open/close + for (RoomTile tile : room.getLayout().getTilesAt(room.getLayout().getTile(this.getX(), this.getY()), this.getBaseItem().getWidth(), this.getBaseItem().getLength(), this.getRotation())) + if (room.hasHabbosAt(tile.x, tile.y)) + return; + // Gate closed = 0, open = 1 if (this.getExtradata().length() == 0) this.setExtradata("0"); - this.setExtradata((Integer.valueOf(this.getExtradata()) + 1) % 2 + ""); + this.setExtradata((Integer.parseInt(this.getExtradata()) + 1) % 2 + ""); room.updateTile(room.getLayout().getTile(this.getX(), this.getY())); this.needsUpdate(true); room.updateItemState(this); diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionGuildFurni.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionGuildFurni.java index 667c5f44..b4374f86 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionGuildFurni.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionGuildFurni.java @@ -6,12 +6,18 @@ import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.messages.ServerMessage; +import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; public class InteractionGuildFurni extends InteractionDefault { private int guildId; + private static final THashSet ROTATION_8_ITEMS = new THashSet() { + { + this.add("gld_wall_tall"); + } + }; public InteractionGuildFurni(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); @@ -23,6 +29,14 @@ public class InteractionGuildFurni extends InteractionDefault { this.guildId = 0; } + @Override + public int getMaximumRotations() { + if(ROTATION_8_ITEMS.stream().anyMatch(x -> x.equalsIgnoreCase(this.getBaseItem().getName()))) { + return 8; + } + return this.getBaseItem().getRotations(); + } + @Override public void serializeExtradata(ServerMessage serverMessage) { Guild guild = Emulator.getGameEnvironment().getGuildManager().getGuild(this.guildId); diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionGuildGate.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionGuildGate.java index 176ae78d..41290215 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionGuildGate.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionGuildGate.java @@ -3,6 +3,7 @@ package com.eu.habbo.habbohotel.items.interactions; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.Item; +import com.eu.habbo.habbohotel.items.interactions.interfaces.ConditionalGate; import com.eu.habbo.habbohotel.permissions.Permission; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomTile; @@ -13,7 +14,7 @@ import com.eu.habbo.threading.runnables.CloseGate; import java.sql.ResultSet; import java.sql.SQLException; -public class InteractionGuildGate extends InteractionGuildFurni { +public class InteractionGuildGate extends InteractionGuildFurni implements ConditionalGate { public InteractionGuildGate(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); this.setExtradata("0"); @@ -61,4 +62,9 @@ public class InteractionGuildGate extends InteractionGuildFurni { this.setExtradata("0"); room.updateItemState(this); } + + @Override + public void onRejected(RoomUnit roomUnit, Room room, Object[] objects) { + + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionHabboClubGate.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionHabboClubGate.java index f9aa57dc..f356d4d3 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionHabboClubGate.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionHabboClubGate.java @@ -3,6 +3,7 @@ package com.eu.habbo.habbohotel.items.interactions; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.Item; +import com.eu.habbo.habbohotel.items.interactions.interfaces.ConditionalGate; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; @@ -12,7 +13,7 @@ import com.eu.habbo.threading.runnables.CloseGate; import java.sql.ResultSet; import java.sql.SQLException; -public class InteractionHabboClubGate extends InteractionDefault { +public class InteractionHabboClubGate extends InteractionDefault implements ConditionalGate { public InteractionHabboClubGate(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); this.setExtradata("0"); @@ -42,14 +43,6 @@ public class InteractionHabboClubGate extends InteractionDefault { if (this.canWalkOn(roomUnit, room, objects)) { this.setExtradata("1"); room.updateItemState(this); - } else { - Habbo habbo = room.getHabbo(roomUnit); - - if (habbo != null) { - habbo.getClient().sendResponse(new CustomNotificationComposer(CustomNotificationComposer.GATE_NO_HC)); - } - - roomUnit.setGoalLocation(roomUnit.getCurrentLocation()); } } @@ -70,4 +63,14 @@ public class InteractionHabboClubGate extends InteractionDefault { Emulator.getThreading().run(new CloseGate(this, room), 1000); } + + @Override + public void onRejected(RoomUnit roomUnit, Room room, Object[] objects) { + if (roomUnit == null || room == null) + return; + + room.getHabbo(roomUnit).getClient().sendResponse( + new CustomNotificationComposer(CustomNotificationComposer.GATE_NO_HC) + ); + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionMannequin.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionMannequin.java index 2901a7b9..f9c304a4 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionMannequin.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionMannequin.java @@ -6,6 +6,7 @@ import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.HabboItem; +import com.eu.habbo.habbohotel.users.clothingvalidation.ClothingValidationManager; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDataComposer; import com.eu.habbo.messages.outgoing.users.UserDataComposer; @@ -22,6 +23,11 @@ public class InteractionMannequin extends HabboItem { super(id, userId, item, extradata, limitedStack, limitedSells); } + @Override + public int getMaximumRotations() { + return 8; + } + @Override public void serializeExtradata(ServerMessage serverMessage) { serverMessage.appendInt(1 + (this.isLimited() ? 256 : 0)); @@ -60,26 +66,39 @@ public class InteractionMannequin extends HabboItem { @Override public void onClick(GameClient client, Room room, Object[] objects) throws Exception { - String[] lookCode = this.getExtradata().split(":")[1].split("\\."); + String[] data = this.getExtradata().split(":"); - StringBuilder look = new StringBuilder(); - for (String part : client.getHabbo().getHabboInfo().getLook().split("\\.")) { - String type = part.split("-")[0]; + if(data.length < 2) + return; - boolean found = false; - for (String s : lookCode) { - if (s.contains(type)) { - found = true; - look.append(s).append("."); - } - } + String gender = data[0]; + String figure = data[1]; - if (!found) { - look.append(part).append("."); - } + if (gender.isEmpty() || figure.isEmpty() || (!gender.equalsIgnoreCase("m") && !gender.equalsIgnoreCase("f")) || !client.getHabbo().getHabboInfo().getGender().name().equalsIgnoreCase(gender)) + return; + + String newFigure = ""; + + for (String playerFigurePart : client.getHabbo().getHabboInfo().getLook().split("\\.")) { + if (!playerFigurePart.startsWith("ch") && !playerFigurePart.startsWith("lg")) + newFigure += playerFigurePart + "."; } - client.getHabbo().getHabboInfo().setLook(look.substring(0, look.length() - 1)); + String newFigureParts = figure; + + for (String newFigurePart : newFigureParts.split("\\.")) { + if (newFigurePart.startsWith("hd")) + newFigureParts = newFigureParts.replace(newFigurePart, ""); + } + + if (newFigureParts.equals("")) return; + + String newLook = newFigure + newFigureParts; + + if (newLook.length() > 512) + return; + + client.getHabbo().getHabboInfo().setLook(ClothingValidationManager.VALIDATE_ON_MANNEQUIN ? ClothingValidationManager.validateLook(client.getHabbo(), newLook, client.getHabbo().getHabboInfo().getGender().name()) : newLook); room.sendComposer(new RoomUserDataComposer(client.getHabbo()).compose()); client.sendResponse(new UserDataComposer(client.getHabbo())); } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionMultiHeight.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionMultiHeight.java index 765b6e3b..47cba012 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionMultiHeight.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionMultiHeight.java @@ -15,6 +15,7 @@ import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; @@ -68,39 +69,39 @@ public class InteractionMultiHeight extends HabboItem { this.setExtradata("0"); if (this.getBaseItem().getMultiHeights().length > 0) { - this.setExtradata("" + (Integer.valueOf(this.getExtradata()) + 1) % (this.getBaseItem().getMultiHeights().length)); + this.setExtradata("" + (Integer.parseInt(this.getExtradata()) + 1) % (this.getBaseItem().getMultiHeights().length)); this.needsUpdate(true); room.updateTiles(room.getLayout().getTilesAt(room.getLayout().getTile(this.getX(), this.getY()), this.getBaseItem().getWidth(), this.getBaseItem().getLength(), this.getRotation())); room.updateItemState(this); //room.sendComposer(new UpdateStackHeightComposer(this.getX(), this.getY(), this.getBaseItem().getMultiHeights()[Integer.valueOf(this.getExtradata())] * 256.0D).compose()); } + } + } + } - if (this.isWalkable()) { - List unitsOnItem = new ArrayList<>(); - unitsOnItem.addAll(room.getHabbosOnItem(this).stream().map(Habbo::getRoomUnit).filter(Objects::nonNull).collect(Collectors.toList())); - unitsOnItem.addAll(room.getBotsOnItem(this).stream().map(Bot::getRoomUnit).filter(Objects::nonNull).collect(Collectors.toList())); + public void updateUnitsOnItem(Room room) { + THashSet occupiedTiles = room.getLayout().getTilesAt(room.getLayout().getTile(this.getX(), this.getY()), this.getBaseItem().getWidth(), this.getBaseItem().getLength(), this.getRotation()); - THashSet updatedUnits = new THashSet<>(); - for (RoomUnit unit : unitsOnItem) { - if (unit.hasStatus(RoomUnitStatus.MOVE)) - continue; + for(RoomTile tile : occupiedTiles) { + Collection unitsOnItem = room.getRoomUnitsAt(room.getLayout().getTile(tile.x, tile.y)); - if (this.getBaseItem().getMultiHeights().length >= 0) { - if (this.getBaseItem().allowSit()) { - unit.setStatus(RoomUnitStatus.SIT, this.getBaseItem().getMultiHeights()[(this.getExtradata().isEmpty() ? 0 : Integer.valueOf(this.getExtradata()) % (this.getBaseItem().getMultiHeights().length))] * 1.0D + ""); - } else { - unit.setZ(unit.getCurrentLocation().getStackHeight()); - unit.setPreviousLocationZ(unit.getZ()); - } - } + THashSet updatedUnits = new THashSet<>(); + for (RoomUnit unit : unitsOnItem) { + if (unit.hasStatus(RoomUnitStatus.MOVE) && unit.getGoal() != tile) + continue; - updatedUnits.add(unit); - } - - room.sendComposer(new RoomUserStatusComposer(updatedUnits, true).compose()); + if (this.getBaseItem().allowSit() || unit.hasStatus(RoomUnitStatus.SIT)) { + unit.sitUpdate = true; + unit.statusUpdate(true); + } else { + unit.setZ(unit.getCurrentLocation().getStackHeight()); + unit.setPreviousLocationZ(unit.getZ()); + unit.statusUpdate(true); } } } + + //room.sendComposer(new RoomUserStatusComposer(updatedUnits, true).compose()); } @Override diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionMuteArea.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionMuteArea.java index fcc9522a..29a7c0ac 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionMuteArea.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionMuteArea.java @@ -1,8 +1,21 @@ package com.eu.habbo.habbohotel.items.interactions; +import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.Item; +import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomTile; +import com.eu.habbo.habbohotel.rooms.RoomTileState; +import com.eu.habbo.habbohotel.users.HabboItem; +import com.eu.habbo.habbohotel.wired.WiredEffectType; +import com.eu.habbo.messages.outgoing.rooms.items.ItemExtraDataComposer; +import com.eu.habbo.messages.outgoing.rooms.items.RemoveFloorItemComposer; +import com.eu.habbo.messages.outgoing.rooms.items.RoomFloorItemsComposer; +import gnu.trove.TCollections; +import gnu.trove.map.TIntObjectMap; import gnu.trove.map.hash.THashMap; +import gnu.trove.map.hash.TIntObjectHashMap; +import gnu.trove.set.hash.THashSet; import java.awt.*; import java.sql.ResultSet; @@ -25,25 +38,122 @@ public class InteractionMuteArea extends InteractionCustomValues { { this.put("tilesBack", "0"); } + + { + this.put("state", "0"); + } }; + private THashSet tiles; + public InteractionMuteArea(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem, defaultValues); + tiles = new THashSet<>(); } public InteractionMuteArea(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) { super(id, userId, item, extradata, limitedStack, limitedSells, defaultValues); + tiles = new THashSet<>(); + } + + @Override + public void onClick(GameClient client, Room room, Object[] objects) throws Exception { + super.onClick(client, room, objects); + + if((objects.length >= 2 && objects[1] instanceof WiredEffectType) || (client != null && room.hasRights(client.getHabbo()))) { + this.values.put("state", this.values.get("state").equals("0") ? "1" : "0"); + room.sendComposer(new ItemExtraDataComposer(this).compose()); + } + } + + @Override + public void onPlace(Room room) { + super.onPlace(room); + this.regenAffectedTiles(room); + } + + @Override + public void onPickUp(Room room) { + super.onPickUp(room); + this.tiles.clear(); + } + + @Override + public void onMove(Room room, RoomTile oldLocation, RoomTile newLocation) { + super.onMove(room, oldLocation, newLocation); + this.regenAffectedTiles(room); } public boolean inSquare(RoomTile location) { - try { + Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); + + if(!this.values.get("state").equals("1")) + return false; + + if(room != null && this.tiles.size() == 0) { + regenAffectedTiles(room); + } + + return this.tiles.contains(location); + + /*try { return new Rectangle( - this.getX() - Integer.valueOf(this.values.get("tilesBack")), + this.getX() - Integer.parseInt(this.values.get("tilesBack")), this.getY() + Integer.valueOf(this.values.get("tilesLeft")) - (Integer.valueOf(this.values.get("tilesLeft")) + Integer.valueOf(this.values.get("tilesRight"))), Integer.valueOf(this.values.get("tilesLeft")) + Integer.valueOf(this.values.get("tilesRight")) + 1, Integer.valueOf(this.values.get("tilesFront")) + Integer.valueOf(this.values.get("tilesBack")) + 1).contains(location.x, location.y); } catch (Exception e) { return false; + }*/ + } + + private void regenAffectedTiles(Room room) { + int minX = Math.max(0, this.getX() - Integer.parseInt(this.values.get("tilesBack"))); + int minY = Math.max(0, this.getY() - Integer.parseInt(this.values.get("tilesRight"))); + int maxX = Math.min(room.getLayout().getMapSizeX(), this.getX() + Integer.parseInt(this.values.get("tilesFront"))); + int maxY = Math.min(room.getLayout().getMapSizeY(), this.getY() + Integer.parseInt(this.values.get("tilesLeft"))); + + this.tiles.clear(); + + for(int x = minX; x <= maxX; x++) { + for(int y = minY; y <= maxY; y++) { + RoomTile tile = room.getLayout().getTile((short)x, (short)y); + if(tile != null && tile.state != RoomTileState.INVALID) + this.tiles.add(tile); + } + } + } + + @Override + public void onCustomValuesSaved(Room room, GameClient client) { + super.onCustomValuesSaved(room, client); + + this.regenAffectedTiles(room); + + // show the effect + Item effectItem = Emulator.getGameEnvironment().getItemManager().getItem("mutearea_sign2"); + + if(effectItem != null) { + TIntObjectMap ownerNames = TCollections.synchronizedMap(new TIntObjectHashMap<>(0)); + ownerNames.put(-1, "System"); + THashSet items = new THashSet<>(); + + int id = 0; + for(RoomTile tile : this.tiles) { + id--; + HabboItem item = new InteractionDefault(id, -1, effectItem, "1", 0, 0); + item.setX(tile.x); + item.setY(tile.y); + item.setZ(tile.relativeHeight()); + items.add(item); + } + + client.sendResponse(new RoomFloorItemsComposer(ownerNames, items)); + Emulator.getThreading().run(() -> { + for(HabboItem item : items) { + client.sendResponse(new RemoveFloorItemComposer(item, true)); + } + }, 3000); } } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionObstacle.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionObstacle.java index 5b3cdb75..a63dcad8 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionObstacle.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionObstacle.java @@ -1,33 +1,34 @@ package com.eu.habbo.habbohotel.items.interactions; -import com.eu.habbo.Emulator; -import com.eu.habbo.habbohotel.achievements.AchievementManager; import com.eu.habbo.habbohotel.gameclients.GameClient; +import com.eu.habbo.habbohotel.items.ICycleable; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.pets.HorsePet; import com.eu.habbo.habbohotel.pets.Pet; -import com.eu.habbo.habbohotel.pets.PetTasks; -import com.eu.habbo.habbohotel.rooms.Room; -import com.eu.habbo.habbohotel.rooms.RoomUnit; -import com.eu.habbo.habbohotel.rooms.RoomUnitStatus; -import com.eu.habbo.habbohotel.rooms.RoomUserRotation; +import com.eu.habbo.habbohotel.rooms.*; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.messages.ServerMessage; -import com.eu.habbo.threading.runnables.HabboItemNewState; +import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.Objects; + +public class InteractionObstacle extends HabboItem implements ICycleable { + + private THashSet middleTiles; -public class InteractionObstacle extends HabboItem { public InteractionObstacle(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); this.setExtradata("0"); + this.middleTiles = new THashSet<>(); } public InteractionObstacle(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) { super(id, userId, item, extradata, limitedStack, limitedSells); this.setExtradata("0"); + this.middleTiles = new THashSet<>(); } @Override @@ -40,20 +41,12 @@ public class InteractionObstacle extends HabboItem { @Override public boolean canWalkOn(RoomUnit roomUnit, Room room, Object[] objects) { - Pet pet = room.getPet(roomUnit); - - if (pet instanceof HorsePet) { - HorsePet horsePet = (HorsePet) pet; - - return horsePet.getRider() != null; - } - - return false; + return true; } @Override public boolean isWalkable() { - return false; + return true; } @Override @@ -63,36 +56,32 @@ public class InteractionObstacle extends HabboItem { @Override public void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - Habbo habbo = room.getHabbo(roomUnit); + /*Pet pet = room.getPet(roomUnit); - if (habbo != null) { - Pet pet = room.getPet(roomUnit); + if (pet instanceof HorsePet && ((HorsePet) pet).getRider() != null) { + if (pet.getTask() != null && pet.getTask().equals(PetTasks.RIDE)) { + if (pet.getRoomUnit().hasStatus(RoomUnitStatus.JUMP)) { + pet.getRoomUnit().removeStatus(RoomUnitStatus.JUMP); + Emulator.getThreading().run(new HabboItemNewState(this, room, "0"), 2000); + } else { + int state = 0; + for (int i = 0; i < 2; i++) { + state = Emulator.getRandom().nextInt(4) + 1; - if (pet instanceof HorsePet && ((HorsePet) pet).getRider() != null) { - if (pet.getTask() != null && pet.getTask().equals(PetTasks.RIDE)) { - if (pet.getRoomUnit().hasStatus(RoomUnitStatus.JUMP)) { - pet.getRoomUnit().removeStatus(RoomUnitStatus.JUMP); - Emulator.getThreading().run(new HabboItemNewState(this, room, "0"), 2000); - } else { - int state = 0; - for (int i = 0; i < 2; i++) { - state = Emulator.getRandom().nextInt(4) + 1; - - if (state == 4) - break; - } - - this.setExtradata(state + ""); - pet.getRoomUnit().setStatus(RoomUnitStatus.JUMP, "0"); - - AchievementManager.progressAchievement(habbo, Emulator.getGameEnvironment().getAchievementManager().getAchievement("HorseConsecutiveJumpsCount")); - AchievementManager.progressAchievement(habbo, Emulator.getGameEnvironment().getAchievementManager().getAchievement("HorseJumping")); + if (state == 4) + break; } - room.updateItemState(this); + this.setExtradata(state + ""); + pet.getRoomUnit().setStatus(RoomUnitStatus.JUMP, "0"); + + AchievementManager.progressAchievement(habbo, Emulator.getGameEnvironment().getAchievementManager().getAchievement("HorseConsecutiveJumpsCount")); + AchievementManager.progressAchievement(habbo, Emulator.getGameEnvironment().getAchievementManager().getAchievement("HorseJumping")); } + + room.updateItemState(this); } - } + }*/ } @Override @@ -138,4 +127,70 @@ public class InteractionObstacle extends HabboItem { } } } + + @Override + public void onPlace(Room room) { + super.onPlace(room); + this.calculateMiddleTiles(room); + } + + @Override + public void onPickUp(Room room) { + super.onPickUp(room); + middleTiles.clear(); + } + + @Override + public void onMove(Room room, RoomTile oldLocation, RoomTile newLocation) { + super.onMove(room, oldLocation, newLocation); + this.calculateMiddleTiles(room); + } + + private void calculateMiddleTiles(Room room) { + middleTiles.clear(); + + if(this.getRotation() == 2) { + middleTiles.add(room.getLayout().getTile((short)(this.getX() + 1), this.getY())); + middleTiles.add(room.getLayout().getTile((short)(this.getX() + 1), (short)(this.getY() + 1))); + } + else if(this.getRotation() == 4) { + middleTiles.add(room.getLayout().getTile(this.getX(), (short)(this.getY() + 1))); + middleTiles.add(room.getLayout().getTile((short)(this.getX() + 1), (short)(this.getY() + 1))); + } + } + + @Override + public RoomTileState getOverrideTileState(RoomTile tile, Room room) { + if(this.middleTiles.contains(tile)) + return RoomTileState.BLOCKED; + + return null; + } + + @Override + public void cycle(Room room) { + if(this.middleTiles.size() == 0) { + this.calculateMiddleTiles(room); + } + + for(RoomTile tile : this.middleTiles) { + for(RoomUnit unit : tile.getUnits()) { + if(unit.getPath().size() == 0 && !unit.hasStatus(RoomUnitStatus.MOVE)) { + if(unit.getBodyRotation().getValue() != this.getRotation() && Objects.requireNonNull(unit.getBodyRotation().getOpposite()).getValue() != this.getRotation()) + continue; + + RoomTile tileInfront = room.getLayout().getTileInFront(unit.getCurrentLocation(), unit.getBodyRotation().getValue()); + if(tileInfront.state != RoomTileState.INVALID && tileInfront.state != RoomTileState.BLOCKED && room.getRoomUnitsAt(tileInfront).size() == 0) { + unit.setGoalLocation(tileInfront); + } + else { + RoomTile tileBehind = room.getLayout().getTileInFront(unit.getCurrentLocation(), Objects.requireNonNull(unit.getBodyRotation().getOpposite()).getValue()); + if(tileBehind.state != RoomTileState.INVALID && tileBehind.state != RoomTileState.BLOCKED && room.getRoomUnitsAt(tileBehind).size() == 0) { + unit.setGoalLocation(tileBehind); + } + } + } + } + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionOneWayGate.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionOneWayGate.java index 844b042e..6a26e6cb 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionOneWayGate.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionOneWayGate.java @@ -7,9 +7,14 @@ import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomTile; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.HabboItem; +import com.eu.habbo.habbohotel.wired.WiredHandler; +import com.eu.habbo.habbohotel.wired.WiredTriggerType; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.rooms.users.RoomUserWalkEvent; import com.eu.habbo.messages.outgoing.rooms.items.ItemIntStateComposer; import com.eu.habbo.threading.runnables.RoomUnitWalkToLocation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.sql.ResultSet; import java.sql.SQLException; @@ -17,6 +22,8 @@ import java.util.ArrayList; import java.util.List; public class InteractionOneWayGate extends HabboItem { + private static final Logger LOGGER = LoggerFactory.getLogger(InteractionOneWayGate.class); + private boolean walkable = false; public InteractionOneWayGate(ResultSet set, Item baseItem) throws SQLException { @@ -74,7 +81,6 @@ public class InteractionOneWayGate extends HabboItem { if (unit == null) return; - if (tileInfront.x == unit.getX() && tileInfront.y == unit.getY()) { if (!currentLocation.hasUnits()) { List onSuccess = new ArrayList(); @@ -86,6 +92,8 @@ public class InteractionOneWayGate extends HabboItem { RoomTile tile = room.getLayout().getTileInFront(room.getLayout().getTile(this.getX(), this.getY()), this.getRotation() + 4); unit.setGoalLocation(tile); Emulator.getThreading().run(new RoomUnitWalkToLocation(unit, tile, room, onFail, onFail)); + + Emulator.getThreading().run(() -> WiredHandler.handle(WiredTriggerType.WALKS_ON_FURNI, unit, room, new Object[]{this}), 500); }); onFail.add(() -> { diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionPressurePlate.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionPressurePlate.java index 0eee202b..06d19289 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionPressurePlate.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionPressurePlate.java @@ -8,12 +8,13 @@ import com.eu.habbo.habbohotel.rooms.RoomTile; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.outgoing.rooms.items.ItemStateComposer; import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; -public class InteractionPressurePlate extends HabboItem { +public class InteractionPressurePlate extends InteractionDefault { public InteractionPressurePlate(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); this.setExtradata("0"); @@ -39,14 +40,6 @@ public class InteractionPressurePlate extends HabboItem { super.onClick(client, room, objects); } - @Override - public void serializeExtradata(ServerMessage serverMessage) { - serverMessage.appendInt((this.isLimited() ? 256 : 0)); - serverMessage.appendString(this.getExtradata()); - - super.serializeExtradata(serverMessage); - } - @Override public void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { @@ -99,7 +92,7 @@ public class InteractionPressurePlate extends HabboItem { } this.setExtradata(occupied ? "1" : "0"); - room.updateItem(this); + room.updateItemState(this); } @Override diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionPushable.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionPushable.java index 3cd88425..a8d0db0e 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionPushable.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionPushable.java @@ -50,7 +50,7 @@ public abstract class InteractionPushable extends InteractionDefault { if (this.currentThread != null) this.currentThread.dead = true; - this.currentThread = new KickBallAction(this, room, roomUnit, direction, velocity); + this.currentThread = new KickBallAction(this, room, roomUnit, direction, velocity, false); Emulator.getThreading().run(this.currentThread, 0); } } @@ -69,7 +69,7 @@ public abstract class InteractionPushable extends InteractionDefault { if (this.currentThread != null) this.currentThread.dead = true; - this.currentThread = new KickBallAction(this, room, client.getHabbo().getRoomUnit(), direction, velocity); + this.currentThread = new KickBallAction(this, room, client.getHabbo().getRoomUnit(), direction, velocity, false); Emulator.getThreading().run(this.currentThread, 0); } } @@ -80,6 +80,7 @@ public abstract class InteractionPushable extends InteractionDefault { super.onWalkOn(roomUnit, room, objects); int velocity; + boolean isDrag = false; RoomUserRotation direction; if (this.getX() == roomUnit.getGoal().x && this.getY() == roomUnit.getGoal().y) //User clicked on the tile the ball is on, they want to kick it @@ -92,13 +93,14 @@ public abstract class InteractionPushable extends InteractionDefault { velocity = this.getDragVelocity(roomUnit, room); direction = this.getDragDirection(roomUnit, room); this.onDrag(room, roomUnit, velocity, direction); + isDrag = true; } if (velocity > 0) { if (this.currentThread != null) this.currentThread.dead = true; - this.currentThread = new KickBallAction(this, room, roomUnit, direction, velocity); + this.currentThread = new KickBallAction(this, room, roomUnit, direction, velocity, isDrag); Emulator.getThreading().run(this.currentThread, 0); } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionTeleport.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionTeleport.java index 69d7fe3a..42813714 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionTeleport.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionTeleport.java @@ -93,7 +93,7 @@ public class InteractionTeleport extends HabboItem { // set state 1 and walk on item this.roomUnitID = unit.getId(); this.setExtradata("1"); - room.updateItem(this); + room.updateItemState(this); unit.setGoalLocation(infrontTile); List onSuccess = new ArrayList(); @@ -111,7 +111,7 @@ public class InteractionTeleport extends HabboItem { walkable = this.getBaseItem().allowWalk(); room.updateTile(currentLocation); this.setExtradata("0"); - room.updateItem(this); + room.updateItemState(this); this.roomUnitID = -1; unit.removeOverrideTile(currentLocation); unit.setCanLeaveRoomByDoor(true); diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionTrophy.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionTrophy.java index 791109a4..80f2c39c 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionTrophy.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionTrophy.java @@ -13,4 +13,9 @@ public class InteractionTrophy extends InteractionDefault { public InteractionTrophy(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) { super(id, userId, item, extradata, limitedStack, limitedSells); } + + @Override + public boolean allowWiredResetState() { + return false; + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionVendingMachine.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionVendingMachine.java index be0f5cba..63a32a1a 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionVendingMachine.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionVendingMachine.java @@ -7,6 +7,8 @@ import com.eu.habbo.habbohotel.rooms.*; 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.wired.WiredHandler; +import com.eu.habbo.habbohotel.wired.WiredTriggerType; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.outgoing.rooms.items.FloorItemUpdateComposer; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserStatusComposer; @@ -34,8 +36,12 @@ public class InteractionVendingMachine extends HabboItem { } public THashSet getActivatorTiles(Room room) { - THashSet tiles = new THashSet(); - tiles.add(getSquareInFront(room.getLayout(), this)); + THashSet tiles = new THashSet<>(); + RoomTile tileInFront = getSquareInFront(room.getLayout(), this); + + if (tileInFront != null) + tiles.add(tileInFront); + tiles.add(room.getLayout().getTile(this.getX(), this.getY())); return tiles; } @@ -71,7 +77,13 @@ public class InteractionVendingMachine extends HabboItem { this.setExtradata("1"); room.updateItem(this); - if(!unit.isWalking()) { + try { + super.onClick(client, room, new Object[]{"TOGGLE_OVERRIDE"}); + } catch (Exception e) { + e.printStackTrace(); + } + + if(!unit.isWalking() && !unit.hasStatus(RoomUnitStatus.SIT) && !unit.hasStatus(RoomUnitStatus.LAY)) { this.rotateToMachine(room, unit); } @@ -94,8 +106,6 @@ public class InteractionVendingMachine extends HabboItem { @Override public void onClick(GameClient client, Room room, Object[] objects) throws Exception { - super.onClick(client, room, objects); - if (client == null) { return; } @@ -118,7 +128,7 @@ public class InteractionVendingMachine extends HabboItem { if(!inActivatorSpace) { RoomTile tileToWalkTo = null; for(RoomTile tile : activatorTiles) { - if(room.getLayout().tileWalkable(tile.x, tile.y) && (tileToWalkTo == null || tileToWalkTo.distance(unit.getCurrentLocation()) > tile.distance(unit.getCurrentLocation()))) { + if((tile.state == RoomTileState.OPEN || tile.state == RoomTileState.SIT) && (tileToWalkTo == null || tileToWalkTo.distance(unit.getCurrentLocation()) > tile.distance(unit.getCurrentLocation()))) { tileToWalkTo = tile; } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWaterItem.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWaterItem.java index 0332c717..4b283da1 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWaterItem.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWaterItem.java @@ -1,6 +1,7 @@ package com.eu.habbo.habbohotel.items.interactions; import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomLayout; @@ -13,7 +14,7 @@ import java.awt.*; import java.sql.ResultSet; import java.sql.SQLException; -public class InteractionWaterItem extends InteractionDefault { +public class InteractionWaterItem extends InteractionMultiHeight { public InteractionWaterItem(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); } @@ -30,15 +31,22 @@ public class InteractionWaterItem extends InteractionDefault { @Override public void onPickUp(Room room) { + super.onPickUp(room); this.setExtradata("0"); this.needsUpdate(true); } @Override public void onMove(Room room, RoomTile oldLocation, RoomTile newLocation) { + super.onMove(room, oldLocation, newLocation); this.update(); } + @Override + public void onClick(GameClient client, Room room, Object[] objects) throws Exception { + super.onClick(client, room, new Object[] { }); + } + public void update() { Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); @@ -75,7 +83,7 @@ public class InteractionWaterItem extends InteractionDefault { if (!this.getExtradata().equals(updatedData)) { this.setExtradata(updatedData); this.needsUpdate(true); - room.updateItem(this); + room.updateItemState(this); } } @@ -83,9 +91,4 @@ public class InteractionWaterItem extends InteractionDefault { public boolean allowWiredResetState() { return false; } - - @Override - public boolean canToggle(Habbo habbo, Room room) { - return false; - } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWired.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWired.java index a465367c..c19b1ec9 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWired.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWired.java @@ -15,7 +15,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -public abstract class InteractionWired extends HabboItem { +public abstract class InteractionWired extends InteractionDefault { private static final Logger LOGGER = LoggerFactory.getLogger(InteractionWired.class); private long cooldown; @@ -37,25 +37,6 @@ public abstract class InteractionWired extends HabboItem { public abstract void loadWiredData(ResultSet set, Room room) throws SQLException; - @Override - public void onWalkOn(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - super.onWalkOn(roomUnit, room, objects); - } - - @Override - public void onWalkOff(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - super.onWalkOff(roomUnit, room, objects); - } - - - @Override - public void serializeExtradata(ServerMessage serverMessage) { - serverMessage.appendInt((this.isLimited() ? 256 : 0)); - serverMessage.appendString(this.getExtradata()); - - super.serializeExtradata(serverMessage); - } - @Override public void run() { if (this.needsUpdate()) { diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredCondition.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredCondition.java index d8c7ed41..7bf21fe1 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredCondition.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredCondition.java @@ -41,21 +41,6 @@ public abstract class InteractionWiredCondition extends InteractionWired { } } - @Override - public void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - - } - - @Override - public void onWalkOn(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - - } - - @Override - public void onWalkOff(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - - } - public abstract WiredConditionType getType(); public abstract boolean saveData(ClientMessage packet); diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredEffect.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredEffect.java index a6ae8ab4..59da2b6f 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredEffect.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredEffect.java @@ -6,6 +6,7 @@ import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.wired.WiredEffectType; import com.eu.habbo.messages.ClientMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import com.eu.habbo.messages.outgoing.wired.WiredEffectDataComposer; import java.sql.ResultSet; @@ -42,22 +43,7 @@ public abstract class InteractionWiredEffect extends InteractionWired { } } - @Override - public void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - - } - - @Override - public void onWalkOn(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - - } - - @Override - public void onWalkOff(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - - } - - public abstract boolean saveData(ClientMessage packet, GameClient gameClient); + public abstract boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException; public int getDelay() { return this.delay; diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredHighscore.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredHighscore.java index 9708c565..8fb95dd4 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredHighscore.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredHighscore.java @@ -6,6 +6,9 @@ import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.HabboItem; +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.habbohotel.wired.highscores.WiredHighscoreClearType; import com.eu.habbo.habbohotel.wired.highscores.WiredHighscoreRow; import com.eu.habbo.habbohotel.wired.highscores.WiredHighscoreScoreType; @@ -78,6 +81,9 @@ public class InteractionWiredHighscore extends HabboItem { @Override public void onClick(GameClient client, Room room, Object[] objects) throws Exception { + if (!((client != null && room != null && room.hasRights(client.getHabbo())) || (objects.length >= 2 && objects[1] instanceof WiredEffectType))) + return; + if (this.getExtradata() == null || this.getExtradata().isEmpty() || this.getExtradata().length() == 0) { this.setExtradata("0"); } @@ -89,6 +95,10 @@ public class InteractionWiredHighscore extends HabboItem { } catch (Exception e) { LOGGER.error("Caught exception", e); } + + if(client != null && !(objects.length >= 2 && objects[1] instanceof WiredEffectType)) { + WiredHandler.handle(WiredTriggerType.STATE_CHANGED, client.getHabbo().getRoomUnit(), room, new Object[]{this}); + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredTrigger.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredTrigger.java index 30ed0565..c0bbaabb 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredTrigger.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredTrigger.java @@ -42,21 +42,6 @@ public abstract class InteractionWiredTrigger extends InteractionWired { } } - @Override - public void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - - } - - @Override - public void onWalkOn(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - - } - - @Override - public void onWalkOff(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - - } - public abstract WiredTriggerType getType(); public abstract boolean saveData(ClientMessage packet); 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 6197b017..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 @@ -4,6 +4,7 @@ import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.games.Game; import com.eu.habbo.habbohotel.games.GameState; +import com.eu.habbo.habbohotel.games.wired.WiredGame; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.permissions.Permission; import com.eu.habbo.habbohotel.rooms.Room; @@ -13,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; @@ -62,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; } @@ -98,11 +100,15 @@ public class InteractionGameTimer extends HabboItem implements Runnable { } public void endGame(Room room) { + endGame(room, false); + } + + public void endGame(Room room, boolean isStart) { this.isRunning = false; this.isPaused = false; for (Game game : room.getGames()) { - if (!game.getState().equals(GameState.IDLE)) { + if (!game.getState().equals(GameState.IDLE) && !(isStart && game instanceof WiredGame)) { game.onEnd(); game.stop(); } @@ -144,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 @@ -226,7 +205,7 @@ public class InteractionGameTimer extends HabboItem implements Runnable { return; boolean wasPaused = this.isPaused; - this.endGame(room); + this.endGame(room, true); if(wasPaused) { WiredHandler.handle(WiredTriggerType.GAME_ENDS, null, room, new Object[]{}); @@ -243,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))) @@ -266,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 { @@ -280,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); } } @@ -345,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/items/interactions/games/battlebanzai/InteractionBattleBanzaiTeleporter.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/battlebanzai/InteractionBattleBanzaiTeleporter.java index 067f1056..98a627fe 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/battlebanzai/InteractionBattleBanzaiTeleporter.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/battlebanzai/InteractionBattleBanzaiTeleporter.java @@ -55,18 +55,18 @@ public class InteractionBattleBanzaiTeleporter extends HabboItem { @Override public void onWalkOn(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { super.onWalkOn(roomUnit, room, objects); - HabboItem target = room.getRoomSpecialTypes().getRandomTeleporter(this.getBaseItem(), this); - if (target == null) return; + if(objects.length < 3) { + HabboItem target = room.getRoomSpecialTypes().getRandomTeleporter(null, this); + if (target == null) return; - this.setExtradata("1"); - roomUnit.removeStatus(RoomUnitStatus.MOVE); - target.setExtradata("1"); - room.updateItem(this); - room.updateItem(target); - roomUnit.setGoalLocation(room.getLayout().getTile(roomUnit.getX(), roomUnit.getY())); - roomUnit.setCanWalk(false); - Emulator.getThreading().run(new BanzaiRandomTeleport(this, target, roomUnit, room), 1000); + this.setExtradata("1"); + room.updateItemState(this); + roomUnit.removeStatus(RoomUnitStatus.MOVE); + roomUnit.setGoalLocation(roomUnit.getCurrentLocation()); + roomUnit.setCanWalk(false); + Emulator.getThreading().run(new BanzaiRandomTeleport(this, target, roomUnit, room), 500); + } } @Override diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/football/InteractionFootball.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/football/InteractionFootball.java index 482a3d96..f64b0ade 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/football/InteractionFootball.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/football/InteractionFootball.java @@ -1,15 +1,13 @@ package com.eu.habbo.habbohotel.items.interactions.games.football; +import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.games.GameTeamColors; import com.eu.habbo.habbohotel.games.football.FootballGame; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.items.interactions.InteractionPushable; import com.eu.habbo.habbohotel.items.interactions.games.InteractionGameTeamItem; import com.eu.habbo.habbohotel.items.interactions.games.football.goals.InteractionFootballGoal; -import com.eu.habbo.habbohotel.rooms.Room; -import com.eu.habbo.habbohotel.rooms.RoomTile; -import com.eu.habbo.habbohotel.rooms.RoomUnit; -import com.eu.habbo.habbohotel.rooms.RoomUserRotation; +import com.eu.habbo.habbohotel.rooms.*; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.messages.outgoing.rooms.items.ItemStateComposer; import com.eu.habbo.util.pathfinding.Rotation; @@ -31,15 +29,21 @@ public class InteractionFootball extends InteractionPushable { @Override public int getWalkOnVelocity(RoomUnit roomUnit, Room room) { - if (roomUnit.getPath().isEmpty() && roomUnit.tilesWalked() == 2) + if (roomUnit.getPath().isEmpty() && roomUnit.tilesWalked() == 2 && this.getExtradata().equals("1")) return 0; - return 6; + if (roomUnit.getPath().size() == 0 && roomUnit.tilesWalked() == 1) + return 6; + + return 1; } @Override public int getWalkOffVelocity(RoomUnit roomUnit, Room room) { - return 6; + if (roomUnit.getPath().size() == 0 && roomUnit.tilesWalked() == 0) + return 6; + + return 1; } @Override @@ -79,8 +83,17 @@ public class InteractionFootball extends InteractionPushable { @Override public int getNextRollDelay(int currentStep, int totalSteps) { - int t = 2500; - return (totalSteps == 1) ? 500 : 100 * ((t = t / t - 1) * t * t * t * t + 1) + (currentStep * 100); + + if(totalSteps > 4) { + if(currentStep <= 4) { + return 125; + } + } + + return 500; + + /*int t = 2500; + return (totalSteps == 1) ? 500 : 100 * ((t = t / t - 1) * t * t * t * t + 1) + (currentStep * 100);*/ } @Override @@ -136,9 +149,9 @@ public class InteractionFootball extends InteractionPushable { @Override public boolean validMove(Room room, RoomTile from, RoomTile to) { - if (to == null) return false; + if (to == null || to.state == RoomTileState.INVALID) return false; HabboItem topItem = room.getTopItemAt(to.x, to.y, this); - return !(!room.getLayout().tileWalkable(to.x, to.y) || (topItem != null && (!topItem.getBaseItem().allowStack() || topItem.getBaseItem().allowSit() || topItem.getBaseItem().allowLay()))); + return (topItem == null || topItem.getBaseItem().allowStack()); } //Events @@ -176,8 +189,11 @@ public class InteractionFootball extends InteractionPushable { game.onScore(kicker, color); } - this.setExtradata(nextRoll <= 200 ? "8" : (nextRoll <= 250 ? "7" : (nextRoll <= 300 ? "6" : (nextRoll <= 350 ? "5" : (nextRoll <= 400 ? "4" : (nextRoll <= 450 ? "3" : (nextRoll <= 500 ? "2" : "1"))))))); + this.setExtradata(Math.abs(currentStep - (totalSteps + 1)) + ""); room.sendComposer(new ItemStateComposer(this).compose()); + + /*this.setExtradata(nextRoll <= 200 ? "8" : (nextRoll <= 250 ? "7" : (nextRoll <= 300 ? "6" : (nextRoll <= 350 ? "5" : (nextRoll <= 400 ? "4" : (nextRoll <= 450 ? "3" : (nextRoll <= 500 ? "2" : "1"))))))); + room.sendComposer(new ItemStateComposer(this).compose());*/ } @Override @@ -194,7 +210,7 @@ public class InteractionFootball extends InteractionPushable { @Override public boolean canStillMove(Room room, RoomTile from, RoomTile to, RoomUserRotation direction, RoomUnit kicker, int nextRoll, int currentStep, int totalSteps) { HabboItem topItem = room.getTopItemAt(from.x, from.y, this); - return !(room.hasHabbosAt(to.x, to.y) || (topItem != null && topItem.getBaseItem().getName().startsWith("fball_goal_") && currentStep != 1)); + return !((Emulator.getRandom().nextInt(10) >= 3 && room.hasHabbosAt(to.x, to.y)) || (topItem != null && topItem.getBaseItem().getName().startsWith("fball_goal_") && currentStep != 1)); } @Override diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/football/InteractionFootballGate.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/football/InteractionFootballGate.java index 73db3741..265b4cb9 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/football/InteractionFootballGate.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/football/InteractionFootballGate.java @@ -7,6 +7,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.clothingvalidation.ClothingValidationManager; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDataComposer; import com.eu.habbo.messages.outgoing.users.UpdateUserLookComposer; @@ -120,7 +121,7 @@ public class InteractionFootballGate extends HabboItem { UserSavedLookEvent lookEvent = new UserSavedLookEvent(habbo, habbo.getHabboInfo().getGender(), oldlook); Emulator.getPluginManager().fireEvent(lookEvent); if (!lookEvent.isCancelled()) { - habbo.getHabboInfo().setLook(lookEvent.newLook); + habbo.getHabboInfo().setLook(ClothingValidationManager.VALIDATE_ON_FBALLGATE ? ClothingValidationManager.validateLook(habbo, lookEvent.newLook, lookEvent.gender.name()) : lookEvent.newLook); Emulator.getThreading().run(habbo.getHabboInfo()); habbo.getClient().sendResponse(new UpdateUserLookComposer(habbo)); room.sendComposer(new RoomUserDataComposer(habbo).compose()); @@ -134,7 +135,7 @@ public class InteractionFootballGate extends HabboItem { Emulator.getPluginManager().fireEvent(lookEvent); if (!lookEvent.isCancelled()) { habbo.getHabboStats().cache.put(CACHE_KEY, habbo.getHabboInfo().getLook()); - habbo.getHabboInfo().setLook(lookEvent.newLook); + habbo.getHabboInfo().setLook(ClothingValidationManager.VALIDATE_ON_FBALLGATE ? ClothingValidationManager.validateLook(habbo, lookEvent.newLook, lookEvent.gender.name()) : lookEvent.newLook); Emulator.getThreading().run(habbo.getHabboInfo()); habbo.getClient().sendResponse(new UpdateUserLookComposer(habbo)); room.sendComposer(new RoomUserDataComposer(habbo).compose()); diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/football/goals/InteractionFootballGoal.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/football/goals/InteractionFootballGoal.java index 7386b365..a3ef5202 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/football/goals/InteractionFootballGoal.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/football/goals/InteractionFootballGoal.java @@ -26,7 +26,7 @@ public class InteractionFootballGoal extends InteractionGameTeamItem { @Override public boolean isWalkable() { - return true; + return this.getBaseItem().allowWalk(); } @Override diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/interfaces/ConditionalGate.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/interfaces/ConditionalGate.java new file mode 100644 index 00000000..3f1b06cb --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/interfaces/ConditionalGate.java @@ -0,0 +1,8 @@ +package com.eu.habbo.habbohotel.items.interactions.interfaces; + +import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.rooms.RoomUnit; + +public interface ConditionalGate { + public void onRejected(RoomUnit roomUnit, Room room, Object[] objects); +} diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionDateRangeActive.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionDateRangeActive.java index 30ba25bd..d4b92964 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionDateRangeActive.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionDateRangeActive.java @@ -6,6 +6,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.wired.WiredConditionType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -64,18 +65,29 @@ public class WiredConditionDateRangeActive extends InteractionWiredCondition { @Override public String getWiredData() { - return this.startDate + "\t" + this.endDate; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.startDate, + this.endDate + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split("\t"); + String wiredData = set.getString("wired_data"); - if (data.length == 2) { - try { - this.startDate = Integer.valueOf(data[0]); - this.endDate = Integer.valueOf(data[1]); - } catch (Exception e) { + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.startDate = data.startDate; + this.endDate = data.endDate; + } else { + String[] data = wiredData.split("\t"); + + if (data.length == 2) { + try { + this.startDate = Integer.parseInt(data[0]); + this.endDate = Integer.parseInt(data[1]); + } catch (Exception e) { + } } } } @@ -85,4 +97,14 @@ public class WiredConditionDateRangeActive extends InteractionWiredCondition { this.startDate = 0; this.endDate = 0; } + + static class JsonData { + int startDate; + int endDate; + + public JsonData(int startDate, int endDate) { + this.startDate = startDate; + this.endDate = endDate; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveFurni.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveFurni.java index ba2b2bf7..ddce19a5 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveFurni.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveFurni.java @@ -4,6 +4,7 @@ import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition; import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.rooms.RoomTile; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.habbohotel.wired.WiredConditionType; @@ -14,6 +15,8 @@ import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.List; +import java.util.stream.Collectors; public class WiredConditionFurniHaveFurni extends InteractionWiredCondition { public static final WiredConditionType type = WiredConditionType.FURNI_HAS_FURNI; @@ -35,68 +38,65 @@ public class WiredConditionFurniHaveFurni extends InteractionWiredCondition { public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) { this.refresh(); - boolean foundSomething = false; - for (HabboItem item : this.items) { - boolean found = false; + if(this.items.isEmpty()) + return true; - THashSet stackedItems = room.getItemsAt(room.getLayout().getTile(item.getX(), item.getY())); - - if (stackedItems == null) - continue; - - if (stackedItems.isEmpty() && this.all) - return false; - - for (HabboItem i : stackedItems) { - if (i == item) - continue; - - if (i.getZ() >= item.getZ()) { - found = true; - foundSomething = true; - } - } - - if (this.all) { - if (!found) - return false; - } else { - if (found) - return true; - } + if(this.all) { + return this.items.stream().allMatch(item -> { + double minZ = item.getZ() + Item.getCurrentHeight(item); + THashSet occupiedTiles = room.getLayout().getTilesAt(room.getLayout().getTile(item.getX(), item.getY()), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation()); + return occupiedTiles.stream().anyMatch(tile -> room.getItemsAt(tile).stream().anyMatch(matchedItem -> matchedItem != item && matchedItem.getZ() >= minZ)); + }); + } + else { + return this.items.stream().anyMatch(item -> { + double minZ = item.getZ() + Item.getCurrentHeight(item); + THashSet occupiedTiles = room.getLayout().getTilesAt(room.getLayout().getTile(item.getX(), item.getY()), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation()); + return occupiedTiles.stream().anyMatch(tile -> room.getItemsAt(tile).stream().anyMatch(matchedItem -> matchedItem != item && matchedItem.getZ() >= minZ)); + }); } - - return this.items.isEmpty() || foundSomething; - } @Override public String getWiredData() { this.refresh(); - - StringBuilder data = new StringBuilder((this.all ? "1" : "0") + ":"); - - for (HabboItem item : this.items) - data.append(item.getId()).append(";"); - - return data.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.all, + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split(":"); + String wiredData = set.getString("wired_data"); - if (data.length >= 1) { - this.all = (data[0].equals("1")); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.all = data.all; - if (data.length == 2) { - String[] items = data[1].split(";"); + for(int id : data.itemIds) { + HabboItem item = room.getHabboItem(id); - for (String s : items) { - HabboItem item = room.getHabboItem(Integer.valueOf(s)); + if (item != null) { + this.items.add(item); + } + } - if (item != null) - this.items.add(item); + } else { + String[] data = wiredData.split(":"); + + if (data.length >= 1) { + this.all = (data[0].equals("1")); + + if (data.length == 2) { + String[] items = data[1].split(";"); + + for (String s : items) { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item != null) + this.items.add(item); + } } } } @@ -137,8 +137,6 @@ public class WiredConditionFurniHaveFurni extends InteractionWiredCondition { @Override public boolean saveData(ClientMessage packet) { - this.items.clear(); - int count; packet.readInt(); @@ -147,6 +145,9 @@ public class WiredConditionFurniHaveFurni extends InteractionWiredCondition { packet.readString(); count = packet.readInt(); + if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false; + + this.items.clear(); Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); @@ -180,4 +181,14 @@ public class WiredConditionFurniHaveFurni extends InteractionWiredCondition { this.items.remove(item); } } + + static class JsonData { + boolean all; + List itemIds; + + public JsonData(boolean all, List itemIds) { + this.all = all; + this.itemIds = itemIds; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveHabbo.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveHabbo.java index 304eded6..a0d07087 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveHabbo.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveHabbo.java @@ -14,13 +14,13 @@ import com.eu.habbo.habbohotel.wired.WiredConditionType; import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; -import gnu.trove.map.hash.THashMap; import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collection; -import java.util.Map; +import java.util.List; +import java.util.stream.Collectors; public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition { public static final WiredConditionType type = WiredConditionType.FURNI_HAVE_HABBO; @@ -51,75 +51,58 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition { if (this.items.isEmpty()) return true; - THashMap> tiles = new THashMap<>(); - for (HabboItem item : this.items) { - tiles.put(item, room.getLayout().getTilesAt(room.getLayout().getTile(item.getX(), item.getY()), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation())); - } - Collection habbos = room.getHabbos(); Collection bots = room.getCurrentBots().valueCollection(); Collection pets = room.getCurrentPets().valueCollection(); - for (Map.Entry> set : tiles.entrySet()) { - boolean found = false; - for (Habbo habbo : habbos) { - if (set.getValue().contains(habbo.getRoomUnit().getCurrentLocation())) { - found = true; - } - } - - if (!found) { - for (Bot bot : bots) { - if (set.getValue().contains(bot.getRoomUnit().getCurrentLocation())) { - found = true; - } - } - } - - if (!found) { - for (Pet pet : pets) { - if (set.getValue().contains(pet.getRoomUnit().getCurrentLocation())) { - found = true; - } - } - } - - if (!found) return false; - } - - return true; + return this.items.stream().allMatch(item -> { + THashSet occupiedTiles = room.getLayout().getTilesAt(room.getLayout().getTile(item.getX(), item.getY()), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation()); + return habbos.stream().anyMatch(character -> occupiedTiles.contains(character.getRoomUnit().getCurrentLocation())) || + bots.stream().anyMatch(character -> occupiedTiles.contains(character.getRoomUnit().getCurrentLocation())) || + pets.stream().anyMatch(character -> occupiedTiles.contains(character.getRoomUnit().getCurrentLocation())); + }); } @Override public String getWiredData() { this.refresh(); - - StringBuilder data = new StringBuilder((this.all ? "1" : "0") + ":"); - - for (HabboItem item : this.items) { - data.append(item.getId()).append(";"); - } - - return data.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.all, + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items.clear(); + String wiredData = set.getString("wired_data"); - String[] data = set.getString("wired_data").split(":"); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.all = data.all; - if (data.length >= 1) { - this.all = (data[0].equals("1")); + for(int id : data.itemIds) { + HabboItem item = room.getHabboItem(id); - if (data.length == 2) { - String[] items = data[1].split(";"); + if (item != null) { + this.items.add(item); + } + } + } else { + String[] data = wiredData.split(":"); - for (String s : items) { - HabboItem item = room.getHabboItem(Integer.valueOf(s)); + if (data.length >= 1) { + this.all = (data[0].equals("1")); - if (item != null) - this.items.add(item); + if (data.length == 2) { + String[] items = data[1].split(";"); + + for (String s : items) { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item != null) + this.items.add(item); + } } } } @@ -154,14 +137,15 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition { @Override public boolean saveData(ClientMessage packet) { - this.items.clear(); - int count; packet.readInt(); packet.readString(); count = packet.readInt(); + if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false; + + this.items.clear(); Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); @@ -196,4 +180,14 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition { this.items.remove(item); } } + + static class JsonData { + boolean all; + List itemIds; + + public JsonData(boolean all, List itemIds) { + this.all = all; + this.itemIds = itemIds; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniTypeMatch.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniTypeMatch.java index 06e3cbaa..47c42d64 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniTypeMatch.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniTypeMatch.java @@ -14,6 +14,8 @@ import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.List; +import java.util.stream.Collectors; public class WiredConditionFurniTypeMatch extends InteractionWiredCondition { public static final WiredConditionType type = WiredConditionType.STUFF_IS; @@ -37,43 +39,55 @@ public class WiredConditionFurniTypeMatch extends InteractionWiredCondition { public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) { this.refresh(); + if(items.isEmpty()) + return false; + if (stuff != null) { if (stuff.length >= 1) { if (stuff[0] instanceof HabboItem) { - HabboItem item = (HabboItem) stuff[0]; - - for (HabboItem i : this.items) { - if (i.getBaseItem().getId() == item.getBaseItem().getId()) - return true; - } - - return false; + HabboItem triggeringItem = (HabboItem)stuff[0]; + return this.items.stream().anyMatch(item -> item == triggeringItem); } } } - return true; + + return false; } @Override public String getWiredData() { this.refresh(); - - StringBuilder data = new StringBuilder(); - - for (HabboItem item : this.items) - data.append(item.getId()).append(";"); - - return data.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items.clear(); + String wiredData = set.getString("wired_data"); - String[] data = set.getString("wired_data").split(";"); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); - for (String s : data) - this.items.add(room.getHabboItem(Integer.valueOf(s))); + for(int id : data.itemIds) { + HabboItem item = room.getHabboItem(id); + + if (item != null) { + this.items.add(item); + } + } + } else { + String[] data = wiredData.split(";"); + + for (String s : data) { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item != null) { + this.items.add(item); + } + } + } } @Override @@ -104,12 +118,13 @@ public class WiredConditionFurniTypeMatch extends InteractionWiredCondition { @Override public boolean saveData(ClientMessage packet) { - this.items.clear(); - packet.readInt(); packet.readString(); int count = packet.readInt(); + if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false; + + this.items.clear(); Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); @@ -139,4 +154,12 @@ public class WiredConditionFurniTypeMatch extends InteractionWiredCondition { this.items.remove(item); } } + + static class JsonData { + List itemIds; + + public JsonData(List itemIds) { + this.itemIds = itemIds; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboCount.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboCount.java index b131e517..d5e93e21 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboCount.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboCount.java @@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.wired.WiredConditionType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -34,15 +35,26 @@ public class WiredConditionHabboCount extends InteractionWiredCondition { @Override public String getWiredData() { - return this.lowerLimit + ":" + this.upperLimit; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.lowerLimit, + this.upperLimit + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split(":"); + String wiredData = set.getString("wired_data"); - this.lowerLimit = Integer.valueOf(data[0]); - this.upperLimit = Integer.valueOf(data[1]); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.lowerLimit = data.lowerLimit; + this.upperLimit = data.upperLimit; + } else { + String[] data = wiredData.split(":"); + + this.lowerLimit = Integer.parseInt(data[0]); + this.upperLimit = Integer.parseInt(data[1]); + } } @Override @@ -82,4 +94,14 @@ public class WiredConditionHabboCount extends InteractionWiredCondition { return true; } + + static class JsonData { + int lowerLimit; + int upperLimit; + + public JsonData(int lowerLimit, int upperLimit) { + this.lowerLimit = lowerLimit; + this.upperLimit = upperLimit; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboHasEffect.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboHasEffect.java index fdde8793..7e1580f0 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboHasEffect.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboHasEffect.java @@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.wired.WiredConditionType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -32,12 +33,21 @@ public class WiredConditionHabboHasEffect extends InteractionWiredCondition { @Override public String getWiredData() { - return this.effectId + ""; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.effectId + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - this.effectId = Integer.valueOf(set.getString("wired_data")); + String wiredData = set.getString("wired_data"); + + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.effectId = data.effectId; + } else { + this.effectId = Integer.parseInt(wiredData); + } } @Override @@ -73,4 +83,12 @@ public class WiredConditionHabboHasEffect extends InteractionWiredCondition { return true; } + + static class JsonData { + int effectId; + + public JsonData(int effectId) { + this.effectId = effectId; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboHasHandItem.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboHasHandItem.java index e47107c3..0d351e98 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboHasHandItem.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboHasHandItem.java @@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.wired.WiredConditionType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; import org.slf4j.Logger; @@ -66,13 +67,22 @@ public class WiredConditionHabboHasHandItem extends InteractionWiredCondition { @Override public String getWiredData() { - return this.handItem + ""; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.handItem + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { try { - this.handItem = Integer.valueOf(set.getString("wired_data")); + String wiredData = set.getString("wired_data"); + + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.handItem = data.handItemId; + } else { + this.handItem = Integer.parseInt(wiredData); + } } catch (Exception e) { LOGGER.error("Caught exception", e); } @@ -82,4 +92,12 @@ public class WiredConditionHabboHasHandItem extends InteractionWiredCondition { public void onPickUp() { this.handItem = 0; } + + static class JsonData { + int handItemId; + + public JsonData(int handItemId) { + this.handItemId = handItemId; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboWearsBadge.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboWearsBadge.java index d2ddf27c..b4f0df9f 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboWearsBadge.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboWearsBadge.java @@ -7,6 +7,7 @@ import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboBadge; import com.eu.habbo.habbohotel.wired.WiredConditionType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -44,12 +45,21 @@ public class WiredConditionHabboWearsBadge extends InteractionWiredCondition { @Override public String getWiredData() { - return this.badge; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.badge + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - this.badge = set.getString("wired_data"); + String wiredData = set.getString("wired_data"); + + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.badge = data.badge; + } else { + this.badge = wiredData; + } } @Override @@ -85,4 +95,12 @@ public class WiredConditionHabboWearsBadge extends InteractionWiredCondition { return true; } + + static class JsonData { + String badge; + + public JsonData(String badge) { + this.badge = badge; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionLessTimeElapsed.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionLessTimeElapsed.java index 95e907ed..b40ee5e7 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionLessTimeElapsed.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionLessTimeElapsed.java @@ -6,6 +6,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.wired.WiredConditionType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -32,16 +33,23 @@ public class WiredConditionLessTimeElapsed extends InteractionWiredCondition { @Override public String getWiredData() { - return this.cycles + ""; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.cycles + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String data = set.getString("wired_data"); + String wiredData = set.getString("wired_data"); try { - if (!data.equals("")) - this.cycles = Integer.valueOf(data); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.cycles = data.cycles; + } else { + if (!wiredData.equals("")) + this.cycles = Integer.parseInt(wiredData); + } } catch (Exception e) { } } @@ -80,4 +88,12 @@ public class WiredConditionLessTimeElapsed extends InteractionWiredCondition { return true; } + + static class JsonData { + int cycles; + + public JsonData(int cycles) { + this.cycles = cycles; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionMatchStatePosition.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionMatchStatePosition.java index 73371bab..76ece81c 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionMatchStatePosition.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionMatchStatePosition.java @@ -3,6 +3,7 @@ package com.eu.habbo.habbohotel.items.interactions.wired.conditions; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition; +import com.eu.habbo.habbohotel.items.interactions.wired.interfaces.InteractionWiredMatchFurniSettings; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.HabboItem; @@ -15,8 +16,10 @@ import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; -public class WiredConditionMatchStatePosition extends InteractionWiredCondition { +public class WiredConditionMatchStatePosition extends InteractionWiredCondition implements InteractionWiredMatchFurniSettings { public static final WiredConditionType type = WiredConditionType.MATCH_SSHOT; private THashSet settings; @@ -49,7 +52,7 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition message.appendInt(this.settings.size()); for (WiredMatchFurniSetting item : this.settings) - message.appendInt(item.itemId); + message.appendInt(item.item_id); message.appendInt(this.getBaseItem().getSpriteId()); message.appendInt(this.getId()); @@ -67,8 +70,6 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition @Override public boolean saveData(ClientMessage packet) { - this.settings.clear(); - int count; packet.readInt(); @@ -84,6 +85,9 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition return true; count = packet.readInt(); + if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false; + + this.settings.clear(); for (int i = 0; i < count; i++) { int itemId = packet.readInt(); @@ -104,7 +108,7 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition THashSet s = new THashSet<>(); for (WiredMatchFurniSetting setting : this.settings) { - HabboItem item = room.getHabboItem(setting.itemId); + HabboItem item = room.getHabboItem(setting.item_id); if (item != null) { if (this.state) { @@ -137,38 +141,42 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition @Override public String getWiredData() { - StringBuilder data = new StringBuilder(this.settings.size() + ":"); - - if (this.settings.isEmpty()) { - data.append("\t;"); - } else { - for (WiredMatchFurniSetting item : this.settings) - data.append(item.toString()).append(";"); - } - - data.append(":").append(this.state ? 1 : 0).append(":").append(this.direction ? 1 : 0).append(":").append(this.position ? 1 : 0); - - return data.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.state, + this.position, + this.direction, + new ArrayList<>(this.settings) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split(":"); + String wiredData = set.getString("wired_data"); - int itemCount = Integer.valueOf(data[0]); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.state = data.state; + this.position = data.position; + this.direction = data.direction; + this.settings.addAll(data.settings); + } else { + String[] data = wiredData.split(":"); - String[] items = data[1].split(";"); + int itemCount = Integer.parseInt(data[0]); - for (int i = 0; i < itemCount; i++) { - String[] stuff = items[i].split("-"); + String[] items = data[1].split(";"); - if (stuff.length >= 5) - this.settings.add(new WiredMatchFurniSetting(Integer.valueOf(stuff[0]), stuff[1], Integer.valueOf(stuff[2]), Integer.valueOf(stuff[3]), Integer.valueOf(stuff[4]))); + for (int i = 0; i < itemCount; i++) { + String[] stuff = items[i].split("-"); + + if (stuff.length >= 5) + this.settings.add(new WiredMatchFurniSetting(Integer.parseInt(stuff[0]), stuff[1], Integer.parseInt(stuff[2]), Integer.parseInt(stuff[3]), Integer.parseInt(stuff[4]))); + } + + this.state = data[2].equals("1"); + this.direction = data[3].equals("1"); + this.position = data[4].equals("1"); } - - this.state = data[2].equals("1"); - this.direction = data[3].equals("1"); - this.position = data[4].equals("1"); } @Override @@ -186,7 +194,7 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition THashSet remove = new THashSet<>(); for (WiredMatchFurniSetting setting : this.settings) { - HabboItem item = room.getHabboItem(setting.itemId); + HabboItem item = room.getHabboItem(setting.item_id); if (item == null) { remove.add(setting); } @@ -197,4 +205,38 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition } } } + + @Override + public THashSet getMatchFurniSettings() { + return this.settings; + } + + @Override + public boolean shouldMatchState() { + return this.state; + } + + @Override + public boolean shouldMatchRotation() { + return this.direction; + } + + @Override + public boolean shouldMatchPosition() { + return this.position; + } + + static class JsonData { + boolean state; + boolean position; + boolean direction; + List settings; + + public JsonData(boolean state, boolean position, boolean direction, List settings) { + this.state = state; + this.position = position; + this.direction = direction; + this.settings = settings; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionMoreTimeElapsed.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionMoreTimeElapsed.java index a1fa3c5c..0be6ba15 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionMoreTimeElapsed.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionMoreTimeElapsed.java @@ -6,6 +6,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.wired.WiredConditionType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -32,16 +33,23 @@ public class WiredConditionMoreTimeElapsed extends InteractionWiredCondition { @Override public String getWiredData() { - return this.cycles + ""; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.cycles + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String data = set.getString("wired_data"); + String wiredData = set.getString("wired_data"); try { - if (!data.equals("")) - this.cycles = Integer.valueOf(data); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.cycles = data.cycles; + } else { + if (!wiredData.equals("")) + this.cycles = Integer.parseInt(wiredData); + } } catch (Exception e) { } } @@ -80,4 +88,12 @@ public class WiredConditionMoreTimeElapsed extends InteractionWiredCondition { return true; } + + static class JsonData { + int cycles; + + public JsonData(int cycles) { + this.cycles = cycles; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveFurni.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveFurni.java index c64fb8b5..279f61bd 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveFurni.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveFurni.java @@ -4,6 +4,7 @@ import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition; import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.rooms.RoomTile; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.habbohotel.wired.WiredConditionOperator; @@ -15,6 +16,8 @@ import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.List; +import java.util.stream.Collectors; public class WiredConditionNotFurniHaveFurni extends InteractionWiredCondition { public static final WiredConditionType type = WiredConditionType.NOT_FURNI_HAVE_FURNI; @@ -39,50 +42,62 @@ public class WiredConditionNotFurniHaveFurni extends InteractionWiredCondition { if (this.items.isEmpty()) return true; - for (HabboItem item : this.items) { - THashSet things = room.getItemsAt(item.getX(), item.getY(), item.getZ() + Item.getCurrentHeight(item)); - things.removeAll(this.items); - if (!things.isEmpty()) { - if (this.all) - return false; - else - continue; - } - return true; + if(this.all) { + return this.items.stream().allMatch(item -> { + double minZ = item.getZ() + Item.getCurrentHeight(item); + THashSet occupiedTiles = room.getLayout().getTilesAt(room.getLayout().getTile(item.getX(), item.getY()), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation()); + return occupiedTiles.stream().noneMatch(tile -> room.getItemsAt(tile).stream().anyMatch(matchedItem -> matchedItem != item && matchedItem.getZ() >= minZ)); + }); + } + else { + return this.items.stream().anyMatch(item -> { + double minZ = item.getZ() + Item.getCurrentHeight(item); + THashSet occupiedTiles = room.getLayout().getTilesAt(room.getLayout().getTile(item.getX(), item.getY()), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation()); + return occupiedTiles.stream().noneMatch(tile -> room.getItemsAt(tile).stream().anyMatch(matchedItem -> matchedItem != item && matchedItem.getZ() >= minZ)); + }); } - - return false; } @Override public String getWiredData() { this.refresh(); - - StringBuilder data = new StringBuilder((this.all ? "1" : "0") + ":"); - - for (HabboItem item : this.items) - data.append(item.getId()).append(";"); - - return data.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.all, + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items.clear(); + String wiredData = set.getString("wired_data"); - String[] data = set.getString("wired_data").split(":"); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.all = data.all; - if (data.length >= 1) { - this.all = (data[0].equals("1")); + for (int id : data.itemIds) { + HabboItem item = room.getHabboItem(id); - if (data.length == 2) { - String[] items = data[1].split(";"); + if (item != null) { + this.items.add(item); + } + } + } else { + String[] data = wiredData.split(":"); - for (String s : items) { - HabboItem item = room.getHabboItem(Integer.valueOf(s)); + if (data.length >= 1) { + this.all = (data[0].equals("1")); - if (item != null) - this.items.add(item); + if (data.length == 2) { + String[] items = data[1].split(";"); + + for (String s : items) { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item != null) + this.items.add(item); + } } } } @@ -123,16 +138,16 @@ public class WiredConditionNotFurniHaveFurni extends InteractionWiredCondition { @Override public boolean saveData(ClientMessage packet) { - this.items.clear(); - - int count; packet.readInt(); this.all = packet.readInt() == 1; packet.readString(); - count = packet.readInt(); + int count = packet.readInt(); + if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false; + + this.items.clear(); Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); @@ -169,6 +184,18 @@ public class WiredConditionNotFurniHaveFurni extends InteractionWiredCondition { @Override public WiredConditionOperator operator() { - return this.all ? WiredConditionOperator.AND : WiredConditionOperator.OR; + // NICE TRY BUT THAT'S NOT HOW IT WORKS. NOTHING IN HABBO IS AN "OR" CONDITION - EVERY CONDITION MUST BE SUCCESS FOR THE STACK TO EXECUTE, BUT LET'S LEAVE IT IMPLEMENTED FOR PLUGINS TO USE. + //return this.all ? WiredConditionOperator.AND : WiredConditionOperator.OR; + return WiredConditionOperator.AND; + } + + static class JsonData { + boolean all; + List itemIds; + + public JsonData(boolean all, List itemIds) { + this.all = all; + this.itemIds = itemIds; + } } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveHabbo.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveHabbo.java index ef61c69c..87f3bc9a 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveHabbo.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveHabbo.java @@ -14,13 +14,13 @@ import com.eu.habbo.habbohotel.wired.WiredConditionType; import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; -import gnu.trove.map.hash.THashMap; import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collection; -import java.util.Map; +import java.util.List; +import java.util.stream.Collectors; public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition { public static final WiredConditionType type = WiredConditionType.NOT_FURNI_HAVE_HABBO; @@ -51,75 +51,58 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition { if (this.items.isEmpty()) return true; - THashMap> tiles = new THashMap<>(); - for (HabboItem item : this.items) { - tiles.put(item, room.getLayout().getTilesAt(room.getLayout().getTile(item.getX(), item.getY()), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation())); - } - Collection habbos = room.getHabbos(); Collection bots = room.getCurrentBots().valueCollection(); Collection pets = room.getCurrentPets().valueCollection(); - for (Map.Entry> set : tiles.entrySet()) { - if (!habbos.isEmpty()) { - for (Habbo habbo : habbos) { - if (set.getValue().contains(habbo.getRoomUnit().getCurrentLocation())) { - return false; - } - } - } - - if (!bots.isEmpty()) { - for (Bot bot : bots) { - if (set.getValue().contains(bot.getRoomUnit().getCurrentLocation())) { - return false; - } - } - } - - if (!pets.isEmpty()) { - for (Pet pet : pets) { - if (set.getValue().contains(pet.getRoomUnit().getCurrentLocation())) { - return false; - } - } - } - - } - - return true; + return this.items.stream().noneMatch(item -> { + THashSet occupiedTiles = room.getLayout().getTilesAt(room.getLayout().getTile(item.getX(), item.getY()), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation()); + return habbos.stream().anyMatch(character -> occupiedTiles.contains(character.getRoomUnit().getCurrentLocation())) || + bots.stream().anyMatch(character -> occupiedTiles.contains(character.getRoomUnit().getCurrentLocation())) || + pets.stream().anyMatch(character -> occupiedTiles.contains(character.getRoomUnit().getCurrentLocation())); + }); } @Override public String getWiredData() { this.refresh(); - - StringBuilder data = new StringBuilder((this.all ? "1" : "0") + ":"); - - for (HabboItem item : this.items) { - data.append(item.getId()).append(";"); - } - - return data.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.all, + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items.clear(); + String wiredData = set.getString("wired_data"); - String[] data = set.getString("wired_data").split(":"); + if (wiredData.startsWith("{")) { + WiredConditionFurniHaveHabbo.JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, WiredConditionFurniHaveHabbo.JsonData.class); + this.all = data.all; - if (data.length >= 1) { - this.all = (data[0].equals("1")); + for(int id : data.itemIds) { + HabboItem item = room.getHabboItem(id); - if (data.length == 2) { - String[] items = data[1].split(";"); + if (item != null) { + this.items.add(item); + } + } + } else { + String[] data = wiredData.split(":"); - for (String s : items) { - HabboItem item = room.getHabboItem(Integer.valueOf(s)); + if (data.length >= 1) { + this.all = (data[0].equals("1")); - if (item != null) - this.items.add(item); + if (data.length == 2) { + String[] items = data[1].split(";"); + + for (String s : items) { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item != null) + this.items.add(item); + } } } } @@ -154,14 +137,14 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition { @Override public boolean saveData(ClientMessage packet) { - this.items.clear(); - - int count; packet.readInt(); packet.readString(); - count = packet.readInt(); + int count = packet.readInt(); + if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false; + + this.items.clear(); Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); @@ -196,4 +179,14 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition { this.items.remove(item); } } + + static class JsonData { + boolean all; + List itemIds; + + public JsonData(boolean all, List itemIds) { + this.all = all; + this.itemIds = itemIds; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniTypeMatch.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniTypeMatch.java index 95b5d8e3..30c9ea51 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniTypeMatch.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniTypeMatch.java @@ -14,6 +14,8 @@ import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.List; +import java.util.stream.Collectors; public class WiredConditionNotFurniTypeMatch extends InteractionWiredCondition { public static final WiredConditionType type = WiredConditionType.NOT_STUFF_IS; @@ -32,15 +34,14 @@ public class WiredConditionNotFurniTypeMatch extends InteractionWiredCondition { public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) { this.refresh(); + if(items.isEmpty()) + return true; + if (stuff != null) { if (stuff.length >= 1) { if (stuff[0] instanceof HabboItem) { - HabboItem item = (HabboItem) stuff[0]; - - for (HabboItem i : this.items) { - if (i.getBaseItem().getId() == item.getBaseItem().getId()) - return false; - } + HabboItem triggeringItem = (HabboItem)stuff[0]; + return this.items.stream().noneMatch(item -> item == triggeringItem); } } } @@ -51,23 +52,37 @@ public class WiredConditionNotFurniTypeMatch extends InteractionWiredCondition { @Override public String getWiredData() { this.refresh(); - - StringBuilder data = new StringBuilder(); - - for (HabboItem item : this.items) - data.append(item.getId()).append(";"); - - return data.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items.clear(); + String wiredData = set.getString("wired_data"); - String[] data = set.getString("wired_data").split(";"); + if (wiredData.startsWith("{")) { + WiredConditionFurniTypeMatch.JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, WiredConditionFurniTypeMatch.JsonData.class); - for (String s : data) - this.items.add(room.getHabboItem(Integer.valueOf(s))); + for(int id : data.itemIds) { + HabboItem item = room.getHabboItem(id); + + if (item != null) { + this.items.add(item); + } + } + } else { + String[] data = set.getString("wired_data").split(";"); + + for (String s : data) { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item != null) { + this.items.add(item); + } + } + } } @Override @@ -103,12 +118,13 @@ public class WiredConditionNotFurniTypeMatch extends InteractionWiredCondition { @Override public boolean saveData(ClientMessage packet) { - this.items.clear(); - packet.readInt(); packet.readString(); int count = packet.readInt(); + if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false; + + this.items.clear(); Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); @@ -138,4 +154,12 @@ public class WiredConditionNotFurniTypeMatch extends InteractionWiredCondition { this.items.remove(item); } } + + static class JsonData { + List itemIds; + + public JsonData(List itemIds) { + this.itemIds = itemIds; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboCount.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboCount.java index 194d47c1..3075c4ff 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboCount.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboCount.java @@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.wired.WiredConditionType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -34,14 +35,25 @@ public class WiredConditionNotHabboCount extends InteractionWiredCondition { @Override public String getWiredData() { - return this.lowerLimit + ":" + this.upperLimit; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.lowerLimit, + this.upperLimit + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split(":"); - this.lowerLimit = Integer.valueOf(data[0]); - this.upperLimit = Integer.valueOf(data[1]); + String wiredData = set.getString("wired_data"); + + if (wiredData.startsWith("{")) { + WiredConditionHabboCount.JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, WiredConditionHabboCount.JsonData.class); + this.lowerLimit = data.lowerLimit; + this.upperLimit = data.upperLimit; + } else { + String[] data = wiredData.split(":"); + this.lowerLimit = Integer.parseInt(data[0]); + this.upperLimit = Integer.parseInt(data[1]); + } } @Override @@ -81,4 +93,14 @@ public class WiredConditionNotHabboCount extends InteractionWiredCondition { return true; } + + static class JsonData { + int lowerLimit; + int upperLimit; + + public JsonData(int lowerLimit, int upperLimit) { + this.lowerLimit = lowerLimit; + this.upperLimit = upperLimit; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboHasEffect.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboHasEffect.java index 0994a2a3..ae1c20bb 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboHasEffect.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboHasEffect.java @@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.wired.WiredConditionType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -32,12 +33,21 @@ public class WiredConditionNotHabboHasEffect extends InteractionWiredCondition { @Override public String getWiredData() { - return this.effectId + ""; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.effectId + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - this.effectId = Integer.valueOf(set.getString("wired_data")); + String wiredData = set.getString("wired_data"); + + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.effectId = data.effectId; + } else { + this.effectId = Integer.parseInt(wiredData); + } } @Override @@ -73,4 +83,12 @@ public class WiredConditionNotHabboHasEffect extends InteractionWiredCondition { return true; } + + static class JsonData { + int effectId; + + public JsonData(int effectId) { + this.effectId = effectId; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboWearsBadge.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboWearsBadge.java index 3a30238f..6df96d6b 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboWearsBadge.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboWearsBadge.java @@ -7,6 +7,7 @@ import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboBadge; import com.eu.habbo.habbohotel.wired.WiredConditionType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -45,12 +46,21 @@ public class WiredConditionNotHabboWearsBadge extends InteractionWiredCondition @Override public String getWiredData() { - return this.badge; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.badge + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - this.badge = set.getString("wired_data"); + String wiredData = set.getString("wired_data"); + + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.badge = data.badge; + } else { + this.badge = wiredData; + } } @Override @@ -86,4 +96,12 @@ public class WiredConditionNotHabboWearsBadge extends InteractionWiredCondition return true; } + + static class JsonData { + String badge; + + public JsonData(String badge) { + this.badge = badge; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotInTeam.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotInTeam.java index fba63af0..b805c7b1 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotInTeam.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotInTeam.java @@ -7,6 +7,7 @@ import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.wired.WiredConditionType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -31,27 +32,31 @@ public class WiredConditionNotInTeam extends InteractionWiredCondition { Habbo habbo = room.getHabbo(roomUnit); if (habbo != null) { - if (habbo.getHabboInfo().getGamePlayer() != null) { - return !habbo.getHabboInfo().getGamePlayer().getTeamColor().equals(this.teamColor); - } - return true; // user is not part of any team + return habbo.getHabboInfo().getGamePlayer() == null || !habbo.getHabboInfo().getGamePlayer().getTeamColor().equals(this.teamColor); // user is not part of any team } - return false; + return true; } @Override public String getWiredData() { - return this.teamColor.type + ""; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.teamColor + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String data = set.getString("wired_data"); - try { - if (!data.equals("")) - this.teamColor = GameTeamColors.values()[Integer.valueOf(data)]; + String wiredData = set.getString("wired_data"); + + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.teamColor = data.teamColor; + } else { + if (!wiredData.equals("")) + this.teamColor = GameTeamColors.values()[Integer.parseInt(wiredData)]; + } } catch (Exception e) { this.teamColor = GameTeamColors.RED; } @@ -91,4 +96,12 @@ public class WiredConditionNotInTeam extends InteractionWiredCondition { return true; } + + static class JsonData { + GameTeamColors teamColor; + + public JsonData(GameTeamColors teamColor) { + this.teamColor = teamColor; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotMatchStatePosition.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotMatchStatePosition.java index 2f0dc9d4..bc29186d 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotMatchStatePosition.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotMatchStatePosition.java @@ -1,192 +1,32 @@ package com.eu.habbo.habbohotel.items.interactions.wired.conditions; -import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.items.Item; -import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition; +import com.eu.habbo.habbohotel.items.interactions.wired.interfaces.InteractionWiredMatchFurniSettings; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; -import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.habbohotel.wired.WiredConditionType; -import com.eu.habbo.habbohotel.wired.WiredHandler; -import com.eu.habbo.habbohotel.wired.WiredMatchFurniSetting; -import com.eu.habbo.messages.ClientMessage; -import com.eu.habbo.messages.ServerMessage; -import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; -public class WiredConditionNotMatchStatePosition extends InteractionWiredCondition { +public class WiredConditionNotMatchStatePosition extends WiredConditionMatchStatePosition { public static final WiredConditionType type = WiredConditionType.NOT_MATCH_SSHOT; - private THashSet settings; - - private boolean state; - private boolean position; - private boolean rotation; - public WiredConditionNotMatchStatePosition(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); - this.settings = new THashSet<>(); } public WiredConditionNotMatchStatePosition(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) { super(id, userId, item, extradata, limitedStack, limitedSells); - this.settings = new THashSet<>(); } @Override public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) { - if (this.settings.isEmpty()) - return true; - - THashSet s = new THashSet<>(); - - for (WiredMatchFurniSetting setting : this.settings) { - HabboItem item = room.getHabboItem(setting.itemId); - - if (item != null) { - boolean stateMatches = !this.state || item.getExtradata().equals(setting.state); - boolean positionMatches = !this.position || (setting.x == item.getX() && setting.y == item.getY()); - boolean directionMatches = !this.rotation || setting.rotation == item.getRotation(); - - if (stateMatches && positionMatches && directionMatches) - return false; - } else { - s.add(setting); - } - } - - if (!s.isEmpty()) { - for (WiredMatchFurniSetting setting : s) { - this.settings.remove(setting); - } - } - - return true; - } - - @Override - public String getWiredData() { - StringBuilder data = new StringBuilder(this.settings.size() + ":"); - - if (this.settings.isEmpty()) { - data.append("\t;"); - } else { - for (WiredMatchFurniSetting item : this.settings) - data.append(item.toString()).append(";"); - } - - data.append(":").append(this.state ? 1 : 0).append(":").append(this.rotation ? 1 : 0).append(":").append(this.position ? 1 : 0); - - return data.toString(); - } - - @Override - public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split(":"); - - int itemCount = Integer.valueOf(data[0]); - - String[] items = data[1].split(";"); - - for (int i = 0; i < itemCount; i++) { - String[] stuff = items[i].split("-"); - - if (stuff.length >= 5) - this.settings.add(new WiredMatchFurniSetting(Integer.valueOf(stuff[0]), stuff[1], Integer.valueOf(stuff[2]), Integer.valueOf(stuff[3]), Integer.valueOf(stuff[4]))); - } - - this.state = data[2].equals("1"); - this.rotation = data[3].equals("1"); - this.position = data[4].equals("1"); - } - - @Override - public void onPickUp() { - this.settings.clear(); - this.state = false; - this.rotation = false; - this.position = false; + return !super.execute(roomUnit, room, stuff); } @Override public WiredConditionType getType() { return type; } - - @Override - public void serializeWiredData(ServerMessage message, Room room) { - this.refresh(); - - message.appendBoolean(false); - message.appendInt(WiredHandler.MAXIMUM_FURNI_SELECTION); - message.appendInt(this.settings.size()); - - for (WiredMatchFurniSetting item : this.settings) - message.appendInt(item.itemId); - - message.appendInt(this.getBaseItem().getSpriteId()); - message.appendInt(this.getId()); - message.appendString(""); - message.appendInt(4); - message.appendInt(this.state ? 1 : 0); - message.appendInt(this.rotation ? 1 : 0); - message.appendInt(this.position ? 1 : 0); - message.appendInt(10); - message.appendInt(0); - message.appendInt(this.getType().code); - message.appendInt(0); - message.appendInt(0); - } - - @Override - public boolean saveData(ClientMessage packet) { - this.settings.clear(); - - int count; - packet.readInt(); - - this.state = packet.readInt() == 1; - this.rotation = packet.readInt() == 1; - this.position = packet.readInt() == 1; - - packet.readString(); - - Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); - - if (room == null) - return true; - - count = packet.readInt(); - - for (int i = 0; i < count; i++) { - int itemId = packet.readInt(); - HabboItem item = room.getHabboItem(itemId); - - if (item != null) - this.settings.add(new WiredMatchFurniSetting(item.getId(), item.getExtradata(), item.getRotation(), item.getX(), item.getY())); - } - - return true; - } - - private void refresh() { - Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); - - if (room != null) { - THashSet remove = new THashSet<>(); - - for (WiredMatchFurniSetting setting : this.settings) { - HabboItem item = room.getHabboItem(setting.itemId); - if (item == null) { - remove.add(setting); - } - } - - for (WiredMatchFurniSetting setting : remove) { - this.settings.remove(setting); - } - } - } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotTriggerOnFurni.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotTriggerOnFurni.java index eb853f9c..21ea027e 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotTriggerOnFurni.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotTriggerOnFurni.java @@ -1,26 +1,16 @@ package com.eu.habbo.habbohotel.items.interactions.wired.conditions; -import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.items.Item; -import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition; import com.eu.habbo.habbohotel.rooms.Room; -import com.eu.habbo.habbohotel.rooms.RoomLayout; import com.eu.habbo.habbohotel.rooms.RoomUnit; -import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.habbohotel.wired.WiredConditionType; -import com.eu.habbo.habbohotel.wired.WiredHandler; -import com.eu.habbo.messages.ClientMessage; -import com.eu.habbo.messages.ServerMessage; -import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; -public class WiredConditionNotTriggerOnFurni extends InteractionWiredCondition { +public class WiredConditionNotTriggerOnFurni extends WiredConditionTriggerOnFurni { public static final WiredConditionType type = WiredConditionType.NOT_ACTOR_ON_FURNI; - private THashSet items = new THashSet<>(); - public WiredConditionNotTriggerOnFurni(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); } @@ -31,115 +21,19 @@ public class WiredConditionNotTriggerOnFurni extends InteractionWiredCondition { @Override public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) { - if (roomUnit == null) return false; + if (roomUnit == null) + return false; + this.refresh(); if (this.items.isEmpty()) return true; - for (HabboItem item : this.items) { - if (RoomLayout.getRectangle(item.getX(), item.getY(), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation()).contains(roomUnit.getX(), roomUnit.getY())) - return false; - } - - return true; - } - - @Override - public String getWiredData() { - this.refresh(); - - StringBuilder data = new StringBuilder(); - - for (HabboItem item : this.items) - data.append(item.getId()).append(";"); - - return data.toString(); - } - - @Override - public void loadWiredData(ResultSet set, Room room) throws SQLException { - this.items.clear(); - - String[] data = set.getString("wired_data").split(";"); - - for (String s : data) { - HabboItem item = room.getHabboItem(Integer.valueOf(s)); - - if (item != null) { - this.items.add(item); - } - } - } - - @Override - public void onPickUp() { - this.items.clear(); + return !triggerOnFurni(roomUnit, room); } @Override public WiredConditionType getType() { return type; } - - @Override - public void serializeWiredData(ServerMessage message, Room room) { - this.refresh(); - - message.appendBoolean(false); - message.appendInt(WiredHandler.MAXIMUM_FURNI_SELECTION); - message.appendInt(this.items.size()); - - for (HabboItem item : this.items) - message.appendInt(item.getId()); - - message.appendInt(this.getBaseItem().getSpriteId()); - message.appendInt(this.getId()); - message.appendString(""); - message.appendInt(0); - message.appendInt(0); - message.appendInt(this.getType().code); - message.appendInt(0); - message.appendInt(0); - } - - @Override - public boolean saveData(ClientMessage packet) { - this.items.clear(); - - packet.readInt(); - packet.readString(); - - int count = packet.readInt(); - - Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); - - if (room != null) { - for (int i = 0; i < count; i++) { - HabboItem item = room.getHabboItem(packet.readInt()); - - if (item != null) { - this.items.add(item); - } - } - } - - return true; - } - - private void refresh() { - THashSet items = new THashSet<>(); - - Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); - if (room == null) { - items.addAll(this.items); - } else { - for (HabboItem item : this.items) { - if (item.getRoomId() != room.getId()) - items.add(item); - } - } - - this.items.removeAll(items); - } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTeamMember.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTeamMember.java index 9349cbb2..027db810 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTeamMember.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTeamMember.java @@ -7,6 +7,7 @@ import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.wired.WiredConditionType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -41,16 +42,23 @@ public class WiredConditionTeamMember extends InteractionWiredCondition { @Override public String getWiredData() { - return this.teamColor.type + ""; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.teamColor + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String data = set.getString("wired_data"); - try { - if (!data.equals("")) - this.teamColor = GameTeamColors.values()[Integer.valueOf(data)]; + String wiredData = set.getString("wired_data"); + + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.teamColor = data.teamColor; + } else { + if (!wiredData.equals("")) + this.teamColor = GameTeamColors.values()[Integer.parseInt(wiredData)]; + } } catch (Exception e) { this.teamColor = GameTeamColors.RED; } @@ -90,4 +98,12 @@ public class WiredConditionTeamMember extends InteractionWiredCondition { return true; } + + static class JsonData { + GameTeamColors teamColor; + + public JsonData(GameTeamColors teamColor) { + this.teamColor = teamColor; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTriggerOnFurni.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTriggerOnFurni.java index 5cb27d1c..250d4751 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTriggerOnFurni.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTriggerOnFurni.java @@ -4,7 +4,7 @@ import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition; import com.eu.habbo.habbohotel.rooms.Room; -import com.eu.habbo.habbohotel.rooms.RoomLayout; +import com.eu.habbo.habbohotel.rooms.RoomTile; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.habbohotel.wired.WiredConditionOperator; @@ -16,11 +16,13 @@ import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.List; +import java.util.stream.Collectors; public class WiredConditionTriggerOnFurni extends InteractionWiredCondition { public static final WiredConditionType type = WiredConditionType.TRIGGER_ON_FURNI; - private THashSet items = new THashSet<>(); + protected THashSet items = new THashSet<>(); public WiredConditionTriggerOnFurni(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); @@ -32,45 +34,74 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition { @Override public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) { - if (roomUnit == null) return false; + if (roomUnit == null) + return false; this.refresh(); if (this.items.isEmpty()) - return true; + return false; - for (HabboItem item : this.items) { - if (RoomLayout.getRectangle(item.getX(), item.getY(), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation()).contains(roomUnit.getX(), roomUnit.getY())) - return true; + return triggerOnFurni(roomUnit, room); + } + + protected boolean triggerOnFurni(RoomUnit roomUnit, Room room) { + /* + * 1. If a Habbo IS NOT walking we only have to check if the Habbo is on one of the selected tiles. + * 2. If a Habbo IS walking we have to check if the next tile in the walking path is one of the selected items + * */ + if (!roomUnit.isWalking()) { + THashSet itemsAtUser = room.getItemsAt(roomUnit.getCurrentLocation()); + return this.items.stream().anyMatch(itemsAtUser::contains); + } else { + RoomTile firstTileInPath = room.getLayout() + .findPath(roomUnit.getCurrentLocation(), roomUnit.getGoal(), roomUnit.getGoal(), roomUnit) + .peek(); + + if (firstTileInPath == null) + return false; + + return this.items + .stream() + .anyMatch(conditionItem -> conditionItem + .getOccupyingTiles(room.getLayout()) + .contains(firstTileInPath) + ); } - - return false; } @Override public String getWiredData() { this.refresh(); - - StringBuilder data = new StringBuilder(); - - for (HabboItem item : this.items) { - data.append(item.getId()).append(";"); - } - - return data.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items.clear(); + String wiredData = set.getString("wired_data"); - String[] data = set.getString("wired_data").split(";"); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); - for (String s : data) { - HabboItem item = room.getHabboItem(Integer.valueOf(s)); + for(int id : data.itemIds) { + HabboItem item = room.getHabboItem(id); - if (item != null) { - this.items.add(item); + if (item != null) { + this.items.add(item); + } + } + } else { + String[] data = wiredData.split(";"); + + for (String s : data) { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item != null) { + this.items.add(item); + } } } } @@ -108,12 +139,13 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition { @Override public boolean saveData(ClientMessage packet) { - this.items.clear(); - packet.readInt(); packet.readString(); int count = packet.readInt(); + if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false; + + this.items.clear(); Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); @@ -130,7 +162,7 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition { return true; } - private void refresh() { + protected void refresh() { THashSet items = new THashSet<>(); Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); @@ -148,6 +180,14 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition { @Override public WiredConditionOperator operator() { - return WiredConditionOperator.OR; + return WiredConditionOperator.AND; + } + + static class JsonData { + List itemIds; + + public JsonData(List itemIds) { + this.itemIds = itemIds; + } } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotClothes.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotClothes.java index ec22bf63..f0a5b3f8 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotClothes.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotClothes.java @@ -1,5 +1,6 @@ package com.eu.habbo.habbohotel.items.interactions.wired.effects; +import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.bots.Bot; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.Item; @@ -7,12 +8,16 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.wired.WiredEffectType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; +import com.google.gson.Gson; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; +import java.util.regex.Pattern; public class WiredEffectBotClothes extends InteractionWiredEffect { public static final WiredEffectType type = WiredEffectType.BOT_CLOTHES; @@ -44,18 +49,27 @@ public class WiredEffectBotClothes extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); - - String[] data = packet.readString().split(((char) 9) + ""); - - if (data.length == 2) { - this.botName = data[0]; - this.botLook = data[1]; - } - + String dataString = packet.readString(); packet.readInt(); - this.setDelay(packet.readInt()); + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + String splitBy = "\t"; + if(!dataString.contains(splitBy)) + throw new WiredSaveException("Malformed data string"); + + String[] data = dataString.split(Pattern.quote(splitBy)); + + if (data.length != 2) + throw new WiredSaveException("Malformed data string. Invalid data length"); + + this.botName = data[0].substring(0, Math.min(data[0].length(), Emulator.getConfig().getInt("hotel.wired.message.max_length", 100))); + this.botLook = data[1]; + this.setDelay(delay); return true; } @@ -69,31 +83,39 @@ public class WiredEffectBotClothes extends InteractionWiredEffect { public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) { List bots = room.getBots(this.botName); - if (bots.size() != 1) { - return false; + if (bots.size() == 1) { + Bot bot = bots.get(0); + bot.setFigure(this.botLook); } - Bot bot = bots.get(0); - bot.setFigure(this.botLook); - return true; } @Override public String getWiredData() { - return this.getDelay() + "" + ((char) 9) + "" + - this.botName + ((char) 9) + - this.botLook; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.botName, this.botLook, this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split(((char) 9) + ""); + String wiredData = set.getString("wired_data"); - if (data.length >= 3) { - this.setDelay(Integer.valueOf(data[0])); - this.botName = data[1]; - this.botLook = data[2]; + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + this.botName = data.bot_name; + this.botLook = data.look; + } + else { + String[] data = wiredData.split(((char) 9) + ""); + + if (data.length >= 3) { + this.setDelay(Integer.valueOf(data[0])); + this.botName = data[1]; + this.botLook = data[2]; + } + + this.needsUpdate(true); } } @@ -119,4 +141,16 @@ public class WiredEffectBotClothes extends InteractionWiredEffect { public void setBotLook(String botLook) { this.botLook = botLook; } + + static class JsonData { + String bot_name; + String look; + int delay; + + public JsonData(String bot_name, String look, int delay) { + this.bot_name = bot_name; + this.look = look; + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotFollowHabbo.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotFollowHabbo.java index 928068af..ee1b28b1 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotFollowHabbo.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotFollowHabbo.java @@ -1,5 +1,6 @@ package com.eu.habbo.habbohotel.items.interactions.wired.effects; +import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.bots.Bot; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.Item; @@ -9,8 +10,10 @@ import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.wired.WiredEffectType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import gnu.trove.procedure.TObjectProcedure; import java.sql.ResultSet; @@ -67,13 +70,25 @@ public class WiredEffectBotFollowHabbo extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); + int mode = packet.readInt(); - this.mode = packet.readInt(); - this.botName = packet.readString().replace("\t", ""); + if(mode != 0 && mode != 1) + throw new WiredSaveException("Mode is invalid"); + + String botName = packet.readString().replace("\t", ""); + botName = botName.substring(0, Math.min(botName.length(), Emulator.getConfig().getInt("hotel.wired.message.max_length", 100))); packet.readInt(); - this.setDelay(packet.readInt()); + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.botName = botName; + this.mode = mode; + this.setDelay(delay); + return true; } @@ -105,17 +120,29 @@ public class WiredEffectBotFollowHabbo extends InteractionWiredEffect { @Override public String getWiredData() { - return this.getDelay() + "" + ((char) 9) + "" + this.mode + "" + ((char) 9) + this.botName; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.botName, this.mode, this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split(((char) 9) + ""); + String wiredData = set.getString("wired_data"); - if (data.length == 3) { - this.setDelay(Integer.valueOf(data[0])); - this.mode = (data[1].equalsIgnoreCase("1") ? 1 : 0); - this.botName = data[2]; + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + this.mode = data.mode; + this.botName = data.bot_name; + } + else { + String[] data = wiredData.split(((char) 9) + ""); + + if (data.length == 3) { + this.setDelay(Integer.valueOf(data[0])); + this.mode = (data[1].equalsIgnoreCase("1") ? 1 : 0); + this.botName = data[2]; + } + + this.needsUpdate(true); } } @@ -130,4 +157,16 @@ public class WiredEffectBotFollowHabbo extends InteractionWiredEffect { public boolean requiresTriggeringUser() { return true; } + + static class JsonData { + String bot_name; + int mode; + int delay; + + public JsonData(String bot_name, int mode, int delay) { + this.bot_name = bot_name; + this.mode = mode; + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotGiveHandItem.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotGiveHandItem.java index 94173cdd..27fc7888 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotGiveHandItem.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotGiveHandItem.java @@ -7,13 +7,17 @@ import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger; import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.rooms.RoomTile; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; 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.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import com.eu.habbo.threading.runnables.RoomUnitGiveHanditem; -import com.eu.habbo.threading.runnables.RoomUnitWalkToRoomUnit; +import com.eu.habbo.threading.runnables.RoomUnitWalkToLocation; import gnu.trove.procedure.TObjectProcedure; import java.sql.ResultSet; @@ -70,13 +74,25 @@ public class WiredEffectBotGiveHandItem extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); - this.itemId = packet.readInt(); - this.botName = packet.readString(); + int itemId = packet.readInt(); + + if(itemId < 0) + itemId = 0; + + String botName = packet.readString(); packet.readInt(); - this.setDelay(packet.readInt()); + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.itemId = itemId; + this.botName = botName.substring(0, Math.min(botName.length(), Emulator.getConfig().getInt("hotel.wired.message.max_length", 100))); + this.setDelay(delay); + return true; } @@ -94,15 +110,22 @@ public class WiredEffectBotGiveHandItem extends InteractionWiredEffect { Bot bot = bots.get(0); List tasks = new ArrayList<>(); - tasks.add(new RoomUnitGiveHanditem(habbo.getRoomUnit(), room, this.itemId)); + tasks.add(new RoomUnitGiveHanditem(roomUnit, room, this.itemId)); tasks.add(new RoomUnitGiveHanditem(bot.getRoomUnit(), room, 0)); + tasks.add(() -> { + if(roomUnit.getRoom() != null && roomUnit.getRoom().getId() == room.getId() && roomUnit.getCurrentLocation().distance(bot.getRoomUnit().getCurrentLocation()) < 2) { + WiredHandler.handle(WiredTriggerType.BOT_REACHED_AVTR, bot.getRoomUnit(), room, new Object[]{}); + } + }); + + RoomTile tile = bot.getRoomUnit().getClosestAdjacentTile(roomUnit.getX(), roomUnit.getY(), true); + + if(tile != null) { + bot.getRoomUnit().setGoalLocation(tile); + } Emulator.getThreading().run(new RoomUnitGiveHanditem(bot.getRoomUnit(), room, this.itemId)); - - List failedReach = new ArrayList<>(); - failedReach.add(() -> tasks.forEach(Runnable::run)); - - Emulator.getThreading().run(new RoomUnitWalkToRoomUnit(bot.getRoomUnit(), habbo.getRoomUnit(), room, tasks, failedReach)); + Emulator.getThreading().run(new RoomUnitWalkToLocation(bot.getRoomUnit(), tile, room, tasks, tasks)); return true; } @@ -112,17 +135,29 @@ public class WiredEffectBotGiveHandItem extends InteractionWiredEffect { @Override public String getWiredData() { - return this.getDelay() + "" + ((char) 9) + "" + this.itemId + "" + ((char) 9) + "" + this.botName; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.botName, this.itemId, this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split(((char) 9) + ""); + String wiredData = set.getString("wired_data"); - if (data.length == 3) { - this.setDelay(Integer.valueOf(data[0])); - this.itemId = Integer.valueOf(data[1]); - this.botName = data[2]; + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + this.itemId = data.item_id; + this.botName = data.bot_name; + } + else { + String[] data = wiredData.split(((char) 9) + ""); + + if (data.length == 3) { + this.setDelay(Integer.valueOf(data[0])); + this.itemId = Integer.valueOf(data[1]); + this.botName = data[2]; + } + + this.needsUpdate(true); } } @@ -137,4 +172,16 @@ public class WiredEffectBotGiveHandItem extends InteractionWiredEffect { public boolean requiresTriggeringUser() { return true; } + + static class JsonData { + String bot_name; + int item_id; + int delay; + + public JsonData(String bot_name, int item_id, int delay) { + this.bot_name = bot_name; + this.item_id = item_id; + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTalk.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTalk.java index e73978a0..735b0f39 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTalk.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTalk.java @@ -9,12 +9,16 @@ import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; 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.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; +import java.util.regex.Pattern; public class WiredEffectBotTalk extends InteractionWiredEffect { public static final WiredEffectType type = WiredEffectType.BOT_TALK; @@ -48,20 +52,35 @@ public class WiredEffectBotTalk extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); - this.mode = packet.readInt(); + int mode = packet.readInt(); - String[] data = packet.readString().split(((char) 9) + ""); + if(mode != 0 && mode != 1) + throw new WiredSaveException("Mode is invalid"); - if (data.length == 2) { - this.botName = data[0]; - this.message = data[1]; - } + String dataString = packet.readString(); + + String splitBy = "\t"; + if(!dataString.contains(splitBy)) + throw new WiredSaveException("Malformed data string"); + + String[] data = dataString.split(Pattern.quote(splitBy)); + + if (data.length != 2) + throw new WiredSaveException("Malformed data string. Invalid data length"); packet.readInt(); - this.setDelay(packet.readInt()); + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.setDelay(delay); + this.botName = data[0].substring(0, Math.min(data[0].length(), Emulator.getConfig().getInt("hotel.wired.message.max_length", 100))); + this.message = data[1].substring(0, Math.min(data[1].length(), Emulator.getConfig().getInt("hotel.wired.message.max_length", 100))); + this.mode = mode; return true; } @@ -78,24 +97,29 @@ public class WiredEffectBotTalk extends InteractionWiredEffect { Habbo habbo = room.getHabbo(roomUnit); if (habbo != null) { - message = message.replace(Emulator.getTexts().getValue("wired.variable.username"), habbo.getHabboInfo().getUsername()) - .replace(Emulator.getTexts().getValue("wired.variable.credits"), habbo.getHabboInfo().getCredits() + "") - .replace(Emulator.getTexts().getValue("wired.variable.pixels"), habbo.getHabboInfo().getPixels() + "") - .replace(Emulator.getTexts().getValue("wired.variable.points"), habbo.getHabboInfo().getCurrencyAmount(Emulator.getConfig().getInt("seasonal.primary.type")) + ""); + message = message.replace(Emulator.getTexts().getValue("wired.variable.username", "%username%"), habbo.getHabboInfo().getUsername()) + .replace(Emulator.getTexts().getValue("wired.variable.credits", "%credits%"), habbo.getHabboInfo().getCredits() + "") + .replace(Emulator.getTexts().getValue("wired.variable.pixels", "%pixels%"), habbo.getHabboInfo().getPixels() + "") + .replace(Emulator.getTexts().getValue("wired.variable.points", "%points%"), habbo.getHabboInfo().getCurrencyAmount(Emulator.getConfig().getInt("seasonal.primary.type")) + "") + .replace(Emulator.getTexts().getValue("wired.variable.owner", "%owner%"), room.getOwnerName()) + .replace(Emulator.getTexts().getValue("wired.variable.item_count", "%item_count%"), room.itemCount() + "") + .replace(Emulator.getTexts().getValue("wired.variable.name", "%name%"), this.botName) + .replace(Emulator.getTexts().getValue("wired.variable.roomname", "%roomname%"), room.getName()) + .replace(Emulator.getTexts().getValue("wired.variable.user_count", "%user_count%"), room.getUserCount() + ""); } List bots = room.getBots(this.botName); - if (bots.size() != 1) { - return false; - } + if (bots.size() == 1) { + Bot bot = bots.get(0); - Bot bot = bots.get(0); - - if (this.mode == 1) { - bot.shout(message); - } else { - bot.talk(message); + if(!WiredHandler.handle(WiredTriggerType.SAY_SOMETHING, bot.getRoomUnit(), room, new Object[]{ message })) { + if (this.mode == 1) { + bot.shout(message); + } else { + bot.talk(message); + } + } } return true; @@ -103,19 +127,31 @@ public class WiredEffectBotTalk extends InteractionWiredEffect { @Override public String getWiredData() { - return this.getDelay() + "" + ((char) 9) + "" + this.mode + "" + ((char) 9) + "" + this.botName + "" + ((char) 9) + "" + this.message; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.botName, this.mode, this.message, this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String d = set.getString("wired_data"); - String[] data = d.split(((char) 9) + ""); + String wiredData = set.getString("wired_data"); - if (data.length == 4) { - this.setDelay(Integer.valueOf(data[0])); - this.mode = data[1].equalsIgnoreCase("1") ? 1 : 0; - this.botName = data[2]; - this.message = data[3]; + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + this.mode = data.mode; + this.botName = data.bot_name; + this.message = data.message; + } + else { + String[] data = wiredData.split(((char) 9) + ""); + + if (data.length == 4) { + this.setDelay(Integer.valueOf(data[0])); + this.mode = data[1].equalsIgnoreCase("1") ? 1 : 0; + this.botName = data[2]; + this.message = data[3]; + } + + this.needsUpdate(true); } } @@ -155,4 +191,18 @@ public class WiredEffectBotTalk extends InteractionWiredEffect { protected long requiredCooldown() { return 500; } + + static class JsonData { + String bot_name; + int mode; + String message; + int delay; + + public JsonData(String bot_name, int mode, String message, int delay) { + this.bot_name = bot_name; + this.mode = mode; + this.message = message; + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTalkToHabbo.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTalkToHabbo.java index aec24c88..8fede69c 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTalkToHabbo.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTalkToHabbo.java @@ -10,14 +10,18 @@ import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; 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.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import gnu.trove.procedure.TObjectProcedure; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import java.util.regex.Pattern; public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect { public static final WiredEffectType type = WiredEffectType.BOT_TALK_TO_AVATAR; @@ -69,19 +73,34 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); - this.mode = packet.readInt(); - String[] data = packet.readString().split("" + ((char) 9)); + int mode = packet.readInt(); - if (data.length == 2) { - this.botName = data[0]; - this.message = data[1]; - } + if(mode != 0 && mode != 1) + throw new WiredSaveException("Mode is invalid"); + + String dataString = packet.readString(); + String splitBy = "\t"; + if(!dataString.contains(splitBy)) + throw new WiredSaveException("Malformed data string"); + + String[] data = dataString.split(Pattern.quote(splitBy)); + + if (data.length != 2) + throw new WiredSaveException("Malformed data string. Invalid data length"); packet.readInt(); - this.setDelay(packet.readInt()); + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.botName = data[0].substring(0, Math.min(data[0].length(), Emulator.getConfig().getInt("hotel.wired.message.max_length", 100))); + this.message = data[1].substring(0, Math.min(data[1].length(), Emulator.getConfig().getInt("hotel.wired.message.max_length", 100))); + this.mode = mode; + this.setDelay(delay); return true; } @@ -97,10 +116,15 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect { if (habbo != null) { String m = this.message; - m = m.replace(Emulator.getTexts().getValue("wired.variable.username"), habbo.getHabboInfo().getUsername()) - .replace(Emulator.getTexts().getValue("wired.variable.credits"), habbo.getHabboInfo().getCredits() + "") - .replace(Emulator.getTexts().getValue("wired.variable.pixels"), habbo.getHabboInfo().getPixels() + "") - .replace(Emulator.getTexts().getValue("wired.variable.points"), habbo.getHabboInfo().getCurrencyAmount(Emulator.getConfig().getInt("seasonal.primary.type")) + ""); + m = m.replace(Emulator.getTexts().getValue("wired.variable.username", "%username%"), habbo.getHabboInfo().getUsername()) + .replace(Emulator.getTexts().getValue("wired.variable.credits", "%credits%"), habbo.getHabboInfo().getCredits() + "") + .replace(Emulator.getTexts().getValue("wired.variable.pixels", "%pixels%"), habbo.getHabboInfo().getPixels() + "") + .replace(Emulator.getTexts().getValue("wired.variable.points", "%points%"), habbo.getHabboInfo().getCurrencyAmount(Emulator.getConfig().getInt("seasonal.primary.type")) + "") + .replace(Emulator.getTexts().getValue("wired.variable.owner", "%owner%"), room.getOwnerName()) + .replace(Emulator.getTexts().getValue("wired.variable.item_count", "%item_count%"), room.itemCount() + "") + .replace(Emulator.getTexts().getValue("wired.variable.name", "%name%"), this.botName) + .replace(Emulator.getTexts().getValue("wired.variable.roomname", "%roomname%"), room.getName()) + .replace(Emulator.getTexts().getValue("wired.variable.user_count", "%user_count%"), room.getUserCount() + ""); List bots = room.getBots(this.botName); @@ -110,10 +134,12 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect { Bot bot = bots.get(0); - if (this.mode == 1) { - bot.whisper(m, habbo); - } else { - bot.talk(habbo.getHabboInfo().getUsername() + ": " + m); + if(!WiredHandler.handle(WiredTriggerType.SAY_SOMETHING, bot.getRoomUnit(), room, new Object[]{ m })) { + if (this.mode == 1) { + bot.whisper(m, habbo); + } else { + bot.talk(habbo.getHabboInfo().getUsername() + ": " + m); + } } return true; @@ -124,18 +150,31 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect { @Override public String getWiredData() { - return this.getDelay() + "" + ((char) 9) + "" + this.mode + "" + ((char) 9) + "" + this.botName + "" + ((char) 9) + "" + this.message; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.botName, this.mode, this.message, this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split(((char) 9) + ""); + String wiredData = set.getString("wired_data"); - if (data.length == 4) { - this.setDelay(Integer.valueOf(data[0])); - this.mode = data[1].equalsIgnoreCase("1") ? 1 : 0; - this.botName = data[2]; - this.message = data[3]; + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + this.mode = data.mode; + this.botName = data.bot_name; + this.message = data.message; + } + else { + String[] data = wiredData.split(((char) 9) + ""); + + if (data.length == 4) { + this.setDelay(Integer.valueOf(data[0])); + this.mode = data[1].equalsIgnoreCase("1") ? 1 : 0; + this.botName = data[2]; + this.message = data[3]; + } + + this.needsUpdate(true); } } @@ -151,4 +190,18 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect { public boolean requiresTriggeringUser() { return true; } + + static class JsonData { + String bot_name; + int mode; + String message; + int delay; + + public JsonData(String bot_name, int mode, String message, int delay) { + this.bot_name = bot_name; + this.mode = mode; + this.message = message; + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTeleport.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTeleport.java index b88e7877..07bbac6f 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTeleport.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTeleport.java @@ -14,6 +14,7 @@ import com.eu.habbo.habbohotel.wired.WiredEffectType; import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserEffectComposer; import com.eu.habbo.threading.runnables.RoomUnitTeleport; import com.eu.habbo.threading.runnables.SendRoomUnitEffectComposer; @@ -21,8 +22,10 @@ import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; public class WiredEffectBotTeleport extends InteractionWiredEffect { public static final WiredEffectType type = WiredEffectType.BOT_TELEPORT; @@ -77,6 +80,7 @@ public class WiredEffectBotTeleport extends InteractionWiredEffect { } } + Emulator.getThreading().run(() -> { roomUnit.isWiredTeleporting = true; }, Math.max(0, WiredHandler.TELEPORT_DELAY - 500)); Emulator.getThreading().run(new RoomUnitTeleport(roomUnit, room, tile.x, tile.y, tile.getStackHeight() + (tile.state == RoomTileState.SIT ? -0.5 : 0), roomUnit.getEffectId()), WiredHandler.TELEPORT_DELAY); } @@ -110,19 +114,36 @@ public class WiredEffectBotTeleport extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); - this.botName = packet.readString(); + String botName = packet.readString(); + int itemsCount = packet.readInt(); - this.items.clear(); - - int count = packet.readInt(); - - for (int i = 0; i < count; i++) { - this.items.add(Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(packet.readInt())); + if(itemsCount > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) { + throw new WiredSaveException("Too many furni selected"); } - this.setDelay(packet.readInt()); + List newItems = new ArrayList<>(); + + for (int i = 0; i < itemsCount; i++) { + int itemId = packet.readInt(); + HabboItem it = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(itemId); + + if(it == null) + throw new WiredSaveException(String.format("Item %s not found", itemId)); + + newItems.add(it); + } + + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.items.clear(); + this.items.addAll(newItems); + this.botName = botName.substring(0, Math.min(botName.length(), Emulator.getConfig().getInt("hotel.wired.message.max_length", 100))); + this.setDelay(delay); return true; } @@ -164,38 +185,57 @@ public class WiredEffectBotTeleport extends InteractionWiredEffect { @Override public String getWiredData() { - StringBuilder wiredData = new StringBuilder(this.getDelay() + "\t" + this.botName + ";"); + ArrayList itemIds = new ArrayList<>(); - if (this.items != null && !this.items.isEmpty()) { + if (this.items != null) { for (HabboItem item : this.items) { if (item.getRoomId() != 0) { - wiredData.append(item.getId()).append(";"); + itemIds.add(item.getId()); } } } - return wiredData.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.botName, itemIds, this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items = new THashSet<>(); - String[] wiredData = set.getString("wired_data").split("\t"); - if (wiredData.length >= 2) { - this.setDelay(Integer.valueOf(wiredData[0])); - String[] data = wiredData[1].split(";"); + String wiredData = set.getString("wired_data"); - if (data.length > 1) { - this.botName = data[0]; + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + this.botName = data.bot_name; - for (int i = 1; i < data.length; i++) { - HabboItem item = room.getHabboItem(Integer.valueOf(data[i])); + for(int itemId : data.items) { + HabboItem item = room.getHabboItem(itemId); - if (item != null) - this.items.add(item); + if (item != null) + this.items.add(item); + } + } + else { + String[] wiredDataSplit = set.getString("wired_data").split("\t"); + + if (wiredDataSplit.length >= 2) { + this.setDelay(Integer.valueOf(wiredDataSplit[0])); + String[] data = wiredDataSplit[1].split(";"); + + if (data.length > 1) { + this.botName = data[0]; + + for (int i = 1; i < data.length; i++) { + HabboItem item = room.getHabboItem(Integer.valueOf(data[i])); + + if (item != null) + this.items.add(item); + } } } + + this.needsUpdate(true); } } @@ -205,4 +245,16 @@ public class WiredEffectBotTeleport extends InteractionWiredEffect { this.items.clear(); this.setDelay(0); } + + static class JsonData { + String bot_name; + List items; + int delay; + + public JsonData(String bot_name, List items, int delay) { + this.bot_name = bot_name; + this.items = items; + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotWalkToFurni.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotWalkToFurni.java index 1b0efe08..73906c87 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotWalkToFurni.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotWalkToFurni.java @@ -12,26 +12,29 @@ import com.eu.habbo.habbohotel.wired.WiredEffectType; import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; public class WiredEffectBotWalkToFurni extends InteractionWiredEffect { public static final WiredEffectType type = WiredEffectType.BOT_MOVE; - private THashSet items; + private List items; private String botName = ""; public WiredEffectBotWalkToFurni(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); - this.items = new THashSet<>(); + this.items = new ArrayList<>(); } public WiredEffectBotWalkToFurni(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) { super(id, userId, item, extradata, limitedStack, limitedSells); - this.items = new THashSet<>(); + this.items = new ArrayList<>(); } @Override @@ -64,19 +67,36 @@ public class WiredEffectBotWalkToFurni extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); - this.botName = packet.readString(); + String botName = packet.readString(); + int itemsCount = packet.readInt(); - this.items.clear(); - - int count = packet.readInt(); - - for (int i = 0; i < count; i++) { - this.items.add(Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(packet.readInt())); + if(itemsCount > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) { + throw new WiredSaveException("Too many furni selected"); } - this.setDelay(packet.readInt()); + List newItems = new ArrayList<>(); + + for (int i = 0; i < itemsCount; i++) { + int itemId = packet.readInt(); + HabboItem it = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(itemId); + + if(it == null) + throw new WiredSaveException(String.format("Item %s not found", itemId)); + + newItems.add(it); + } + + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.items.clear(); + this.items.addAll(newItems); + this.botName = botName.substring(0, Math.min(botName.length(), Emulator.getConfig().getInt("hotel.wired.message.max_length", 100))); + this.setDelay(delay); return true; } @@ -91,33 +111,23 @@ public class WiredEffectBotWalkToFurni extends InteractionWiredEffect { List bots = room.getBots(this.botName); if (this.items.isEmpty() || bots.size() != 1) { - return false; + return true; } Bot bot = bots.get(0); - THashSet items = new THashSet<>(); + this.items.removeIf(item -> item == null || item.getRoomId() != this.getRoomId() || Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(item.getId()) == null); - for (HabboItem item : this.items) { - if (Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(item.getId()) == null) - items.add(item); - } + // Bots shouldn't walk to the tile they are already standing on + List possibleItems = this.items.stream() + .filter(item -> !room.getBotsOnItem(item).contains(bot)) + .collect(Collectors.toList()); - for (HabboItem item : items) { - this.items.remove(item); - } + // Get a random tile of possible tiles to walk to + if (possibleItems.size() > 0) { + HabboItem item = possibleItems.get(Emulator.getRandom().nextInt(possibleItems.size())); - if (this.items.size() > 0) { - int i = Emulator.getRandom().nextInt(this.items.size()) + 1; - int j = 1; - for (HabboItem item : this.items) { - if (item.getRoomId() != 0 && item.getRoomId() == bot.getRoom().getId()) { - if (i == j) { - bot.getRoomUnit().setGoalLocation(room.getLayout().getTile(item.getX(), item.getY())); - break; - } else { - j++; - } - } + if (item.getRoomId() != 0 && item.getRoomId() == bot.getRoom().getId()) { + bot.getRoomUnit().setGoalLocation(room.getLayout().getTile(item.getX(), item.getY())); } } @@ -126,38 +136,57 @@ public class WiredEffectBotWalkToFurni extends InteractionWiredEffect { @Override public String getWiredData() { - StringBuilder wiredData = new StringBuilder(this.getDelay() + "\t" + this.botName + ";"); + ArrayList itemIds = new ArrayList<>(); - if (this.items != null && !this.items.isEmpty()) { + if (this.items != null) { for (HabboItem item : this.items) { if (item.getRoomId() != 0) { - wiredData.append(item.getId()).append(";"); + itemIds.add(item.getId()); } } } - return wiredData.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.botName, itemIds, this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - this.items = new THashSet<>(); - String[] wiredData = set.getString("wired_data").split("\t"); + this.items = new ArrayList<>(); - if (wiredData.length > 1) { - this.setDelay(Integer.valueOf(wiredData[0])); - String[] data = wiredData[1].split(";"); + String wiredData = set.getString("wired_data"); - if (data.length >= 1) { - this.botName = data[0]; + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + this.botName = data.bot_name; - for (int i = 1; i < data.length; i++) { - HabboItem item = room.getHabboItem(Integer.valueOf(data[i])); + for(int itemId : data.items) { + HabboItem item = room.getHabboItem(itemId); - if (item != null) - this.items.add(item); + if (item != null) + this.items.add(item); + } + } + else { + String[] wiredDataSplit = set.getString("wired_data").split("\t"); + + if (wiredDataSplit.length >= 2) { + this.setDelay(Integer.valueOf(wiredDataSplit[0])); + String[] data = wiredDataSplit[1].split(";"); + + if (data.length > 1) { + this.botName = data[0]; + + for (int i = 1; i < data.length; i++) { + HabboItem item = room.getHabboItem(Integer.valueOf(data[i])); + + if (item != null) + this.items.add(item); + } } } + + this.needsUpdate(true); } } @@ -167,4 +196,16 @@ public class WiredEffectBotWalkToFurni extends InteractionWiredEffect { this.botName = ""; this.setDelay(0); } + + static class JsonData { + String bot_name; + List items; + int delay; + + public JsonData(String bot_name, List items, int delay) { + this.bot_name = bot_name; + this.items = items; + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectChangeFurniDirection.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectChangeFurniDirection.java index bbb44819..0ce892d7 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectChangeFurniDirection.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectChangeFurniDirection.java @@ -5,19 +5,19 @@ import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect; import com.eu.habbo.habbohotel.rooms.*; -import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboItem; -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.habbohotel.wired.*; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import com.eu.habbo.messages.outgoing.rooms.items.FloorItemOnRollerComposer; import gnu.trove.map.hash.THashMap; import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; import java.util.Map; public class WiredEffectChangeFurniDirection extends InteractionWiredEffect { @@ -31,9 +31,9 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect { public static final WiredEffectType type = WiredEffectType.MOVE_DIRECTION; - private final THashMap items = new THashMap<>(0); + private final THashMap items = new THashMap<>(0); private RoomUserRotation startRotation = RoomUserRotation.NORTH; - private int rotateAction = 0; + private int blockedAction = 0; public WiredEffectChangeFurniDirection(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); @@ -57,29 +57,56 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect { } if (this.items.isEmpty()) return false; - for (Map.Entry entry : this.items.entrySet()) { - RoomUserRotation currentRotation = entry.getValue(); - RoomTile targetTile = room.getLayout().getTileInFront(room.getLayout().getTile(entry.getKey().getX(), entry.getKey().getY()), entry.getValue().getValue()); + + for (Map.Entry entry : this.items.entrySet()) { + HabboItem item = entry.getKey(); + RoomTile targetTile = room.getLayout().getTileInFront(room.getLayout().getTile(item.getX(), item.getY()), entry.getValue().direction.getValue()); int count = 1; - while ((targetTile == null || !targetTile.getAllowStack() || targetTile.state == RoomTileState.INVALID || targetTile.state == RoomTileState.BLOCKED) && count < 8) { - entry.setValue(this.nextRotation(entry.getValue())); - targetTile = room.getLayout().getTileInFront(room.getLayout().getTile(entry.getKey().getX(), entry.getKey().getY()), entry.getValue().getValue()); - count++; - } + while ((targetTile == null || targetTile.state == RoomTileState.INVALID || room.furnitureFitsAt(targetTile, item, item.getRotation(), false) != FurnitureMovementError.NONE) && count < 8) { + entry.getValue().direction = this.nextRotation(entry.getValue().direction); - if (targetTile != null && targetTile.state == RoomTileState.OPEN) { - boolean hasHabbos = false; - for (Habbo habbo : room.getHabbosAt(targetTile)) { - hasHabbos = true; - Emulator.getThreading().run(() -> WiredHandler.handle(WiredTriggerType.COLLISION, habbo.getRoomUnit(), room, new Object[]{entry.getKey()})); + RoomTile tile = room.getLayout().getTileInFront(room.getLayout().getTile(item.getX(), item.getY()), entry.getValue().direction.getValue()); + if (tile != null && tile.state != RoomTileState.INVALID) { + targetTile = tile; } - if (!hasHabbos) { - THashSet refreshTiles = room.getLayout().getTilesAt(room.getLayout().getTile(entry.getKey().getX(), entry.getKey().getY()), entry.getKey().getBaseItem().getWidth(), entry.getKey().getBaseItem().getLength(), entry.getKey().getRotation()); - room.sendComposer(new FloorItemOnRollerComposer(entry.getKey(), null, targetTile, targetTile.getStackHeight() - entry.getKey().getZ(), room).compose()); - room.getLayout().getTilesAt(room.getLayout().getTile(entry.getKey().getX(), entry.getKey().getY()), entry.getKey().getBaseItem().getWidth(), entry.getKey().getBaseItem().getLength(), entry.getKey().getRotation()); - room.updateTiles(refreshTiles); + count++; + } + } + + for (Map.Entry entry : this.items.entrySet()) { + HabboItem item = entry.getKey(); + int newDirection = entry.getValue().direction.getValue(); + + RoomTile targetTile = room.getLayout().getTileInFront(room.getLayout().getTile(item.getX(), item.getY()), newDirection); + + if(item.getRotation() != entry.getValue().rotation) { + if(room.furnitureFitsAt(targetTile, item, entry.getValue().rotation, false) != FurnitureMovementError.NONE) + continue; + + room.moveFurniTo(entry.getKey(), targetTile, entry.getValue().rotation, null, true); + } + + boolean hasRoomUnits = false; + THashSet newOccupiedTiles = room.getLayout().getTilesAt(targetTile, item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation()); + for(RoomTile tile : newOccupiedTiles) { + for (RoomUnit _roomUnit : room.getRoomUnits(tile)) { + hasRoomUnits = true; + if(_roomUnit.getCurrentLocation() == targetTile) { + Emulator.getThreading().run(() -> WiredHandler.handle(WiredTriggerType.COLLISION, _roomUnit, room, new Object[]{entry.getKey()})); + break; + } + } + } + + if (targetTile != null && targetTile.state != RoomTileState.INVALID && room.furnitureFitsAt(targetTile, item, item.getRotation(), false) == FurnitureMovementError.NONE) { + if (!hasRoomUnits) { + RoomTile oldLocation = room.getLayout().getTile(entry.getKey().getX(), entry.getKey().getY()); + double oldZ = entry.getKey().getZ(); + if(room.moveFurniTo(entry.getKey(), targetTile, item.getRotation(), null, false) == FurnitureMovementError.NONE) { + room.sendComposer(new FloorItemOnRollerComposer(entry.getKey(), null, oldLocation, oldZ, targetTile, entry.getKey().getZ(), 0, room).compose()); + } } } } @@ -89,41 +116,63 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect { @Override public String getWiredData() { - StringBuilder data = new StringBuilder(this.getDelay() + this.startRotation.getValue() + "\t" + this.rotateAction + "\t" + this.items.size()); - - for (Map.Entry entry : this.items.entrySet()) { - data.append("\t").append(entry.getKey().getId()).append(":").append(entry.getValue().getValue()); - } - - return data.toString(); + ArrayList settings = new ArrayList<>(this.items.values()); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.startRotation, this.blockedAction, settings, this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split("\t"); - if (data.length >= 1) { - this.setDelay(Integer.valueOf(data[0])); + this.items.clear(); + + String wiredData = set.getString("wired_data"); + + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + this.startRotation = data.start_direction; + this.blockedAction = data.blocked_action; + + for(WiredChangeDirectionSetting setting : data.items) { + HabboItem item = room.getHabboItem(setting.item_id); + + if (item != null) { + this.items.put(item, setting); + } + } } - if (data.length >= 3) { - this.startRotation = RoomUserRotation.fromValue(Integer.valueOf(data[0])); - this.rotateAction = Integer.valueOf(data[1]); + else { + String[] data = wiredData.split("\t"); - int itemCount = Integer.valueOf(data[2]); + if (data.length >= 4) { + this.setDelay(Integer.parseInt(data[0])); + this.startRotation = RoomUserRotation.fromValue(Integer.parseInt(data[1])); + this.blockedAction = Integer.parseInt(data[2]); - if (itemCount > 0) { - for (int i = 3; i < data.length; i++) { - String[] subData = data[i].split(":"); + int itemCount = Integer.parseInt(data[3]); - if (subData.length == 2) { - HabboItem item = room.getHabboItem(Integer.valueOf(subData[0])); + if (itemCount > 0) { + for (int i = 4; i < data.length; i++) { + String[] subData = data[i].split(":"); - if (item != null) { - this.items.put(item, RoomUserRotation.fromValue(Integer.valueOf(subData[1]))); + if (subData.length >= 2) { + HabboItem item = room.getHabboItem(Integer.parseInt(subData[0])); + + if (item != null) { + int rotation = item.getRotation(); + + if (subData.length > 2) { + rotation = Integer.parseInt(subData[2]); + } + + this.items.put(item, new WiredChangeDirectionSetting(item.getId(), rotation, RoomUserRotation.fromValue(Integer.parseInt(subData[1])))); + } } } } } + + this.needsUpdate(true); } } @@ -131,7 +180,7 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect { public void onPickUp() { this.setDelay(0); this.items.clear(); - this.rotateAction = 0; + this.blockedAction = 0; this.startRotation = RoomUserRotation.NORTH; } @@ -145,15 +194,15 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect { message.appendBoolean(false); message.appendInt(WiredHandler.MAXIMUM_FURNI_SELECTION); message.appendInt(this.items.size()); - for (Map.Entry item : this.items.entrySet()) { + for (Map.Entry item : this.items.entrySet()) { message.appendInt(item.getKey().getId()); } message.appendInt(this.getBaseItem().getSpriteId()); message.appendInt(this.getId()); message.appendString(""); message.appendInt(2); - message.appendInt(this.startRotation.getValue()); - message.appendInt(this.rotateAction); + message.appendInt(this.startRotation != null ? this.startRotation.getValue() : 0); + message.appendInt(this.blockedAction); message.appendInt(0); message.appendInt(this.getType().code); message.appendInt(this.getDelay()); @@ -161,30 +210,60 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { - this.items.clear(); + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); - this.startRotation = RoomUserRotation.fromValue(packet.readInt()); - this.rotateAction = packet.readInt(); + int startDirectionInt = packet.readInt(); + + if(startDirectionInt < 0 || startDirectionInt > 7 || (startDirectionInt % 2) != 0) { + throw new WiredSaveException("Start direction is invalid"); + } + + RoomUserRotation startDirection = RoomUserRotation.fromValue(startDirectionInt); + + int blockedActionInt = packet.readInt(); + + if(blockedActionInt < 0 || blockedActionInt > 6) { + throw new WiredSaveException("Blocked action is invalid"); + } + packet.readString(); - int furniCount = packet.readInt(); - for (int i = 0; i < furniCount; i++) { - HabboItem item = gameClient.getHabbo().getHabboInfo().getCurrentRoom().getHabboItem(packet.readInt()); + int itemsCount = packet.readInt(); - if (item != null) { - this.items.put(item, this.startRotation); - } + if(itemsCount > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) { + throw new WiredSaveException("Too many furni selected"); } - this.setDelay(packet.readInt()); + + THashMap newItems = new THashMap<>(); + + for (int i = 0; i < itemsCount; i++) { + int itemId = packet.readInt(); + HabboItem it = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(itemId); + + if(it == null) + throw new WiredSaveException(String.format("Item %s not found", itemId)); + + newItems.put(it, new WiredChangeDirectionSetting(it.getId(), it.getRotation(), startDirection)); + } + + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.items.clear(); + this.items.putAll(newItems); + this.startRotation = startDirection; + this.blockedAction = blockedActionInt; + this.setDelay(delay); + return true; } private RoomUserRotation nextRotation(RoomUserRotation currentRotation) { - switch (this.rotateAction) { + switch (this.blockedAction) { case ACTION_TURN_BACK: - return RoomUserRotation.fromValue(currentRotation.getValue() + 4); - + return RoomUserRotation.fromValue(currentRotation.getValue()).getOpposite(); case ACTION_TURN_LEFT_45: return RoomUserRotation.counterClockwise(currentRotation); case ACTION_TURN_LEFT_90: @@ -198,8 +277,6 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect { case ACTION_WAIT: default: return currentRotation; - - } } @@ -207,4 +284,18 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect { protected long requiredCooldown() { return 495; } + + static class JsonData { + RoomUserRotation start_direction; + int blocked_action; + List items; + int delay; + + public JsonData(RoomUserRotation start_direction, int blocked_action, List items, int delay) { + this.start_direction = start_direction; + this.blocked_action = blocked_action; + this.items = items; + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveHotelviewBonusRarePoints.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveHotelviewBonusRarePoints.java index 1a84a14d..63920ffc 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveHotelviewBonusRarePoints.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveHotelviewBonusRarePoints.java @@ -9,6 +9,7 @@ import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.wired.WiredEffectType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.outgoing.hotelview.BonusRareComposer; @@ -70,7 +71,7 @@ public class WiredEffectGiveHotelviewBonusRarePoints extends InteractionWiredEff packet.readInt(); try { - this.amount = Integer.valueOf(packet.readString()); + this.amount = Integer.parseInt(packet.readString()); } catch (Exception e) { return false; } @@ -103,20 +104,26 @@ public class WiredEffectGiveHotelviewBonusRarePoints extends InteractionWiredEff @Override public String getWiredData() { - return this.getDelay() + "\t" + this.amount; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.getDelay(), this.amount)); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String wireData = set.getString("wired_data"); + String wiredData = set.getString("wired_data"); this.amount = 0; - if (wireData.split("\t").length >= 2) { - super.setDelay(Integer.valueOf(wireData.split("\t")[0])); + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + this.amount = data.amount; + } else { + if (wiredData.split("\t").length >= 2) { + super.setDelay(Integer.parseInt(wiredData.split("\t")[0])); - try { - this.amount = Integer.valueOf(this.getWiredData().split("\t")[1]); - } catch (Exception e) { + try { + this.amount = Integer.parseInt(wiredData.split("\t")[1]); + } catch (Exception e) { + } } } } @@ -131,4 +138,14 @@ public class WiredEffectGiveHotelviewBonusRarePoints extends InteractionWiredEff public boolean requiresTriggeringUser() { return true; } + + static class JsonData { + int delay; + int amount; + + public JsonData(int delay, int amount) { + this.delay = delay; + this.amount = amount; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveHotelviewHofPoints.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveHotelviewHofPoints.java index 5bca3009..0bd62164 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveHotelviewHofPoints.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveHotelviewHofPoints.java @@ -9,6 +9,7 @@ import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.wired.WiredEffectType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; import gnu.trove.procedure.TObjectProcedure; @@ -101,21 +102,31 @@ public class WiredEffectGiveHotelviewHofPoints extends InteractionWiredEffect { @Override public String getWiredData() { - return this.getDelay() + "\t" + this.amount; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.amount, this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String wireData = set.getString("wired_data"); - this.amount = 0; + String wiredData = set.getString("wired_data"); - if (wireData.split("\t").length >= 2) { - super.setDelay(Integer.valueOf(wireData.split("\t")[0])); + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.amount = data.amount; + this.setDelay(data.delay); + } + else { + this.amount = 0; - try { - this.amount = Integer.valueOf(this.getWiredData().split("\t")[1]); - } catch (Exception e) { + if (wiredData.split("\t").length >= 2) { + super.setDelay(Integer.valueOf(wiredData.split("\t")[0])); + + try { + this.amount = Integer.valueOf(this.getWiredData().split("\t")[1]); + } catch (Exception e) { + } } + + this.needsUpdate(true); } } @@ -129,4 +140,14 @@ public class WiredEffectGiveHotelviewHofPoints extends InteractionWiredEffect { public boolean requiresTriggeringUser() { return true; } + + static class JsonData { + int amount; + int delay; + + public JsonData(int amount, int delay) { + this.amount = amount; + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveRespect.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveRespect.java index 233a97e9..4a3b966f 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveRespect.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveRespect.java @@ -10,6 +10,7 @@ import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.wired.WiredEffectType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; import gnu.trove.procedure.TObjectProcedure; @@ -101,22 +102,32 @@ public class WiredEffectGiveRespect extends InteractionWiredEffect { @Override public String getWiredData() { - return this.getDelay() + "\t" + this.respects; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.respects, this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String wireData = set.getString("wired_data"); - String[] data = wireData.split("\t"); - this.respects = 0; + String wiredData = set.getString("wired_data"); - if (data.length >= 2) { - super.setDelay(Integer.valueOf(data[0])); + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.respects = data.amount; + this.setDelay(data.delay); + } + else { + String[] data = wiredData.split("\t"); + this.respects = 0; - try { - this.respects = Integer.valueOf(data[1]); - } catch (Exception e) { + if (data.length >= 2) { + super.setDelay(Integer.valueOf(data[0])); + + try { + this.respects = Integer.valueOf(data[1]); + } catch (Exception e) { + } } + + this.needsUpdate(true); } } @@ -130,4 +141,14 @@ public class WiredEffectGiveRespect extends InteractionWiredEffect { public boolean requiresTriggeringUser() { return true; } + + static class JsonData { + int amount; + int delay; + + public JsonData(int amount, int delay) { + this.amount = amount; + this.delay = delay; + } + } } \ No newline at end of file diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveReward.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveReward.java index e61973e9..f4c3a2ba 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveReward.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveReward.java @@ -56,43 +56,52 @@ public class WiredEffectGiveReward extends InteractionWiredEffect { @Override public String getWiredData() { - StringBuilder data = new StringBuilder(this.limit + ":" + this.given + ":" + this.rewardTime + ":" + (this.uniqueRewards ? 1 : 0) + ":" + this.limitationInterval + ":" + this.getDelay() + ":"); - if (this.rewardItems.isEmpty()) { - data.append("\t"); - } else { - for (WiredGiveRewardItem item : this.rewardItems) { - data.append(item.toString()).append(";"); - } - } - - return data.toString(); + ArrayList rewards = new ArrayList<>(this.rewardItems); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.limit, this.given, this.rewardTime, this.uniqueRewards, this.limitationInterval, rewards, this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split(":"); - if (data.length > 0) { - this.limit = Integer.valueOf(data[0]); - this.given = Integer.valueOf(data[1]); - this.rewardTime = Integer.valueOf(data[2]); - this.uniqueRewards = data[3].equals("1"); - this.limitationInterval = Integer.valueOf(data[4]); - this.setDelay(Integer.valueOf(data[5])); + String wiredData = set.getString("wired_data"); - if (data.length > 6) { - if (!data[6].equalsIgnoreCase("\t")) { - String[] items = data[6].split(";"); + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + this.limit = data.limit; + this.given = data.given; + this.rewardTime = data.reward_time; + this.uniqueRewards = data.unique_rewards; + this.limitationInterval = data.limit_interval; + this.rewardItems.clear(); + this.rewardItems.addAll(data.rewards); + } + else { + String[] data = wiredData.split(":"); + if (data.length > 0) { + this.limit = Integer.valueOf(data[0]); + this.given = Integer.valueOf(data[1]); + this.rewardTime = Integer.valueOf(data[2]); + this.uniqueRewards = data[3].equals("1"); + this.limitationInterval = Integer.valueOf(data[4]); + this.setDelay(Integer.valueOf(data[5])); - this.rewardItems.clear(); + if (data.length > 6) { + if (!data[6].equalsIgnoreCase("\t")) { + String[] items = data[6].split(";"); - for (String s : items) { - try { - this.rewardItems.add(new WiredGiveRewardItem(s)); - } catch (Exception e) { + this.rewardItems.clear(); + + for (String s : items) { + try { + this.rewardItems.add(new WiredGiveRewardItem(s)); + } catch (Exception e) { + } } } } + + this.needsUpdate(true); } } } @@ -167,8 +176,7 @@ public class WiredEffectGiveReward extends InteractionWiredEffect { @Override public boolean saveData(ClientMessage packet, GameClient gameClient) { if (gameClient.getHabbo().hasPermission(Permission.ACC_SUPERWIRED)) { - packet.readInt(); - + int argsLength = packet.readInt(); this.rewardTime = packet.readInt(); this.uniqueRewards = packet.readInt() == 1; this.limit = packet.readInt(); @@ -196,11 +204,10 @@ public class WiredEffectGiveReward extends InteractionWiredEffect { return false; } - WiredHandler.dropRewards(this.getId()); - - packet.readString(); packet.readInt(); this.setDelay(packet.readInt()); + + WiredHandler.dropRewards(this.getId()); return true; } @@ -217,4 +224,24 @@ public class WiredEffectGiveReward extends InteractionWiredEffect { protected long requiredCooldown() { return 0; } + + static class JsonData { + int limit; + int given; + int reward_time; + boolean unique_rewards; + int limit_interval; + List rewards; + int delay; + + public JsonData(int limit, int given, int reward_time, boolean unique_rewards, int limit_interval, List rewards, int delay) { + this.limit = limit; + this.given = given; + this.reward_time = reward_time; + this.unique_rewards = unique_rewards; + this.limit_interval = limit_interval; + this.rewards = rewards; + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveScore.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveScore.java index 91475710..5a326356 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveScore.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveScore.java @@ -1,5 +1,6 @@ package com.eu.habbo.habbohotel.items.interactions.wired.effects; +import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.games.Game; import com.eu.habbo.habbohotel.items.Item; @@ -9,8 +10,10 @@ import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.wired.WiredEffectType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import gnu.trove.iterator.TObjectIntIterator; import gnu.trove.map.TObjectIntMap; import gnu.trove.map.hash.TObjectIntHashMap; @@ -61,7 +64,7 @@ public class WiredEffectGiveScore extends InteractionWiredEffect { if (iterator.value() < this.count) { iterator.setValue(iterator.value() + 1); - habbo.getHabboInfo().getGamePlayer().addScore(this.score); + habbo.getHabboInfo().getGamePlayer().addScore(this.score, true); return true; } @@ -74,7 +77,7 @@ public class WiredEffectGiveScore extends InteractionWiredEffect { this.data.put(new AbstractMap.SimpleEntry<>(game.getStartTime(), habbo.getHabboInfo().getId()), 1); if (habbo.getHabboInfo().getGamePlayer() != null) { - habbo.getHabboInfo().getGamePlayer().addScore(this.score); + habbo.getHabboInfo().getGamePlayer().addScore(this.score, true); } return true; @@ -85,17 +88,29 @@ public class WiredEffectGiveScore extends InteractionWiredEffect { @Override public String getWiredData() { - return this.score + ";" + this.count + ";" + this.getDelay(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.score, this.count, this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split(";"); + String wiredData = set.getString("wired_data"); - if (data.length == 3) { - this.score = Integer.valueOf(data[0]); - this.count = Integer.valueOf(data[1]); - this.setDelay(Integer.valueOf(data[2])); + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.score = data.score; + this.count = data.count; + this.setDelay(data.delay); + } + else { + String[] data = wiredData.split(";"); + + if (data.length == 3) { + this.score = Integer.valueOf(data[0]); + this.count = Integer.valueOf(data[1]); + this.setDelay(Integer.valueOf(data[2])); + } + + this.needsUpdate(true); } } @@ -147,14 +162,30 @@ public class WiredEffectGiveScore extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); - this.score = packet.readInt(); - this.count = packet.readInt(); + int score = packet.readInt(); + + if(score < 1 || score > 100) + throw new WiredSaveException("Score is invalid"); + + int timesPerGame = packet.readInt(); + + if(timesPerGame < 1 || timesPerGame > 10) + throw new WiredSaveException("Times per game is invalid"); + packet.readString(); packet.readInt(); - this.setDelay(packet.readInt()); + + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.score = score; + this.count = timesPerGame; + this.setDelay(delay); return true; } @@ -163,4 +194,16 @@ public class WiredEffectGiveScore extends InteractionWiredEffect { public boolean requiresTriggeringUser() { return true; } + + static class JsonData { + int score; + int count; + int delay; + + public JsonData(int score, int count, int delay) { + this.score = score; + this.count = count; + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveScoreToTeam.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveScoreToTeam.java index 738fc508..dcbc1481 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveScoreToTeam.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveScoreToTeam.java @@ -1,17 +1,20 @@ package com.eu.habbo.habbohotel.items.interactions.wired.effects; +import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.games.Game; +import com.eu.habbo.habbohotel.games.GameState; import com.eu.habbo.habbohotel.games.GameTeam; import com.eu.habbo.habbohotel.games.GameTeamColors; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; -import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.wired.WiredEffectType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import gnu.trove.map.hash.TIntIntHashMap; import java.sql.ResultSet; @@ -36,49 +39,52 @@ public class WiredEffectGiveScoreToTeam extends InteractionWiredEffect { @Override public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) { - Habbo habbo = room.getHabbo(roomUnit); + for (Game game : room.getGames()) { + if (game != null && game.state.equals(GameState.RUNNING)) { + int c = this.startTimes.get(game.getStartTime()); - if (habbo != null) { - Class game = habbo.getHabboInfo().getCurrentGame(); + if (c < this.count) { + GameTeam team = game.getTeam(this.teamColor); - if (game != null) { - Game g = room.getGame(game); + if (team != null) { + team.addTeamScore(this.points); - if (g != null) { - int c = this.startTimes.get(g.getStartTime()); - - if (c < this.count) { - GameTeam team = g.getTeam(this.teamColor); - - if (team != null) { - team.addTeamScore(this.points); - - this.startTimes.put(g.getStartTime(), c++); - - return true; - } + this.startTimes.put(game.getStartTime(), c + 1); } } } } - return false; + return true; } @Override public String getWiredData() { - return this.points + ";" + this.count + ";" + this.teamColor.type + ";" + this.getDelay(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.points, this.count, this.teamColor, this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split(";"); + String wiredData = set.getString("wired_data"); - if (data.length == 4) { - this.points = Integer.valueOf(data[0]); - this.count = Integer.valueOf(data[1]); - this.teamColor = GameTeamColors.values()[Integer.valueOf(data[2])]; - this.setDelay(Integer.valueOf(data[3])); + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.points = data.score; + this.count = data.count; + this.teamColor = data.team; + this.setDelay(data.delay); + } + else { + String[] data = set.getString("wired_data").split(";"); + + if (data.length == 4) { + this.points = Integer.valueOf(data[0]); + this.count = Integer.valueOf(data[1]); + this.teamColor = GameTeamColors.values()[Integer.valueOf(data[2])]; + this.setDelay(Integer.valueOf(data[3])); + } + + this.needsUpdate(true); } } @@ -115,15 +121,51 @@ public class WiredEffectGiveScoreToTeam extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); - this.points = packet.readInt(); - this.count = packet.readInt(); - this.teamColor = GameTeamColors.values()[packet.readInt()]; + int points = packet.readInt(); + + if(points < 1 || points > 100) + throw new WiredSaveException("Points is invalid"); + + int timesPerGame = packet.readInt(); + + if(timesPerGame < 1 || timesPerGame > 10) + throw new WiredSaveException("Times per game is invalid"); + + int team = packet.readInt(); + + if(team < 1 || team > 4) + throw new WiredSaveException("Team is invalid"); + packet.readString(); packet.readInt(); - this.setDelay(packet.readInt()); + + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.points = points; + this.count = timesPerGame; + this.teamColor = GameTeamColors.values()[team]; + this.setDelay(delay); + return true; } + + static class JsonData { + int score; + int count; + GameTeamColors team; + int delay; + + public JsonData(int score, int count, GameTeamColors team, int delay) { + this.score = score; + this.count = count; + this.team = team; + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectJoinTeam.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectJoinTeam.java index 3285865a..8d367009 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectJoinTeam.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectJoinTeam.java @@ -1,6 +1,8 @@ package com.eu.habbo.habbohotel.items.interactions.wired.effects; +import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.gameclients.GameClient; +import com.eu.habbo.habbohotel.games.Game; import com.eu.habbo.habbohotel.games.GameTeamColors; import com.eu.habbo.habbohotel.games.wired.WiredGame; import com.eu.habbo.habbohotel.items.Item; @@ -10,8 +12,10 @@ import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.wired.WiredEffectType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import gnu.trove.procedure.TObjectProcedure; import java.sql.ResultSet; @@ -37,16 +41,19 @@ public class WiredEffectJoinTeam extends InteractionWiredEffect { Habbo habbo = room.getHabbo(roomUnit); if (habbo != null) { - if (habbo.getHabboInfo().getGamePlayer() == null) { - WiredGame game = (WiredGame) room.getGame(WiredGame.class); + WiredGame game = (WiredGame) room.getGameOrCreate(WiredGame.class); - if (game == null) { - game = new WiredGame(room); - room.addGame(game); - } - - return game.addHabbo(habbo, this.teamColor); + if (habbo.getHabboInfo().getGamePlayer() != null && habbo.getHabboInfo().getCurrentGame() != null && (habbo.getHabboInfo().getCurrentGame() != WiredGame.class || (habbo.getHabboInfo().getCurrentGame() == WiredGame.class && habbo.getHabboInfo().getGamePlayer().getTeamColor() != this.teamColor))) { + // remove from current game + Game currentGame = room.getGame(habbo.getHabboInfo().getCurrentGame()); + currentGame.removeHabbo(habbo); } + + if(habbo.getHabboInfo().getGamePlayer() == null) { + game.addHabbo(habbo, this.teamColor); + } + + return true; } return false; @@ -54,19 +61,30 @@ public class WiredEffectJoinTeam extends InteractionWiredEffect { @Override public String getWiredData() { - return this.getDelay() + "\t" + this.teamColor.type + ""; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.teamColor, this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split("\t"); + String wiredData = set.getString("wired_data"); - if (data.length >= 1) { - this.setDelay(Integer.valueOf(data[0])); + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + this.teamColor = data.team; + } + else { + String[] data = set.getString("wired_data").split("\t"); - if (data.length >= 2) { - this.teamColor = GameTeamColors.values()[Integer.valueOf(data[1])]; + if (data.length >= 1) { + this.setDelay(Integer.valueOf(data[0])); + + if (data.length >= 2) { + this.teamColor = GameTeamColors.values()[Integer.valueOf(data[1])]; + } } + + this.needsUpdate(true); } } @@ -116,12 +134,22 @@ public class WiredEffectJoinTeam extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { + packet.readInt(); + int team = packet.readInt(); + + if(team < 1 || team > 4) + throw new WiredSaveException("Team is invalid"); + packet.readInt(); - this.teamColor = GameTeamColors.values()[packet.readInt()]; - int unknownInt = packet.readInt(); packet.readString(); - this.setDelay(packet.readInt()); + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.teamColor = GameTeamColors.values()[team]; + this.setDelay(delay); return true; } @@ -130,4 +158,14 @@ public class WiredEffectJoinTeam extends InteractionWiredEffect { public boolean requiresTriggeringUser() { return true; } + + static class JsonData { + GameTeamColors team; + int delay; + + public JsonData(GameTeamColors team, int delay) { + this.team = team; + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectKickHabbo.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectKickHabbo.java index 72897ebf..e0f2ecd2 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectKickHabbo.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectKickHabbo.java @@ -12,8 +12,10 @@ import com.eu.habbo.habbohotel.rooms.RoomChatMessageBubbles; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.wired.WiredEffectType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserWhisperComposer; import com.eu.habbo.threading.runnables.RoomUnitKick; import gnu.trove.procedure.TObjectProcedure; @@ -69,24 +71,35 @@ public class WiredEffectKickHabbo extends InteractionWiredEffect { @Override public String getWiredData() { - return this.getDelay() + "\t" + this.message; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.message, this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - try { - String[] data = set.getString("wired_data").split("\t"); + String wiredData = set.getString("wired_data"); - if (data.length >= 1) { - this.setDelay(Integer.valueOf(data[0])); + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + this.message = data.message; + } + else { + try { + String[] data = set.getString("wired_data").split("\t"); - if (data.length >= 2) { - this.message = data[1]; + if (data.length >= 1) { + this.setDelay(Integer.valueOf(data[0])); + + if (data.length >= 2) { + this.message = data[1]; + } } + } catch (Exception e) { + this.message = ""; + this.setDelay(0); } - } catch (Exception e) { - this.message = ""; - this.setDelay(0); + + this.needsUpdate(true); } } @@ -135,11 +148,17 @@ public class WiredEffectKickHabbo extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); - this.message = packet.readString(); + String message = packet.readString(); packet.readInt(); - this.setDelay(packet.readInt()); + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.message = message.substring(0, Math.min(message.length(), Emulator.getConfig().getInt("hotel.wired.message.max_length", 100))); + this.setDelay(delay); return true; } @@ -148,4 +167,14 @@ public class WiredEffectKickHabbo extends InteractionWiredEffect { public boolean requiresTriggeringUser() { return true; } + + static class JsonData { + String message; + int delay; + + public JsonData(String message, int delay) { + this.message = message; + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectLeaveTeam.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectLeaveTeam.java index 248adcda..deff061e 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectLeaveTeam.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectLeaveTeam.java @@ -1,5 +1,6 @@ package com.eu.habbo.habbohotel.items.interactions.wired.effects; +import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.games.Game; import com.eu.habbo.habbohotel.games.wired.WiredGame; @@ -10,8 +11,10 @@ import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.wired.WiredEffectType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import gnu.trove.procedure.TObjectProcedure; import java.sql.ResultSet; @@ -39,7 +42,7 @@ public class WiredEffectLeaveTeam extends InteractionWiredEffect { Game game = room.getGame(habbo.getHabboInfo().getCurrentGame()); if (game == null) { - game = room.getGame(WiredGame.class); + game = room.getGameOrCreate(WiredGame.class); } if (game != null) { @@ -53,12 +56,20 @@ public class WiredEffectLeaveTeam extends InteractionWiredEffect { @Override public String getWiredData() { - return this.getDelay() + ""; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - this.setDelay(Integer.valueOf(set.getString("wired_data"))); + String wiredData = set.getString("wired_data"); + + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + } + else { + this.setDelay(Integer.valueOf(wiredData)); + } } @Override @@ -105,11 +116,24 @@ public class WiredEffectLeaveTeam extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); packet.readString(); packet.readInt(); - this.setDelay(packet.readInt()); + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.setDelay(delay); return true; } + + static class JsonData { + int delay; + + public JsonData(int delay) { + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMatchFurni.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMatchFurni.java index 6b337571..bb615d8d 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMatchFurni.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMatchFurni.java @@ -3,18 +3,16 @@ package com.eu.habbo.habbohotel.items.interactions.wired.effects; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.Item; -import com.eu.habbo.habbohotel.items.interactions.InteractionRoller; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect; -import com.eu.habbo.habbohotel.rooms.Room; -import com.eu.habbo.habbohotel.rooms.RoomTile; -import com.eu.habbo.habbohotel.rooms.RoomTileState; -import com.eu.habbo.habbohotel.rooms.RoomUnit; +import com.eu.habbo.habbohotel.items.interactions.wired.interfaces.InteractionWiredMatchFurniSettings; +import com.eu.habbo.habbohotel.rooms.*; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.habbohotel.wired.WiredEffectType; import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.habbohotel.wired.WiredMatchFurniSetting; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import com.eu.habbo.messages.outgoing.rooms.items.FloorItemOnRollerComposer; import gnu.trove.set.hash.THashSet; import org.slf4j.Logger; @@ -22,8 +20,11 @@ import org.slf4j.LoggerFactory; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; -public class WiredEffectMatchFurni extends InteractionWiredEffect { +public class WiredEffectMatchFurni extends InteractionWiredEffect implements InteractionWiredMatchFurniSettings { private static final Logger LOGGER = LoggerFactory.getLogger(WiredEffectMatchFurni.class); private static final WiredEffectType type = WiredEffectType.MATCH_SSHOT; @@ -45,163 +46,94 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect { @Override public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) { - THashSet tilesToUpdate = new THashSet<>(this.settings.size()); - //this.refresh(); if(this.settings.isEmpty()) - return false; + return true; for (WiredMatchFurniSetting setting : this.settings) { - HabboItem item = room.getHabboItem(setting.itemId); + HabboItem item = room.getHabboItem(setting.item_id); if (item != null) { if (this.state && (this.checkForWiredResetPermission && item.allowWiredResetState())) { - if (!setting.state.equals(" ")) { + if (!setting.state.equals(" ") && !item.getExtradata().equals(setting.state)) { item.setExtradata(setting.state); - tilesToUpdate.addAll(room.getLayout().getTilesAt(room.getLayout().getTile(item.getX(), item.getY()), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation())); + room.updateItemState(item); } } - int oldRotation = item.getRotation(); - boolean slideAnimation = true; - double offsetZ = 0; + RoomTile oldLocation = room.getLayout().getTile(item.getX(), item.getY()); + double oldZ = item.getZ(); - if (this.direction && item.getRotation() != setting.rotation) { - item.setRotation(setting.rotation); - slideAnimation = false; - - room.scheduledTasks.add(() -> { - room.getLayout().getTilesAt(room.getLayout().getTile(item.getX(), item.getY()), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), oldRotation).forEach(t -> { - room.updateBotsAt(t.x, t.y); - room.updateHabbosAt(t.x, t.y); - }); - room.getLayout().getTilesAt(room.getLayout().getTile(item.getX(), item.getY()), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), setting.rotation).forEach(t -> { - room.updateBotsAt(t.x, t.y); - room.updateHabbosAt(t.x, t.y); - }); - }); + if(this.direction && !this.position) { + if(item.getRotation() != setting.rotation && room.furnitureFitsAt(oldLocation, item, setting.rotation, false) == FurnitureMovementError.NONE) { + room.moveFurniTo(item, oldLocation, setting.rotation, null, true); + } } + else if(this.position) { + boolean slideAnimation = !this.direction || item.getRotation() == setting.rotation; + RoomTile newLocation = room.getLayout().getTile((short) setting.x, (short) setting.y); + int newRotation = this.direction ? setting.rotation : item.getRotation(); - RoomTile t = null; - - if (this.position) { - t = room.getLayout().getTile((short) setting.x, (short) setting.y); - - if (t != null && t.state != RoomTileState.INVALID) { - boolean canMove = true; - - if (t.x == item.getX() && t.y == item.getY() || room.hasHabbosAt(t.x, t.y)) { - canMove = !(room.getTopItemAt(t.x, t.y) == item); - slideAnimation = false; - } - - - if (canMove && !room.hasHabbosAt(t.x, t.y)) { - THashSet tiles = room.getLayout().getTilesAt(t, item.getBaseItem().getWidth(), item.getBaseItem().getLength(), setting.rotation); - double highestZ = -1d; - for (RoomTile tile : tiles) { - if (tile.state == RoomTileState.INVALID) { - highestZ = -1d; - break; - } - - if (item instanceof InteractionRoller && room.hasItemsAt(tile.x, tile.y)) { - highestZ = -1d; - break; - } - - double stackHeight = room.getStackHeight(tile.x, tile.y, false, item); - if (stackHeight > highestZ) { - highestZ = stackHeight; - } - } - - if (highestZ != -1d) { - tilesToUpdate.addAll(tiles); - - offsetZ = highestZ - item.getZ(); - double totalHeight = item.getZ() + offsetZ; - if (totalHeight > 40) break; - tilesToUpdate.addAll(room.getLayout().getTilesAt(room.getLayout().getTile(item.getX(), item.getY()), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), oldRotation)); - - if (!slideAnimation) { - item.setX(t.x); - item.setY(t.y); - } + if(newLocation != null && newLocation.state != RoomTileState.INVALID && (newLocation != oldLocation || newRotation != item.getRotation()) && room.furnitureFitsAt(newLocation, item, newRotation, true) == FurnitureMovementError.NONE) { + if(room.moveFurniTo(item, newLocation, newRotation, null, !slideAnimation) == FurnitureMovementError.NONE) { + if(slideAnimation) { + room.sendComposer(new FloorItemOnRollerComposer(item, null, oldLocation, oldZ, newLocation, item.getZ(), 0, room).compose()); } } } } - if (slideAnimation && t != null) { - room.sendComposer(new FloorItemOnRollerComposer(item, null, t, offsetZ, room).compose()); - } else { - room.updateItem(item); - } - - item.needsUpdate(true); } } - room.updateTiles(tilesToUpdate); - return true; } @Override public String getWiredData() { this.refresh(); - - StringBuilder data = new StringBuilder(this.settings.size() + ":"); - - if (this.settings.isEmpty()) { - data.append(";"); - } else { - Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); - - for (WiredMatchFurniSetting item : this.settings) { - HabboItem i; - - if (room != null) { - i = room.getHabboItem(item.itemId); - - if (i != null) { - data.append(item.toString(this.checkForWiredResetPermission && i.allowWiredResetState())).append(";"); - } - } - } - } - - data.append(":").append(this.state ? 1 : 0).append(":").append(this.direction ? 1 : 0).append(":").append(this.position ? 1 : 0).append(":").append(this.getDelay()); - - return data.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.state, this.direction, this.position, new ArrayList(this.settings), this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split(":"); + String wiredData = set.getString("wired_data"); - int itemCount = Integer.valueOf(data[0]); - - String[] items = data[1].split(";"); - - for (int i = 0; i < items.length; i++) { - try { - - String[] stuff = items[i].split("-"); - - if (stuff.length >= 5) { - this.settings.add(new WiredMatchFurniSetting(Integer.valueOf(stuff[0]), stuff[1], Integer.valueOf(stuff[2]), Integer.valueOf(stuff[3]), Integer.valueOf(stuff[4]))); - } - - } catch (Exception e) { - LOGGER.error("Caught exception", e); - } + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + this.state = data.state; + this.direction = data.direction; + this.position = data.position; + this.settings.clear(); + this.settings.addAll(data.items); } + else { + String[] data = set.getString("wired_data").split(":"); - this.state = data[2].equals("1"); - this.direction = data[3].equals("1"); - this.position = data[4].equals("1"); - this.setDelay(Integer.valueOf(data[5])); + int itemCount = Integer.parseInt(data[0]); + + String[] items = data[1].split(Pattern.quote(";")); + + for (int i = 0; i < items.length; i++) { + try { + + String[] stuff = items[i].split(Pattern.quote("-")); + + if (stuff.length >= 5) { + this.settings.add(new WiredMatchFurniSetting(Integer.parseInt(stuff[0]), stuff[1], Integer.parseInt(stuff[2]), Integer.parseInt(stuff[3]), Integer.parseInt(stuff[4]))); + } + + } catch (Exception e) { + LOGGER.error("Caught exception", e); + } + } + + this.state = data[2].equals("1"); + this.direction = data[3].equals("1"); + this.position = data[4].equals("1"); + this.setDelay(Integer.parseInt(data[5])); + this.needsUpdate(true); + } } @Override @@ -227,7 +159,7 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect { message.appendInt(this.settings.size()); for (WiredMatchFurniSetting item : this.settings) - message.appendInt(item.itemId); + message.appendInt(item.item_id); message.appendInt(this.getBaseItem().getSpriteId()); message.appendInt(this.getId()); @@ -243,36 +175,49 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { - this.settings.clear(); - - //packet.readInt(); - - int count; + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); - this.state = packet.readInt() == 1; - this.direction = packet.readInt() == 1; - this.position = packet.readInt() == 1; + boolean setState = packet.readInt() == 1; + boolean setDirection = packet.readInt() == 1; + boolean setPosition = packet.readInt() == 1; packet.readString(); Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); if (room == null) - return true; + throw new WiredSaveException("Trying to save wired in unloaded room"); - count = packet.readInt(); + int itemsCount = packet.readInt(); - for (int i = 0; i < count; i++) { - int itemId = packet.readInt(); - HabboItem item = room.getHabboItem(itemId); - - if (item != null) - this.settings.add(new WiredMatchFurniSetting(item.getId(), this.checkForWiredResetPermission && item.allowWiredResetState() ? item.getExtradata() : " ", item.getRotation(), item.getX(), item.getY())); + if(itemsCount > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) { + throw new WiredSaveException("Too many furni selected"); } - this.setDelay(packet.readInt()); + List newSettings = new ArrayList<>(); + + for (int i = 0; i < itemsCount; i++) { + int itemId = packet.readInt(); + HabboItem it = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(itemId); + + if(it == null) + throw new WiredSaveException(String.format("Item %s not found", itemId)); + + newSettings.add(new WiredMatchFurniSetting(it.getId(), this.checkForWiredResetPermission && it.allowWiredResetState() ? it.getExtradata() : " ", it.getRotation(), it.getX(), it.getY())); + } + + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.state = setState; + this.direction = setDirection; + this.position = setPosition; + this.settings.clear(); + this.settings.addAll(newSettings); + this.setDelay(delay); return true; } @@ -284,7 +229,7 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect { THashSet remove = new THashSet<>(); for (WiredMatchFurniSetting setting : this.settings) { - HabboItem item = room.getHabboItem(setting.itemId); + HabboItem item = room.getHabboItem(setting.item_id); if (item == null) { remove.add(setting); } @@ -295,4 +240,40 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect { } } } + + @Override + public THashSet getMatchFurniSettings() { + return this.settings; + } + + @Override + public boolean shouldMatchState() { + return this.state; + } + + @Override + public boolean shouldMatchRotation() { + return this.direction; + } + + @Override + public boolean shouldMatchPosition() { + return this.position; + } + + static class JsonData { + boolean state; + boolean direction; + boolean position; + List items; + int delay; + + public JsonData(boolean state, boolean direction, boolean position, List items, int delay) { + this.state = state; + this.direction = direction; + this.position = position; + this.items = items; + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniAway.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniAway.java index 556e56c3..76fe1ed9 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniAway.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniAway.java @@ -12,11 +12,16 @@ import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.habbohotel.wired.WiredTriggerType; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import com.eu.habbo.messages.outgoing.rooms.items.FloorItemOnRollerComposer; import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; public class WiredEffectMoveFurniAway extends InteractionWiredEffect { public static final WiredEffectType type = WiredEffectType.FLEE; @@ -44,64 +49,47 @@ public class WiredEffectMoveFurniAway extends InteractionWiredEffect { for (HabboItem item : this.items) { RoomTile t = room.getLayout().getTile(item.getX(), item.getY()); - double shortest = 1000.0D; - Habbo target = null; - - for (Habbo habbo : room.getHabbos()) { - if (habbo.getRoomUnit().getCurrentLocation().distance(t) <= shortest) { - shortest = habbo.getRoomUnit().getCurrentLocation().distance(t); - target = habbo; - } - } + RoomUnit target = room.getRoomUnits().stream().min(Comparator.comparingDouble(a -> a.getCurrentLocation().distance(t))).orElse(null); if (target != null) { - if (RoomLayout.tilesAdjecent(target.getRoomUnit().getCurrentLocation(), room.getLayout().getTile(item.getX(), item.getY())) && (target.getRoomUnit().getX() == item.getX() || target.getRoomUnit().getY() == item.getY())) { - final Habbo finalTarget = target; - Emulator.getThreading().run(() -> WiredHandler.handle(WiredTriggerType.COLLISION, finalTarget.getRoomUnit(), room, new Object[]{item}), 500); - + if (target.getCurrentLocation().distance(t) <= 1) { + Emulator.getThreading().run(() -> WiredHandler.handle(WiredTriggerType.COLLISION, target, room, new Object[]{item}), 500); continue; } int x = 0; int y = 0; - if (target.getRoomUnit().getX() == item.getX()) { - if (item.getY() < target.getRoomUnit().getY()) + if (target.getX() == item.getX()) { + if (item.getY() < target.getY()) y--; else y++; - } else if (target.getRoomUnit().getY() == item.getY()) { - if (item.getX() < target.getRoomUnit().getX()) + } else if (target.getY() == item.getY()) { + if (item.getX() < target.getX()) x--; else x++; - } else if (target.getRoomUnit().getX() - item.getX() > target.getRoomUnit().getY() - item.getY()) { - if (target.getRoomUnit().getX() - item.getX() > 0) + } else if (target.getX() - item.getX() > target.getY() - item.getY()) { + if (target.getX() - item.getX() > 0) x--; else x++; } else { - if (target.getRoomUnit().getY() - item.getY() > 0) + if (target.getY() - item.getY() > 0) y--; else y++; } - RoomTile newTile = room.getLayout().getTile((short) (item.getX() + x), (short) (item.getY() + y)); + RoomTile newLocation = room.getLayout().getTile((short) (item.getX() + x), (short) (item.getY() + y)); + RoomTile oldLocation = room.getLayout().getTile(item.getX(), item.getY()); + double oldZ = item.getZ(); - if (newTile != null && newTile.state == RoomTileState.OPEN) { - if (room.getLayout().tileExists(newTile.x, newTile.y)) { - HabboItem topItem = room.getTopItemAt(newTile.x, newTile.y); - - if (topItem == null || topItem.getBaseItem().allowStack()) { - double offsetZ = 0; - - if (topItem != null) - offsetZ = topItem.getZ() + topItem.getBaseItem().getHeight() - item.getZ(); - - room.sendComposer(new FloorItemOnRollerComposer(item, null, newTile, offsetZ, room).compose()); - } + if(newLocation != null && newLocation.state != RoomTileState.INVALID && newLocation != oldLocation && room.furnitureFitsAt(newLocation, item, item.getRotation(), true) == FurnitureMovementError.NONE) { + if(room.moveFurniTo(item, newLocation, item.getRotation(), null, false) == FurnitureMovementError.NONE) { + room.sendComposer(new FloorItemOnRollerComposer(item, null, oldLocation, oldZ, newLocation, item.getZ(), 0, room).compose()); } } } @@ -111,32 +99,40 @@ public class WiredEffectMoveFurniAway extends InteractionWiredEffect { @Override public String getWiredData() { - StringBuilder wiredData = new StringBuilder(this.getDelay() + "\t"); - - if (this.items != null && !this.items.isEmpty()) { - for (HabboItem item : this.items) { - wiredData.append(item.getId()).append(";"); - } - } - - return wiredData.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.getDelay(), + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items = new THashSet<>(); - String[] wiredData = set.getString("wired_data").split("\t"); + String wiredData = set.getString("wired_data"); - if (wiredData.length >= 1) { - this.setDelay(Integer.valueOf(wiredData[0])); - } - if (wiredData.length == 2) { - if (wiredData[1].contains(";")) { - for (String s : wiredData[1].split(";")) { - HabboItem item = room.getHabboItem(Integer.valueOf(s)); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + for (Integer id: data.itemIds) { + HabboItem item = room.getHabboItem(id); + if (item != null) { + this.items.add(item); + } + } + } else { + String[] wiredDataOld = wiredData.split("\t"); - if (item != null) - this.items.add(item); + if (wiredDataOld.length >= 1) { + this.setDelay(Integer.parseInt(wiredDataOld[0])); + } + if (wiredDataOld.length == 2) { + if (wiredDataOld[1].contains(";")) { + for (String s : wiredDataOld[1].split(";")) { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item != null) + this.items.add(item); + } } } } @@ -182,19 +178,35 @@ public class WiredEffectMoveFurniAway extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); packet.readString(); + int itemsCount = packet.readInt(); - this.items.clear(); - - int count = packet.readInt(); - - for (int i = 0; i < count; i++) { - this.items.add(Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(packet.readInt())); + if(itemsCount > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) { + throw new WiredSaveException("Too many furni selected"); } - this.setDelay(packet.readInt()); + List newItems = new ArrayList<>(); + + for (int i = 0; i < itemsCount; i++) { + int itemId = packet.readInt(); + HabboItem it = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(itemId); + + if(it == null) + throw new WiredSaveException(String.format("Item %s not found", itemId)); + + newItems.add(it); + } + + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.items.clear(); + this.items.addAll(newItems); + this.setDelay(delay); return true; } @@ -203,4 +215,14 @@ public class WiredEffectMoveFurniAway extends InteractionWiredEffect { protected long requiredCooldown() { return 495; } + + static class JsonData { + int delay; + List itemIds; + + public JsonData(int delay, List itemIds) { + this.delay = delay; + this.itemIds = itemIds; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniTo.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniTo.java index bb7853c8..3b9367e2 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniTo.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniTo.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public class WiredEffectMoveFurniTo extends InteractionWiredEffect { public static final WiredEffectType type = WiredEffectType.MOVE_FURNI_TO; @@ -123,24 +124,23 @@ public class WiredEffectMoveFurniTo extends InteractionWiredEffect { @Override public String getWiredData() { - THashSet items = new THashSet<>(); + THashSet itemsToRemove = new THashSet<>(); for (HabboItem item : this.items) { if (item.getRoomId() != this.getRoomId() || Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(item.getId()) == null) - items.add(item); + itemsToRemove.add(item); } - for (HabboItem item : items) { + for (HabboItem item : itemsToRemove) { this.items.remove(item); } - StringBuilder data = new StringBuilder(this.direction + "\t" + this.spacing + "\t" + this.getDelay() + "\t"); - - for (HabboItem item : this.items) { - data.append(item.getId()).append("\r"); - } - - return data.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.direction, + this.spacing, + this.getDelay(), + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override @@ -176,22 +176,37 @@ public class WiredEffectMoveFurniTo extends InteractionWiredEffect { @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items.clear(); + String wiredData = set.getString("wired_data"); - String[] data = set.getString("wired_data").split("\t"); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.direction = data.direction; + this.spacing = data.spacing; + this.setDelay(data.delay); - if (data.length == 4) { - try { - this.direction = Integer.valueOf(data[0]); - this.spacing = Integer.valueOf(data[1]); - this.setDelay(Integer.valueOf(data[2])); - } catch (Exception e) { - } - - for (String s : data[3].split("\r")) { - HabboItem item = room.getHabboItem(Integer.valueOf(s)); - - if (item != null) + for (Integer id: data.itemIds) { + HabboItem item = room.getHabboItem(id); + if (item != null) { this.items.add(item); + } + } + } else { + String[] data = wiredData.split("\t"); + + if (data.length == 4) { + try { + this.direction = Integer.parseInt(data[0]); + this.spacing = Integer.parseInt(data[1]); + this.setDelay(Integer.parseInt(data[2])); + } catch (Exception e) { + } + + for (String s : data[3].split("\r")) { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item != null) + this.items.add(item); + } } } } @@ -209,4 +224,18 @@ public class WiredEffectMoveFurniTo extends InteractionWiredEffect { protected long requiredCooldown() { return 495; } + + static class JsonData { + int direction; + int spacing; + int delay; + List itemIds; + + public JsonData(int direction, int spacing, int delay, List itemIds) { + this.direction = direction; + this.spacing = spacing; + this.delay = delay; + this.itemIds = itemIds; + } + } } \ No newline at end of file diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniTowards.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniTowards.java index 849a59b2..c069dc93 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniTowards.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniTowards.java @@ -11,6 +11,7 @@ import com.eu.habbo.habbohotel.wired.WiredEffectType; import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import com.eu.habbo.messages.outgoing.rooms.items.FloorItemOnRollerComposer; import com.eu.habbo.threading.runnables.WiredCollissionRunnable; import gnu.trove.map.hash.THashMap; @@ -19,7 +20,9 @@ import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; /** * Wired effect: move to closest user @@ -82,7 +85,7 @@ public class WiredEffectMoveFurniTowards extends InteractionWiredEffect { @Override public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) { - THashSet items = new THashSet(); + THashSet items = new THashSet<>(); for (HabboItem item : this.items) { if (Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(item.getId()) == null) @@ -103,7 +106,7 @@ public class WiredEffectMoveFurniTowards extends InteractionWiredEffect { RoomUserRotation lastDirection = lastDirections.get(item.getId()); // 1. Check if any user is within 3 tiles from the item - Habbo target = null; // closest found user + RoomUnit target = null; // closest found user RoomLayout layout = room.getLayout(); boolean collided = false; @@ -128,12 +131,12 @@ public class WiredEffectMoveFurniTowards extends InteractionWiredEffect { } if (startTile != null && layout.tileExists(startTile.x, startTile.y)) { - THashSet habbosAtTile = room.getHabbosAt(startTile.x, startTile.y); - if (habbosAtTile.size() > 0) { - target = habbosAtTile.iterator().next(); + Collection roomUnitsAtTile = room.getRoomUnitsAt(startTile); + if (roomUnitsAtTile.size() > 0) { + target = roomUnitsAtTile.iterator().next(); if (i == 0) { // i = 0 means right next to it collided = true; - Emulator.getThreading().run(new WiredCollissionRunnable(target.getRoomUnit(), room, new Object[]{item})); + Emulator.getThreading().run(new WiredCollissionRunnable(target, room, new Object[]{item})); } break; } @@ -145,23 +148,23 @@ public class WiredEffectMoveFurniTowards extends InteractionWiredEffect { continue; if (target != null) { - if (target.getRoomUnit().getX() == item.getX()) { - if (item.getY() < target.getRoomUnit().getY()) + if (target.getX() == item.getX()) { + if (item.getY() < target.getY()) moveDirection = RoomUserRotation.SOUTH; else moveDirection = RoomUserRotation.NORTH; - } else if (target.getRoomUnit().getY() == item.getY()) { - if (item.getX() < target.getRoomUnit().getX()) + } else if (target.getY() == item.getY()) { + if (item.getX() < target.getX()) moveDirection = RoomUserRotation.EAST; else moveDirection = RoomUserRotation.WEST; - } else if (target.getRoomUnit().getX() - item.getX() > target.getRoomUnit().getY() - item.getY()) { - if (target.getRoomUnit().getX() - item.getX() > 0) + } else if (target.getX() - item.getX() > target.getY() - item.getY()) { + if (target.getX() - item.getX() > 0) moveDirection = RoomUserRotation.EAST; else moveDirection = RoomUserRotation.WEST; } else { - if (target.getRoomUnit().getY() - item.getY() > 0) + if (target.getY() - item.getY() > 0) moveDirection = RoomUserRotation.SOUTH; else moveDirection = RoomUserRotation.NORTH; @@ -213,13 +216,15 @@ public class WiredEffectMoveFurniTowards extends InteractionWiredEffect { RoomTile newTile = room.getLayout().getTileInFront(room.getLayout().getTile(item.getX(), item.getY()), moveDirection.getValue()); - if (newTile != null) { - lastDirections.put(item.getId(), moveDirection); + RoomTile oldLocation = room.getLayout().getTile(item.getX(), item.getY()); + double oldZ = item.getZ(); - FurnitureMovementError error = room.furnitureFitsAt(newTile, item, item.getRotation()); - if (error == FurnitureMovementError.NONE) { - double offset = room.getStackHeight(newTile.x, newTile.y, false, item) - item.getZ(); - room.sendComposer(new FloorItemOnRollerComposer(item, null, newTile, offset, room).compose()); + if(newTile != null) { + lastDirections.put(item.getId(), moveDirection); + if(newTile.state != RoomTileState.INVALID && newTile != oldLocation && room.furnitureFitsAt(newTile, item, item.getRotation(), true) == FurnitureMovementError.NONE) { + if (room.moveFurniTo(item, newTile, item.getRotation(), null, false) == FurnitureMovementError.NONE) { + room.sendComposer(new FloorItemOnRollerComposer(item, null, oldLocation, oldZ, newTile, item.getZ(), 0, room).compose()); + } } } } @@ -229,32 +234,41 @@ public class WiredEffectMoveFurniTowards extends InteractionWiredEffect { @Override public String getWiredData() { - StringBuilder wiredData = new StringBuilder(this.getDelay() + "\t"); - - if (this.items != null && !this.items.isEmpty()) { - for (HabboItem item : this.items) { - wiredData.append(item.getId()).append(";"); - } - } - - return wiredData.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.getDelay(), + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items = new THashSet<>(); - String[] wiredData = set.getString("wired_data").split("\t"); + String wiredData = set.getString("wired_data"); - if (wiredData.length >= 1) { - this.setDelay(Integer.valueOf(wiredData[0])); - } - if (wiredData.length == 2) { - if (wiredData[1].contains(";")) { - for (String s : wiredData[1].split(";")) { - HabboItem item = room.getHabboItem(Integer.valueOf(s)); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); - if (item != null) - this.items.add(item); + for (Integer id: data.itemIds) { + HabboItem item = room.getHabboItem(id); + if (item != null) { + this.items.add(item); + } + } + } else { + String[] wiredDataOld = wiredData.split("\t"); + + if (wiredDataOld.length >= 1) { + this.setDelay(Integer.parseInt(wiredDataOld[0])); + } + if (wiredDataOld.length == 2) { + if (wiredDataOld[1].contains(";")) { + for (String s : wiredDataOld[1].split(";")) { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item != null) + this.items.add(item); + } } } } @@ -300,19 +314,36 @@ public class WiredEffectMoveFurniTowards extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); packet.readString(); - this.items.clear(); + int itemsCount = packet.readInt(); - int count = packet.readInt(); - - for (int i = 0; i < count; i++) { - this.items.add(Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(packet.readInt())); + if(itemsCount > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) { + throw new WiredSaveException("Too many furni selected"); } - this.setDelay(packet.readInt()); + List newItems = new ArrayList<>(); + + for (int i = 0; i < itemsCount; i++) { + int itemId = packet.readInt(); + HabboItem it = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(itemId); + + if(it == null) + throw new WiredSaveException(String.format("Item %s not found", itemId)); + + newItems.add(it); + } + + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.items.clear(); + this.items.addAll(newItems); + this.setDelay(delay); return true; } @@ -321,4 +352,14 @@ public class WiredEffectMoveFurniTowards extends InteractionWiredEffect { protected long requiredCooldown() { return 495; } + + static class JsonData { + int delay; + List itemIds; + + public JsonData(int delay, List itemIds) { + this.delay = delay; + this.itemIds = itemIds; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveRotateFurni.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveRotateFurni.java index ae37a0f3..5928e671 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveRotateFurni.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveRotateFurni.java @@ -2,210 +2,141 @@ package com.eu.habbo.habbohotel.items.interactions.wired.effects; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.gameclients.GameClient; +import com.eu.habbo.habbohotel.items.ICycleable; import com.eu.habbo.habbohotel.items.Item; -import com.eu.habbo.habbohotel.items.interactions.InteractionRoller; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect; import com.eu.habbo.habbohotel.rooms.*; -import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboItem; 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.ClientMessage; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.outgoing.rooms.items.FloorItemOnRollerComposer; -import com.eu.habbo.messages.outgoing.rooms.items.FloorItemUpdateComposer; import gnu.trove.set.hash.THashSet; -import org.apache.commons.math3.util.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import java.awt.*; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +public class WiredEffectMoveRotateFurni extends InteractionWiredEffect implements ICycleable { + + private static final Logger LOGGER = LoggerFactory.getLogger(WiredEffectMoveRotateFurni.class); -public class WiredEffectMoveRotateFurni extends InteractionWiredEffect { public static final WiredEffectType type = WiredEffectType.MOVE_ROTATE; private final THashSet items = new THashSet<>(WiredHandler.MAXIMUM_FURNI_SELECTION / 2); private int direction; private int rotation; + private THashSet itemCooldowns; public WiredEffectMoveRotateFurni(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); + this.itemCooldowns = new THashSet<>(); } public WiredEffectMoveRotateFurni(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) { super(id, userId, item, extradata, limitedStack, limitedSells); + this.itemCooldowns = new THashSet<>(); } @Override public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) { // remove items that are no longer in the room - this.items.removeIf( item -> Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(item.getId()) == null); - - THashSet tilesToUpdate = new THashSet<>(Math.min(this.items.size(), 10)); + this.items.removeIf(item -> Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(item.getId()) == null); for (HabboItem item : this.items) { - //Handle rotation - if (this.rotation > 0) { - tilesToUpdate.addAll(room.getLayout().getTilesAt(room.getLayout().getTile(item.getX(), item.getY()), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation())); - int newRotation = this.getNewRotation(item); + if(this.itemCooldowns.contains(item)) + continue; - //Verify if rotation result in a valid position - FurnitureMovementError rotateError = room.furnitureFitsAt(room.getLayout().getTile(item.getX(), item.getY()), item, newRotation); - if (item.getRotation() != newRotation && (rotateError.equals(FurnitureMovementError.TILE_HAS_HABBOS) || rotateError.equals(FurnitureMovementError.TILE_HAS_PETS) || - rotateError.equals(FurnitureMovementError.TILE_HAS_BOTS) || rotateError.equals(FurnitureMovementError.NONE))) - { - item.setRotation(newRotation); - if(this.direction == 0) { - tilesToUpdate.addAll(room.getLayout().getTilesAt(room.getLayout().getTile(item.getX(), item.getY()), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation())); - room.sendComposer(new FloorItemUpdateComposer(item).compose()); - for (RoomTile t : tilesToUpdate) { - room.updateHabbosAt(t.x, t.y); - room.updateBotsAt(t.x, t.y); - } - } - } - } + int newRotation = this.rotation > 0 ? this.getNewRotation(item) : item.getRotation(); + RoomTile newLocation = room.getLayout().getTile(item.getX(), item.getY()); + RoomTile oldLocation = room.getLayout().getTile(item.getX(), item.getY()); + double oldZ = item.getZ(); - //handle movement - if (this.direction > 0) { + if(this.direction > 0) { RoomUserRotation moveDirection = this.getMovementDirection(); - boolean validMove = false; - RoomLayout layout = room.getLayout(); - if (layout == null) return false; - - RoomTile newTile = layout.getTile( - (short) (item.getX() + ((moveDirection == RoomUserRotation.WEST || moveDirection == RoomUserRotation.NORTH_WEST || moveDirection == RoomUserRotation.SOUTH_WEST) ? -1 : (((moveDirection == RoomUserRotation.EAST || moveDirection == RoomUserRotation.SOUTH_EAST || moveDirection == RoomUserRotation.NORTH_EAST) ? 1 : 0)))), - (short) (item.getY() + ((moveDirection == RoomUserRotation.NORTH || moveDirection == RoomUserRotation.NORTH_EAST || moveDirection == RoomUserRotation.NORTH_WEST) ? 1 : ((moveDirection == RoomUserRotation.SOUTH || moveDirection == RoomUserRotation.SOUTH_EAST || moveDirection == RoomUserRotation.SOUTH_WEST) ? -1 : 0))) + newLocation = room.getLayout().getTile( + (short) (item.getX() + ((moveDirection == RoomUserRotation.WEST || moveDirection == RoomUserRotation.NORTH_WEST || moveDirection == RoomUserRotation.SOUTH_WEST) ? -1 : (((moveDirection == RoomUserRotation.EAST || moveDirection == RoomUserRotation.SOUTH_EAST || moveDirection == RoomUserRotation.NORTH_EAST) ? 1 : 0)))), + (short) (item.getY() + ((moveDirection == RoomUserRotation.NORTH || moveDirection == RoomUserRotation.NORTH_EAST || moveDirection == RoomUserRotation.NORTH_WEST) ? 1 : ((moveDirection == RoomUserRotation.SOUTH || moveDirection == RoomUserRotation.SOUTH_EAST || moveDirection == RoomUserRotation.SOUTH_WEST) ? -1 : 0))) ); + } - if (newTile != null) { - boolean hasHabbos = false; - for (Habbo habbo : room.getHabbosAt(newTile)) { - hasHabbos = true; - WiredHandler.handle(WiredTriggerType.COLLISION, habbo.getRoomUnit(), room, new Object[]{item}); - } + boolean slideAnimation = item.getRotation() == newRotation; - if (!hasHabbos && room.getStackHeight(newTile.x, newTile.y, true, item) != Short.MAX_VALUE) { - java.awt.Rectangle rectangle = new Rectangle(newTile.x, - newTile.y, - item.getBaseItem().getWidth(), - item.getBaseItem().getLength()); - - double offset = -Short.MAX_VALUE; - validMove = true; - for (short x = (short) rectangle.x; x < rectangle.x + rectangle.getWidth(); x++) { - if (!validMove) { - break; - } - - for (short y = (short) rectangle.y; y < rectangle.y + rectangle.getHeight(); y++) { - RoomTile tile = layout.getTile(x, y); - if (tile == null || tile.state == RoomTileState.INVALID || !tile.getAllowStack()) { - validMove = false; - break; - } - - THashSet itemsAtNewTile = room.getItemsAt(tile); - if (item instanceof InteractionRoller && !itemsAtNewTile.isEmpty()) { - validMove = false; - break; - } - - ArrayList>> tileItems = new ArrayList<>(rectangle.width * rectangle.height); - tileItems.add(Pair.create(tile, itemsAtNewTile)); - if (!item.canStackAt(room, tileItems)) { - validMove = false; - break; - } - - HabboItem i = room.getTopItemAt(x, y, item); - if (i != null && !i.getBaseItem().allowStack()) { - validMove = false; - break; - } - - offset = Math.max(room.getStackHeight(newTile.x, newTile.y, false, item) - item.getZ(), offset); - - tilesToUpdate.add(tile); - } - } - if (item.getZ() + offset > 40) { - offset = 40 - item.getZ(); - } - - if (validMove) { - if(this.rotation > 0) { - item.setX(newTile.x); - item.setY(newTile.y); - item.setZ(item.getZ() + offset); - room.sendComposer(new FloorItemUpdateComposer(item).compose()); - for (RoomTile t : tilesToUpdate) { - room.updateHabbosAt(t.x, t.y); - room.updateBotsAt(t.x, t.y); - } - } - else { - room.sendComposer(new FloorItemOnRollerComposer(item, null, newTile, offset, room).compose()); - } - } + FurnitureMovementError furniMoveTest = room.furnitureFitsAt(newLocation, item, newRotation, true); + if(newLocation != null && newLocation.state != RoomTileState.INVALID && (newLocation != oldLocation || newRotation != item.getRotation()) && (furniMoveTest == FurnitureMovementError.NONE || ((furniMoveTest == FurnitureMovementError.TILE_HAS_BOTS || furniMoveTest == FurnitureMovementError.TILE_HAS_HABBOS || furniMoveTest == FurnitureMovementError.TILE_HAS_PETS) && newLocation == oldLocation))) { + if(room.furnitureFitsAt(newLocation, item, newRotation, false) == FurnitureMovementError.NONE && room.moveFurniTo(item, newLocation, newRotation, null, !slideAnimation) == FurnitureMovementError.NONE) { + this.itemCooldowns.add(item); + if(slideAnimation) { + room.sendComposer(new FloorItemOnRollerComposer(item, null, oldLocation, oldZ, newLocation, item.getZ(), 0, room).compose()); } } } } - if (!tilesToUpdate.isEmpty()) { - room.updateTiles(tilesToUpdate); - } - return true; } @Override public String getWiredData() { - THashSet items = new THashSet<>(this.items.size() / 2); + THashSet itemsToRemove = new THashSet<>(this.items.size() / 2); Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); for (HabboItem item : this.items) { if (item.getRoomId() != this.getRoomId() || (room != null && room.getHabboItem(item.getId()) == null)) - items.add(item); + itemsToRemove.add(item); } - for (HabboItem item : items) { + for (HabboItem item : itemsToRemove) { this.items.remove(item); } - StringBuilder data = new StringBuilder(this.direction + "\t" + - this.rotation + "\t" + - this.getDelay() + "\t"); - - for (HabboItem item : this.items) { - data.append(item.getId()).append("\r"); - } - - return data.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.direction, + this.rotation, + this.getDelay(), + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items.clear(); + String wiredData = set.getString("wired_data"); - String[] data = set.getString("wired_data").split("\t"); - - if (data.length == 4) { - try { - this.direction = Integer.parseInt(data[0]); - this.rotation = Integer.parseInt(data[1]); - this.setDelay(Integer.parseInt(data[2])); - } catch (Exception e) { - } - - for (String s : data[3].split("\r")) { - HabboItem item = room.getHabboItem(Integer.parseInt(s)); - - if (item != null) + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + this.direction = data.direction; + this.rotation = data.rotation; + for (Integer id: data.itemIds) { + HabboItem item = room.getHabboItem(id); + if (item != null) { this.items.add(item); + } + } + } else { + String[] data = wiredData.split("\t"); + + if (data.length == 4) { + try { + this.direction = Integer.parseInt(data[0]); + this.rotation = Integer.parseInt(data[1]); + this.setDelay(Integer.parseInt(data[2])); + } catch (Exception e) { + System.out.println(e); + } + + for (String s : data[3].split("\r")) { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item != null) + this.items.add(item); + } } } } @@ -225,7 +156,7 @@ public class WiredEffectMoveRotateFurni extends InteractionWiredEffect { @Override public void serializeWiredData(ServerMessage message, Room room) { - THashSet items = new THashSet<>(this.items.size() / 2); + THashSet items = new THashSet<>(); for (HabboItem item : this.items) { if (item.getRoomId() != this.getRoomId() || Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(item.getId()) == null) @@ -268,6 +199,7 @@ public class WiredEffectMoveRotateFurni extends InteractionWiredEffect { packet.readString(); int count = packet.readInt(); + if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count", 5)) return false; this.items.clear(); for (int i = 0; i < count; i++) { @@ -282,30 +214,78 @@ public class WiredEffectMoveRotateFurni extends InteractionWiredEffect { /** * Returns a new rotation for an item based on the wired options - * @param item + * + * @param item HabboItem * @return new rotation */ private int getNewRotation(HabboItem item) { int rotationToAdd = 0; - if (this.rotation == 1) { - rotationToAdd = 2; - } else if (this.rotation == 2) { - rotationToAdd = 6; + + if(item.getMaximumRotations() == 2) { + return item.getRotation() == 0 ? 4 : 0; } - //Random rotation - else if (this.rotation == 3) { - if (Emulator.getRandom().nextInt(2) == 1) { - rotationToAdd = 2; - } else { - rotationToAdd = 6; + else if(item.getMaximumRotations() == 1) { + return item.getRotation(); + } + else if(item.getMaximumRotations() > 4) { + if (this.rotation == 1) { + return item.getRotation() == item.getMaximumRotations() - 1 ? 0 : item.getRotation() + 1; + } else if (this.rotation == 2) { + return item.getRotation() > 0 ? item.getRotation() - 1 : item.getMaximumRotations() - 1; + } else if (this.rotation == 3) { //Random rotation + THashSet possibleRotations = new THashSet<>(); + for (int i = 0; i < item.getMaximumRotations(); i++) + { + possibleRotations.add(i); + } + + possibleRotations.remove(item.getRotation()); + + if(possibleRotations.size() > 0) { + int index = Emulator.getRandom().nextInt(possibleRotations.size()); + Iterator iter = possibleRotations.iterator(); + for (int i = 0; i < index; i++) { + iter.next(); + } + return iter.next(); + } + } + } + else { + if (this.rotation == 1) { + return (item.getRotation() + 2) % 8; + } else if (this.rotation == 2) { + int rot = (item.getRotation() - 2) % 8; + if(rot < 0) { + rot += 8; + } + return rot; + } else if (this.rotation == 3) { //Random rotation + THashSet possibleRotations = new THashSet<>(); + for (int i = 0; i < item.getMaximumRotations(); i++) + { + possibleRotations.add(i * 2); + } + + possibleRotations.remove(item.getRotation()); + + if(possibleRotations.size() > 0) { + int index = Emulator.getRandom().nextInt(possibleRotations.size()); + Iterator iter = possibleRotations.iterator(); + for (int i = 0; i < index; i++) { + iter.next(); + } + return iter.next(); + } } } - return ((item.getRotation() + rotationToAdd) % 8) % (item.getBaseItem().getWidth() > 1 || item.getBaseItem().getLength() > 1 ? 4 : 8); + return item.getRotation(); } /** * Returns the direction of movement based on the wired settings + * * @return direction */ private RoomUserRotation getMovementDirection() { @@ -319,20 +299,35 @@ public class WiredEffectMoveRotateFurni extends InteractionWiredEffect { movemementDirection = RoomUserRotation.WEST; } } else if (this.direction == 3) { - if (Emulator.getRandom().nextInt(2) == 1) { - movemementDirection = RoomUserRotation.NORTH; - } else { + if (Emulator.getRandom().nextInt(2) != 1) { movemementDirection = RoomUserRotation.SOUTH; } } else if (this.direction == 4) { movemementDirection = RoomUserRotation.SOUTH; } else if (this.direction == 5) { movemementDirection = RoomUserRotation.EAST; - } else if (this.direction == 6) { - movemementDirection = RoomUserRotation.NORTH; } else if (this.direction == 7) { movemementDirection = RoomUserRotation.WEST; } return movemementDirection; } -} \ No newline at end of file + + @Override + public void cycle(Room room) { + this.itemCooldowns.clear(); + } + + static class JsonData { + int direction; + int rotation; + int delay; + List itemIds; + + public JsonData(int direction, int rotation, int delay, List itemIds) { + this.direction = direction; + this.rotation = rotation; + this.delay = delay; + this.itemIds = itemIds; + } + } +} diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMuteHabbo.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMuteHabbo.java index 27a1d2b3..39788018 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMuteHabbo.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMuteHabbo.java @@ -10,6 +10,7 @@ import com.eu.habbo.habbohotel.rooms.RoomChatMessageBubbles; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.wired.WiredEffectType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserWhisperComposer; @@ -79,19 +80,32 @@ public class WiredEffectMuteHabbo extends InteractionWiredEffect { @Override public String getWiredData() { - return this.getDelay() + "\t" + this.length + "\t" + this.message; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.getDelay(), + this.length, + this.message + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split("\t"); + String wiredData = set.getString("wired_data"); - if (data.length >= 3) { - try { - this.setDelay(Integer.valueOf(data[0])); - this.length = Integer.valueOf(data[1]); - this.message = data[2]; - } catch (Exception e) { + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + this.length = data.length; + this.message = data.message; + } else { + String[] data = wiredData.split("\t"); + + if (data.length >= 3) { + try { + this.setDelay(Integer.valueOf(data[0])); + this.length = Integer.valueOf(data[1]); + this.message = data[2]; + } catch (Exception e) { + } } } } @@ -112,4 +126,16 @@ public class WiredEffectMuteHabbo extends InteractionWiredEffect { public boolean requiresTriggeringUser() { return true; } + + static class JsonData { + int delay; + int length; + String message; + + public JsonData(int delay, int length, String message) { + this.delay = delay; + this.length = length; + this.message = message; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectResetTimers.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectResetTimers.java index 5d6f6cfe..583e4f6a 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectResetTimers.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectResetTimers.java @@ -8,6 +8,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.wired.WiredEffectType; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.threading.runnables.WiredResetTimers; @@ -85,17 +86,25 @@ public class WiredEffectResetTimers extends InteractionWiredEffect { @Override public String getWiredData() { - return this.delay + ""; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.delay + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String data = set.getString("wired_data"); + String wiredData = set.getString("wired_data"); - try { - if (!data.equals("")) - this.delay = Integer.valueOf(data); - } catch (Exception e) { + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.delay = data.delay; + } else { + try { + if (!wiredData.equals("")) { + this.delay = Integer.parseInt(wiredData); + } + } catch (Exception e) { + } } this.setDelay(this.delay); @@ -111,4 +120,12 @@ public class WiredEffectResetTimers extends InteractionWiredEffect { public WiredEffectType getType() { return type; } + + static class JsonData { + int delay; + + public JsonData(int delay) { + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTeleport.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTeleport.java index ebd7254a..304703f1 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTeleport.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTeleport.java @@ -14,6 +14,7 @@ import com.eu.habbo.habbohotel.wired.WiredEffectType; import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserEffectComposer; import com.eu.habbo.threading.runnables.RoomUnitTeleport; import com.eu.habbo.threading.runnables.SendRoomUnitEffectComposer; @@ -25,6 +26,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; public class WiredEffectTeleport extends InteractionWiredEffect { public static final WiredEffectType type = WiredEffectType.TELEPORT; @@ -78,6 +80,7 @@ public class WiredEffectTeleport extends InteractionWiredEffect { } } + Emulator.getThreading().run(() -> { roomUnit.isWiredTeleporting = true; }, Math.max(0, WiredHandler.TELEPORT_DELAY - 500)); Emulator.getThreading().run(new RoomUnitTeleport(roomUnit, room, tile.x, tile.y, tile.getStackHeight() + (tile.state == RoomTileState.SIT ? -0.5 : 0), roomUnit.getEffectId()), WiredHandler.TELEPORT_DELAY); } @@ -127,19 +130,36 @@ public class WiredEffectTeleport extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); packet.readString(); - this.items.clear(); + int itemsCount = packet.readInt(); - int count = packet.readInt(); - - for (int i = 0; i < count; i++) { - this.items.add(Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(packet.readInt())); + if(itemsCount > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) { + throw new WiredSaveException("Too many furni selected"); } - this.setDelay(packet.readInt()); + List newItems = new ArrayList<>(); + + for (int i = 0; i < itemsCount; i++) { + int itemId = packet.readInt(); + HabboItem it = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(itemId); + + if(it == null) + throw new WiredSaveException(String.format("Item %s not found", itemId)); + + newItems.add(it); + } + + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.items.clear(); + this.items.addAll(newItems); + this.setDelay(delay); return true; } @@ -162,32 +182,40 @@ public class WiredEffectTeleport extends InteractionWiredEffect { @Override public String getWiredData() { - StringBuilder wiredData = new StringBuilder(this.getDelay() + "\t"); - - if (this.items != null && !this.items.isEmpty()) { - for (HabboItem item : this.items) { - wiredData.append(item.getId()).append(";"); - } - } - - return wiredData.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.getDelay(), + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items = new ArrayList<>(); - String[] wiredData = set.getString("wired_data").split("\t"); + String wiredData = set.getString("wired_data"); - if (wiredData.length >= 1) { - this.setDelay(Integer.valueOf(wiredData[0])); - } - if (wiredData.length == 2) { - if (wiredData[1].contains(";")) { - for (String s : wiredData[1].split(";")) { - HabboItem item = room.getHabboItem(Integer.valueOf(s)); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + for (Integer id: data.itemIds) { + HabboItem item = room.getHabboItem(id); + if (item != null) { + this.items.add(item); + } + } + } else { + String[] wiredDataOld = wiredData.split("\t"); - if (item != null) - this.items.add(item); + if (wiredDataOld.length >= 1) { + this.setDelay(Integer.parseInt(wiredDataOld[0])); + } + if (wiredDataOld.length == 2) { + if (wiredDataOld[1].contains(";")) { + for (String s : wiredDataOld[1].split(";")) { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item != null) + this.items.add(item); + } } } } @@ -213,4 +241,14 @@ public class WiredEffectTeleport extends InteractionWiredEffect { protected long requiredCooldown() { return 50L; } + + static class JsonData { + int delay; + List itemIds; + + public JsonData(int delay, List itemIds) { + this.delay = delay; + this.itemIds = itemIds; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectToggleFurni.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectToggleFurni.java index e602c042..05eef1f3 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectToggleFurni.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectToggleFurni.java @@ -3,12 +3,20 @@ package com.eu.habbo.habbohotel.items.interactions.wired.effects; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.Item; -import com.eu.habbo.habbohotel.items.interactions.InteractionCrackable; -import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect; -import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger; +import com.eu.habbo.habbohotel.items.interactions.*; +import com.eu.habbo.habbohotel.items.interactions.games.InteractionGameGate; +import com.eu.habbo.habbohotel.items.interactions.games.InteractionGameScoreboard; +import com.eu.habbo.habbohotel.items.interactions.games.InteractionGameTeamItem; import com.eu.habbo.habbohotel.items.interactions.games.InteractionGameTimer; +import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.InteractionBattleBanzaiPuck; +import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.InteractionBattleBanzaiTeleporter; +import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.InteractionBattleBanzaiTile; import com.eu.habbo.habbohotel.items.interactions.games.freeze.InteractionFreezeBlock; +import com.eu.habbo.habbohotel.items.interactions.games.freeze.InteractionFreezeExitTile; import com.eu.habbo.habbohotel.items.interactions.games.freeze.InteractionFreezeTile; +import com.eu.habbo.habbohotel.items.interactions.games.tag.InteractionTagField; +import com.eu.habbo.habbohotel.items.interactions.games.tag.InteractionTagPole; +import com.eu.habbo.habbohotel.items.interactions.pets.*; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; @@ -17,6 +25,7 @@ import com.eu.habbo.habbohotel.wired.WiredEffectType; import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import gnu.trove.procedure.TObjectProcedure; import gnu.trove.set.hash.THashSet; import org.slf4j.Logger; @@ -26,6 +35,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; public class WiredEffectToggleFurni extends InteractionWiredEffect { private static final Logger LOGGER = LoggerFactory.getLogger(WiredEffectToggleFurni.class); @@ -34,6 +44,46 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect { private final THashSet items; + private static final List> FORBIDDEN_TYPES = new ArrayList>() { + { + this.add(InteractionWired.class); + this.add(InteractionTeleport.class); + this.add(InteractionPushable.class); + this.add(InteractionTagPole.class); + this.add(InteractionTagField.class); + this.add(InteractionCrackable.class); + this.add(InteractionGameScoreboard.class); + this.add(InteractionGameGate.class); + this.add(InteractionFreezeTile.class); + this.add(InteractionFreezeBlock.class); + this.add(InteractionFreezeExitTile.class); + this.add(InteractionBattleBanzaiTeleporter.class); + this.add(InteractionBattleBanzaiTile.class); + this.add(InteractionMonsterPlantSeed.class); + this.add(InteractionPetBreedingNest.class); + this.add(InteractionPetDrink.class); + this.add(InteractionPetFood.class); + this.add(InteractionPetToy.class); + this.add(InteractionBadgeDisplay.class); + this.add(InteractionClothing.class); + this.add(InteractionVendingMachine.class); + this.add(InteractionGift.class); + this.add(InteractionPressurePlate.class); + this.add(InteractionMannequin.class); + this.add(InteractionGymEquipment.class); + this.add(InteractionHopper.class); + this.add(InteractionObstacle.class); + this.add(InteractionOneWayGate.class); + this.add(InteractionPuzzleBox.class); + this.add(InteractionRoller.class); + this.add(InteractionSwitch.class); + this.add(InteractionTent.class); + this.add(InteractionTrap.class); + this.add(InteractionTrophy.class); + this.add(InteractionWater.class); + } + }; + public WiredEffectToggleFurni(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); this.items = new THashSet<>(); @@ -92,24 +142,36 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); packet.readString(); - this.items.clear(); + int itemsCount = packet.readInt(); - int count = packet.readInt(); - - for (int i = 0; i < count; i++) { - HabboItem item = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(packet.readInt()); - - if (item instanceof InteractionFreezeBlock || item instanceof InteractionFreezeTile || item instanceof InteractionCrackable) - continue; - - this.items.add(item); + if(itemsCount > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) { + throw new WiredSaveException("Too many furni selected"); } - this.setDelay(packet.readInt()); + List newItems = new ArrayList<>(); + + for (int i = 0; i < itemsCount; i++) { + int itemId = packet.readInt(); + HabboItem it = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(itemId); + + if(it == null) + throw new WiredSaveException(String.format("Item %s not found", itemId)); + + newItems.add(it); + } + + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.items.clear(); + this.items.addAll(newItems); + this.setDelay(delay); return true; } @@ -122,7 +184,7 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect { THashSet itemsToRemove = new THashSet<>(); for (HabboItem item : this.items) { - if (item == null || item.getRoomId() == 0 || item instanceof InteractionFreezeBlock || item instanceof InteractionFreezeTile) { + if (item == null || item.getRoomId() == 0 || FORBIDDEN_TYPES.stream().anyMatch(a -> a.isAssignableFrom(item.getClass()))) { itemsToRemove.add(item); continue; } @@ -132,7 +194,7 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect { int state = 0; if (!item.getExtradata().isEmpty()) { try { - state = Integer.valueOf(item.getExtradata()); // assumes that extradata is state, could be something else for trophies etc. + state = Integer.parseInt(item.getExtradata()); // assumes that extradata is state, could be something else for trophies etc. } catch (NumberFormatException ignored) { } @@ -151,35 +213,48 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect { @Override public String getWiredData() { - StringBuilder wiredData = new StringBuilder(this.getDelay() + "\t"); - - if (this.items != null && !this.items.isEmpty()) { - for (HabboItem item : this.items) { - wiredData.append(item.getId()).append(";"); - } - } - - return wiredData.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.getDelay(), + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items.clear(); - String[] wiredData = set.getString("wired_data").split("\t"); + String wiredData = set.getString("wired_data"); - if (wiredData.length >= 1) { - this.setDelay(Integer.valueOf(wiredData[0])); - } - if (wiredData.length == 2) { - if (wiredData[1].contains(";")) { - for (String s : wiredData[1].split(";")) { - HabboItem item = room.getHabboItem(Integer.valueOf(s)); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + for (Integer id: data.itemIds) { + HabboItem item = room.getHabboItem(id); - if (item instanceof InteractionFreezeBlock || item instanceof InteractionFreezeTile || item instanceof InteractionCrackable) - continue; + if (item instanceof InteractionFreezeBlock || item instanceof InteractionFreezeTile || item instanceof InteractionCrackable) { + continue; + } - if (item != null) - this.items.add(item); + if (item != null) { + this.items.add(item); + } + } + } else { + String[] wiredDataOld = wiredData.split("\t"); + + if (wiredDataOld.length >= 1) { + this.setDelay(Integer.parseInt(wiredDataOld[0])); + } + if (wiredDataOld.length == 2) { + if (wiredDataOld[1].contains(";")) { + for (String s : wiredDataOld[1].split(";")) { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item instanceof InteractionFreezeBlock || item instanceof InteractionFreezeTile || item instanceof InteractionCrackable) + continue; + + if (item != null) + this.items.add(item); + } } } } @@ -195,4 +270,14 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect { public WiredEffectType getType() { return type; } + + static class JsonData { + int delay; + List itemIds; + + public JsonData(int delay, List itemIds) { + this.delay = delay; + this.itemIds = itemIds; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectToggleRandom.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectToggleRandom.java index 98b41137..4fbd9203 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectToggleRandom.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectToggleRandom.java @@ -3,11 +3,18 @@ package com.eu.habbo.habbohotel.items.interactions.wired.effects; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.Item; -import com.eu.habbo.habbohotel.items.interactions.InteractionCrackable; -import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect; -import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger; +import com.eu.habbo.habbohotel.items.interactions.*; +import com.eu.habbo.habbohotel.items.interactions.games.InteractionGameGate; +import com.eu.habbo.habbohotel.items.interactions.games.InteractionGameScoreboard; import com.eu.habbo.habbohotel.items.interactions.games.InteractionGameTimer; +import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.InteractionBattleBanzaiTeleporter; +import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.InteractionBattleBanzaiTile; import com.eu.habbo.habbohotel.items.interactions.games.freeze.InteractionFreezeBlock; +import com.eu.habbo.habbohotel.items.interactions.games.freeze.InteractionFreezeExitTile; +import com.eu.habbo.habbohotel.items.interactions.games.freeze.InteractionFreezeTile; +import com.eu.habbo.habbohotel.items.interactions.games.tag.InteractionTagField; +import com.eu.habbo.habbohotel.items.interactions.games.tag.InteractionTagPole; +import com.eu.habbo.habbohotel.items.interactions.pets.*; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.HabboItem; @@ -15,6 +22,7 @@ import com.eu.habbo.habbohotel.wired.WiredEffectType; import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import gnu.trove.procedure.TObjectProcedure; import gnu.trove.set.hash.THashSet; import org.slf4j.Logger; @@ -24,6 +32,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; public class WiredEffectToggleRandom extends InteractionWiredEffect { private static final Logger LOGGER = LoggerFactory.getLogger(WiredEffectToggleRandom.class); @@ -32,6 +41,46 @@ public class WiredEffectToggleRandom extends InteractionWiredEffect { private final THashSet items = new THashSet<>(); + private static final List> FORBIDDEN_TYPES = new ArrayList>() { + { + this.add(InteractionWired.class); + this.add(InteractionTeleport.class); + this.add(InteractionPushable.class); + this.add(InteractionTagPole.class); + this.add(InteractionTagField.class); + this.add(InteractionCrackable.class); + this.add(InteractionGameScoreboard.class); + this.add(InteractionGameGate.class); + this.add(InteractionFreezeTile.class); + this.add(InteractionFreezeBlock.class); + this.add(InteractionFreezeExitTile.class); + this.add(InteractionBattleBanzaiTeleporter.class); + this.add(InteractionBattleBanzaiTile.class); + this.add(InteractionMonsterPlantSeed.class); + this.add(InteractionPetBreedingNest.class); + this.add(InteractionPetDrink.class); + this.add(InteractionPetFood.class); + this.add(InteractionPetToy.class); + this.add(InteractionBadgeDisplay.class); + this.add(InteractionClothing.class); + this.add(InteractionVendingMachine.class); + this.add(InteractionGift.class); + this.add(InteractionPressurePlate.class); + this.add(InteractionMannequin.class); + this.add(InteractionGymEquipment.class); + this.add(InteractionHopper.class); + this.add(InteractionObstacle.class); + this.add(InteractionOneWayGate.class); + this.add(InteractionPuzzleBox.class); + this.add(InteractionRoller.class); + this.add(InteractionSwitch.class); + this.add(InteractionTent.class); + this.add(InteractionTrap.class); + this.add(InteractionTrophy.class); + this.add(InteractionWater.class); + } + }; + public WiredEffectToggleRandom(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); } @@ -88,24 +137,36 @@ public class WiredEffectToggleRandom extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); packet.readString(); - this.items.clear(); + int itemsCount = packet.readInt(); - int count = packet.readInt(); - - for (int i = 0; i < count; i++) { - HabboItem item = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(packet.readInt()); - - if (item instanceof InteractionFreezeBlock || item instanceof InteractionGameTimer || item instanceof InteractionCrackable) - continue; - - this.items.add(item); + if(itemsCount > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) { + throw new WiredSaveException("Too many furni selected"); } - this.setDelay(packet.readInt()); + List newItems = new ArrayList<>(); + + for (int i = 0; i < itemsCount; i++) { + int itemId = packet.readInt(); + HabboItem it = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(itemId); + + if(it == null) + throw new WiredSaveException(String.format("Item %s not found", itemId)); + + newItems.add(it); + } + + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.items.clear(); + this.items.addAll(newItems); + this.setDelay(delay); return true; } @@ -115,7 +176,7 @@ public class WiredEffectToggleRandom extends InteractionWiredEffect { THashSet items = this.items; for (HabboItem item : items) { - if (item.getRoomId() == 0) { + if (item.getRoomId() == 0 || FORBIDDEN_TYPES.stream().anyMatch(a -> a.isAssignableFrom(item.getClass()))) { this.items.remove(item); continue; } @@ -132,35 +193,46 @@ public class WiredEffectToggleRandom extends InteractionWiredEffect { @Override public String getWiredData() { - StringBuilder wiredData = new StringBuilder(this.getDelay() + "\t"); - - if (!this.items.isEmpty()) { - for (HabboItem item : this.items) { - wiredData.append(item.getId()).append(";"); - } - } - - return wiredData.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.getDelay(), + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items.clear(); - String[] wiredData = set.getString("wired_data").split("\t"); + String wiredData = set.getString("wired_data"); - if (wiredData.length >= 1) { - this.setDelay(Integer.valueOf(wiredData[0])); - } - if (wiredData.length == 2) { - if (wiredData[1].contains(";")) { - for (String s : wiredData[1].split(";")) { - HabboItem item = room.getHabboItem(Integer.valueOf(s)); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + for (Integer id: data.itemIds) { + HabboItem item = room.getHabboItem(id); + + if (item instanceof InteractionFreezeBlock || item instanceof InteractionGameTimer || item instanceof InteractionCrackable) + continue; - if (item instanceof InteractionFreezeBlock || item instanceof InteractionGameTimer || item instanceof InteractionCrackable) - continue; + if (item != null) + this.items.add(item); + } + } else { + String[] wiredDataOld = wiredData.split("\t"); - if (item != null) - this.items.add(item); + if (wiredDataOld.length >= 1) { + this.setDelay(Integer.parseInt(wiredDataOld[0])); + } + if (wiredDataOld.length == 2) { + if (wiredDataOld[1].contains(";")) { + for (String s : wiredDataOld[1].split(";")) { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item instanceof InteractionFreezeBlock || item instanceof InteractionGameTimer || item instanceof InteractionCrackable) + continue; + + if (item != null) + this.items.add(item); + } } } } @@ -176,4 +248,14 @@ public class WiredEffectToggleRandom extends InteractionWiredEffect { public WiredEffectType getType() { return type; } + + static class JsonData { + int delay; + List itemIds; + + public JsonData(int delay, List itemIds) { + this.delay = delay; + this.itemIds = itemIds; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTriggerStacks.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTriggerStacks.java index 41a38dd8..db37872b 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTriggerStacks.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTriggerStacks.java @@ -13,6 +13,7 @@ import com.eu.habbo.habbohotel.wired.WiredEffectType; import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import gnu.trove.procedure.TObjectProcedure; import gnu.trove.set.hash.THashSet; @@ -20,6 +21,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; public class WiredEffectTriggerStacks extends InteractionWiredEffect { public static final WiredEffectType type = WiredEffectType.CALL_STACKS; @@ -83,19 +85,36 @@ public class WiredEffectTriggerStacks extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); packet.readString(); - this.items.clear(); + int itemsCount = packet.readInt(); - int count = packet.readInt(); - - for (int i = 0; i < count; i++) { - this.items.add(Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(packet.readInt())); + if(itemsCount > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) { + throw new WiredSaveException("Too many furni selected"); } - this.setDelay(packet.readInt()); + List newItems = new ArrayList<>(); + + for (int i = 0; i < itemsCount; i++) { + int itemId = packet.readInt(); + HabboItem it = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(itemId); + + if(it == null) + throw new WiredSaveException(String.format("Item %s not found", itemId)); + + newItems.add(it); + } + + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.items.clear(); + this.items.addAll(newItems); + this.setDelay(delay); return true; } @@ -138,32 +157,40 @@ public class WiredEffectTriggerStacks extends InteractionWiredEffect { @Override public String getWiredData() { - StringBuilder wiredData = new StringBuilder(this.getDelay() + "\t"); - - if (this.items != null && !this.items.isEmpty()) { - for (HabboItem item : this.items) { - wiredData.append(item.getId()).append(";"); - } - } - - return wiredData.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.getDelay(), + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items = new THashSet<>(); - String[] wiredData = set.getString("wired_data").split("\t"); + String wiredData = set.getString("wired_data"); - if (wiredData.length >= 1) { - this.setDelay(Integer.valueOf(wiredData[0])); - } - if (wiredData.length == 2) { - if (wiredData[1].contains(";")) { - for (String s : wiredData[1].split(";")) { - HabboItem item = room.getHabboItem(Integer.valueOf(s)); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + for (Integer id: data.itemIds) { + HabboItem item = room.getHabboItem(id); + if (item != null) { + this.items.add(item); + } + } + } else { + String[] wiredDataOld = wiredData.split("\t"); - if (item != null) - this.items.add(item); + if (wiredDataOld.length >= 1) { + this.setDelay(Integer.parseInt(wiredDataOld[0])); + } + if (wiredDataOld.length == 2) { + if (wiredDataOld[1].contains(";")) { + for (String s : wiredDataOld[1].split(";")) { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item != null) + this.items.add(item); + } } } } @@ -184,4 +211,14 @@ public class WiredEffectTriggerStacks extends InteractionWiredEffect { protected long requiredCooldown() { return 250; } + + static class JsonData { + int delay; + List itemIds; + + public JsonData(int delay, List itemIds) { + this.delay = delay; + this.itemIds = itemIds; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectWhisper.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectWhisper.java index 3cc5872a..56d6f35e 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectWhisper.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectWhisper.java @@ -5,14 +5,16 @@ import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger; -import com.eu.habbo.habbohotel.rooms.Room; -import com.eu.habbo.habbohotel.rooms.RoomChatMessage; -import com.eu.habbo.habbohotel.rooms.RoomChatMessageBubbles; -import com.eu.habbo.habbohotel.rooms.RoomUnit; +import com.eu.habbo.habbohotel.permissions.Permission; +import com.eu.habbo.habbohotel.rooms.*; import com.eu.habbo.habbohotel.users.Habbo; +import com.eu.habbo.habbohotel.wired.WiredChangeDirectionSetting; 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.ClientMessage; import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.incoming.wired.WiredSaveException; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserWhisperComposer; import gnu.trove.procedure.TObjectProcedure; @@ -68,15 +70,25 @@ public class WiredEffectWhisper extends InteractionWiredEffect { } @Override - public boolean saveData(ClientMessage packet, GameClient gameClient) { + public boolean saveData(ClientMessage packet, GameClient gameClient) throws WiredSaveException { packet.readInt(); - this.message = Emulator.getGameEnvironment().getWordFilter().filter(packet.readString(), null); - if (this.message.length() > 100) { - this.message = ""; + String message = packet.readString(); + + if(gameClient.getHabbo() == null || !gameClient.getHabbo().hasPermission(Permission.ACC_SUPERWIRED)) { + message = Emulator.getGameEnvironment().getWordFilter().filter(message, null); + message = message.substring(0, Math.min(message.length(), Emulator.getConfig().getInt("hotel.wired.message.max_length", 100))); } + packet.readInt(); - this.setDelay(packet.readInt()); + + int delay = packet.readInt(); + + if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) + throw new WiredSaveException("Delay too long"); + + this.message = message; + this.setDelay(delay); return true; } @@ -87,7 +99,9 @@ public class WiredEffectWhisper extends InteractionWiredEffect { Habbo habbo = room.getHabbo(roomUnit); if (habbo != null) { - habbo.getClient().sendResponse(new RoomUserWhisperComposer(new RoomChatMessage(this.message.replace("%user%", habbo.getHabboInfo().getUsername()).replace("%online_count%", Emulator.getGameEnvironment().getHabboManager().getOnlineCount() + "").replace("%room_count%", Emulator.getGameEnvironment().getRoomManager().getActiveRooms().size() + ""), habbo, habbo, RoomChatMessageBubbles.WIRED))); + String msg = this.message.replace("%user%", habbo.getHabboInfo().getUsername()).replace("%online_count%", Emulator.getGameEnvironment().getHabboManager().getOnlineCount() + "").replace("%room_count%", Emulator.getGameEnvironment().getRoomManager().getActiveRooms().size() + ""); + habbo.getClient().sendResponse(new RoomUserWhisperComposer(new RoomChatMessage(msg, habbo, habbo, RoomChatMessageBubbles.WIRED))); + Emulator.getThreading().run(() -> WiredHandler.handle(WiredTriggerType.SAY_SOMETHING, roomUnit, room, new Object[]{ msg })); if (habbo.getRoomUnit().isIdle()) { habbo.getRoomUnit().getRoom().unIdle(habbo); @@ -107,17 +121,27 @@ public class WiredEffectWhisper extends InteractionWiredEffect { @Override public String getWiredData() { - return this.getDelay() + "\t" + this.message; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData(this.message, this.getDelay())); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String wireData = set.getString("wired_data"); - this.message = ""; + String wiredData = set.getString("wired_data"); - if (wireData.split("\t").length >= 2) { - super.setDelay(Integer.valueOf(wireData.split("\t")[0])); - this.message = wireData.split("\t")[1]; + if(wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.setDelay(data.delay); + this.message = data.message; + } + else { + this.message = ""; + + if (wiredData.split("\t").length >= 2) { + super.setDelay(Integer.valueOf(wiredData.split("\t")[0])); + this.message = wiredData.split("\t")[1]; + } + + this.needsUpdate(true); } } @@ -136,4 +160,14 @@ public class WiredEffectWhisper extends InteractionWiredEffect { public boolean requiresTriggeringUser() { return true; } + + static class JsonData { + String message; + int delay; + + public JsonData(String message, int delay) { + this.message = message; + this.delay = delay; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredBlob.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredBlob.java index 0017efe8..8f859fd2 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredBlob.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredBlob.java @@ -68,7 +68,7 @@ public class WiredBlob extends InteractionDefault { GamePlayer player = habbo.getHabboInfo().getGamePlayer(); if (player != null) { - player.addScore(this.POINTS_REWARD); + player.addScore(this.POINTS_REWARD, true); BattleBanzaiGame battleBanzaiGame = (BattleBanzaiGame) room.getGame(BattleBanzaiGame.class); diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/interfaces/InteractionWiredMatchFurniSettings.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/interfaces/InteractionWiredMatchFurniSettings.java new file mode 100644 index 00000000..6db447f7 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/interfaces/InteractionWiredMatchFurniSettings.java @@ -0,0 +1,11 @@ +package com.eu.habbo.habbohotel.items.interactions.wired.interfaces; + +import com.eu.habbo.habbohotel.wired.WiredMatchFurniSetting; +import gnu.trove.set.hash.THashSet; + +public interface InteractionWiredMatchFurniSettings { + public THashSet getMatchFurniSettings(); + public boolean shouldMatchState(); + public boolean shouldMatchRotation(); + public boolean shouldMatchPosition(); +} diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerAtSetTime.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerAtSetTime.java index 414412eb..f6364641 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerAtSetTime.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerAtSetTime.java @@ -7,6 +7,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger; import com.eu.habbo.habbohotel.items.interactions.wired.WiredTriggerReset; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.habbohotel.wired.WiredTriggerType; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -39,13 +40,22 @@ public class WiredTriggerAtSetTime extends InteractionWiredTrigger implements Wi @Override public String getWiredData() { - return this.executeTime + ""; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.executeTime + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - if (set.getString("wired_data").length() >= 1) { - this.executeTime = (Integer.valueOf(set.getString("wired_data"))); + String wiredData = set.getString("wired_data"); + + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.executeTime = data.executeTime; + } else { + if (wiredData.length() >= 1) { + this.executeTime = (Integer.parseInt(wiredData)); + } } if (this.executeTime < 500) { @@ -115,4 +125,12 @@ public class WiredTriggerAtSetTime extends InteractionWiredTrigger implements Wi Emulator.getThreading().run(new WiredExecuteTask(this, Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId())), this.executeTime); } + + static class JsonData { + int executeTime; + + public JsonData(int executeTime) { + this.executeTime = executeTime; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerAtTimeLong.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerAtTimeLong.java index 4bcec897..751d21c7 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerAtTimeLong.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerAtTimeLong.java @@ -7,6 +7,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger; import com.eu.habbo.habbohotel.items.interactions.wired.WiredTriggerReset; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.habbohotel.wired.WiredTriggerType; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -38,13 +39,22 @@ public class WiredTriggerAtTimeLong extends InteractionWiredTrigger implements W @Override public String getWiredData() { - return this.executeTime + ""; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.executeTime + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - if (set.getString("wired_data").length() >= 1) { - this.executeTime = (Integer.valueOf(set.getString("wired_data"))); + String wiredData = set.getString("wired_data"); + + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.executeTime = data.executeTime; + } else { + if (wiredData.length() >= 1) { + this.executeTime = (Integer.parseInt(wiredData)); + } } if (this.executeTime < 500) { @@ -113,4 +123,12 @@ public class WiredTriggerAtTimeLong extends InteractionWiredTrigger implements W Emulator.getThreading().run(new WiredExecuteTask(this, Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId())), this.executeTime); } + + static class JsonData { + int executeTime; + + public JsonData(int executeTime) { + this.executeTime = executeTime; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerBotReachedFurni.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerBotReachedFurni.java index 73c543c3..596fbc8f 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerBotReachedFurni.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerBotReachedFurni.java @@ -21,11 +21,12 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; public class WiredTriggerBotReachedFurni extends InteractionWiredTrigger { private static final Logger LOGGER = LoggerFactory.getLogger(WiredTriggerBotReachedFurni.class); - public final static WiredTriggerType type = WiredTriggerType.BOT_REACHED_STF; + public final static WiredTriggerType type = WiredTriggerType.WALKS_ON_FURNI; private THashSet items; private String botName = ""; @@ -73,7 +74,7 @@ public class WiredTriggerBotReachedFurni extends InteractionWiredTrigger { message.appendString(this.botName); message.appendInt(0); message.appendInt(0); - message.appendInt(this.getType().code); + message.appendInt(WiredTriggerType.BOT_REACHED_STF.code); if (!this.isTriggeredByRoomUnit()) { List invalidTriggers = new ArrayList<>(); @@ -114,54 +115,55 @@ public class WiredTriggerBotReachedFurni extends InteractionWiredTrigger { @Override public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) { - List bots = room.getBots(this.botName); - - for (Bot bot : bots) { - if (bot.getRoomUnit().equals(roomUnit)) { - for (Object o : stuff) { - if (this.items.contains(o)) - return true; - } + if (stuff.length >= 1) { + if (stuff[0] instanceof HabboItem) { + return this.items.contains(stuff[0]) && room.getBots(this.botName).stream().anyMatch(bot -> bot.getRoomUnit() == roomUnit); } } - return false; } @Override public String getWiredData() { - StringBuilder wiredData = new StringBuilder(this.botName + ":"); - - if (!this.items.isEmpty()) { - for (HabboItem item : this.items) { - wiredData.append(item.getId()).append(";"); - } - } - - return wiredData.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.botName, + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items.clear(); + String wiredData = set.getString("wired_data"); - String[] data = set.getString("wired_data").split(":"); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.botName = data.botName; + for (Integer id: data.itemIds) { + HabboItem item = room.getHabboItem(id); + if (item != null) { + this.items.add(item); + } + } + } else { + String[] data = wiredData.split(":"); - if (data.length == 1) { - this.botName = data[0]; - } else if (data.length == 2) { - this.botName = data[0]; + if (data.length == 1) { + this.botName = data[0]; + } else if (data.length == 2) { + this.botName = data[0]; - String[] items = data[1].split(";"); + String[] items = data[1].split(";"); - for (int i = 0; i < items.length; i++) { - try { - HabboItem item = room.getHabboItem(Integer.valueOf(items[i])); + for (String id : items) { + try { + HabboItem item = room.getHabboItem(Integer.parseInt(id)); - if (item != null) - this.items.add(item); - } catch (Exception e) { - LOGGER.error("Caught exception", e); + if (item != null) + this.items.add(item); + } catch (Exception e) { + LOGGER.error("Caught exception", e); + } } } } @@ -172,4 +174,14 @@ public class WiredTriggerBotReachedFurni extends InteractionWiredTrigger { this.items.clear(); this.botName = ""; } + + static class JsonData { + String botName; + List itemIds; + + public JsonData(String botName, List itemIds) { + this.botName = botName; + this.itemIds = itemIds; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerBotReachedHabbo.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerBotReachedHabbo.java index 7da199f7..0e7b22fd 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerBotReachedHabbo.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerBotReachedHabbo.java @@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.habbohotel.wired.WiredTriggerType; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -57,26 +58,26 @@ public class WiredTriggerBotReachedHabbo extends InteractionWiredTrigger { @Override public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) { - if (stuff.length == 0) - return false; - - List bots = room.getBots(this.botName); - - for (Bot bot : bots) { - if (bot.getRoomUnit().equals(stuff[0])) - return true; - } - return false; + return room.getBots(this.botName).stream().anyMatch(bot -> bot.getRoomUnit() == roomUnit); } @Override public String getWiredData() { - return this.botName; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.botName + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - this.botName = set.getString("wired_data"); + String wiredData = set.getString("wired_data"); + + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.botName = data.botName; + } else { + this.botName = wiredData; + } } @Override @@ -88,4 +89,12 @@ public class WiredTriggerBotReachedHabbo extends InteractionWiredTrigger { public boolean isTriggeredByRoomUnit() { return true; } + + static class JsonData { + String botName; + + public JsonData(String botName) { + this.botName = botName; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerFurniStateToggled.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerFurniStateToggled.java index c31b571a..f97f332f 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerFurniStateToggled.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerFurniStateToggled.java @@ -16,12 +16,13 @@ import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.List; +import java.util.stream.Collectors; public class WiredTriggerFurniStateToggled extends InteractionWiredTrigger { private static final WiredTriggerType type = WiredTriggerType.STATE_CHANGED; private THashSet items; - private String message = ""; public WiredTriggerFurniStateToggled(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); @@ -55,34 +56,35 @@ public class WiredTriggerFurniStateToggled extends InteractionWiredTrigger { @Override public String getWiredData() { - StringBuilder wiredData = new StringBuilder(super.getDelay() + ":\t:"); - - if (this.items != null) { - if (!this.items.isEmpty()) { - for (HabboItem item : this.items) { - wiredData.append(item.getId()).append(";"); - } - } else - wiredData.append("\t"); - } - - return wiredData.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items = new THashSet<>(); String wiredData = set.getString("wired_data"); - if (wiredData.split(":").length >= 3) { - super.setDelay(Integer.valueOf(wiredData.split(":")[0])); - this.message = wiredData.split(":")[1]; - if (!wiredData.split(":")[2].equals("\t")) { - for (String s : wiredData.split(":")[2].split(";")) { - HabboItem item = room.getHabboItem(Integer.valueOf(s)); + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + for (Integer id: data.itemIds) { + HabboItem item = room.getHabboItem(id); + if (item != null) { + this.items.add(item); + } + } + } else { + if (wiredData.split(":").length >= 3) { + super.setDelay(Integer.parseInt(wiredData.split(":")[0])); - if (item != null) - this.items.add(item); + if (!wiredData.split(":")[2].equals("\t")) { + for (String s : wiredData.split(":")[2].split(";")) { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item != null) + this.items.add(item); + } } } } @@ -91,7 +93,6 @@ public class WiredTriggerFurniStateToggled extends InteractionWiredTrigger { @Override public void onPickUp() { this.items.clear(); - this.message = ""; } @Override @@ -126,7 +127,7 @@ public class WiredTriggerFurniStateToggled extends InteractionWiredTrigger { } message.appendInt(this.getBaseItem().getSpriteId()); message.appendInt(this.getId()); - message.appendString(this.message); + message.appendString(""); message.appendInt(0); message.appendInt(0); message.appendInt(this.getType().code); @@ -153,4 +154,12 @@ public class WiredTriggerFurniStateToggled extends InteractionWiredTrigger { public boolean isTriggeredByRoomUnit() { return true; } + + static class JsonData { + List itemIds; + + public JsonData(List itemIds) { + this.itemIds = itemIds; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerHabboEntersRoom.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerHabboEntersRoom.java index 69175e52..9a1400b2 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerHabboEntersRoom.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerHabboEntersRoom.java @@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.habbohotel.wired.WiredTriggerType; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -41,12 +42,21 @@ public class WiredTriggerHabboEntersRoom extends InteractionWiredTrigger { @Override public String getWiredData() { - return this.username; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.username + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - this.username = set.getString("wired_data"); + String wiredData = set.getString("wired_data"); + + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.username = data.username; + } else { + this.username = wiredData; + } } @Override @@ -86,4 +96,12 @@ public class WiredTriggerHabboEntersRoom extends InteractionWiredTrigger { public boolean isTriggeredByRoomUnit() { return true; } + + static class JsonData { + String username; + + public JsonData(String username) { + this.username = username; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerHabboSaysKeyword.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerHabboSaysKeyword.java index 9a98f41c..f3b90ae3 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerHabboSaysKeyword.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerHabboSaysKeyword.java @@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.users.Habbo; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.habbohotel.wired.WiredTriggerType; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -28,14 +29,11 @@ public class WiredTriggerHabboSaysKeyword extends InteractionWiredTrigger { @Override public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) { - Habbo habbo = room.getHabbo(roomUnit); - - if (habbo != null) { - if (this.key.length() > 0) { - if (stuff[0] instanceof String) { - if (((String) stuff[0]).toLowerCase().contains(this.key.toLowerCase())) { - return !this.ownerOnly || room.getOwnerId() == habbo.getHabboInfo().getId(); - } + if (this.key.length() > 0) { + if (stuff[0] instanceof String) { + if (((String) stuff[0]).toLowerCase().contains(this.key.toLowerCase())) { + Habbo habbo = room.getHabbo(roomUnit); + return !this.ownerOnly || (habbo != null && room.getOwnerId() == habbo.getHabboInfo().getId()); } } } @@ -44,16 +42,27 @@ public class WiredTriggerHabboSaysKeyword extends InteractionWiredTrigger { @Override public String getWiredData() { - return (this.ownerOnly ? "1" : "0") + "\t" + this.key; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.ownerOnly, + this.key + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - String[] data = set.getString("wired_data").split("\t"); + String wiredData = set.getString("wired_data"); - if (data.length == 2) { - this.ownerOnly = data[0].equalsIgnoreCase("1"); - this.key = data[1]; + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.ownerOnly = data.ownerOnly; + this.key = data.key; + } else { + String[] data = wiredData.split("\t"); + + if (data.length == 2) { + this.ownerOnly = data[0].equalsIgnoreCase("1"); + this.key = data[1]; + } } } @@ -96,4 +105,14 @@ public class WiredTriggerHabboSaysKeyword extends InteractionWiredTrigger { public boolean isTriggeredByRoomUnit() { return true; } + + static class JsonData { + boolean ownerOnly; + String key; + + public JsonData(boolean ownerOnly, String key) { + this.ownerOnly = ownerOnly; + this.key = key; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerHabboWalkOffFurni.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerHabboWalkOffFurni.java index 0e05ba01..64e9dae9 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerHabboWalkOffFurni.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerHabboWalkOffFurni.java @@ -14,14 +14,13 @@ import gnu.trove.set.hash.THashSet; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; public class WiredTriggerHabboWalkOffFurni extends InteractionWiredTrigger { public static final WiredTriggerType type = WiredTriggerType.WALKS_OFF_FURNI; private THashSet items; - private String message = ""; public WiredTriggerHabboWalkOffFurni(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); @@ -45,55 +44,49 @@ public class WiredTriggerHabboWalkOffFurni extends InteractionWiredTrigger { @Override public String getWiredData() { - StringBuilder wiredData = new StringBuilder(super.getDelay() + ":\t:"); - - if (!this.items.isEmpty()) { - List toRemove = new ArrayList<>(0); - for (HabboItem item : this.items) { - if (item.getRoomId() == this.getRoomId()) { - wiredData.append(item.getId()).append(";"); - } else { - toRemove.add(item); - } - } - - this.items.removeAll(toRemove); - } else - wiredData.append("\t"); - - return wiredData.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new WiredTriggerFurniStateToggled.JsonData( + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items.clear(); String wiredData = set.getString("wired_data"); - if (wiredData.split(":").length >= 3) { - super.setDelay(Integer.valueOf(wiredData.split(":")[0])); - this.message = wiredData.split(":")[1]; - if (!wiredData.split(":")[2].equals("\t")) { - for (String s : wiredData.split(":")[2].split(";")) { - if (s.isEmpty()) - continue; + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + for (Integer id: data.itemIds) { + HabboItem item = room.getHabboItem(id); + if (item != null) { + this.items.add(item); + } + } + } else { + if (wiredData.split(":").length >= 3) { + super.setDelay(Integer.parseInt(wiredData.split(":")[0])); - try { - HabboItem item = room.getHabboItem(Integer.valueOf(s)); + if (!wiredData.split(":")[2].equals("\t")) { + for (String s : wiredData.split(":")[2].split(";")) { + if (s.isEmpty()) + continue; - if (item != null) - this.items.add(item); - } catch (Exception e) { + try { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item != null) + this.items.add(item); + } catch (Exception e) { + } } } } } - } @Override public void onPickUp() { this.items.clear(); - this.message = ""; } @Override @@ -126,7 +119,7 @@ public class WiredTriggerHabboWalkOffFurni extends InteractionWiredTrigger { } message.appendInt(this.getBaseItem().getSpriteId()); message.appendInt(this.getId()); - message.appendString(this.message); + message.appendString(""); message.appendInt(0); message.appendInt(0); message.appendInt(this.getType().code); @@ -154,4 +147,12 @@ public class WiredTriggerHabboWalkOffFurni extends InteractionWiredTrigger { public boolean isTriggeredByRoomUnit() { return true; } + + static class JsonData { + List itemIds; + + public JsonData(List itemIds) { + this.itemIds = itemIds; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerHabboWalkOnFurni.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerHabboWalkOnFurni.java index 1ebad4c9..257f23bb 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerHabboWalkOnFurni.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerHabboWalkOnFurni.java @@ -16,12 +16,12 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; public class WiredTriggerHabboWalkOnFurni extends InteractionWiredTrigger { public static final WiredTriggerType type = WiredTriggerType.WALKS_ON_FURNI; private THashSet items; - private String message = ""; public WiredTriggerHabboWalkOnFurni(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); @@ -73,7 +73,7 @@ public class WiredTriggerHabboWalkOnFurni extends InteractionWiredTrigger { } message.appendInt(this.getBaseItem().getSpriteId()); message.appendInt(this.getId()); - message.appendString(this.message); + message.appendString(""); message.appendInt(0); message.appendInt(0); message.appendInt(this.getType().code); @@ -99,44 +99,40 @@ public class WiredTriggerHabboWalkOnFurni extends InteractionWiredTrigger { @Override public String getWiredData() { - StringBuilder wiredData = new StringBuilder(super.getDelay() + ":\t:"); - - if (!this.items.isEmpty()) { - List toRemove = new ArrayList<>(0); - for (HabboItem item : this.items) { - if (item.getRoomId() == this.getRoomId()) { - wiredData.append(item.getId()).append(";"); - } else { - toRemove.add(item); - } - } - - this.items.removeAll(toRemove); - } else - wiredData.append("\t"); - - return wiredData.toString(); + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.items.stream().map(HabboItem::getId).collect(Collectors.toList()) + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { this.items.clear(); String wiredData = set.getString("wired_data"); - if (wiredData.split(":").length >= 3) { - super.setDelay(Integer.valueOf(wiredData.split(":")[0])); - this.message = wiredData.split(":")[1]; - if (!wiredData.split(":")[2].equals("\t")) { - for (String s : wiredData.split(":")[2].split(";")) { - if (s.isEmpty()) - continue; + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + for (Integer id: data.itemIds) { + HabboItem item = room.getHabboItem(id); + if (item != null) { + this.items.add(item); + } + } + } else { + if (wiredData.split(":").length >= 3) { + super.setDelay(Integer.parseInt(wiredData.split(":")[0])); - try { - HabboItem item = room.getHabboItem(Integer.valueOf(s)); + if (!wiredData.split(":")[2].equals("\t")) { + for (String s : wiredData.split(":")[2].split(";")) { + if (s.isEmpty()) + continue; - if (item != null) - this.items.add(item); - } catch (Exception e) { + try { + HabboItem item = room.getHabboItem(Integer.parseInt(s)); + + if (item != null) + this.items.add(item); + } catch (Exception e) { + } } } } @@ -146,11 +142,18 @@ public class WiredTriggerHabboWalkOnFurni extends InteractionWiredTrigger { @Override public void onPickUp() { this.items.clear(); - this.message = ""; } @Override public boolean isTriggeredByRoomUnit() { return true; } + + static class JsonData { + List itemIds; + + public JsonData(List itemIds) { + this.itemIds = itemIds; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerRepeater.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerRepeater.java index a0f693c9..36d48b3e 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerRepeater.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerRepeater.java @@ -41,13 +41,22 @@ public class WiredTriggerRepeater extends InteractionWiredTrigger implements ICy @Override public String getWiredData() { - return this.repeatTime + ""; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.repeatTime + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - if (set.getString("wired_data").length() >= 1) { - this.repeatTime = (Integer.valueOf(set.getString("wired_data"))); + String wiredData = set.getString("wired_data"); + + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.repeatTime = data.repeatTime; + } else { + if (wiredData.length() >= 1) { + this.repeatTime = (Integer.valueOf(wiredData)); + } } if (this.repeatTime < 500) { @@ -136,4 +145,12 @@ public class WiredTriggerRepeater extends InteractionWiredTrigger implements ICy } } } + + static class JsonData { + int repeatTime; + + public JsonData(int repeatTime) { + this.repeatTime = repeatTime; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerRepeaterLong.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerRepeaterLong.java index ff3f9688..ad93a09d 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerRepeaterLong.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerRepeaterLong.java @@ -40,13 +40,22 @@ public class WiredTriggerRepeaterLong extends InteractionWiredTrigger implements @Override public String getWiredData() { - return this.repeatTime + ""; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.repeatTime + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - if (set.getString("wired_data").length() >= 1) { - this.repeatTime = (Integer.valueOf(set.getString("wired_data"))); + String wiredData = set.getString("wired_data"); + + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.repeatTime = data.repeatTime; + } else { + if (wiredData.length() >= 1) { + this.repeatTime = (Integer.valueOf(wiredData)); + } } if (this.repeatTime < 5000) { @@ -130,4 +139,12 @@ public class WiredTriggerRepeaterLong extends InteractionWiredTrigger implements } } } + + static class JsonData { + int repeatTime; + + public JsonData(int repeatTime) { + this.repeatTime = repeatTime; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerScoreAchieved.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerScoreAchieved.java index b8fc74dd..1f558d88 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerScoreAchieved.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerScoreAchieved.java @@ -4,6 +4,7 @@ import com.eu.habbo.habbohotel.items.Item; import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomUnit; +import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.habbohotel.wired.WiredTriggerType; import com.eu.habbo.messages.ClientMessage; import com.eu.habbo.messages.ServerMessage; @@ -37,14 +38,23 @@ public class WiredTriggerScoreAchieved extends InteractionWiredTrigger { @Override public String getWiredData() { - return this.score + ""; + return WiredHandler.getGsonBuilder().create().toJson(new JsonData( + this.score + )); } @Override public void loadWiredData(ResultSet set, Room room) throws SQLException { - try { - this.score = Integer.valueOf(set.getString("wired_data")); - } catch (Exception e) { + String wiredData = set.getString("wired_data"); + + if (wiredData.startsWith("{")) { + JsonData data = WiredHandler.getGsonBuilder().create().fromJson(wiredData, JsonData.class); + this.score = data.score; + } else { + try { + this.score = Integer.parseInt(wiredData); + } catch (Exception e) { + } } } @@ -85,4 +95,12 @@ public class WiredTriggerScoreAchieved extends InteractionWiredTrigger { public boolean isTriggeredByRoomUnit() { return true; } + + static class JsonData { + int score; + + public JsonData(int score) { + this.score = score; + } + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/messenger/Messenger.java b/src/main/java/com/eu/habbo/habbohotel/messenger/Messenger.java index 59c6083a..db3c357c 100644 --- a/src/main/java/com/eu/habbo/habbohotel/messenger/Messenger.java +++ b/src/main/java/com/eu/habbo/habbohotel/messenger/Messenger.java @@ -167,18 +167,6 @@ public class Messenger { return map; } - public static int friendLimit(Habbo habbo) { - if (habbo.hasPermission("acc_infinite_friends")) { - return Integer.MAX_VALUE; - } - - if (habbo.getHabboStats().hasActiveClub()) { - return MAXIMUM_FRIENDS_HC; - } - - return MAXIMUM_FRIENDS; - } - public static void checkFriendSizeProgress(Habbo habbo) { int progress = habbo.getHabboStats().getAchievementProgress(Emulator.getGameEnvironment().getAchievementManager().getAchievement("FriendListSize")); 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 c891286e..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); @@ -505,6 +515,7 @@ public class ModToolManager { return ban; } + @Deprecated public boolean hasIPBan(Channel habbo) { if (habbo == null) return false; @@ -512,9 +523,13 @@ public class ModToolManager { if (habbo.remoteAddress() == null || ((InetSocketAddress) habbo.remoteAddress()).getAddress() == null) return false; + return this.hasIPBan(((InetSocketAddress) habbo.remoteAddress()).getAddress().getHostAddress()); + } + + public boolean hasIPBan(String ipAddress) { boolean banned = false; try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT * FROM bans WHERE ip = ? AND (type = 'ip' OR type = 'super') AND ban_expire > ? LIMIT 1")) { - statement.setString(1, ((InetSocketAddress) habbo.remoteAddress()).getAddress().getHostAddress()); + statement.setString(1, ipAddress); statement.setInt(2, Emulator.getIntUnixTimestamp()); try (ResultSet set = statement.executeQuery()) { @@ -525,7 +540,6 @@ public class ModToolManager { } catch (SQLException e) { LOGGER.error("Caught SQL exception", e); } - return banned; } diff --git a/src/main/java/com/eu/habbo/habbohotel/permissions/Permission.java b/src/main/java/com/eu/habbo/habbohotel/permissions/Permission.java index 5dfdd12f..469f9072 100644 --- a/src/main/java/com/eu/habbo/habbohotel/permissions/Permission.java +++ b/src/main/java/com/eu/habbo/habbohotel/permissions/Permission.java @@ -6,6 +6,7 @@ public class Permission { public static String ACC_EMPTY_OTHERS = "acc_empty_others"; public static String ACC_ENABLE_OTHERS = "acc_enable_others"; public static String ACC_SEE_WHISPERS = "acc_see_whispers"; + public static String ACC_SEE_TENTCHAT = "acc_see_tentchat"; public static String ACC_SUPERWIRED = "acc_superwired"; public static String ACC_SUPPORTTOOL = "acc_supporttool"; public static String ACC_UNKICKABLE = "acc_unkickable"; diff --git a/src/main/java/com/eu/habbo/habbohotel/pets/Pet.java b/src/main/java/com/eu/habbo/habbohotel/pets/Pet.java index d5e13742..afd7e035 100644 --- a/src/main/java/com/eu/habbo/habbohotel/pets/Pet.java +++ b/src/main/java/com/eu/habbo/habbohotel/pets/Pet.java @@ -578,6 +578,7 @@ public class Pet implements ISerialize, Runnable { this.addHappyness(10); this.addExperience(10); this.addRespect(); + this.needsUpdate = true; if (habbo != null) { habbo.getHabboStats().petRespectPointsToGive--; diff --git a/src/main/java/com/eu/habbo/habbohotel/rooms/Room.java b/src/main/java/com/eu/habbo/habbohotel/rooms/Room.java index 9a0803fb..58321d7d 100644 --- a/src/main/java/com/eu/habbo/habbohotel/rooms/Room.java +++ b/src/main/java/com/eu/habbo/habbohotel/rooms/Room.java @@ -1,6 +1,7 @@ package com.eu.habbo.habbohotel.rooms; import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.achievements.AchievementManager; import com.eu.habbo.habbohotel.bots.Bot; import com.eu.habbo.habbohotel.bots.VisitorBot; import com.eu.habbo.habbohotel.commands.CommandHandler; @@ -115,6 +116,8 @@ public class Room implements Comparable, ISerialize, Runnable { public static int IDLE_CYCLES_KICK = 480; public static String PREFIX_FORMAT = "[%prefix%] "; public static int ROLLERS_MAXIMUM_ROLL_AVATARS = 1; + public static boolean MUTEAREA_CAN_WHISPER = false; + public static double MAXIMUM_FURNI_HEIGHT = 40d; static { for (int i = 1; i <= 3; i++) { @@ -380,6 +383,11 @@ public class Room implements Comparable, ISerialize, Runnable { this.updateItem(item); } } + + for (HabboItem item : this.roomSpecialTypes.getItemsOfType(InteractionFireworks.class)) { + item.setExtradata("1"); + this.updateItem(item); + } } Emulator.getPluginManager().fireEvent(new RoomLoadedEvent(this)); @@ -565,12 +573,14 @@ public class Room implements Comparable, ISerialize, Runnable { return RoomTileState.INVALID; RoomTileState result = RoomTileState.OPEN; - HabboItem highestItem = null; - HabboItem lowestChair = this.getLowestChair(tile); + //HabboItem highestItem = null; + //HabboItem lowestChair = this.getLowestChair(tile); THashSet items = this.getItemsAt(tile); if (items == null) return RoomTileState.INVALID; + HabboItem tallestItem = null; + for (HabboItem item : items) { if (exclude != null && item == exclude) continue; @@ -578,13 +588,16 @@ public class Room implements Comparable, ISerialize, Runnable { return RoomTileState.LAY; } - if (highestItem != null && highestItem.getZ() + Item.getCurrentHeight(highestItem) > item.getZ() + Item.getCurrentHeight(item)) + /*if (highestItem != null && highestItem.getZ() + Item.getCurrentHeight(highestItem) > item.getZ() + Item.getCurrentHeight(item)) continue; - highestItem = item; - if (result == RoomTileState.OPEN) { - result = this.checkStateForItem(item, tile); - } + highestItem = item;*/ + + if(tallestItem != null && tallestItem.getZ() + Item.getCurrentHeight(tallestItem) > item.getZ() + Item.getCurrentHeight(item)) + continue; + + result = this.checkStateForItem(item, tile); + tallestItem = item; /*if (lowestChair != null && item.getZ() > lowestChair.getZ() + 1.5) { continue; @@ -601,7 +614,7 @@ public class Room implements Comparable, ISerialize, Runnable { }*/ } - if (lowestChair != null) return RoomTileState.SIT; + //if (lowestChair != null) return RoomTileState.SIT; return result; } @@ -750,13 +763,20 @@ public class Room implements Comparable, ISerialize, Runnable { THashSet roomUnits = new THashSet<>(); for (Habbo habbo : habbos) { + double oldZ = habbo.getRoomUnit().getZ(); + RoomUserRotation oldRotation = habbo.getRoomUnit().getBodyRotation(); double z = habbo.getRoomUnit().getCurrentLocation().getStackHeight(); + boolean updated = false; - if ((item == null && !habbo.getRoomUnit().cmdSit) || (item != null && !item.getBaseItem().allowSit())) + if (habbo.getRoomUnit().hasStatus(RoomUnitStatus.SIT) && ((item == null && !habbo.getRoomUnit().cmdSit) || (item != null && !item.getBaseItem().allowSit()))) { habbo.getRoomUnit().removeStatus(RoomUnitStatus.SIT); + updated = true; + } - if ((item == null && !habbo.getRoomUnit().cmdLay) || (item != null && !item.getBaseItem().allowLay())) + if (habbo.getRoomUnit().hasStatus(RoomUnitStatus.LAY) && ((item == null && !habbo.getRoomUnit().cmdLay) || (item != null && !item.getBaseItem().allowLay()))) { habbo.getRoomUnit().removeStatus(RoomUnitStatus.LAY); + updated = true; + } if (item != null && (item.getBaseItem().allowSit() || item.getBaseItem().allowLay())) { habbo.getRoomUnit().setZ(item.getZ()); @@ -766,12 +786,16 @@ public class Room implements Comparable, ISerialize, Runnable { habbo.getRoomUnit().setZ(z); habbo.getRoomUnit().setPreviousLocationZ(z); } - roomUnits.add(habbo.getRoomUnit()); + + if(habbo.getRoomUnit().getCurrentLocation().is(x, y) && (oldZ != z || updated || oldRotation != habbo.getRoomUnit().getBodyRotation())) { + habbo.getRoomUnit().statusUpdate(true); + //roomUnits.add(habbo.getRoomUnit()); + } } - if (!roomUnits.isEmpty()) { + /*if (!roomUnits.isEmpty()) { this.sendComposer(new RoomUserStatusComposer(roomUnits, true).compose()); - } + }*/ } public void updateBotsAt(short x, short y) { @@ -962,7 +986,6 @@ public class Room implements Comparable, ISerialize, Runnable { Emulator.getPluginManager().fireEvent(new RoomUnloadedEvent(this)); } - @SuppressWarnings("NullableProblems") @Override public int compareTo(Room o) { if (o.getUserCount() != this.getUserCount()) { @@ -1187,8 +1210,11 @@ public class Room implements Comparable, ISerialize, Runnable { habbo.getRoomUnit().increaseIdleTimer(); if (habbo.getRoomUnit().isIdle()) { - this.sendComposer(new RoomUnitIdleComposer(habbo.getRoomUnit()).compose()); - WiredHandler.handle(WiredTriggerType.IDLES, habbo.getRoomUnit(), this, new Object[]{habbo}); + boolean danceIsNone = (habbo.getRoomUnit().getDanceType() == DanceType.NONE); + if (danceIsNone) + this.sendComposer(new RoomUnitIdleComposer(habbo.getRoomUnit()).compose()); + if (danceIsNone && !Emulator.getConfig().getBoolean("hotel.roomuser.idle.not_dancing.ignore.wired_idle")) + WiredHandler.handle(WiredTriggerType.IDLES, habbo.getRoomUnit(), this, new Object[]{habbo}); } } else { habbo.getRoomUnit().increaseIdleTimer(); @@ -1204,6 +1230,19 @@ public class Room implements Comparable, ISerialize, Runnable { } } + if (Emulator.getConfig().getBoolean("hotel.rooms.deco_hosting")) { + //Check if the user isn't the owner id + if (this.ownerId != habbo.getHabboInfo().getId()) { + //Check if the time already have 1 minute (120 / 2 = 60s) + if (habbo.getRoomUnit().getTimeInRoom() >= 120) { + AchievementManager.progressAchievement(this.ownerId, Emulator.getGameEnvironment().getAchievementManager().getAchievement("RoomDecoHosting")); + habbo.getRoomUnit().resetTimeInRoom(); + } else { + habbo.getRoomUnit().increaseTimeInRoom(); + } + } + } + if (habbo.getHabboStats().mutedBubbleTracker && habbo.getHabboStats().allowTalk()) { habbo.getHabboStats().mutedBubbleTracker = false; this.sendComposer(new RoomUserIgnoredComposer(habbo, RoomUserIgnoredComposer.UNIGNORED).compose()); @@ -1397,7 +1436,7 @@ public class Room implements Comparable, ISerialize, Runnable { roomUserRolledEvent = new UserRolledEvent(null, null, null); } - ArrayList unitsOnTile = new ArrayList(rollerTile.getUnits()); + ArrayList unitsOnTile = new ArrayList<>(rollerTile.getUnits()); for (RoomUnit unit : rollerTile.getUnits()) { if (unit.getRoomUnitType() == RoomUnitType.PET) { @@ -1408,7 +1447,7 @@ public class Room implements Comparable, ISerialize, Runnable { } } - HabboItem nextTileChair = this.getLowestChair(tileInFront); + HabboItem nextTileChair = this.getTallestChair(tileInFront); THashSet usersRolledThisTile = new THashSet<>(); @@ -1445,7 +1484,7 @@ public class Room implements Comparable, ISerialize, Runnable { tile.setStackHeight(ridingUnit.getZ() + zOffset); rolledUnitIds.add(ridingUnit.getId()); updatedUnit.remove(ridingUnit); - messages.add(new RoomUnitOnRollerComposer(ridingUnit, roller, ridingUnit.getCurrentLocation(), ridingUnit.getZ(), tile, tile.getStackHeight() + (nextTileChair != null ? -1 : 0), room)); + messages.add(new RoomUnitOnRollerComposer(ridingUnit, roller, ridingUnit.getCurrentLocation(), ridingUnit.getZ(), tile, tile.getStackHeight(), room)); isRiding = true; } } @@ -1454,16 +1493,16 @@ public class Room implements Comparable, ISerialize, Runnable { usersRolledThisTile.add(unit.getId()); rolledUnitIds.add(unit.getId()); updatedUnit.remove(unit); - messages.add(new RoomUnitOnRollerComposer(unit, roller, unit.getCurrentLocation(), unit.getZ() + (isRiding ? 1 : 0), tile, tile.getStackHeight() + (isRiding ? 1 : 0) + (nextTileChair != null ? -1 : 0), room)); + messages.add(new RoomUnitOnRollerComposer(unit, roller, unit.getCurrentLocation(), unit.getZ() + (isRiding ? 1 : 0), tile, tile.getStackHeight() + (isRiding ? 1 : 0), room)); if (itemsOnRoller.isEmpty()) { HabboItem item = room.getTopItemAt(tileInFront.x, tileInFront.y); - if (item != null && itemsNewTile.contains(item)) { + if (item != null && itemsNewTile.contains(item) && !itemsOnRoller.contains(item)) { Emulator.getThreading().run(() -> { if (unit.getGoal() == rollerTile) { try { - item.onWalkOn(unit, room, null); + item.onWalkOn(unit, room, new Object[] { rollerTile, tileInFront }); } catch (Exception e) { LOGGER.error("Caught exception", e); } @@ -1602,23 +1641,22 @@ public class Room implements Comparable, ISerialize, Runnable { } if (!unit.isWalking() && !unit.cmdSit) { - HabboItem topItem = this.getLowestChair(this.getLayout().getTile(unit.getX(), unit.getY())); + RoomTile thisTile = this.getLayout().getTile(unit.getX(), unit.getY()); + HabboItem topItem = this.getTallestChair(thisTile); if (topItem == null || !topItem.getBaseItem().allowSit()) { if (unit.hasStatus(RoomUnitStatus.SIT)) { unit.removeStatus(RoomUnitStatus.SIT); update = true; } - } else { - if (!unit.hasStatus(RoomUnitStatus.SIT) || unit.sitUpdate) { - this.dance(unit, DanceType.NONE); - //int tileHeight = this.layout.getTile(topItem.getX(), topItem.getY()).z; - unit.setStatus(RoomUnitStatus.SIT, (Item.getCurrentHeight(topItem) * 1.0D) + ""); - unit.setZ(topItem.getZ()); - unit.setRotation(RoomUserRotation.values()[topItem.getRotation()]); - unit.sitUpdate = false; - return true; - } + } else if (thisTile.state == RoomTileState.SIT && (!unit.hasStatus(RoomUnitStatus.SIT) || unit.sitUpdate)) { + this.dance(unit, DanceType.NONE); + //int tileHeight = this.layout.getTile(topItem.getX(), topItem.getY()).z; + unit.setStatus(RoomUnitStatus.SIT, (Item.getCurrentHeight(topItem) * 1.0D) + ""); + unit.setZ(topItem.getZ()); + unit.setRotation(RoomUserRotation.values()[topItem.getRotation()]); + unit.sitUpdate = false; + return true; } } } @@ -1946,7 +1984,7 @@ public class Room implements Comparable, ISerialize, Runnable { if (extraData.length == 4) { if (extraData[0].equalsIgnoreCase("1")) { - return Color.getHSBColor(Integer.valueOf(extraData[1]), Integer.valueOf(extraData[2]), Integer.valueOf(extraData[3])); + return Color.getHSBColor(Integer.parseInt(extraData[1]), Integer.parseInt(extraData[2]), Integer.parseInt(extraData[3])); } } } @@ -2162,7 +2200,7 @@ public class Room implements Comparable, ISerialize, Runnable { synchronized (this.games) { for (Game game : this.games) { - if (game != null && gameType.isInstance(game)) { + if (gameType.isInstance(game)) { return game; } } @@ -2171,6 +2209,20 @@ public class Room implements Comparable, ISerialize, Runnable { return null; } + public Game getGameOrCreate(Class gameType) { + Game game = this.getGame(gameType); + if(game == null) { + try { + game = gameType.getDeclaredConstructor(Room.class).newInstance(this); + this.addGame(game); + } catch (Exception e) { + LOGGER.error("Error getting game " + gameType.getName(), e); + } + } + + return game; + } + public ConcurrentSet getGames() { return this.games; } @@ -2375,7 +2427,10 @@ public class Room implements Comparable, ISerialize, Runnable { this.roomSpecialTypes.addUndefined(item); } else if (item instanceof InteractionSnowboardSlope) { this.roomSpecialTypes.addUndefined(item); + } else if (item instanceof InteractionFireworks) { + this.roomSpecialTypes.addUndefined(item); } + } } @@ -2900,6 +2955,25 @@ public class Room implements Comparable, ISerialize, Runnable { return habbos; } + public THashSet getHabbosAndBotsAt(short x, short y) { + return this.getHabbosAndBotsAt(this.layout.getTile(x, y)); + } + + public THashSet getHabbosAndBotsAt(RoomTile tile) { + THashSet list = new THashSet<>(); + + for (Bot bot : this.getBotsAt(tile)) { + list.add(bot.getRoomUnit()); + } + + for(Habbo habbo : this.getHabbosAt(tile)) + { + list.add(habbo.getRoomUnit()); + } + + return list; + } + public THashSet getHabbosOnItem(HabboItem item) { THashSet habbos = new THashSet<>(); for (short x = item.getX(); x < item.getX() + item.getBaseItem().getLength(); x++) { @@ -2938,7 +3012,7 @@ public class Room implements Comparable, ISerialize, Runnable { this.teleportRoomUnitToLocation(roomUnit, x, y, 0.0); } - void teleportRoomUnitToLocation(RoomUnit roomUnit, short x, short y, double z) { + public void teleportRoomUnitToLocation(RoomUnit roomUnit, short x, short y, double z) { if (this.loaded) { RoomTile tile = this.layout.getTile(x, y); @@ -3045,7 +3119,7 @@ public class Room implements Comparable, ISerialize, Runnable { } } habbo.getHabboStats().lastChat = millis; - if (roomChatMessage != null && roomChatMessage.getMessage().equalsIgnoreCase("i am a pirate")) { + if (roomChatMessage != null && Emulator.getConfig().getBoolean("easter_eggs.enabled") && roomChatMessage.getMessage().equalsIgnoreCase("i am a pirate")) { habbo.getHabboStats().chatCounter.addAndGet(1); Emulator.getThreading().run(new YouAreAPirate(habbo, this)); return; @@ -3065,9 +3139,11 @@ public class Room implements Comparable, ISerialize, Runnable { if (roomChatMessage == null || roomChatMessage.getMessage() == null || roomChatMessage.getMessage().equals("")) return; - for (HabboItem area : this.getRoomSpecialTypes().getItemsOfType(InteractionMuteArea.class)) { - if (((InteractionMuteArea) area).inSquare(habbo.getRoomUnit().getCurrentLocation())) { - return; + if(!habbo.hasPermission(Permission.ACC_NOMUTE) && (!MUTEAREA_CAN_WHISPER || chatType != RoomChatType.WHISPER)) { + for (HabboItem area : this.getRoomSpecialTypes().getItemsOfType(InteractionMuteArea.class)) { + if (((InteractionMuteArea) area).inSquare(habbo.getRoomUnit().getCurrentLocation())) { + return; + } } } @@ -3130,7 +3206,7 @@ public class Room implements Comparable, ISerialize, Runnable { ServerMessage prefixMessage = null; if (Emulator.getPluginManager().isRegistered(UsernameTalkEvent.class, true)) { - UsernameTalkEvent usernameTalkEvent = (UsernameTalkEvent) Emulator.getPluginManager().fireEvent(new UsernameTalkEvent(habbo, roomChatMessage, chatType)); + UsernameTalkEvent usernameTalkEvent = Emulator.getPluginManager().fireEvent(new UsernameTalkEvent(habbo, roomChatMessage, chatType)); if (usernameTalkEvent.hasCustomComposer()) { prefixMessage = usernameTalkEvent.getCustomComposer(); } @@ -3141,7 +3217,7 @@ public class Room implements Comparable, ISerialize, Runnable { } ServerMessage clearPrefixMessage = prefixMessage != null ? new RoomUserNameChangedComposer(habbo).compose() : null; - Rectangle show = this.roomSpecialTypes.tentAt(habbo.getRoomUnit().getCurrentLocation()); + Rectangle tentRectangle = this.roomSpecialTypes.tentAt(habbo.getRoomUnit().getCurrentLocation()); String trimmedMessage = roomChatMessage.getMessage().replaceAll("\\s+$",""); @@ -3187,7 +3263,7 @@ public class Room implements Comparable, ISerialize, Runnable { if ((h.getRoomUnit().getCurrentLocation().distance(habbo.getRoomUnit().getCurrentLocation()) <= this.chatDistance || h.equals(habbo) || this.hasRights(h) || - noChatLimit) && (show == null || RoomLayout.tileInSquare(show, h.getRoomUnit().getCurrentLocation()))) { + noChatLimit) && (tentRectangle == null || RoomLayout.tileInSquare(tentRectangle, h.getRoomUnit().getCurrentLocation()))) { if (!h.getHabboStats().userIgnored(habbo.getHabboInfo().getId())) { if (prefixMessage != null && !h.getHabboStats().preferOldChat) { h.getClient().sendResponse(prefixMessage); @@ -3197,13 +3273,19 @@ public class Room implements Comparable, ISerialize, Runnable { h.getClient().sendResponse(clearPrefixMessage); } } + continue; } + // Staff should be able to see the tent chat anyhow + showTentChatMessageOutsideTentIfPermitted(h, roomChatMessage, tentRectangle); } } else if (chatType == RoomChatType.SHOUT) { ServerMessage message = new RoomUserShoutComposer(roomChatMessage).compose(); for (Habbo h : this.getHabbos()) { - if (!h.getHabboStats().userIgnored(habbo.getHabboInfo().getId()) && (show == null || RoomLayout.tileInSquare(show, h.getRoomUnit().getCurrentLocation()))) { + // Show the message + // If the receiving Habbo has not ignored the sending Habbo + // AND the sending Habbo is NOT in a tent OR the receiving Habbo is in the same tent as the sending Habbo + if (!h.getHabboStats().userIgnored(habbo.getHabboInfo().getId()) && (tentRectangle == null || RoomLayout.tileInSquare(tentRectangle, h.getRoomUnit().getCurrentLocation()))) { if (prefixMessage != null && !h.getHabboStats().preferOldChat) { h.getClient().sendResponse(prefixMessage); } @@ -3211,7 +3293,10 @@ public class Room implements Comparable, ISerialize, Runnable { if (clearPrefixMessage != null && !h.getHabboStats().preferOldChat) { h.getClient().sendResponse(clearPrefixMessage); } + continue; } + // Staff should be able to see the tent chat anyhow, even when not in the same tent + showTentChatMessageOutsideTentIfPermitted(h, roomChatMessage, tentRectangle); } } @@ -3244,10 +3329,18 @@ public class Room implements Comparable, ISerialize, Runnable { RoomChatMessage itemMessage = new RoomChatMessage(Emulator.getTexts().getValue(item.getBaseItem().getName() + ".message." + randomValue, item.getBaseItem().getName() + ".message." + randomValue + " not found!"), habbo, RoomChatMessageBubbles.getBubble(Emulator.getConfig().getInt(item.getBaseItem().getName() + ".message.bubble", RoomChatMessageBubbles.PARROT.getType()))); - this.sendComposer(new RoomUserShoutComposer(itemMessage).compose()); + this.sendComposer(new RoomUserTalkComposer(itemMessage).compose()); try { item.onClick(habbo.getClient(), this, new Object[0]); + item.setExtradata("1"); + updateItemState(item); + + Emulator.getThreading().run(() -> { + item.setExtradata("0"); + updateItemState(item); + }, 2000); + break; } catch (Exception e) { LOGGER.error("Caught exception", e); @@ -3255,11 +3348,25 @@ public class Room implements Comparable, ISerialize, Runnable { } } } - } } } + /** + * Sends the given message to the receiving Habbo if the Habbo has the ACC_SEE_TENTCHAT permission and is not within the tent + * @param receivingHabbo The receiving Habbo + * @param roomChatMessage The message to receive + * @param tentRectangle The whole tent area from where the sending Habbo is saying something + */ + private void showTentChatMessageOutsideTentIfPermitted(Habbo receivingHabbo, RoomChatMessage roomChatMessage, Rectangle tentRectangle) { + if (receivingHabbo != null && receivingHabbo.hasPermission(Permission.ACC_SEE_TENTCHAT) && tentRectangle != null && !RoomLayout.tileInSquare(tentRectangle, receivingHabbo.getRoomUnit().getCurrentLocation())) { + RoomChatMessage staffChatMessage = new RoomChatMessage(roomChatMessage); + staffChatMessage.setMessage("[" + Emulator.getTexts().getValue("hotel.room.tent.prefix") + "] " + staffChatMessage.getMessage()); + final ServerMessage staffMessage = new RoomUserWhisperComposer(staffChatMessage).compose(); + receivingHabbo.getClient().sendResponse(staffMessage); + } + } + public THashSet getLockedTiles() { THashSet lockedTiles = new THashSet<>(); @@ -3336,9 +3443,9 @@ public class Room implements Comparable, ISerialize, Runnable { return items; if (this.loaded) { - if (this.tileCache.containsKey(tile)) { - return this.tileCache.get(tile); - } + THashSet cachedItems = this.tileCache.get(tile); + if(cachedItems != null) + return cachedItems; } TIntObjectIterator iterator = this.roomItems.iterator(); @@ -3444,6 +3551,27 @@ public class Room implements Comparable, ISerialize, Runnable { return highestItem; } + public HabboItem getTopItemAt(THashSet tiles, HabboItem exclude) { + HabboItem highestItem = null; + for(RoomTile tile : tiles) { + + if (tile == null) + continue; + + for (HabboItem item : this.getItemsAt(tile.x, tile.y)) { + if (exclude != null && exclude == item) + continue; + + if (highestItem != null && highestItem.getZ() + Item.getCurrentHeight(highestItem) > item.getZ() + Item.getCurrentHeight(item)) + continue; + + highestItem = item; + } + } + + return highestItem; + } + public double getTopHeightAt(int x, int y) { HabboItem item = this.getTopItemAt(x, y); @@ -3486,10 +3614,37 @@ public class Room implements Comparable, ISerialize, Runnable { return lowestChair; } + public HabboItem getTallestChair(RoomTile tile) { + HabboItem lowestChair = null; + + THashSet items = this.getItemsAt(tile); + if (items != null && !items.isEmpty()) { + for (HabboItem item : items) { + + if(!item.getBaseItem().allowSit()) + continue; + + if(lowestChair != null && lowestChair.getZ() + Item.getCurrentHeight(lowestChair) > item.getZ() + Item.getCurrentHeight(item)) + continue; + + lowestChair = item; + } + } + + return lowestChair; + } + public double getStackHeight(short x, short y, boolean calculateHeightmap, HabboItem exclude) { if (x < 0 || y < 0 || this.layout == null) return calculateHeightmap ? Short.MAX_VALUE : 0.0; + + if (Emulator.getPluginManager().isRegistered(FurnitureStackHeightEvent.class, true)) { + FurnitureStackHeightEvent event = Emulator.getPluginManager().fireEvent(new FurnitureStackHeightEvent(x, y, this)); + if(event.hasPluginHelper()) { + return calculateHeightmap ? event.getHeight() * 256.0D : event.getHeight(); + } + } double height = this.layout.getHeightAtSquare(x, y); boolean canStack = true; @@ -3506,14 +3661,14 @@ public class Room implements Comparable, ISerialize, Runnable { HabboItem item = this.getTopItemAt(x, y, exclude); if (item != null) { canStack = item.getBaseItem().allowStack(); - height = item.getZ() + Item.getCurrentHeight(item); + height = item.getZ() + (item.getBaseItem().allowSit() ? 0 : Item.getCurrentHeight(item)); } - HabboItem lowestChair = this.getLowestChair(x, y); + /*HabboItem lowestChair = this.getLowestChair(x, y); if (lowestChair != null && lowestChair != exclude) { canStack = true; height = lowestChair.getZ(); - } + }*/ if (calculateHeightmap) { return (canStack ? height * 256.0D : Short.MAX_VALUE); @@ -3589,41 +3744,19 @@ public class Room implements Comparable, ISerialize, Runnable { if (items == null) return false; - HabboItem topItem = null; - HabboItem lowestSitItem = null; - boolean canSitUnder = false; + HabboItem tallestItem = null; for (HabboItem item : items) { - if ((lowestSitItem == null || lowestSitItem.getZ() > item.getZ()) && item.getBaseItem().allowSit()) { - lowestSitItem = item; - canSitUnder = true; - } + if(tallestItem != null && tallestItem.getZ() + Item.getCurrentHeight(tallestItem) > item.getZ() + Item.getCurrentHeight(item)) + continue; - if (lowestSitItem != null && canSitUnder) { - if (item != lowestSitItem) { - double distance = item.getZ() - lowestSitItem.getZ(); - - if (distance >= 0 && distance < 0.8) { - canSitUnder = false; - } - } - } - - if (topItem == null || Item.getCurrentHeight(item) > Item.getCurrentHeight(topItem)) { - topItem = item; - } + tallestItem = item; } - if (topItem == null) + if (tallestItem == null) return false; - if (lowestSitItem == null) - return false; - - if (topItem == lowestSitItem) - return true; - - return topItem.getZ() <= lowestSitItem.getZ() || (canSitUnder); + return tallestItem.getBaseItem().allowSit(); } public boolean canLayAt(int x, int y) { @@ -3755,20 +3888,27 @@ public class Room implements Comparable, ISerialize, Runnable { } } - //TODO: Return Enum - public int guildRightLevel(Habbo habbo) { + public RoomRightLevels getGuildRightLevel(Habbo habbo) { if (this.guild > 0 && habbo.getHabboStats().hasGuild(this.guild)) { Guild guild = Emulator.getGameEnvironment().getGuildManager().getGuild(this.guild); if (Emulator.getGameEnvironment().getGuildManager().getOnlyAdmins(guild).get(habbo.getHabboInfo().getId()) != null) - return 3; + return RoomRightLevels.GUILD_ADMIN; if (guild.getRights()) { - return 2; + return RoomRightLevels.GUILD_RIGHTS; } } - return 0; + return RoomRightLevels.NONE; + } + + /** + * @deprecated Deprecated since 2.5.0. Use {@link #getGuildRightLevel(Habbo)} instead. + */ + @Deprecated + public int guildRightLevel(Habbo habbo) { + return this.getGuildRightLevel(habbo).level; } public boolean isOwner(Habbo habbo) { @@ -3885,16 +4025,9 @@ public class Room implements Comparable, ISerialize, Runnable { } else if (this.hasRights(habbo) && !this.hasGuild()) { flatCtrl = RoomRightLevels.RIGHTS; } else if (this.hasGuild()) { - int level = this.guildRightLevel(habbo); - - if (level == 3) { - flatCtrl = RoomRightLevels.GUILD_ADMIN; - } else if (level == 2) { - flatCtrl = RoomRightLevels.GUILD_RIGHTS; - } + flatCtrl = this.getGuildRightLevel(habbo); } - habbo.getClient().sendResponse(new RoomRightsComposer(flatCtrl)); habbo.getRoomUnit().setStatus(RoomUnitStatus.FLAT_CONTROL, flatCtrl.level + ""); habbo.getRoomUnit().setRightsLevel(flatCtrl); @@ -4034,6 +4167,10 @@ public class Room implements Comparable, ISerialize, Runnable { if (this.layout == null) return; this.updateTiles(this.getLayout().getTilesAt(this.layout.getTile(item.getX(), item.getY()), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation())); + + if(item instanceof InteractionMultiHeight) { + ((InteractionMultiHeight)item).updateUnitsOnItem(this); + } } } @@ -4199,14 +4336,16 @@ public class Room implements Comparable, ISerialize, Runnable { } public void dance(RoomUnit unit, DanceType danceType) { - boolean isDancing = !unit.getDanceType().equals(DanceType.NONE); - unit.setDanceType(danceType); - this.sendComposer(new RoomUserDanceComposer(unit).compose()); + if(unit.getDanceType() != danceType) { + boolean isDancing = !unit.getDanceType().equals(DanceType.NONE); + unit.setDanceType(danceType); + this.sendComposer(new RoomUserDanceComposer(unit).compose()); - if (danceType.equals(DanceType.NONE) && isDancing) { - WiredHandler.handle(WiredTriggerType.STOPS_DANCING, unit, this, new Object[]{unit}); - } else if (!danceType.equals(DanceType.NONE) && !isDancing) { - WiredHandler.handle(WiredTriggerType.STARTS_DANCING, unit, this, new Object[]{unit}); + if (danceType.equals(DanceType.NONE) && isDancing) { + WiredHandler.handle(WiredTriggerType.STOPS_DANCING, unit, this, new Object[]{unit}); + } else if (!danceType.equals(DanceType.NONE) && !isDancing) { + WiredHandler.handle(WiredTriggerType.STARTS_DANCING, unit, this, new Object[]{unit}); + } } } @@ -4329,10 +4468,8 @@ public class Room implements Comparable, ISerialize, Runnable { return FurnitureMovementError.MAX_ITEMS; } - - rotation %= 8; - if (this.hasRights(habbo) || this.guildRightLevel(habbo) >= 2 || habbo.hasPermission(Permission.ACC_MOVEROTATE)) { + if (this.hasRights(habbo) || this.getGuildRightLevel(habbo).isEqualOrGreaterThan(RoomRightLevels.GUILD_RIGHTS) || habbo.hasPermission(Permission.ACC_MOVEROTATE)) { return FurnitureMovementError.NONE; } @@ -4352,6 +4489,10 @@ public class Room implements Comparable, ISerialize, Runnable { } public FurnitureMovementError furnitureFitsAt(RoomTile tile, HabboItem item, int rotation) { + return furnitureFitsAt(tile, item, rotation, true); + } + + public FurnitureMovementError furnitureFitsAt(RoomTile tile, HabboItem item, int rotation, boolean checkForUnits) { if (!this.layout.fitsOnMap(tile, item.getBaseItem().getWidth(), item.getBaseItem().getLength(), rotation)) return FurnitureMovementError.INVALID_MOVE; @@ -4359,10 +4500,10 @@ public class Room implements Comparable, ISerialize, Runnable { THashSet occupiedTiles = this.layout.getTilesAt(tile, item.getBaseItem().getWidth(), item.getBaseItem().getLength(), rotation); for (RoomTile t : occupiedTiles) { - - if (this.hasHabbosAt(t.x, t.y)) return FurnitureMovementError.TILE_HAS_HABBOS; - if (this.hasBotsAt(t.x, t.y)) return FurnitureMovementError.TILE_HAS_BOTS; - if (this.hasPetsAt(t.x, t.y)) return FurnitureMovementError.TILE_HAS_PETS; + if(t.state == RoomTileState.INVALID) return FurnitureMovementError.INVALID_MOVE; + if (checkForUnits && this.hasHabbosAt(t.x, t.y)) return FurnitureMovementError.TILE_HAS_HABBOS; + if (checkForUnits && this.hasBotsAt(t.x, t.y)) return FurnitureMovementError.TILE_HAS_BOTS; + if (checkForUnits && this.hasPetsAt(t.x, t.y)) return FurnitureMovementError.TILE_HAS_PETS; } List>> tileFurniList = new ArrayList<>(); @@ -4382,27 +4523,37 @@ public class Room implements Comparable, ISerialize, Runnable { return FurnitureMovementError.NONE; } - public FurnitureMovementError placeFloorFurniAt(HabboItem item, RoomTile tile, int rotation, Habbo owner) throws Exception { + public FurnitureMovementError placeFloorFurniAt(HabboItem item, RoomTile tile, int rotation, Habbo owner) { + boolean pluginHelper = false; if (Emulator.getPluginManager().isRegistered(FurniturePlacedEvent.class, true)) { - Event furniturePlacedEvent = new FurniturePlacedEvent(item, owner, tile); - Emulator.getPluginManager().fireEvent(furniturePlacedEvent); + FurniturePlacedEvent event = Emulator.getPluginManager().fireEvent(new FurniturePlacedEvent(item, owner, tile)); - if (furniturePlacedEvent.isCancelled()) + if (event.isCancelled()) { return FurnitureMovementError.CANCEL_PLUGIN_PLACE; + } + + pluginHelper = event.hasPluginHelper(); } THashSet occupiedTiles = this.layout.getTilesAt(tile, item.getBaseItem().getWidth(), item.getBaseItem().getLength(), rotation); FurnitureMovementError fits = furnitureFitsAt(tile, item, rotation); - if (!fits.equals(FurnitureMovementError.NONE)) { + if (!fits.equals(FurnitureMovementError.NONE) && !pluginHelper) { return fits; } double height = tile.getStackHeight(); + for(RoomTile tile2 : occupiedTiles) { + double sHeight = tile2.getStackHeight(); + if(sHeight > height) { + height = sHeight; + } + } + if (Emulator.getPluginManager().isRegistered(FurnitureBuildheightEvent.class, true)) { - FurnitureBuildheightEvent event = (FurnitureBuildheightEvent) Emulator.getPluginManager().fireEvent(new FurnitureBuildheightEvent(item, owner, 0.00, height)); + FurnitureBuildheightEvent event = Emulator.getPluginManager().fireEvent(new FurnitureBuildheightEvent(item, owner, 0.00, height)); if (event.hasChangedHeight()) { height = event.getUpdatedHeight(); } @@ -4433,7 +4584,7 @@ public class Room implements Comparable, ISerialize, Runnable { } public FurnitureMovementError placeWallFurniAt(HabboItem item, String wallPosition, Habbo owner) { - if (!(this.hasRights(owner) || this.guildRightLevel(owner) >= 2)) { + if (!(this.hasRights(owner) || this.getGuildRightLevel(owner).isEqualOrGreaterThan(RoomRightLevels.GUILD_RIGHTS))) { return FurnitureMovementError.NO_RIGHTS; } @@ -4459,13 +4610,20 @@ public class Room implements Comparable, ISerialize, Runnable { } public FurnitureMovementError moveFurniTo(HabboItem item, RoomTile tile, int rotation, Habbo actor) { - RoomTile oldLocation = this.layout.getTile(item.getX(), item.getY()); - if (Emulator.getPluginManager().isRegistered(FurnitureMovedEvent.class, true)) { - if (Emulator.getPluginManager().fireEvent(new FurnitureMovedEvent(item, actor, oldLocation, tile)).isCancelled()) - return FurnitureMovementError.CANCEL_PLUGIN_MOVE; - } + return moveFurniTo(item, tile, rotation, actor, true); + } - HabboItem topItem = this.getTopItemAt(tile.x, tile.y); + public FurnitureMovementError moveFurniTo(HabboItem item, RoomTile tile, int rotation, Habbo actor, boolean sendUpdates) { + RoomTile oldLocation = this.layout.getTile(item.getX(), item.getY()); + + boolean pluginHelper = false; + if (Emulator.getPluginManager().isRegistered(FurnitureMovedEvent.class, true)) { + FurnitureMovedEvent event = Emulator.getPluginManager().fireEvent(new FurnitureMovedEvent(item, actor, oldLocation, tile)); + if(event.isCancelled()) { + return FurnitureMovementError.CANCEL_PLUGIN_MOVE; + } + pluginHelper = event.hasPluginHelper(); + } boolean magicTile = item instanceof InteractionStackHelper; @@ -4474,8 +4632,10 @@ public class Room implements Comparable, ISerialize, Runnable { //Check if can be placed at new position THashSet occupiedTiles = this.layout.getTilesAt(tile, item.getBaseItem().getWidth(), item.getBaseItem().getLength(), rotation); - if (!stackHelper.isPresent()) { - if (topItem != item) { + HabboItem topItem = this.getTopItemAt(occupiedTiles, null); + + if (!stackHelper.isPresent() && !pluginHelper) { + if (oldLocation != tile) { for (RoomTile t : occupiedTiles) { HabboItem tileTopItem = this.getTopItemAt(t.x, t.y); if (!magicTile && ((tileTopItem != null && tileTopItem != item ? (t.state.equals(RoomTileState.INVALID) || !t.getAllowStack() || !tileTopItem.getBaseItem().allowStack()) : this.calculateTileState(t, item).equals(RoomTileState.INVALID)))) @@ -4499,9 +4659,9 @@ public class Room implements Comparable, ISerialize, Runnable { THashSet oldOccupiedTiles = this.layout.getTilesAt(this.layout.getTile(item.getX(), item.getY()), item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation()); int oldRotation = item.getRotation(); - item.setRotation(rotation); if (oldRotation != rotation) { + item.setRotation(rotation); if (Emulator.getPluginManager().isRegistered(FurnitureRotatedEvent.class, true)) { Event furnitureRotatedEvent = new FurnitureRotatedEvent(item, actor, oldRotation); Emulator.getPluginManager().fireEvent(furnitureRotatedEvent); @@ -4511,27 +4671,42 @@ public class Room implements Comparable, ISerialize, Runnable { return FurnitureMovementError.CANCEL_PLUGIN_ROTATE; } } + + if((!stackHelper.isPresent() && topItem != null && topItem != item && !topItem.getBaseItem().allowStack())|| (topItem != null && topItem != item && topItem.getZ() + Item.getCurrentHeight(topItem) + Item.getCurrentHeight(item) > MAXIMUM_FURNI_HEIGHT)) + { + item.setRotation(oldRotation); + return FurnitureMovementError.CANT_STACK; + } + + // ) } //Place at new position double height; if (stackHelper.isPresent()) { - height = stackHelper.get().getExtradata().isEmpty() ? Double.valueOf("0.0") : (Double.valueOf(stackHelper.get().getExtradata()) / 100); - } else if (item.equals(topItem) && tile.x == item.getX() && tile.y == item.getY()) { + height = stackHelper.get().getExtradata().isEmpty() ? Double.parseDouble("0.0") : (Double.parseDouble(stackHelper.get().getExtradata()) / 100); + } else if (item == topItem) { height = item.getZ(); } else { height = this.getStackHeight(tile.x, tile.y, false, item); + for(RoomTile til : occupiedTiles) { + double sHeight = this.getStackHeight(til.x, til.y, false, item); + if(sHeight > height) { + height = sHeight; + } + } } if (Emulator.getPluginManager().isRegistered(FurnitureBuildheightEvent.class, true)) { - FurnitureBuildheightEvent event = (FurnitureBuildheightEvent) Emulator.getPluginManager().fireEvent(new FurnitureBuildheightEvent(item, actor, 0.00, height)); + FurnitureBuildheightEvent event = Emulator.getPluginManager().fireEvent(new FurnitureBuildheightEvent(item, actor, 0.00, height)); if (event.hasChangedHeight()) { height = event.getUpdatedHeight(); } } - if(height > 40d) return FurnitureMovementError.CANT_STACK; + if(height > MAXIMUM_FURNI_HEIGHT) return FurnitureMovementError.CANT_STACK; + if(height < this.getLayout().getHeightAtSquare(tile.x, tile.y)) return FurnitureMovementError.CANT_STACK; //prevent furni going under the floor item.setX(tile.x); item.setY(tile.y); @@ -4540,8 +4715,8 @@ public class Room implements Comparable, ISerialize, Runnable { item.setZ(tile.z); item.setExtradata("" + item.getZ() * 100); } - if (item.getZ() > 40d) { - item.setZ(40); + if (item.getZ() > MAXIMUM_FURNI_HEIGHT) { + item.setZ(MAXIMUM_FURNI_HEIGHT); } @@ -4550,7 +4725,10 @@ public class Room implements Comparable, ISerialize, Runnable { item.needsUpdate(true); Emulator.getThreading().run(item); - this.sendComposer(new FloorItemUpdateComposer(item).compose()); + if(sendUpdates) { + this.sendComposer(new FloorItemUpdateComposer(item).compose()); + } + //Update old & new tiles occupiedTiles.removeAll(oldOccupiedTiles); occupiedTiles.addAll(oldOccupiedTiles); @@ -4562,9 +4740,9 @@ public class Room implements Comparable, ISerialize, Runnable { t.x, t.y, this.getHabbosAt(t.x, t.y) - .stream() - .filter(h -> !h.getRoomUnit().hasStatus(RoomUnitStatus.MOVE)) - .collect(Collectors.toCollection(THashSet::new)) + /*.stream() + .filter(h -> !h.getRoomUnit().hasStatus(RoomUnitStatus.MOVE) || h.getRoomUnit().getGoal() == t) + .collect(Collectors.toCollection(THashSet::new))*/ ); this.updateBotsAt(t.x, t.y); } @@ -4600,8 +4778,8 @@ public class Room implements Comparable, ISerialize, Runnable { item.setZ(tile.z); item.setExtradata("" + item.getZ() * 100); } - if (item.getZ() > 40d) { - item.setZ(40); + if (item.getZ() > MAXIMUM_FURNI_HEIGHT) { + item.setZ(MAXIMUM_FURNI_HEIGHT); } double offset = this.getStackHeight(tile.x, tile.y, false, item) - item.getZ(); this.sendComposer(new FloorItemOnRollerComposer(item, null, tile, offset, this).compose()); @@ -4615,26 +4793,35 @@ public class Room implements Comparable, ISerialize, Runnable { } public THashSet getRoomUnits() { + return getRoomUnits(null); + } + + public THashSet getRoomUnits(RoomTile atTile) { THashSet units = new THashSet<>(); for (Habbo habbo : this.currentHabbos.values()) { - if (habbo != null && habbo.getRoomUnit() != null && habbo.getRoomUnit().getRoom() != null && habbo.getRoomUnit().getRoom().getId() == this.getId()) { + if (habbo != null && habbo.getRoomUnit() != null && habbo.getRoomUnit().getRoom() != null && habbo.getRoomUnit().getRoom().getId() == this.getId() && (atTile == null || habbo.getRoomUnit().getCurrentLocation() == atTile)) { units.add(habbo.getRoomUnit()); } } for (Pet pet : this.currentPets.valueCollection()) { - if (pet != null && pet.getRoomUnit() != null && pet.getRoomUnit().getRoom() != null && pet.getRoomUnit().getRoom().getId() == this.getId()) { + if (pet != null && pet.getRoomUnit() != null && pet.getRoomUnit().getRoom() != null && pet.getRoomUnit().getRoom().getId() == this.getId() && (atTile == null || pet.getRoomUnit().getCurrentLocation() == atTile)) { units.add(pet.getRoomUnit()); } } for (Bot bot : this.currentBots.valueCollection()) { - if (bot != null && bot.getRoomUnit() != null && bot.getRoomUnit().getRoom() != null && bot.getRoomUnit().getRoom().getId() == this.getId()) { + if (bot != null && bot.getRoomUnit() != null && bot.getRoomUnit().getRoom() != null && bot.getRoomUnit().getRoom().getId() == this.getId() && (atTile == null || bot.getRoomUnit().getCurrentLocation() == atTile)) { units.add(bot.getRoomUnit()); } } return units; } -} \ No newline at end of file + + public Collection getRoomUnitsAt(RoomTile tile) { + THashSet roomUnits = getRoomUnits(); + return roomUnits.stream().filter(unit -> unit.getCurrentLocation() == tile).collect(Collectors.toSet()); + } +} diff --git a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomLayout.java b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomLayout.java index 80eec020..f70f3d3e 100644 --- a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomLayout.java +++ b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomLayout.java @@ -273,6 +273,8 @@ public class RoomLayout { List closedList = new LinkedList<>(); openList.add(oldTile.copy()); + RoomTile doorTile = this.room.getLayout().getDoorTile(); + while (!openList.isEmpty()) { RoomTile current = this.lowestFInOpen(openList); if (current.x == newTile.x && current.y == newTile.y) { @@ -286,7 +288,7 @@ public class RoomLayout { for (RoomTile currentAdj : adjacentNodes) { if (closedList.contains(currentAdj)) continue; - if (roomUnit.canOverrideTile(currentAdj) || (currentAdj.state != RoomTileState.BLOCKED && currentAdj.x == doorX && currentAdj.y == doorY)) { + if (roomUnit.canOverrideTile(currentAdj)) { currentAdj.setPrevious(current); currentAdj.sethCosts(this.findTile(openList, newTile.x, newTile.y)); currentAdj.setgCosts(current); @@ -301,9 +303,14 @@ public class RoomLayout { } double height = currentAdj.getStackHeight() - current.getStackHeight(); - if (!ALLOW_FALLING && height < -MAXIMUM_STEP_HEIGHT) continue; - if (currentAdj.state == RoomTileState.OPEN && height > MAXIMUM_STEP_HEIGHT) continue; - if (currentAdj.hasUnits() && ((!isWalktroughRetry && !this.room.isAllowWalkthrough()) || currentAdj.equals(goalLocation))) { + + if ((!ALLOW_FALLING && height < -MAXIMUM_STEP_HEIGHT) || (currentAdj.state == RoomTileState.OPEN && height > MAXIMUM_STEP_HEIGHT)) { + closedList.add(currentAdj); + openList.remove(currentAdj); + continue; + } + + if (currentAdj.hasUnits() && doorTile.distance(currentAdj) > 2 && (!isWalktroughRetry || !this.room.isAllowWalkthrough() || currentAdj.equals(goalLocation))) { closedList.add(currentAdj); openList.remove(currentAdj); continue; @@ -321,7 +328,7 @@ public class RoomLayout { } } - if (this.room.isAllowWalkthrough() && isWalktroughRetry) { + if (this.room.isAllowWalkthrough() && !isWalktroughRetry) { return this.findPath(oldTile, newTile, goalLocation, roomUnit, true); } 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 250dee09..05ddc66a 100644 --- a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomManager.java +++ b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomManager.java @@ -66,7 +66,7 @@ public class RoomManager { private static final int page = 0; //Configuration. Loaded from database & updated accordingly. public static int MAXIMUM_ROOMS_USER = 25; - public static int MAXIMUM_ROOMS_VIP = 35; + public static int MAXIMUM_ROOMS_HC = 35; public static int HOME_ROOM_ID = 0; public static boolean SHOW_PUBLIC_IN_POPULAR_TAB = false; private final THashMap roomCategories; @@ -377,7 +377,7 @@ public class RoomManager { public void unloadRoomsForHabbo(Habbo habbo) { List roomsToDispose = new ArrayList<>(); for (Room room : this.activeRooms.values()) { - if (!room.isPublicRoom() && !room.isStaffPromotedRoom() && room.getOwnerId() == habbo.getHabboInfo().getId() && room.getUserCount() == 0 && !this.roomCategories.get(room.getCategory()).isPublic()) { + if (!room.isPublicRoom() && !room.isStaffPromotedRoom() && room.getOwnerId() == habbo.getHabboInfo().getId() && room.getUserCount() == 0 && (this.roomCategories.get(room.getCategory()) == null || !this.roomCategories.get(room.getCategory()).isPublic())) { roomsToDispose.add(room); } } @@ -527,18 +527,18 @@ public class RoomManager { if (overrideChecks || room.isOwner(habbo) || room.getState() == RoomState.OPEN || - room.getState() == RoomState.INVISIBLE || habbo.hasPermission(Permission.ACC_ANYROOMOWNER) || habbo.hasPermission(Permission.ACC_ENTERANYROOM) || room.hasRights(habbo) || - (room.hasGuild() && room.guildRightLevel(habbo) > 2)) { + (room.getState().equals(RoomState.INVISIBLE) && room.hasRights(habbo)) || + (room.hasGuild() && room.getGuildRightLevel(habbo).isGreaterThan(RoomRightLevels.GUILD_RIGHTS))) { this.openRoom(habbo, room, doorLocation); } else if (room.getState() == RoomState.LOCKED) { boolean rightsFound = false; synchronized (room.roomUnitLock) { for (Habbo current : room.getHabbos()) { - if (room.hasRights(current) || current.getHabboInfo().getId() == room.getOwnerId() || (room.hasGuild() && room.guildRightLevel(current) >= 2)) { + if (room.hasRights(current) || current.getHabboInfo().getId() == room.getOwnerId() || (room.hasGuild() && room.getGuildRightLevel(current).isEqualOrGreaterThan(RoomRightLevels.GUILD_RIGHTS))) { current.getClient().sendResponse(new DoorbellAddUserComposer(habbo.getHabboInfo().getUsername())); rightsFound = true; } @@ -563,6 +563,9 @@ public class RoomManager { habbo.getClient().sendResponse(new HotelViewComposer()); habbo.getHabboInfo().setLoadingRoom(0); } + } else { + habbo.getClient().sendResponse(new HotelViewComposer()); + habbo.getHabboInfo().setLoadingRoom(0); } } @@ -669,7 +672,7 @@ public class RoomManager { habbo.getClient().sendResponse(new RoomPromotionMessageComposer(null, null)); } - if (room.getOwnerId() != habbo.getHabboInfo().getId()) { + if (room.getOwnerId() != habbo.getHabboInfo().getId() && !habbo.getHabboStats().visitedRoom(room.getId())) { AchievementManager.progressAchievement(habbo, Emulator.getGameEnvironment().getAchievementManager().getAchievement("RoomEntry")); } } @@ -872,7 +875,7 @@ public class RoomManager { habbo.getClient().sendResponse(new RoomUsersGuildBadgesComposer(guildBadges)); - if (room.hasRights(habbo) || (room.hasGuild() && room.guildRightLevel(habbo) >= 2)) { + if (room.hasRights(habbo) || (room.hasGuild() && room.getGuildRightLevel(habbo).isEqualOrGreaterThan(RoomRightLevels.GUILD_RIGHTS))) { if (!room.getHabboQueue().isEmpty()) { for (Habbo waiting : room.getHabboQueue().valueCollection()) { habbo.getClient().sendResponse(new DoorbellAddUserComposer(waiting.getHabboInfo().getUsername())); @@ -913,6 +916,9 @@ public class RoomManager { statement.setInt(2, habbo.getHabboInfo().getId()); statement.setInt(3, (int) (habbo.getHabboStats().roomEnterTimestamp)); statement.execute(); + + if (!habbo.getHabboStats().visitedRoom(room.getId())) + habbo.getHabboStats().addVisitRoom(room.getId()); } catch (SQLException e) { LOGGER.error("Caught SQL exception", e); } @@ -938,6 +944,8 @@ public class RoomManager { if (room.getOwnerId() != habbo.getHabboInfo().getId()) { AchievementManager.progressAchievement(room.getOwnerId(), Emulator.getGameEnvironment().getAchievementManager().getAchievement("RoomDecoHosting"), (int) Math.floor((Emulator.getIntUnixTimestamp() - habbo.getHabboStats().roomEnterTimestamp) / 60000)); } + + habbo.getMessenger().connectionChanged(habbo, habbo.isOnline(), false); } } @@ -1168,7 +1176,6 @@ public class RoomManager { continue; Habbo friend = Emulator.getGameEnvironment().getHabboManager().getHabbo(buddy.getId()); - if (friend == null || friend.getHabboInfo().getCurrentRoom() == null) continue; @@ -1305,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; } @@ -1550,4 +1557,4 @@ public class RoomManager { this.duration = duration; } } -} \ No newline at end of file +} diff --git a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomRightLevels.java b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomRightLevels.java index 9795ec9c..fef685a4 100644 --- a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomRightLevels.java +++ b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomRightLevels.java @@ -36,4 +36,20 @@ public enum RoomRightLevels { RoomRightLevels(int level) { this.level = level; } + + public boolean equals(RoomRightLevels level) { + return this.level == level.level; + } + + public boolean isEqualOrGreaterThan(RoomRightLevels level) { + return this.level >= level.level; + } + + public boolean isGreaterThan(RoomRightLevels level) { + return this.level > level.level; + } + + public boolean isLessThan(RoomRightLevels level) { + return this.level < level.level; + } } diff --git a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomSpecialTypes.java b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomSpecialTypes.java index 0b912776..8a1a1799 100644 --- a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomSpecialTypes.java +++ b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomSpecialTypes.java @@ -100,7 +100,7 @@ public class RoomSpecialTypes { public InteractionBattleBanzaiTeleporter getRandomTeleporter(Item baseItem, InteractionBattleBanzaiTeleporter exclude) { List teleporterList = new ArrayList<>(); for (InteractionBattleBanzaiTeleporter teleporter : this.banzaiTeleporters.values()) { - if (teleporter.getBaseItem() == baseItem) { + if (baseItem == null || teleporter.getBaseItem() == baseItem) { teleporterList.add(teleporter); } } diff --git a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomTrade.java b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomTrade.java index c6ba64e0..f0706c97 100644 --- a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomTrade.java +++ b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomTrade.java @@ -8,6 +8,8 @@ import com.eu.habbo.messages.outgoing.inventory.AddHabboItemComposer; import com.eu.habbo.messages.outgoing.inventory.InventoryRefreshComposer; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserStatusComposer; import com.eu.habbo.messages.outgoing.trading.*; +import com.eu.habbo.plugin.events.furniture.FurnitureRedeemedEvent; +import com.eu.habbo.plugin.events.trading.TradeConfirmEvent; import com.eu.habbo.threading.runnables.QueryDeleteHabboItem; import gnu.trove.set.hash.THashSet; import org.slf4j.Logger; @@ -145,6 +147,12 @@ public class RoomTrade { RoomTradeUser userOne = this.users.get(0); RoomTradeUser userTwo = this.users.get(1); + boolean tradeConfirmEventRegistered = Emulator.getPluginManager().isRegistered(TradeConfirmEvent.class, true); + TradeConfirmEvent tradeConfirmEvent = new TradeConfirmEvent(userOne, userTwo); + if (tradeConfirmEventRegistered) { + Emulator.getPluginManager().fireEvent(tradeConfirmEvent); + } + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection()) { int tradeId = 0; diff --git a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomUnit.java b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomUnit.java index 9521a75c..972030b8 100644 --- a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomUnit.java +++ b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomUnit.java @@ -3,16 +3,13 @@ package com.eu.habbo.habbohotel.rooms; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.bots.Bot; import com.eu.habbo.habbohotel.items.Item; -import com.eu.habbo.habbohotel.items.interactions.InteractionGuildGate; -import com.eu.habbo.habbohotel.items.interactions.InteractionHabboClubGate; -import com.eu.habbo.habbohotel.items.interactions.InteractionWater; -import com.eu.habbo.habbohotel.items.interactions.InteractionWaterItem; +import com.eu.habbo.habbohotel.items.interactions.*; +import com.eu.habbo.habbohotel.items.interactions.interfaces.ConditionalGate; import com.eu.habbo.habbohotel.pets.Pet; import com.eu.habbo.habbohotel.pets.RideablePet; import com.eu.habbo.habbohotel.users.DanceType; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboItem; -import com.eu.habbo.messages.outgoing.generic.alerts.CustomNotificationComposer; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserStatusComposer; import com.eu.habbo.plugin.Event; import com.eu.habbo.plugin.events.roomunit.RoomUnitLookAtPointEvent; @@ -37,6 +34,7 @@ public class RoomUnit { private static final Logger LOGGER = LoggerFactory.getLogger(RoomUnit.class); public boolean isWiredTeleporting = false; + public boolean isLeavingTeleporter = false; private final ConcurrentHashMap status; private final THashMap cacheable; public boolean canRotate = true; @@ -75,6 +73,7 @@ public class RoomUnit { private int effectId; private int effectEndTimestamp; private ScheduledFuture moveBlockingTask; + private int timeInRoom; private int idleTimer; private Room room; @@ -95,6 +94,7 @@ public class RoomUnit { this.effectId = 0; this.isKicked = false; this.overridableTiles = new THashSet<>(); + this.timeInRoom = 0; } public void clearWalking() { @@ -242,7 +242,8 @@ public class RoomUnit { //if(!(this.path.size() == 0 && canSitNextTile)) { - if (!room.tileWalkable(next)) { + double height = next.getStackHeight() - this.currentLocation.getStackHeight(); + if (!room.tileWalkable(next) || (!RoomLayout.ALLOW_FALLING && height < -RoomLayout.MAXIMUM_STEP_HEIGHT) || (next.state == RoomTileState.OPEN && height > RoomLayout.MAXIMUM_STEP_HEIGHT)) { this.room = room; this.path.clear(); this.findPath(); @@ -259,10 +260,10 @@ public class RoomUnit { boolean canSitNextTile = room.canSitAt(next.x, next.y); if (canSitNextTile) { - HabboItem lowestChair = room.getLowestChair(next); + HabboItem tallestChair = room.getTallestChair(next); - if (lowestChair != null) - item = lowestChair; + if (tallestChair != null) + item = tallestChair; } if (next.equals(this.goalLocation) && next.state == RoomTileState.SIT && !overrideChecks) { @@ -299,17 +300,16 @@ public class RoomUnit { if (item != habboItem || !RoomLayout.pointInSquare(item.getX(), item.getY(), item.getX() + item.getBaseItem().getWidth() - 1, item.getY() + item.getBaseItem().getLength() - 1, this.getX(), this.getY())) { if (item.canWalkOn(this, room, null)) { item.onWalkOn(this, room, new Object[]{this.getCurrentLocation(), next}); - } else if (item instanceof InteractionGuildGate || item instanceof InteractionHabboClubGate) { + } else if (item instanceof ConditionalGate) { this.setRotation(oldRotation); this.tilesWalked--; this.setGoalLocation(this.currentLocation); this.status.remove(RoomUnitStatus.MOVE); room.sendComposer(new RoomUserStatusComposer(this).compose()); - if (item instanceof InteractionHabboClubGate && habbo != null) { - habbo.getClient().sendResponse(new CustomNotificationComposer(CustomNotificationComposer.GATE_NO_HC)); + if (habbo != null) { + ((ConditionalGate) item).onRejected(this, this.getRoom(), new Object[]{}); } - return false; } } else { @@ -511,14 +511,14 @@ public class RoomUnit { this.startLocation = this.currentLocation; if (goalLocation != null && !noReset) { + boolean isWalking = this.hasStatus(RoomUnitStatus.MOVE); this.goalLocation = goalLocation; this.findPath(); ///< Quadral: this is where we start formulating a path if (!this.path.isEmpty()) { - this.tilesWalked = 0; + this.tilesWalked = isWalking ? this.tilesWalked : 0; this.cmdSit = false; } else { this.goalLocation = this.currentLocation; - } } } @@ -641,6 +641,18 @@ public class RoomUnit { this.walkTimeOut = walkTimeOut; } + public void increaseTimeInRoom() { + this.timeInRoom++; + } + + public int getTimeInRoom() { + return this.timeInRoom; + } + + public void resetTimeInRoom() { + this.timeInRoom = 0; + } + public void increaseIdleTimer() { this.idleTimer++; } @@ -725,13 +737,12 @@ public class RoomUnit { if (room.getItemsAt(tile).stream().anyMatch(i -> i.canOverrideTile(this, room, tile))) return true; - int tileIndex = (room.getLayout().getMapSizeY() * tile.y) + tile.x + 1; + int tileIndex = (tile.x & 0xFF) | (tile.y << 12); return this.overridableTiles.contains(tileIndex); } public void addOverrideTile(RoomTile tile) { - if (!this.canOverrideTile(tile)) { return; } // Test if the Tile is overridable - int tileIndex = (room.getLayout().getMapSizeY() * tile.y) + tile.x + 1; + int tileIndex = (tile.x & 0xFF) | (tile.y << 12); if (!this.overridableTiles.contains(tileIndex)) { this.overridableTiles.add(tileIndex); } @@ -740,7 +751,7 @@ public class RoomUnit { public void removeOverrideTile(RoomTile tile) { if (room == null || room.getLayout() == null) return; - int tileIndex = (room.getLayout().getMapSizeY() * tile.y) + tile.x + 1; + int tileIndex = (tile.x & 0xFF) | (tile.y << 12); this.overridableTiles.remove(tileIndex); } diff --git a/src/main/java/com/eu/habbo/habbohotel/users/Habbo.java b/src/main/java/com/eu/habbo/habbohotel/users/Habbo.java index af87ae9d..dcc5a05e 100644 --- a/src/main/java/com/eu/habbo/habbohotel/users/Habbo.java +++ b/src/main/java/com/eu/habbo/habbohotel/users/Habbo.java @@ -14,8 +14,10 @@ import com.eu.habbo.messages.outgoing.rooms.FloodCounterComposer; import com.eu.habbo.messages.outgoing.rooms.ForwardToRoomComposer; import com.eu.habbo.messages.outgoing.rooms.users.*; import com.eu.habbo.messages.outgoing.users.*; +import com.eu.habbo.plugin.events.furniture.FurnitureBuildheightEvent; import com.eu.habbo.plugin.events.users.UserCreditsEvent; import com.eu.habbo.plugin.events.users.UserDisconnectEvent; +import com.eu.habbo.plugin.events.users.UserGetIPAddressEvent; import com.eu.habbo.plugin.events.users.UserPointsEvent; import gnu.trove.TIntCollection; import gnu.trove.map.hash.THashMap; @@ -114,11 +116,31 @@ public class Habbo implements Runnable { } - public void connect() { + public boolean connect() { + String ip = ""; + if (!Emulator.getConfig().getBoolean("networking.tcp.proxy") && this.client.getChannel().remoteAddress() != null) { SocketAddress address = this.client.getChannel().remoteAddress(); + ip = ((InetSocketAddress) address).getAddress().getHostAddress(); + } - if (address != null) this.habboInfo.setIpLogin(((InetSocketAddress) address).getAddress().getHostAddress()); + if (Emulator.getPluginManager().isRegistered(UserGetIPAddressEvent.class, true)) { + UserGetIPAddressEvent event = Emulator.getPluginManager().fireEvent(new UserGetIPAddressEvent(this, ip)); + if (event.hasChangedIP()) { + ip = event.getUpdatedIp(); + } + } + + if (!ip.isEmpty()) { + this.habboInfo.setIpLogin(ip); + } + + if (Emulator.getGameEnvironment().getModToolManager().hasMACBan(this.client)) { + return false; + } + + if (Emulator.getGameEnvironment().getModToolManager().hasIPBan(this.habboInfo.getIpLogin())) { + return false; } this.habboInfo.setMachineID(this.client.getMachineId()); @@ -128,6 +150,7 @@ public class Habbo implements Runnable { Emulator.getGameEnvironment().getRoomManager().loadRoomsForHabbo(this); LOGGER.info("{} logged in from IP {}", this.habboInfo.getUsername(), this.habboInfo.getIpLogin()); + return true; } @@ -240,7 +263,8 @@ public class Habbo implements Runnable { return; this.getHabboInfo().addCurrencyAmount(event.type, event.points); - if (this.client != null) this.client.sendResponse(new UserPointsComposer(this.client.getHabbo().getHabboInfo().getCurrencyAmount(type), event.points, event.type)); + if (this.client != null) + this.client.sendResponse(new UserPointsComposer(this.client.getHabbo().getHabboInfo().getCurrencyAmount(type), event.points, event.type)); } @@ -436,9 +460,7 @@ public class Habbo implements Runnable { public void respect(Habbo target) { - if (target != null && target != this.client.getHabbo()) - - { + if (target != null && target != this.client.getHabbo()) { target.getHabboStats().respectPointsReceived++; this.client.getHabbo().getHabboStats().respectPointsGiven++; this.client.getHabbo().getHabboStats().respectPointsToGive--; @@ -449,6 +471,7 @@ public class Habbo implements Runnable { AchievementManager.progressAchievement(target, Emulator.getGameEnvironment().getAchievementManager().getAchievement("RespectEarned")); this.client.getHabbo().getHabboInfo().getCurrentRoom().unIdle(this.client.getHabbo()); + this.client.getHabbo().getHabboInfo().getCurrentRoom().dance(this.client.getHabbo().getRoomUnit(), DanceType.NONE); } } diff --git a/src/main/java/com/eu/habbo/habbohotel/users/HabboItem.java b/src/main/java/com/eu/habbo/habbohotel/users/HabboItem.java index 93639f45..31f98ca8 100644 --- a/src/main/java/com/eu/habbo/habbohotel/users/HabboItem.java +++ b/src/main/java/com/eu/habbo/habbohotel/users/HabboItem.java @@ -243,6 +243,8 @@ public abstract class HabboItem implements Runnable, IEventTriggers { return this.limitedSells; } + public int getMaximumRotations() { return this.baseItem.getRotations(); } + @Override public void run() { try (Connection connection = Emulator.getDatabase().getDataSource().getConnection()) { @@ -301,12 +303,12 @@ public abstract class HabboItem implements Runnable, IEventTriggers { @Override public void onWalkOn(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - if (objects != null && objects.length >= 1 && objects[0] instanceof InteractionWired) - return; + /*if (objects != null && objects.length >= 1 && objects[0] instanceof InteractionWired) + return;*/ WiredHandler.handle(WiredTriggerType.WALKS_ON_FURNI, roomUnit, room, new Object[]{this}); - if ((this.getBaseItem().allowSit() || this.getBaseItem().allowLay()) && roomUnit.getDanceType() != DanceType.NONE) { + if ((this.getBaseItem().allowSit() || this.getBaseItem().allowLay()) && !roomUnit.getDanceType().equals(DanceType.NONE)) { roomUnit.setDanceType(DanceType.NONE); room.sendComposer(new RoomUserDanceComposer(roomUnit).compose()); } @@ -328,7 +330,9 @@ public abstract class HabboItem implements Runnable, IEventTriggers { @Override public void onWalkOff(RoomUnit roomUnit, Room room, Object[] objects) throws Exception { - WiredHandler.handle(WiredTriggerType.WALKS_OFF_FURNI, roomUnit, room, new Object[]{this}); + if(objects != null && objects.length > 0) { + WiredHandler.handle(WiredTriggerType.WALKS_OFF_FURNI, roomUnit, room, new Object[]{this}); + } } public abstract void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception; @@ -376,23 +380,32 @@ public abstract class HabboItem implements Runnable, IEventTriggers { public void onPickUp(Room room) { if (this.getBaseItem().getEffectF() > 0 || this.getBaseItem().getEffectM() > 0) { + HabboItem topItem2 = room.getTopItemAt(this.getX(), this.getY(), this); + int nextEffectM = 0; + int nextEffectF = 0; + + if(topItem2 != null) { + nextEffectM = topItem2.getBaseItem().getEffectM(); + nextEffectF = topItem2.getBaseItem().getEffectF(); + } + for (Habbo habbo : room.getHabbosOnItem(this)) { if (this.getBaseItem().getEffectM() > 0 && habbo.getHabboInfo().getGender().equals(HabboGender.M) && habbo.getRoomUnit().getEffectId() == this.getBaseItem().getEffectM()) { - room.giveEffect(habbo, 0, -1); + room.giveEffect(habbo, nextEffectM, -1); } if (this.getBaseItem().getEffectF() > 0 && habbo.getHabboInfo().getGender().equals(HabboGender.F) && habbo.getRoomUnit().getEffectId() == this.getBaseItem().getEffectF()) { - room.giveEffect(habbo, 0, -1); + room.giveEffect(habbo, nextEffectF, -1); } } for (Bot bot : room.getBotsAt(room.getLayout().getTile(this.getX(), this.getY()))) { if (this.getBaseItem().getEffectM() > 0 && bot.getGender().equals(HabboGender.M) && bot.getRoomUnit().getEffectId() == this.getBaseItem().getEffectM()) { - room.giveEffect(bot.getRoomUnit(), 0, -1); + room.giveEffect(bot.getRoomUnit(), nextEffectM, -1); } if (this.getBaseItem().getEffectF() > 0 && bot.getGender().equals(HabboGender.F) && bot.getRoomUnit().getEffectId() == this.getBaseItem().getEffectF()) { - room.giveEffect(bot.getRoomUnit(), 0, -1); + room.giveEffect(bot.getRoomUnit(), nextEffectF, -1); } } } @@ -400,6 +413,15 @@ public abstract class HabboItem implements Runnable, IEventTriggers { public void onMove(Room room, RoomTile oldLocation, RoomTile newLocation) { if (this.getBaseItem().getEffectF() > 0 || this.getBaseItem().getEffectM() > 0) { + HabboItem topItem2 = room.getTopItemAt(oldLocation.x, oldLocation.y, this); + int nextEffectM = 0; + int nextEffectF = 0; + + if(topItem2 != null) { + nextEffectM = topItem2.getBaseItem().getEffectM(); + nextEffectF = topItem2.getBaseItem().getEffectF(); + } + List oldHabbos = new ArrayList<>(); List newHabbos = new ArrayList<>(); List oldBots = new ArrayList<>(); @@ -420,11 +442,11 @@ public abstract class HabboItem implements Runnable, IEventTriggers { for (Habbo habbo : oldHabbos) { if (this.getBaseItem().getEffectM() > 0 && habbo.getHabboInfo().getGender().equals(HabboGender.M) && habbo.getRoomUnit().getEffectId() == this.getBaseItem().getEffectM()) { - room.giveEffect(habbo, 0, -1); + room.giveEffect(habbo, nextEffectM, -1); } if (this.getBaseItem().getEffectF() > 0 && habbo.getHabboInfo().getGender().equals(HabboGender.F) && habbo.getRoomUnit().getEffectId() == this.getBaseItem().getEffectF()) { - room.giveEffect(habbo, 0, -1); + room.giveEffect(habbo, nextEffectF, -1); } } @@ -440,11 +462,11 @@ public abstract class HabboItem implements Runnable, IEventTriggers { for (Bot bot : oldBots) { if (this.getBaseItem().getEffectM() > 0 && bot.getGender().equals(HabboGender.M) && bot.getRoomUnit().getEffectId() == this.getBaseItem().getEffectM()) { - room.giveEffect(bot.getRoomUnit(), 0, -1); + room.giveEffect(bot.getRoomUnit(), nextEffectM, -1); } if (this.getBaseItem().getEffectF() > 0 && bot.getGender().equals(HabboGender.F) && bot.getRoomUnit().getEffectId() == this.getBaseItem().getEffectF()) { - room.giveEffect(bot.getRoomUnit(), 0, -1); + room.giveEffect(bot.getRoomUnit(), nextEffectF, -1); } } diff --git a/src/main/java/com/eu/habbo/habbohotel/users/HabboManager.java b/src/main/java/com/eu/habbo/habbohotel/users/HabboManager.java index 8975b888..e8bf5f3a 100644 --- a/src/main/java/com/eu/habbo/habbohotel/users/HabboManager.java +++ b/src/main/java/com/eu/habbo/habbohotel/users/HabboManager.java @@ -205,7 +205,7 @@ public class HabboManager { try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT * FROM users WHERE ip_register = ? OR ip_current = ? AND id != ? ORDER BY id DESC LIMIT ?")) { statement.setString(1, habbo.getHabboInfo().getIpRegister()); - statement.setString(2, habbo.getClient().getChannel().remoteAddress().toString()); + statement.setString(2, habbo.getHabboInfo().getIpLogin()); statement.setInt(3, habbo.getHabboInfo().getId()); statement.setInt(4, limit); 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 d7b03956..4463148f 100644 --- a/src/main/java/com/eu/habbo/habbohotel/users/HabboStats.java +++ b/src/main/java/com/eu/habbo/habbohotel/users/HabboStats.java @@ -9,22 +9,21 @@ import com.eu.habbo.habbohotel.catalog.CatalogItem; 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.plugin.events.users.subscriptions.UserSubscriptionCreatedEvent; +import com.eu.habbo.plugin.events.users.subscriptions.UserSubscriptionExtendedEvent; import gnu.trove.list.array.TIntArrayList; import gnu.trove.map.TIntObjectMap; import gnu.trove.map.hash.THashMap; import gnu.trove.map.hash.TIntObjectHashMap; +import gnu.trove.set.hash.THashSet; import gnu.trove.stack.array.TIntArrayStack; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.lang.reflect.Constructor; +import java.sql.*; +import java.util.*; import java.util.concurrent.atomic.AtomicInteger; public class HabboStats implements Runnable { @@ -42,6 +41,7 @@ public class HabboStats implements Runnable { private final THashMap recentPurchases; private final TIntArrayList favoriteRooms; private final TIntArrayList ignoredUsers; + private TIntArrayList roomsVists; public int achievementScore; public int respectPointsReceived; public int respectPointsGiven; @@ -93,6 +93,12 @@ public class HabboStats implements Runnable { private boolean allowTrade; private int clubExpireTimestamp; private int muteEndTime; + public int maxFriends; + public int maxRooms; + public int lastHCPayday; + public int hcGiftsClaimed; + public int hcMessageLastModified = Emulator.getIntUnixTimestamp(); + public THashSet subscriptions; private HabboStats(ResultSet set, HabboInfo habboInfo) throws SQLException { this.cache = new THashMap<>(0); @@ -101,6 +107,7 @@ public class HabboStats implements Runnable { this.recentPurchases = new THashMap<>(0); this.favoriteRooms = new TIntArrayList(0); this.ignoredUsers = new TIntArrayList(0); + this.roomsVists = new TIntArrayList(0); this.secretRecipes = new TIntArrayList(0); this.calendarRewardsClaimed = new TIntArrayList(0); @@ -142,9 +149,15 @@ public class HabboStats implements Runnable { this.forumPostsCount = set.getInt("forums_post_count"); this.uiFlags = set.getInt("ui_flags"); this.hasGottenDefaultSavedSearches = set.getInt("has_gotten_default_saved_searches") == 1; + 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; + this.subscriptions = Emulator.getGameEnvironment().getSubscriptionManager().getSubscriptionsForUser(this.habboInfo.getId()); + try (PreparedStatement statement = set.getStatement().getConnection().prepareStatement("SELECT * FROM user_window_settings WHERE user_id = ? LIMIT 1")) { statement.setInt(1, this.habboInfo.getId()); try (ResultSet nSet = statement.executeQuery()) { @@ -225,6 +238,15 @@ public class HabboStats implements Runnable { } } } + + try (PreparedStatement loadRoomsVisit = set.getStatement().getConnection().prepareStatement("SELECT DISTINCT room_id FROM room_enter_log WHERE user_id = ?")) { + loadRoomsVisit.setInt(1, this.habboInfo.getId()); + try (ResultSet roomSet = loadRoomsVisit.executeQuery()) { + while (roomSet.next()) { + this.roomsVists.add(roomSet.getInt("room_id")); + } + } + } } private static HabboStats createNewStats(HabboInfo habboInfo) { @@ -306,7 +328,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 = ? 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); @@ -341,7 +363,11 @@ public class HabboStats implements Runnable { statement.setInt(32, this.forumPostsCount); statement.setInt(33, this.uiFlags); statement.setInt(34, this.hasGottenDefaultSavedSearches ? 1 : 0); - statement.setInt(35, this.habboInfo.getId()); + statement.setInt(35, this.maxFriends); + statement.setInt(36, this.maxRooms); + statement.setInt(37, this.lastHCPayday); + statement.setInt(38, this.hcGiftsClaimed); + statement.setInt(39, this.habboInfo.getId()); statement.executeUpdate(); } @@ -441,16 +467,113 @@ public class HabboStats implements Runnable { return this.rentedTimeEnd >= Emulator.getIntUnixTimestamp(); } + public Subscription getSubscription(String subscriptionType) { + for(Subscription subscription : subscriptions) { + if(subscription.getSubscriptionType().equalsIgnoreCase(subscriptionType) && subscription.isActive() && subscription.getRemaining() > 0) { + return subscription; + } + } + return null; + } + + public boolean hasSubscription(String subscriptionType) { + Subscription subscription = getSubscription(subscriptionType); + return subscription != null; + } + + public int getSubscriptionExpireTimestamp(String subscriptionType) { + Subscription subscription = getSubscription(subscriptionType); + + if(subscription == null) + return 0; + + return subscription.getTimestampEnd(); + } + + public Subscription createSubscription(String subscriptionType, int duration) { + Subscription subscription = getSubscription(subscriptionType); + + if(subscription != null) { + if (!Emulator.getPluginManager().fireEvent(new UserSubscriptionExtendedEvent(this.habboInfo.getId(), subscription, duration)).isCancelled()) { + subscription.addDuration(duration); + subscription.onExtended(duration); + } + return subscription; + } + + if (!Emulator.getPluginManager().fireEvent(new UserSubscriptionCreatedEvent(this.habboInfo.getId(), subscriptionType, duration)).isCancelled()) { + int startTimestamp = Emulator.getIntUnixTimestamp(); + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("INSERT INTO `users_subscriptions` (`user_id`, `subscription_type`, `timestamp_start`, `duration`, `active`) VALUES (?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS)) { + statement.setInt(1, this.habboInfo.getId()); + statement.setString(2, subscriptionType); + statement.setInt(3, startTimestamp); + statement.setInt(4, duration); + statement.setInt(5, 1); + statement.execute(); + try (ResultSet set = statement.getGeneratedKeys()) { + if (set.next()) { + Class subClazz = Emulator.getGameEnvironment().getSubscriptionManager().getSubscriptionClass(subscriptionType); + try { + Constructor c = subClazz.getConstructor(Integer.class, Integer.class, String.class, Integer.class, Integer.class, Boolean.class); + c.setAccessible(true); + Subscription sub = c.newInstance(set.getInt(1), this.habboInfo.getId(), subscriptionType, startTimestamp, duration, true); + this.subscriptions.add(sub); + sub.onCreated(); + return sub; + } + catch (Exception e) { + LOGGER.error("Caught exception", e); + } + } + } + } catch (SQLException e) { + LOGGER.error("Caught SQL exception", e); + } + } + + return null; + } + public int getClubExpireTimestamp() { - return this.clubExpireTimestamp; + return getSubscriptionExpireTimestamp(Subscription.HABBO_CLUB); } public void setClubExpireTimestamp(int clubExpireTimestamp) { - this.clubExpireTimestamp = clubExpireTimestamp; + Subscription subscription = getSubscription(Subscription.HABBO_CLUB); + int duration = clubExpireTimestamp - Emulator.getIntUnixTimestamp(); + + if(subscription != null) { + duration = clubExpireTimestamp - subscription.getTimestampStart(); + } + + if(duration > 0) { + createSubscription(Subscription.HABBO_CLUB, duration); + } } public boolean hasActiveClub() { - return this.clubExpireTimestamp > Emulator.getIntUnixTimestamp(); + 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() { @@ -510,6 +633,10 @@ public class HabboStats implements Runnable { return this.favoriteRooms.contains(roomId); } + public boolean visitedRoom(int roomId) { return this.roomsVists.contains(roomId); } + + public void addVisitRoom(int roomId) { this.roomsVists.add(roomId); } + public TIntArrayList getFavoriteRooms() { return this.favoriteRooms; } diff --git a/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/ClothingValidationManager.java b/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/ClothingValidationManager.java new file mode 100644 index 00000000..4e470658 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/ClothingValidationManager.java @@ -0,0 +1,214 @@ +package com.eu.habbo.habbohotel.users.clothingvalidation; + +import com.eu.habbo.habbohotel.users.Habbo; +import gnu.trove.TIntCollection; +import gnu.trove.map.hash.THashMap; +import gnu.trove.set.hash.TIntHashSet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.regex.Pattern; + +public class ClothingValidationManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(ClothingValidationManager.class); + + public static String FIGUREDATA_URL = ""; + public static boolean VALIDATE_ON_HC_EXPIRE = false; + public static boolean VALIDATE_ON_LOGIN = false; + public static boolean VALIDATE_ON_CHANGE_LOOKS = false; + public static boolean VALIDATE_ON_MIMIC = false; + public static boolean VALIDATE_ON_MANNEQUIN = false; + public static boolean VALIDATE_ON_FBALLGATE = false; + + private static final Figuredata FIGUREDATA = new Figuredata(); + + /** + * Parses the new figuredata.xml file + * @param newUrl URI of figuredata.xml file. Can be a file path or URL + */ + public static void reloadFiguredata(String newUrl) { + try { + FIGUREDATA.parseXML(newUrl); + } catch (Exception e) { + VALIDATE_ON_HC_EXPIRE = false; + VALIDATE_ON_LOGIN = false; + VALIDATE_ON_CHANGE_LOOKS = false; + VALIDATE_ON_MIMIC = false; + VALIDATE_ON_MANNEQUIN = false; + VALIDATE_ON_FBALLGATE = false; + LOGGER.error("Caught exception", e); + } + } + + /** + * Validates a figure string on a given user + * @param habbo User to validate + * @return Cleaned figure string + */ + public static String validateLook(Habbo habbo) { + return validateLook(habbo.getHabboInfo().getLook(), habbo.getHabboInfo().getGender().name(), habbo.getHabboStats().hasActiveClub(), habbo.getInventory().getWardrobeComponent().getClothingSets()); + } + + /** + * Validates a given figure string and gender on a given user + * @param habbo User to validate + * @param look Figure string + * @param gender Gender (M/F) + * @return Cleaned figure string + */ + public static String validateLook(Habbo habbo, String look, String gender) { + return validateLook(look, gender, habbo.getHabboStats().hasActiveClub(), habbo.getInventory().getWardrobeComponent().getClothingSets()); + } + + /** + * Validates a given figure string against a given gender + * @param look Figure string + * @param gender Gender (M/F) + * @return Cleaned figure string + */ + public static String validateLook(String look, String gender) { + return validateLook(look, gender, false, new TIntHashSet()); + } + + /** + * Validates a given figure string against a given gender with club clothing option + * @param look Figure string + * @param gender Gender (M/F) + * @param isHC Boolean indicating if club clothing is permitted + * @return Cleaned figure string + */ + public static String validateLook(String look, String gender, boolean isHC) { + return validateLook(look, gender, isHC, new TIntHashSet()); + } + + /** + * Validates a figure string with all available options + * @param look Figure string + * @param gender Gender (M/F) + * @param isHC Boolean indicating if club clothing is permitted + * @param ownedClothing Array of owned clothing set IDs. If sellable and setId not in this array clothing will be removed + * @return Cleaned figure string + */ + public static String validateLook(String look, String gender, boolean isHC, TIntCollection ownedClothing) { + if(FIGUREDATA.palettes.size() == 0 || FIGUREDATA.settypes.size() == 0) + return look; + + String[] newLookParts = look.split(Pattern.quote(".")); + ArrayList lookParts = new ArrayList<>(); + + THashMap parts = new THashMap<>(); + + // add mandatory settypes + for(String lookpart : newLookParts) { + if (lookpart.contains("-")) { + String[] data = lookpart.split(Pattern.quote("-")); + FiguredataSettype settype = FIGUREDATA.settypes.get(data[0]); + if(settype != null) { + parts.put(data[0], data); + } + } + } + + FIGUREDATA.settypes.entrySet().stream().filter(x -> !parts.containsKey(x.getKey())).forEach(x -> + { + FiguredataSettype settype = x.getValue(); + + if(gender.equalsIgnoreCase("M") && !isHC && !settype.mandatoryMale0) + return; + + if(gender.equalsIgnoreCase("F") && !isHC && !settype.mandatoryFemale0) + return; + + if(gender.equalsIgnoreCase("M") && isHC && !settype.mandatoryMale1) + return; + + if(gender.equalsIgnoreCase("F") && isHC && !settype.mandatoryFemale1) + return; + + parts.put(x.getKey(), new String[] { x.getKey() }); + }); + + + parts.forEach((key, data) -> { + try { + if (data.length >= 1) { + FiguredataSettype settype = FIGUREDATA.settypes.get(data[0]); + if (settype == null) { + //throw new Exception("Set type " + data[0] + " does not exist"); + return; + } + + FiguredataPalette palette = FIGUREDATA.palettes.get(settype.paletteId); + if (palette == null) { + throw new Exception("Palette " + settype.paletteId + " does not exist"); + } + + int setId; + FiguredataSettypeSet set; + + setId = Integer.parseInt(data.length >= 2 ? data[1] : "-1"); + set = settype.getSet(setId); + + if (set == null || (set.club && !isHC) || !set.selectable || (set.sellable && !ownedClothing.contains(set.id)) || (!set.gender.equalsIgnoreCase("U") && !set.gender.equalsIgnoreCase(gender))) { + if (gender.equalsIgnoreCase("M") && !isHC && !settype.mandatoryMale0) + return; + + if (gender.equalsIgnoreCase("F") && !isHC && !settype.mandatoryFemale0) + return; + + if (gender.equalsIgnoreCase("M") && isHC && !settype.mandatoryMale1) + return; + + if (gender.equalsIgnoreCase("F") && isHC && !settype.mandatoryFemale1) + return; + + set = settype.getFirstNonHCSetForGender(gender); + setId = set.id; + } + + ArrayList dataParts = new ArrayList<>(); + + int color1 = -1; + int color2 = -1; + + if (set.colorable) { + color1 = data.length >= 3 ? Integer.parseInt(data[2]) : -1; + FiguredataPaletteColor color = palette.getColor(color1); + if (color == null || (color.club && !isHC)) { + color1 = palette.getFirstNonHCColor().id; + } + } + + if (data.length >= 4 && set.colorable) { + color2 = Integer.parseInt(data[3]); + FiguredataPaletteColor color = palette.getColor(color2); + if (color == null || (color.club && !isHC)) { + color2 = palette.getFirstNonHCColor().id; + } + } + + dataParts.add(settype.type); + dataParts.add("" + setId); + + if (color1 > -1) { + dataParts.add("" + color1); + } + + if (color2 > -1) { + dataParts.add("" + color2); + } + + lookParts.add(String.join("-", dataParts)); + } + } catch (Exception e) { + //habbo.alert(e.getMessage()); + LOGGER.error("Error in clothing validation", e); + } + }); + + return String.join(".", lookParts); + } + +} diff --git a/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/Figuredata.java b/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/Figuredata.java new file mode 100644 index 00000000..0f4aec7c --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/Figuredata.java @@ -0,0 +1,122 @@ +package com.eu.habbo.habbohotel.users.clothingvalidation; + +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.IOException; +import java.io.StringWriter; +import java.util.Map; +import java.util.TreeMap; + +public class Figuredata { + public Map palettes; + public Map settypes; + + public Figuredata() { + palettes = new TreeMap<>(); + settypes = new TreeMap<>(); + } + + /** + * Parses the figuredata.xml file + * @param uri URI to the figuredata.xml file + * @throws ParserConfigurationException + * @throws IOException + * @throws SAXException + */ + public void parseXML(String uri) throws Exception, ParserConfigurationException, IOException, SAXException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setValidating(false); + factory.setIgnoringElementContentWhitespace(true); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document document = builder.parse(uri); + + Element rootElement = document.getDocumentElement(); + + if(!rootElement.getTagName().equalsIgnoreCase("figuredata") || document.getElementsByTagName("colors") == null || document.getElementsByTagName("sets") == null) { + StringWriter writer = new StringWriter(); + TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document), new StreamResult(writer)); + String documentString = writer.getBuffer().toString(); + throw new Exception("The passed file is not in figuredata format. Received " + documentString.substring(0, Math.min(documentString.length(), 200))); + } + + NodeList palettesList = document.getElementsByTagName("colors").item(0).getChildNodes(); + NodeList settypesList = document.getElementsByTagName("sets").item(0).getChildNodes(); + + palettes.clear(); + settypes.clear(); + + for(int i = 0; i < palettesList.getLength(); i++) { + Node nNode = palettesList.item(i); + if(nNode.getNodeType() == Node.ELEMENT_NODE) { + Element element = (Element) nNode; + int paletteId = Integer.parseInt(element.getAttribute("id")); + FiguredataPalette palette = new FiguredataPalette(paletteId); + + NodeList colorsList = nNode.getChildNodes(); + for (int ii = 0; ii < colorsList.getLength(); ii++) { + if(colorsList.item(ii).getNodeType() == Node.ELEMENT_NODE) { + Element colorElement = (Element) colorsList.item(ii); + FiguredataPaletteColor color = new FiguredataPaletteColor( + Integer.parseInt(colorElement.getAttribute("id")), + Integer.parseInt(colorElement.getAttribute("index")), + !colorElement.getAttribute("club").equals("0"), + colorElement.getAttribute("selectable").equals("1"), + colorElement.getTextContent() + ); + palette.addColor(color); + } + } + + palettes.put(palette.id, palette); + } + } + + for(int i = 0; i < settypesList.getLength(); i++) { + Node nNode = settypesList.item(i); + + if(nNode.getNodeType() == Node.ELEMENT_NODE) { + Element element = (Element) nNode; + + String type = element.getAttribute("type"); + int paletteId = Integer.parseInt(element.getAttribute("paletteid")); + boolean mandM0 = element.getAttribute("mand_m_0").equals("1"); + boolean mandF0 = element.getAttribute("mand_f_0").equals("1"); + boolean mandM1 = element.getAttribute("mand_m_1").equals("1"); + boolean mandF1 = element.getAttribute("mand_f_1").equals("1"); + + FiguredataSettype settype = new FiguredataSettype(type, paletteId, mandM0, mandF0, mandM1, mandF1); + + NodeList setsList = nNode.getChildNodes(); + for (int ii = 0; ii < setsList.getLength(); ii++) { + if(setsList.item(ii).getNodeType() == Node.ELEMENT_NODE) { + Element setElement = (Element) setsList.item(ii); + FiguredataSettypeSet set = new FiguredataSettypeSet( + Integer.parseInt(setElement.getAttribute("id")), + setElement.getAttribute("gender"), + !setElement.getAttribute("club").equals("0"), + setElement.getAttribute("colorable").equals("1"), + setElement.getAttribute("selectable").equals("1"), + setElement.getAttribute("preselectable").equals("1"), + setElement.getAttribute("sellable").equals("1") + ); + settype.addSet(set); + } + } + + settypes.put(settype.type, settype); + } + } + + } +} 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 new file mode 100644 index 00000000..4a1c48d5 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/FiguredataPalette.java @@ -0,0 +1,31 @@ +package com.eu.habbo.habbohotel.users.clothingvalidation; + +import java.util.TreeMap; + +public class FiguredataPalette { + public int id; + public TreeMap colors; + + public FiguredataPalette(int id) { + this.id = id; + this.colors = new TreeMap<>(); + } + + public void addColor(FiguredataPaletteColor color) { + this.colors.put(color.id, color); + } + + public FiguredataPaletteColor getColor(int colorId) { + return this.colors.get(colorId); + } + + public FiguredataPaletteColor getFirstNonHCColor() { + for(FiguredataPaletteColor color : this.colors.values()) { + if(!color.club && color.selectable) + return color; + } + + return this.colors.size() > 0 ? this.colors.entrySet().iterator().next().getValue() : null; + } + +} diff --git a/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/FiguredataPaletteColor.java b/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/FiguredataPaletteColor.java new file mode 100644 index 00000000..7ba0b9a7 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/FiguredataPaletteColor.java @@ -0,0 +1,17 @@ +package com.eu.habbo.habbohotel.users.clothingvalidation; + +public class FiguredataPaletteColor { + public int id; + public int index; + public boolean club; + public boolean selectable; + public String colorHex; + + public FiguredataPaletteColor(int id, int index, boolean club, boolean selectable, String colorHex) { + this.id = id; + this.index = index; + this.club = club; + this.selectable = selectable; + this.colorHex = colorHex; + } +} 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 new file mode 100644 index 00000000..e3698815 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/FiguredataSettype.java @@ -0,0 +1,60 @@ +package com.eu.habbo.habbohotel.users.clothingvalidation; + +import java.util.Map; +import java.util.TreeMap; + +public class FiguredataSettype { + public String type; + public int paletteId; + public boolean mandatoryMale0; + public boolean mandatoryFemale0; + public boolean mandatoryMale1; + public boolean mandatoryFemale1; + public TreeMap sets; + + public FiguredataSettype(String type, int paletteId, boolean mandatoryMale0, boolean mandatoryFemale0, boolean mandatoryMale1, boolean mandatoryFemale1) { + this.type = type; + this.paletteId = paletteId; + this.mandatoryMale0 = mandatoryMale0; + this.mandatoryFemale0 = mandatoryFemale0; + this.mandatoryMale1 = mandatoryMale1; + this.mandatoryFemale1 = mandatoryFemale1; + this.sets = new TreeMap<>(); + } + + public void addSet(FiguredataSettypeSet set) { + this.sets.put(set.id, set); + } + + public FiguredataSettypeSet getSet(int id) { + return this.sets.get(id); + } + + /** + * @param gender Gender (M/F) + * @return First non-sellable and selectable set for given gender + */ + public FiguredataSettypeSet getFirstSetForGender(String gender) { + 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.descendingMap().entrySet().iterator().next().getValue() : null; + } + + /** + * @param gender Gender (M/F) + * @return First non-club, non-sellable and selectable set for given gender + */ + public FiguredataSettypeSet getFirstNonHCSetForGender(String gender) { + for(FiguredataSettypeSet set : this.sets.descendingMap().values()) { + if((set.gender.equalsIgnoreCase(gender) || set.gender.equalsIgnoreCase("u")) && !set.club && !set.sellable && set.selectable) { + return set; + } + } + + return getFirstSetForGender(gender); + } +} diff --git a/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/FiguredataSettypeSet.java b/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/FiguredataSettypeSet.java new file mode 100644 index 00000000..a5a15f38 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/users/clothingvalidation/FiguredataSettypeSet.java @@ -0,0 +1,21 @@ +package com.eu.habbo.habbohotel.users.clothingvalidation; + +public class FiguredataSettypeSet { + public int id; + public String gender; + public boolean club; + public boolean colorable; + public boolean selectable; + public boolean preselectable; + public boolean sellable; + + public FiguredataSettypeSet(int id, String gender, boolean club, boolean colorable, boolean selectable, boolean preselectable, boolean sellable) { + this.id = id; + this.gender = gender; + this.club = club; + this.colorable = colorable; + this.selectable = selectable; + this.preselectable = preselectable; + this.sellable = sellable; + } +} diff --git a/src/main/java/com/eu/habbo/habbohotel/users/inventory/WardrobeComponent.java b/src/main/java/com/eu/habbo/habbohotel/users/inventory/WardrobeComponent.java index 2d207132..cd806c24 100644 --- a/src/main/java/com/eu/habbo/habbohotel/users/inventory/WardrobeComponent.java +++ b/src/main/java/com/eu/habbo/habbohotel/users/inventory/WardrobeComponent.java @@ -14,15 +14,18 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.regex.Pattern; public class WardrobeComponent { private static final Logger LOGGER = LoggerFactory.getLogger(WardrobeComponent.class); private final THashMap looks; private final TIntSet clothing; + private final TIntSet clothingSets; public WardrobeComponent(Habbo habbo) { this.looks = new THashMap<>(); this.clothing = new TIntHashSet(); + this.clothingSets = new TIntHashSet(); try (Connection connection = Emulator.getDatabase().getDataSource().getConnection()) { try (PreparedStatement statement = connection.prepareStatement("SELECT * FROM users_wardrobe WHERE user_id = ?")) { @@ -34,13 +37,19 @@ public class WardrobeComponent { } } - try (PreparedStatement statement = connection.prepareStatement("SELECT * FROM users_clothing WHERE user_id = ?")) { + try (PreparedStatement statement = connection.prepareStatement("SELECT users_clothing.*, catalog_clothing.setid FROM users_clothing LEFT JOIN catalog_clothing ON catalog_clothing.id = users_clothing.clothing_id WHERE users_clothing.user_id = ?")) { statement.setInt(1, habbo.getHabboInfo().getId()); try (ResultSet set = statement.executeQuery()) { while (set.next()) { int value = set.getInt("clothing_id"); - this.clothing.add(value); + + for(String x : set.getString("setid").split(Pattern.quote(","))) { + try { + this.clothingSets.add(Integer.parseInt(x)); + } + catch (Exception e) { } + } } } } @@ -61,6 +70,10 @@ public class WardrobeComponent { return this.clothing; } + public TIntCollection getClothingSets() { + return this.clothingSets; + } + public void dispose() { this.looks.values().stream().filter(item -> item.needsInsert || item.needsUpdate).forEach(item -> { Emulator.getThreading().run(item); diff --git a/src/main/java/com/eu/habbo/habbohotel/users/subscriptions/HcPayDayLogEntry.java b/src/main/java/com/eu/habbo/habbohotel/users/subscriptions/HcPayDayLogEntry.java new file mode 100644 index 00000000..e96d64b3 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/users/subscriptions/HcPayDayLogEntry.java @@ -0,0 +1,64 @@ +package com.eu.habbo.habbohotel.users.subscriptions; + +import com.eu.habbo.Emulator; +import com.eu.habbo.core.DatabaseLoggable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +/** + * @author Beny + */ +public class HcPayDayLogEntry implements Runnable, DatabaseLoggable { + + private static final Logger LOGGER = LoggerFactory.getLogger(HcPayDayLogEntry.class); + private static final String QUERY = "INSERT INTO `logs_hc_payday` (`timestamp`, `user_id`, `hc_streak`, `total_coins_spent`, `reward_coins_spent`, `reward_streak`, `total_payout`, `currency`, `claimed`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + public final int timestamp; + public final int userId; + public final int hcStreak; + public final int totalCoinsSpent; + public final int rewardCoinsSpent; + public final int rewardStreak; + public final int totalPayout; + public final String currency; + public final boolean claimed; + + public HcPayDayLogEntry(int timestamp, int userId, int hcStreak, int totalCoinsSpent, int rewardCoinsSpent, int rewardStreak, int totalPayout, String currency, boolean claimed) { + this.timestamp = timestamp; + this.userId = userId; + this.hcStreak = hcStreak; + this.totalCoinsSpent = totalCoinsSpent; + this.rewardCoinsSpent = rewardCoinsSpent; + this.rewardStreak = rewardStreak; + this.totalPayout = totalPayout; + this.currency = currency; + this.claimed = claimed; + } + + @Override + public String getQuery() { + return QUERY; + } + + @Override + public void log(PreparedStatement statement) throws SQLException { + statement.setInt(1, this.timestamp); + statement.setInt(2, this.userId); + statement.setInt(3, this.hcStreak); + statement.setInt(4, this.totalCoinsSpent); + statement.setInt(5, this.rewardCoinsSpent); + statement.setInt(6, this.rewardStreak); + statement.setInt(7, this.totalPayout); + statement.setString(8, this.currency); + statement.setInt(9, this.claimed ? 1 : 0); + statement.addBatch(); + } + + @Override + public void run() { + Emulator.getDatabaseLogger().store(this); + } +} diff --git a/src/main/java/com/eu/habbo/habbohotel/users/subscriptions/Subscription.java b/src/main/java/com/eu/habbo/habbohotel/users/subscriptions/Subscription.java new file mode 100644 index 00000000..08fba035 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/users/subscriptions/Subscription.java @@ -0,0 +1,147 @@ +package com.eu.habbo.habbohotel.users.subscriptions; + +import com.eu.habbo.Emulator; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +/** + * @author Beny + */ +public class Subscription { + public static final String HABBO_CLUB = "HABBO_CLUB"; + + private final int id; + private final int userId; + private final String subscriptionType; + private final int timestampStart; + private int duration; + private boolean active; + + /** + * Subscription constructor + * @param id ID of the subscription + * @param userId ID of user who has the subscription + * @param subscriptionType Subscription type name (e.g. HABBO_CLUB) + * @param timestampStart Unix timestamp start of subscription + * @param duration Length of subscription in seconds + * @param active Boolean indicating if subscription is active + */ + public Subscription(Integer id, Integer userId, String subscriptionType, Integer timestampStart, Integer duration, Boolean active) { + this.id = id; + this.userId = userId; + this.subscriptionType = subscriptionType; + this.timestampStart = timestampStart; + this.duration = duration; + this.active = active; + } + + /** + * @return ID of the subscription + */ + public int getSubscriptionId() { + return id; + } + + /** + * @return ID of user who has the subscription + */ + public int getUserId() { + return userId; + } + + /** + * @return Subscription type name (e.g. HABBO_CLUB) + */ + public String getSubscriptionType() { + return subscriptionType; + } + + /** + * @return Length of subscription in seconds + */ + public int getDuration() { + return duration; + } + + /** + * Updates the Subscription record with new duration + * @param amount Length of time to add in seconds + */ + public void addDuration(int amount) { + this.duration += amount; + + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection()) { + try (PreparedStatement statement = connection.prepareStatement("UPDATE `users_subscriptions` SET `duration` = ? WHERE `id` = ? LIMIT 1")) { + statement.setInt(1, this.duration); + statement.setInt(2, this.id); + statement.executeUpdate(); + } + } catch (SQLException e) { + SubscriptionManager.LOGGER.error("Caught SQL exception", e); + } + } + + /** + * Sets the subscription as active or inactive. If active and remaining time <= 0 the SubscriptionScheduler will inactivate the subscription and call onExpired() + * @param active Boolean indicating if the subscription is active + */ + public void setActive(boolean active) { + this.active = active; + + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection()) { + try (PreparedStatement statement = connection.prepareStatement("UPDATE `users_subscriptions` SET `active` = ? WHERE `id` = ? LIMIT 1")) { + statement.setInt(1, this.active ? 1 : 0); + statement.setInt(2, this.id); + statement.executeUpdate(); + } + } catch (SQLException e) { + SubscriptionManager.LOGGER.error("Caught SQL exception", e); + } + } + + /** + * @return Remaining duration of subscription in seconds + */ + public int getRemaining() { + return (this.timestampStart + this.duration) - Emulator.getIntUnixTimestamp(); + } + + /** + * @return Unix timestamp start of subscription + */ + public int getTimestampStart() { + return this.timestampStart; + } + + /** + * @return Unix timestamp end of subscription + */ + public int getTimestampEnd() { + return (this.timestampStart + this.duration); + } + + /** + * @return Boolean indicating if the subscription is active + */ + public boolean isActive() { + return active; + } + + /** + * Called when the subscription is first created + */ + public void onCreated() { } + + /** + * Called when the subscription is extended or bought again when already exists + * @param duration Extended duration time in seconds + */ + public void onExtended(int duration) { } + + /** + * Called by SubscriptionScheduler when isActive() && getRemaining() < 0 + */ + public void onExpired() { } +} 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 new file mode 100644 index 00000000..66c3d041 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/users/subscriptions/SubscriptionHabboClub.java @@ -0,0 +1,425 @@ +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; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; +import java.util.TreeMap; + +/** + * @author Beny + */ +public class SubscriptionHabboClub extends Subscription { + + public static boolean HC_PAYDAY_ENABLED = false; + public static int HC_PAYDAY_NEXT_DATE = Integer.MAX_VALUE; // yyyy-MM-dd HH:mm:ss + public static String HC_PAYDAY_INTERVAL = ""; + public static String HC_PAYDAY_QUERY = ""; + 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 + */ + public static boolean HC_PAYDAY_COINSSPENT_RESET_ON_EXPIRE = false; + + /** + * Boolean indicating if HC pay day currency executing. Prevents double execution + */ + public static boolean isExecuting = false; + + public SubscriptionHabboClub(Integer id, Integer userId, String subscriptionType, Integer timestampStart, Integer duration, Boolean active) { + super(id, userId, subscriptionType, timestampStart, duration, active); + } + + /** + * Called when the subscription is first created. + * Actions: + * - Set user's max_friends to MAXIMUM_FRIENDS_HC + * - Set user's max_rooms to MAXIMUM_ROOMS_HC + * - Reset the user's HC pay day timer (used in calculating the coins spent) + * - Send associated HC packets to client + */ + @Override + public void onCreated() { + super.onCreated(); + + HabboInfo habboInfo = Emulator.getGameEnvironment().getHabboManager().getHabboInfo(this.getUserId()); + HabboStats stats = habboInfo.getHabboStats(); + + 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, SubscriptionHabboClub.HABBO_CLUB, UserClubComposer.RESPONSE_TYPE_NORMAL)); + habbo.getClient().sendResponse(new UserPermissionsComposer(habbo)); + } + } + } + + /** + * Called when the subscription is extended by manual action (by admin command or RCON) + * Actions: + * - Extend duration of the subscription + * - Send associated HC packets to client + */ + @Override + public void addDuration(int amount) { + super.addDuration(amount); + + if (amount < 0) { + Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(this.getUserId()); + 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)); + } + } + } + + /** + * Called when the subscription is extended or bought again when already exists + * Actions: + * - Extend duration of the subscription + * - Send associated HC packets to client + */ + @Override + public void onExtended(int duration) { + super.onExtended(duration); + + Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(this.getUserId()); + + 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)); + } + } + + /** + * Called by SubscriptionScheduler when isActive() && getRemaining() < 0 + * Actions: + * - Set user's max_friends to MAXIMUM_FRIENDS + * - Set user's max_rooms to MAXIMUM_ROOMS + * - Remove HC clothing + * - Send associated HC packets to client + */ + @Override + public void onExpired() { + super.onExpired(); + + Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(this.getUserId()); + HabboInfo habboInfo = Emulator.getGameEnvironment().getHabboManager().getHabboInfo(this.getUserId()); + HabboStats stats = habboInfo.getHabboStats(); + + 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) { + habbo.getClient().sendResponse(new UpdateUserLookComposer(habbo)); + } + + if (habbo.getHabboInfo().getCurrentRoom() != null) { + habbo.getHabboInfo().getCurrentRoom().sendComposer(new RoomUserDataComposer(habbo).compose()); + } + } + + 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)); + } + } + + /** + * Calculate's a users upcoming HC Pay day rewards + * + * @param habbo User to calculate for + * @return ClubCenterDataComposer + */ + public static ClubCenterDataComposer calculatePayday(HabboInfo habbo) { + Subscription activeSub = null; + Subscription firstEverSub = null; + int currentHcStreak = 0; + int totalCreditsSpent = 0; + int creditRewardForStreakBonus = 0; + int creditRewardForMonthlySpent = 0; + int timeUntilPayday = 0; + + for (Subscription sub : habbo.getHabboStats().subscriptions) { + if (sub.getSubscriptionType().equalsIgnoreCase(Subscription.HABBO_CLUB)) { + + if (firstEverSub == null || sub.getTimestampStart() < firstEverSub.getTimestampStart()) { + firstEverSub = sub; + } + + 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) { + currentHcStreak = 0; + } + + for (Map.Entry set : HC_PAYDAY_STREAK.entrySet()) { + if (currentHcStreak >= set.getKey() && set.getValue() > creditRewardForStreakBonus) { + creditRewardForStreakBonus = set.getValue(); + } + } + + THashMap queryParams = new THashMap(); + queryParams.put("@user_id", habbo.getId()); + queryParams.put("@timestamp_start", habbo.getHabboStats().lastHCPayday); + queryParams.put("@timestamp_end", HC_PAYDAY_NEXT_DATE); + + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); + PreparedStatement statement = Database.preparedStatementWithParams(connection, HC_PAYDAY_QUERY, queryParams)) { + + try (ResultSet set = statement.executeQuery()) { + while (set.next()) { + totalCreditsSpent = set.getInt("amount_spent"); + } + } + + } catch (SQLException e) { + SubscriptionManager.LOGGER.error("Caught SQL exception", e); + } + + 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 + ); + } + + /** + * Executes the HC Pay day, calculating reward for all active HABBO_CLUB subscribers and issuing rewards. + */ + public static void executePayDay() { + isExecuting = true; + int timestampNow = Emulator.getIntUnixTimestamp(); + + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); + PreparedStatement statement = connection.prepareStatement("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")) { + statement.setInt(1, timestampNow); + statement.setInt(2, timestampNow); + + try (ResultSet set = statement.executeQuery()) { + while (set.next()) { + 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) { + 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) { + SubscriptionManager.LOGGER.error("Exception processing HC payday for user #" + set.getInt("user_id"), e); + } + } + } + + 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); + + 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)")) { + stm2.setInt(1, timestampNow); + stm2.setInt(2, timestampNow); + stm2.setInt(3, timestampNow); + stm2.execute(); + } + + } catch (SQLException e) { + SubscriptionManager.LOGGER.error("Caught SQL exception", e); + } + isExecuting = false; + } + + /** + * 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) { + 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()); + + try (ResultSet set = statement.executeQuery()) { + while (set.next()) { + try { + int logId = set.getInt("id"); + int userId = set.getInt("user_id"); + 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 = ?")) { + stm2.setInt(1, logId); + stm2.execute(); + } + } + } catch (Exception e) { + SubscriptionManager.LOGGER.error("Exception processing HC payday for user #" + set.getInt("user_id"), 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 + * @param amount Amount of currency to reward + * @param currency Currency string (Can be one of: credits, diamonds, duckets, pixels or a currency ID e.g. 5) + * @return Boolean indicating success of the operation + */ + public static boolean claimPayDay(Habbo habbo, int amount, String currency) { + if(habbo == null) + return false; + + int pointCurrency; + switch(currency.toLowerCase()) { + case "credits": + case "coins": + case "credit": + case "coin": + habbo.getClient().getHabbo().getHabboInfo().addCredits(amount); + habbo.getClient().sendResponse(new UserCreditsComposer(habbo.getClient().getHabbo())); + break; + + case "diamonds": + case "diamond": + pointCurrency = 5; + habbo.getClient().getHabbo().getHabboInfo().addCurrencyAmount(pointCurrency, amount); + habbo.getClient().sendResponse(new UserPointsComposer(habbo.getClient().getHabbo().getHabboInfo().getCurrencyAmount(pointCurrency), amount, pointCurrency)); + break; + + case "duckets": + case "ducket": + case "pixels": + case "pixel": + pointCurrency = 0; + habbo.getClient().getHabbo().getHabboInfo().addCurrencyAmount(pointCurrency, amount); + habbo.getClient().sendResponse(new UserPointsComposer(habbo.getClient().getHabbo().getHabboInfo().getCurrencyAmount(pointCurrency), amount, pointCurrency)); + break; + + default: + pointCurrency = Integer.parseInt(currency); + habbo.getClient().getHabbo().getHabboInfo().addCurrencyAmount(pointCurrency, amount); + habbo.getClient().sendResponse(new UserPointsComposer(habbo.getClient().getHabbo().getHabboInfo().getCurrencyAmount(pointCurrency), amount, pointCurrency)); + break; + } + + habbo.alert(Emulator.getTexts().getValue("subscriptions.hc.payday.message", "Woohoo HC Payday has arrived! You have received %amount% credits to your purse. Enjoy!").replace("%amount%", "" + amount)); + + 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/habbohotel/users/subscriptions/SubscriptionManager.java b/src/main/java/com/eu/habbo/habbohotel/users/subscriptions/SubscriptionManager.java new file mode 100644 index 00000000..b39d9d52 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/users/subscriptions/SubscriptionManager.java @@ -0,0 +1,89 @@ +package com.eu.habbo.habbohotel.users.subscriptions; + +import com.eu.habbo.Emulator; +import gnu.trove.map.hash.THashMap; +import gnu.trove.set.hash.THashSet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * @author Beny + */ +public class SubscriptionManager { + + public static final Logger LOGGER = LoggerFactory.getLogger(SubscriptionManager.class); + + public THashMap> types; + + public SubscriptionManager() { + this.types = new THashMap<>(); + } + + public void init() { + this.types.put(Subscription.HABBO_CLUB, SubscriptionHabboClub.class); + } + + public void addSubscriptionType(String type, Class clazz) { + if(this.types.containsKey(type) || this.types.containsValue(clazz)) { + throw new RuntimeException("Subscription Type must be unique. An class with type: " + clazz.getName() + " was already added OR the key: " + type + " is already in use."); + } + + this.types.put(type, clazz); + } + + public void removeSubscriptionType(String type) { + this.types.remove(type); + } + + public Class getSubscriptionClass(String type) { + if(!this.types.containsKey(type)) { + LOGGER.debug("Can't find subscription class: {}", type); + return Subscription.class; + } + + return this.types.get(type); + } + + public void dispose() { + this.types.clear(); + } + + public THashSet getSubscriptionsForUser(int userId) { + THashSet subscriptions = new THashSet<>(); + + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); + PreparedStatement statement = connection.prepareStatement("SELECT * FROM users_subscriptions WHERE user_id = ?")) { + statement.setInt(1, userId); + + try (ResultSet set = statement.executeQuery()) { + while (set.next()) { + Class subClazz = Emulator.getGameEnvironment().getSubscriptionManager().getSubscriptionClass(set.getString("subscription_type")); + Constructor c = subClazz.getConstructor(Integer.class, Integer.class, String.class, Integer.class, Integer.class, Boolean.class); + c.setAccessible(true); + Subscription subscription = c.newInstance(set.getInt("id"), set.getInt("user_id"), set.getString("subscription_type"), set.getInt("timestamp_start"), set.getInt("duration"), set.getInt("active") == 1); + subscriptions.add(subscription); + } + } catch (IllegalAccessException e) { + LOGGER.error("IllegalAccessException", e); + } catch (InstantiationException e) { + LOGGER.error("InstantiationException", e); + } catch (InvocationTargetException e) { + LOGGER.error("InvocationTargetException", e); + } + } catch (SQLException e) { + LOGGER.error("Caught SQL exception", e); + } + catch (NoSuchMethodException e) { + LOGGER.error("Caught NoSuchMethodException", e); + } + + return subscriptions; + } +} diff --git a/src/main/java/com/eu/habbo/habbohotel/users/subscriptions/SubscriptionScheduler.java b/src/main/java/com/eu/habbo/habbohotel/users/subscriptions/SubscriptionScheduler.java new file mode 100644 index 00000000..9f18a449 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/users/subscriptions/SubscriptionScheduler.java @@ -0,0 +1,74 @@ +package com.eu.habbo.habbohotel.users.subscriptions; + +import com.eu.habbo.Emulator; +import com.eu.habbo.core.Scheduler; +import com.eu.habbo.habbohotel.users.Habbo; +import com.eu.habbo.plugin.events.users.subscriptions.UserSubscriptionExpiredEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; + +/** + * @author Beny + */ +public class SubscriptionScheduler extends Scheduler { + + private static final Logger LOGGER = LoggerFactory.getLogger(SubscriptionScheduler.class); + + public SubscriptionScheduler() { + super(Emulator.getConfig().getInt("subscriptions.scheduler.interval", 10)); + this.reloadConfig(); + } + + /** + * Called when config is changed. Should end the scheduler if disabled. + */ + public void reloadConfig() { + if (Emulator.getConfig().getBoolean("subscriptions.scheduler.enabled", true)) { + if (this.disposed) { + this.disposed = false; + this.run(); + } + } else { + this.disposed = true; + } + } + + @Override + public void run() { + super.run(); + + Habbo habbo; + for (Map.Entry map : Emulator.getGameEnvironment().getHabboManager().getOnlineHabbos().entrySet()) { + habbo = map.getValue(); + + try { + if (habbo != null) { + for(Subscription subscription : habbo.getHabboStats().subscriptions) { + if(subscription.isActive() && subscription.getRemaining() < 0) { + if (!Emulator.getPluginManager().fireEvent(new UserSubscriptionExpiredEvent(habbo.getHabboInfo().getId(), subscription)).isCancelled()) { + subscription.onExpired(); + subscription.setActive(false); + } + } + } + } + } catch (Exception e) { + LOGGER.error("Caught exception", e); + } + } + + if(SubscriptionHabboClub.HC_PAYDAY_ENABLED && !SubscriptionHabboClub.isExecuting && SubscriptionHabboClub.HC_PAYDAY_NEXT_DATE < Emulator.getIntUnixTimestamp()) { + SubscriptionHabboClub.executePayDay(); + } + } + + public boolean isDisposed() { + return this.disposed; + } + + public void setDisposed(boolean disposed) { + this.disposed = disposed; + } +} diff --git a/src/main/java/com/eu/habbo/habbohotel/wired/WiredChangeDirectionSetting.java b/src/main/java/com/eu/habbo/habbohotel/wired/WiredChangeDirectionSetting.java new file mode 100644 index 00000000..748bff4f --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/wired/WiredChangeDirectionSetting.java @@ -0,0 +1,15 @@ +package com.eu.habbo.habbohotel.wired; + +import com.eu.habbo.habbohotel.rooms.RoomUserRotation; + +public class WiredChangeDirectionSetting { + public final int item_id; + public int rotation; + public RoomUserRotation direction; + + public WiredChangeDirectionSetting(int itemId, int rotation, RoomUserRotation direction) { + this.item_id = itemId; + this.rotation = rotation; + this.direction = direction; + } +} diff --git a/src/main/java/com/eu/habbo/habbohotel/wired/WiredHandler.java b/src/main/java/com/eu/habbo/habbohotel/wired/WiredHandler.java index 98924182..9f27ad78 100644 --- a/src/main/java/com/eu/habbo/habbohotel/wired/WiredHandler.java +++ b/src/main/java/com/eu/habbo/habbohotel/wired/WiredHandler.java @@ -27,6 +27,7 @@ import com.eu.habbo.plugin.events.furniture.wired.WiredConditionFailedEvent; import com.eu.habbo.plugin.events.furniture.wired.WiredStackExecutedEvent; import com.eu.habbo.plugin.events.furniture.wired.WiredStackTriggeredEvent; import com.eu.habbo.plugin.events.users.UserWiredRewardReceived; +import com.google.gson.GsonBuilder; import gnu.trove.set.hash.THashSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,6 +47,8 @@ public class WiredHandler { public static int MAXIMUM_FURNI_SELECTION = 5; public static int TELEPORT_DELAY = 500; + private static GsonBuilder gsonBuilder = null; + public static boolean handle(WiredTriggerType triggerType, RoomUnit roomUnit, Room room, Object[] stuff) { if (triggerType == WiredTriggerType.CUSTOM) return false; @@ -68,6 +71,9 @@ public class WiredHandler { if (triggers == null || triggers.isEmpty()) return false; + long millis = System.currentTimeMillis(); + THashSet effectsToExecute = new THashSet(); + List triggeredTiles = new ArrayList<>(); for (InteractionWiredTrigger trigger : triggers) { RoomTile tile = room.getLayout().getTile(trigger.getX(), trigger.getY()); @@ -75,7 +81,11 @@ public class WiredHandler { if (triggeredTiles.contains(tile)) continue; - if (handle(trigger, roomUnit, room, stuff)) { + THashSet tEffectsToExecute = new THashSet(); + + if (handle(trigger, roomUnit, room, stuff, tEffectsToExecute)) { + effectsToExecute.addAll(tEffectsToExecute); + if (triggerType.equals(WiredTriggerType.SAY_SOMETHING)) talked = true; @@ -83,12 +93,14 @@ public class WiredHandler { } } + for (InteractionWiredEffect effect : effectsToExecute) { + triggerEffect(effect, roomUnit, room, stuff, millis); + } + return talked; } public static boolean handleCustomTrigger(Class triggerType, RoomUnit roomUnit, Room room, Object[] stuff) { - boolean talked = false; - if (!Emulator.isReady) return false; @@ -106,6 +118,9 @@ public class WiredHandler { if (triggers == null || triggers.isEmpty()) return false; + long millis = System.currentTimeMillis(); + THashSet effectsToExecute = new THashSet(); + List triggeredTiles = new ArrayList<>(); for (InteractionWiredTrigger trigger : triggers) { if (trigger.getClass() != triggerType) continue; @@ -115,18 +130,37 @@ public class WiredHandler { if (triggeredTiles.contains(tile)) continue; - if (handle(trigger, roomUnit, room, stuff)) { + THashSet tEffectsToExecute = new THashSet(); + + if (handle(trigger, roomUnit, room, stuff, tEffectsToExecute)) { + effectsToExecute.addAll(tEffectsToExecute); triggeredTiles.add(tile); } } - return talked; + for (InteractionWiredEffect effect : effectsToExecute) { + triggerEffect(effect, roomUnit, room, stuff, millis); + } + + return effectsToExecute.size() > 0; } public static boolean handle(InteractionWiredTrigger trigger, final RoomUnit roomUnit, final Room room, final Object[] stuff) { + long millis = System.currentTimeMillis(); + THashSet effectsToExecute = new THashSet(); + + if(handle(trigger, roomUnit, room, stuff, effectsToExecute)) { + for (InteractionWiredEffect effect : effectsToExecute) { + triggerEffect(effect, roomUnit, room, stuff, millis); + } + return true; + } + return false; + } + + public static boolean handle(InteractionWiredTrigger trigger, final RoomUnit roomUnit, final Room room, final Object[] stuff, final THashSet effectsToExecute) { long millis = System.currentTimeMillis(); if (Emulator.isReady && trigger.canExecute(millis) && trigger.execute(roomUnit, room, stuff)) { - trigger.setCooldown(millis); trigger.activateBox(room); THashSet conditions = room.getRoomSpecialTypes().getConditions(trigger.getX(), trigger.getY()); @@ -152,6 +186,7 @@ public class WiredHandler { } } + trigger.setCooldown(millis); boolean hasExtraRandom = room.getRoomSpecialTypes().hasExtraType(trigger.getX(), trigger.getY(), WiredExtraRandom.class); boolean hasExtraUnseen = room.getRoomSpecialTypes().hasExtraType(trigger.getX(), trigger.getY(), WiredExtraUnseen.class); @@ -173,13 +208,13 @@ public class WiredHandler { if (extra instanceof WiredExtraUnseen) { extra.setExtradata(extra.getExtradata().equals("1") ? "0" : "1"); InteractionWiredEffect effect = ((WiredExtraUnseen) extra).getUnseenEffect(effectList); - triggerEffect(effect, roomUnit, room, stuff, millis); + effectsToExecute.add(effect); // triggerEffect(effect, roomUnit, room, stuff, millis); break; } } } else { for (final InteractionWiredEffect effect : effectList) { - boolean executed = triggerEffect(effect, roomUnit, room, stuff, millis); + boolean executed = effectsToExecute.add(effect); //triggerEffect(effect, roomUnit, room, stuff, millis); if (hasExtraRandom && executed) { break; } @@ -215,6 +250,12 @@ public class WiredHandler { return executed; } + public static GsonBuilder getGsonBuilder() { + if(gsonBuilder == null) { + gsonBuilder = new GsonBuilder(); + } + return gsonBuilder; + } public static boolean executeEffectsAtTiles(THashSet tiles, final RoomUnit roomUnit, final Room room, final Object[] stuff) { for (RoomTile tile : tiles) { diff --git a/src/main/java/com/eu/habbo/habbohotel/wired/WiredMatchFurniSetting.java b/src/main/java/com/eu/habbo/habbohotel/wired/WiredMatchFurniSetting.java index ea6797f1..7771450b 100644 --- a/src/main/java/com/eu/habbo/habbohotel/wired/WiredMatchFurniSetting.java +++ b/src/main/java/com/eu/habbo/habbohotel/wired/WiredMatchFurniSetting.java @@ -1,14 +1,14 @@ package com.eu.habbo.habbohotel.wired; public class WiredMatchFurniSetting { - public final int itemId; + public final int item_id; public final String state; public final int rotation; public final int x; public final int y; public WiredMatchFurniSetting(int itemId, String state, int rotation, int x, int y) { - this.itemId = itemId; + this.item_id = itemId; this.state = state.replace("\t\t\t", " "); this.rotation = rotation; this.x = x; @@ -21,7 +21,7 @@ public class WiredMatchFurniSetting { } public String toString(boolean includeState) { - return this.itemId + "-" + (this.state.isEmpty() || !includeState ? " " : this.state) + "-" + this.rotation + "-" + this.x + "-" + this.y; + return this.item_id + "-" + (this.state.isEmpty() || !includeState ? " " : this.state) + "-" + this.rotation + "-" + this.x + "-" + this.y; } } diff --git a/src/main/java/com/eu/habbo/messages/PacketManager.java b/src/main/java/com/eu/habbo/messages/PacketManager.java index 36c6e2c9..ee0c8965 100644 --- a/src/main/java/com/eu/habbo/messages/PacketManager.java +++ b/src/main/java/com/eu/habbo/messages/PacketManager.java @@ -64,6 +64,7 @@ import com.eu.habbo.messages.incoming.trading.*; import com.eu.habbo.messages.incoming.unknown.RequestResolutionEvent; import com.eu.habbo.messages.incoming.unknown.UnknownEvent1; import com.eu.habbo.messages.incoming.users.*; +import com.eu.habbo.messages.incoming.wired.WiredApplySetConditionsEvent; import com.eu.habbo.messages.incoming.wired.WiredConditionSaveDataEvent; import com.eu.habbo.messages.incoming.wired.WiredEffectSaveDataEvent; import com.eu.habbo.messages.incoming.wired.WiredTriggerSaveDataEvent; @@ -255,6 +256,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 { @@ -575,6 +580,7 @@ public class PacketManager { this.registerHandler(Incoming.WiredTriggerSaveDataEvent, WiredTriggerSaveDataEvent.class); this.registerHandler(Incoming.WiredEffectSaveDataEvent, WiredEffectSaveDataEvent.class); this.registerHandler(Incoming.WiredConditionSaveDataEvent, WiredConditionSaveDataEvent.class); + this.registerHandler(Incoming.WiredApplySetConditionsEvent, WiredApplySetConditionsEvent.class); } void registerUnknown() 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..75223e4c 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/Incoming.java +++ b/src/main/java/com/eu/habbo/messages/incoming/Incoming.java @@ -1,6 +1,7 @@ package com.eu.habbo.messages.incoming; public class Incoming { + public static final int PongEvent = 2596; public static final int ChangeNameCheckUsernameEvent = 3950; public static final int ConfirmChangeNameEvent = 2977; public static final int ActivateEffectEvent = 2959; @@ -40,6 +41,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 +76,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; @@ -150,6 +155,7 @@ public class Incoming { public static final int RequestInventoryItemsEvent = 3150; public static final int ModToolRoomAlertEvent = 3842; public static final int WiredEffectSaveDataEvent = 2281; + public static final int WiredApplySetConditionsEvent = 3373; public static final int CheckPetNameEvent = 2109; public static final int SecureLoginEvent = 2419; public static final int BotSaveSettingsEvent = 2624; 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/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/catalog/CatalogBuyItemEvent.java b/src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogBuyItemEvent.java index 5e2fe085..68a54353 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,16 +2,15 @@ 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; import com.eu.habbo.habbohotel.pets.PetManager; +import com.eu.habbo.habbohotel.rooms.RoomManager; import com.eu.habbo.habbohotel.users.HabboBadge; import com.eu.habbo.habbohotel.users.HabboInventory; +import com.eu.habbo.habbohotel.users.subscriptions.Subscription; import com.eu.habbo.messages.incoming.MessageHandler; import com.eu.habbo.messages.outgoing.catalog.AlertPurchaseFailedComposer; import com.eu.habbo.messages.outgoing.catalog.AlertPurchaseUnavailableComposer; @@ -65,10 +64,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; } } @@ -76,6 +77,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() { @@ -92,7 +97,7 @@ public class CatalogBuyItemEvent extends MessageHandler { return; } int roomCount = Emulator.getGameEnvironment().getRoomManager().getRoomsForHabbo(this.client.getHabbo()).size(); - int maxRooms = this.client.getHabbo().getHabboStats().hasActiveClub() ? Emulator.getConfig().getInt("hotel.max.rooms.vip") : Emulator.getConfig().getInt("hotel.max.rooms.user"); + int maxRooms = this.client.getHabbo().getHabboStats().hasActiveClub() ? RoomManager.MAXIMUM_ROOMS_HC : RoomManager.MAXIMUM_ROOMS_USER; if (roomCount >= maxRooms) { // checks if a user has the maximum rooms this.client.sendResponse(new CanCreateRoomComposer(roomCount, maxRooms)); // if so throws the max room error. @@ -176,12 +181,19 @@ public class CatalogBuyItemEvent extends MessageHandler { if (!this.client.getHabbo().hasPermission(Permission.ACC_INFINITE_POINTS)) this.client.getHabbo().getHabboInfo().addCurrencyAmount(item.getPointsType(), -totalDuckets); - if (this.client.getHabbo().getHabboStats().getClubExpireTimestamp() <= Emulator.getIntUnixTimestamp()) + + 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 (this.client.getHabbo().getHabboStats().getClubExpireTimestamp() <= Emulator.getIntUnixTimestamp()) this.client.getHabbo().getHabboStats().setClubExpireTimestamp(Emulator.getIntUnixTimestamp()); this.client.getHabbo().getHabboStats().setClubExpireTimestamp(this.client.getHabbo().getHabboStats().getClubExpireTimestamp() + (totalDays * 86400)); + this.client.sendResponse(new UserPermissionsComposer(this.client.getHabbo())); - this.client.sendResponse(new UserClubComposer(this.client.getHabbo())); + this.client.sendResponse(new UserClubComposer(this.client.getHabbo()));*/ if (totalCredits > 0) this.client.sendResponse(new UserCreditsComposer(this.client.getHabbo())); 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 259b5799..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 @@ -1,6 +1,8 @@ package com.eu.habbo.messages.incoming.catalog; +import com.eu.habbo.habbohotel.users.subscriptions.SubscriptionHabboClub; import com.eu.habbo.messages.incoming.MessageHandler; +import com.eu.habbo.messages.outgoing.catalog.ClubCenterDataComposer; import com.eu.habbo.messages.outgoing.catalog.ClubDataComposer; public class RequestClubDataEvent extends MessageHandler { 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/catalog/recycler/RecycleEvent.java b/src/main/java/com/eu/habbo/messages/incoming/catalog/recycler/RecycleEvent.java index a3c69775..05b6fc32 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/catalog/recycler/RecycleEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/catalog/recycler/RecycleEvent.java @@ -27,6 +27,7 @@ public class RecycleEvent extends MessageHandler { THashSet items = new THashSet<>(); int count = this.packet.readInt(); + if (count < Emulator.getConfig().getInt("recycler.value", 8)) return; for (int i = 0; i < count; i++) { HabboItem item = this.client.getHabbo().getInventory().getItemsComponent().getHabboItem(this.packet.readInt()); diff --git a/src/main/java/com/eu/habbo/messages/incoming/friends/AcceptFriendRequestEvent.java b/src/main/java/com/eu/habbo/messages/incoming/friends/AcceptFriendRequestEvent.java index aa5b1821..d5197131 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/friends/AcceptFriendRequestEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/friends/AcceptFriendRequestEvent.java @@ -4,6 +4,8 @@ import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.messenger.Messenger; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.messages.incoming.MessageHandler; +import com.eu.habbo.messages.outgoing.friends.FriendRequestErrorComposer; +import com.eu.habbo.plugin.PluginManager; public class AcceptFriendRequestEvent extends MessageHandler { @Override @@ -17,18 +19,33 @@ public class AcceptFriendRequestEvent extends MessageHandler { if (userId == 0) return; - if (this.client.getHabbo().getMessenger().getFriends().containsKey(userId)) + if (this.client.getHabbo().getMessenger().getFriends().containsKey(userId)) { + this.client.getHabbo().getMessenger().deleteFriendRequests(userId, this.client.getHabbo().getHabboInfo().getId()); continue; + } + + Habbo target = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId); + + if(target == null) { + this.client.sendResponse(new FriendRequestErrorComposer(FriendRequestErrorComposer.TARGET_NOT_FOUND)); + this.client.getHabbo().getMessenger().deleteFriendRequests(userId, this.client.getHabbo().getHabboInfo().getId()); + continue; + } + + if(this.client.getHabbo().getMessenger().getFriends().size() >= this.client.getHabbo().getHabboStats().maxFriends && !this.client.getHabbo().hasPermission("acc_infinite_friends")) { + this.client.sendResponse(new FriendRequestErrorComposer(FriendRequestErrorComposer.FRIEND_LIST_OWN_FULL)); + break; + } + + if(target.getMessenger().getFriends().size() >= target.getHabboStats().maxFriends && !target.hasPermission("acc_infinite_friends")) { + this.client.sendResponse(new FriendRequestErrorComposer(FriendRequestErrorComposer.FRIEND_LIST_TARGET_FULL)); + continue; + } this.client.getHabbo().getMessenger().acceptFriendRequest(userId, this.client.getHabbo().getHabboInfo().getId()); Messenger.checkFriendSizeProgress(this.client.getHabbo()); - - Habbo target = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId); - - if (target != null) { - Messenger.checkFriendSizeProgress(target); - } + Messenger.checkFriendSizeProgress(target); } } } diff --git a/src/main/java/com/eu/habbo/messages/incoming/friends/FriendRequestEvent.java b/src/main/java/com/eu/habbo/messages/incoming/friends/FriendRequestEvent.java index f595d730..758ca1b4 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/friends/FriendRequestEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/friends/FriendRequestEvent.java @@ -74,10 +74,16 @@ public class FriendRequestEvent extends MessageHandler { return; } - if (this.client.getHabbo().getMessenger().getFriends().values().size() >= Messenger.friendLimit(this.client.getHabbo()) && !this.client.getHabbo().hasPermission("acc_infinite_friends")) { + if (this.client.getHabbo().getMessenger().getFriends().values().size() >= this.client.getHabbo().getHabboStats().maxFriends && !this.client.getHabbo().hasPermission("acc_infinite_friends")) { this.client.sendResponse(new FriendRequestErrorComposer(FriendRequestErrorComposer.FRIEND_LIST_OWN_FULL)); return; } + + if (habbo.getMessenger().getFriends().values().size() >= habbo.getHabboStats().maxFriends && !habbo.hasPermission("acc_infinite_friends")) { + this.client.sendResponse(new FriendRequestErrorComposer(FriendRequestErrorComposer.FRIEND_LIST_TARGET_FULL)); + return; + } + Messenger.makeFriendRequest(this.client.getHabbo().getHabboInfo().getId(), id); } else { this.client.sendResponse(new FriendRequestErrorComposer(FriendRequestErrorComposer.TARGET_NOT_FOUND)); diff --git a/src/main/java/com/eu/habbo/messages/incoming/friends/RequestInitFriendsEvent.java b/src/main/java/com/eu/habbo/messages/incoming/friends/RequestInitFriendsEvent.java index c77adfec..2ce35cf7 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/friends/RequestInitFriendsEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/friends/RequestInitFriendsEvent.java @@ -11,9 +11,8 @@ public class RequestInitFriendsEvent extends MessageHandler { @Override public void handle() throws Exception { ArrayList messages = new ArrayList<>(); -// messages.add(new MessengerInitComposer(this.client.getHabbo()).compose()); - messages.add(new FriendsComposer(this.client.getHabbo()).compose()); + messages.addAll(FriendsComposer.getMessagesForBuddyList(this.client.getHabbo().getMessenger().getFriends().values())); this.client.sendResponses(messages); } } diff --git a/src/main/java/com/eu/habbo/messages/incoming/guilds/GuildDeleteEvent.java b/src/main/java/com/eu/habbo/messages/incoming/guilds/GuildDeleteEvent.java index 03e9bd2a..739eabc9 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/guilds/GuildDeleteEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/guilds/GuildDeleteEvent.java @@ -2,11 +2,15 @@ package com.eu.habbo.messages.incoming.guilds; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.guilds.Guild; +import com.eu.habbo.habbohotel.guilds.GuildMember; import com.eu.habbo.habbohotel.permissions.Permission; +import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.messages.incoming.MessageHandler; +import com.eu.habbo.messages.outgoing.guilds.GuildFavoriteRoomUserUpdateComposer; import com.eu.habbo.messages.outgoing.guilds.RemoveGuildFromRoomComposer; import com.eu.habbo.messages.outgoing.rooms.RoomDataComposer; import com.eu.habbo.plugin.events.guilds.GuildDeletedEvent; +import gnu.trove.set.hash.THashSet; public class GuildDeleteEvent extends MessageHandler { @Override @@ -18,6 +22,15 @@ public class GuildDeleteEvent extends MessageHandler { if (guild != null) { if (guild.getOwnerId() == this.client.getHabbo().getHabboInfo().getId() || this.client.getHabbo().hasPermission(Permission.ACC_GUILD_ADMIN)) //TODO Add staff permission override. { + THashSet members = Emulator.getGameEnvironment().getGuildManager().getGuildMembers(guild.getId()); + + for (GuildMember member : members) { + Habbo habbo = Emulator.getGameServer().getGameClientManager().getHabbo(member.getUserId()); + if (habbo != null) + if (habbo.getHabboInfo().getCurrentRoom() != null && habbo.getRoomUnit() != null) + habbo.getHabboInfo().getCurrentRoom().sendComposer(new GuildFavoriteRoomUserUpdateComposer(habbo.getRoomUnit(), null).compose()); + } + Emulator.getGameEnvironment().getGuildManager().deleteGuild(guild); Emulator.getPluginManager().fireEvent(new GuildDeletedEvent(guild, this.client.getHabbo())); Emulator.getGameEnvironment().getRoomManager().getRoom(guild.getRoomId()).sendComposer(new RemoveGuildFromRoomComposer(guildId).compose()); diff --git a/src/main/java/com/eu/habbo/messages/incoming/guilds/GuildRemoveFavoriteEvent.java b/src/main/java/com/eu/habbo/messages/incoming/guilds/GuildRemoveFavoriteEvent.java index cd97c727..6f64afac 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/guilds/GuildRemoveFavoriteEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/guilds/GuildRemoveFavoriteEvent.java @@ -22,7 +22,7 @@ public class GuildRemoveFavoriteEvent extends MessageHandler { this.client.getHabbo().getHabboStats().guild = 0; if (this.client.getHabbo().getHabboInfo().getCurrentRoom() != null && guild != null) { - this.client.getHabbo().getHabboInfo().getCurrentRoom().sendComposer(new GuildFavoriteRoomUserUpdateComposer(this.client.getHabbo().getRoomUnit(), guild).compose()); + this.client.getHabbo().getHabboInfo().getCurrentRoom().sendComposer(new GuildFavoriteRoomUserUpdateComposer(this.client.getHabbo().getRoomUnit(), null).compose()); } this.client.sendResponse(new UserProfileComposer(this.client.getHabbo(), this.client)); diff --git a/src/main/java/com/eu/habbo/messages/incoming/guilds/GuildRemoveMemberEvent.java b/src/main/java/com/eu/habbo/messages/incoming/guilds/GuildRemoveMemberEvent.java index 7652c0da..7ee21067 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/guilds/GuildRemoveMemberEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/guilds/GuildRemoveMemberEvent.java @@ -8,6 +8,7 @@ import com.eu.habbo.habbohotel.permissions.Permission; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.messages.incoming.MessageHandler; +import com.eu.habbo.messages.outgoing.guilds.GuildFavoriteRoomUserUpdateComposer; import com.eu.habbo.messages.outgoing.guilds.GuildInfoComposer; import com.eu.habbo.messages.outgoing.guilds.GuildRefreshMembersListComposer; import com.eu.habbo.plugin.events.guilds.GuildRemovedMemberEvent; @@ -44,8 +45,11 @@ public class GuildRemoveMemberEvent extends MessageHandler { if (habbo.getHabboStats().guild == guildId) habbo.getHabboStats().guild = 0; - if (room != null && habbo.getHabboInfo().getCurrentRoom() == room) { - room.refreshRightsForHabbo(habbo); + if (room != null) { + if (habbo.getHabboInfo().getCurrentRoom() != null && habbo.getRoomUnit() != null) + habbo.getHabboInfo().getCurrentRoom().sendComposer(new GuildFavoriteRoomUserUpdateComposer(habbo.getRoomUnit(), null).compose()); + if (habbo.getHabboInfo().getCurrentRoom() == room) + room.refreshRightsForHabbo(habbo); } habbo.getClient().sendResponse(new GuildInfoComposer(guild, habbo.getClient(), false, null)); diff --git a/src/main/java/com/eu/habbo/messages/incoming/guilds/RequestGuildBuyEvent.java b/src/main/java/com/eu/habbo/messages/incoming/guilds/RequestGuildBuyEvent.java index ee9f2eef..574987fa 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/guilds/RequestGuildBuyEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/guilds/RequestGuildBuyEvent.java @@ -27,7 +27,7 @@ public class RequestGuildBuyEvent extends MessageHandler { if(name.length() > 29 || description.length() > 254) return; - if (Emulator.getConfig().getBoolean("catalog.guild.hc_required", true) && this.client.getHabbo().getHabboStats().getClubExpireTimestamp() < Emulator.getIntUnixTimestamp()) { + if (Emulator.getConfig().getBoolean("catalog.guild.hc_required", true) && !this.client.getHabbo().getHabboStats().hasActiveClub()) { this.client.sendResponse(new GuildEditFailComposer(GuildEditFailComposer.HC_REQUIRED)); return; } @@ -79,6 +79,13 @@ public class RequestGuildBuyEvent extends MessageHandler { base += 3; } + if(name.length() > 29){ + this.client.sendResponse(new GuildEditFailComposer(GuildEditFailComposer.INVALID_GUILD_NAME)); + return; + } + if(description.length() > 254){ + return; + } Guild guild = Emulator.getGameEnvironment().getGuildManager().createGuild(this.client.getHabbo(), roomId, r.getName(), name, description, badge, colorOne, colorTwo); r.setGuild(guild.getId()); @@ -107,4 +114,4 @@ public class RequestGuildBuyEvent extends MessageHandler { } } } -} \ No newline at end of file +} 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 afe9ddf5..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 @@ -8,6 +8,8 @@ import com.eu.habbo.habbohotel.navigation.NavigatorSavedSearch; import com.eu.habbo.habbohotel.permissions.Permission; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboManager; +import com.eu.habbo.habbohotel.users.clothingvalidation.ClothingValidationManager; +import com.eu.habbo.habbohotel.users.subscriptions.SubscriptionHabboClub; import com.eu.habbo.messages.NoAuthMessage; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.incoming.MessageHandler; @@ -17,10 +19,10 @@ 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.SessionRightsComposer; -import com.eu.habbo.messages.outgoing.handshake.SomeConnectionComposer; +import com.eu.habbo.messages.outgoing.handshake.AvailabilityStatusMessageComposer; +import com.eu.habbo.messages.outgoing.handshake.PingComposer; import com.eu.habbo.messages.outgoing.inventory.InventoryAchievementsComposer; import com.eu.habbo.messages.outgoing.inventory.InventoryRefreshComposer; import com.eu.habbo.messages.outgoing.inventory.UserEffectsListComposer; @@ -55,8 +57,9 @@ public class SecureLoginEvent extends MessageHandler { if (!Emulator.isReady) return; - if (Emulator.getCrypto().isEnabled() && !this.client.isHandshakeFinished()) { + if (Emulator.getConfig().getBoolean("encryption.forced", false) && Emulator.getCrypto().isEnabled() && !this.client.isHandshakeFinished()) { Emulator.getGameServer().getGameClientManager().disposeClient(this.client); + LOGGER.warn("Encryption is forced and TLS Handshake isn't finished! Closed connection..."); return; } @@ -64,30 +67,26 @@ public class SecureLoginEvent extends MessageHandler { if (Emulator.getPluginManager().fireEvent(new SSOAuthenticationEvent(sso)).isCancelled()) { Emulator.getGameServer().getGameClientManager().disposeClient(this.client); + LOGGER.info("SSO Authentication is cancelled by a plugin. Closed connection..."); return; } if (sso.isEmpty()) { Emulator.getGameServer().getGameClientManager().disposeClient(this.client); + LOGGER.warn("Client is trying to connect without SSO ticket! Closed connection..."); return; } if (this.client.getHabbo() == null) { Habbo habbo = Emulator.getGameEnvironment().getHabboManager().loadHabbo(sso); if (habbo != null) { - if (Emulator.getGameEnvironment().getModToolManager().hasMACBan(this.client)) { - Emulator.getGameServer().getGameClientManager().disposeClient(this.client); - return; - } - if (Emulator.getGameEnvironment().getModToolManager().hasIPBan(this.client.getChannel())) { - Emulator.getGameServer().getGameClientManager().disposeClient(this.client); - return; - } - try { habbo.setClient(this.client); this.client.setHabbo(habbo); - this.client.getHabbo().connect(); + if(!this.client.getHabbo().connect()) { + Emulator.getGameServer().getGameClientManager().disposeClient(this.client); + return; + } if (this.client.getHabbo().getHabboInfo() == null) { Emulator.getGameServer().getGameClientManager().disposeClient(this.client); @@ -105,6 +104,14 @@ public class SecureLoginEvent extends MessageHandler { Emulator.getGameServer().getGameClientManager().disposeClient(this.client); return; } + + if(ClothingValidationManager.VALIDATE_ON_LOGIN) { + String validated = ClothingValidationManager.validateLook(this.client.getHabbo()); + if(!validated.equals(this.client.getHabbo().getHabboInfo().getLook())) { + this.client.getHabbo().getHabboInfo().setLook(validated); + } + } + ArrayList messages = new ArrayList<>(); messages.add(new SecureLoginOKComposer().compose()); @@ -113,9 +120,9 @@ public class SecureLoginEvent extends MessageHandler { messages.add(new UserClothesComposer(this.client.getHabbo()).compose()); messages.add(new NewUserIdentityComposer(habbo).compose()); messages.add(new UserPermissionsComposer(this.client.getHabbo()).compose()); - messages.add(new SessionRightsComposer().compose()); - messages.add(new SomeConnectionComposer().compose()); - messages.add(new DebugConsoleComposer(Emulator.debugging).compose()); + messages.add(new AvailabilityStatusMessageComposer(true, false, true).compose()); + messages.add(new PingComposer().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()); @@ -128,7 +135,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()); @@ -181,7 +188,7 @@ public class SecureLoginEvent extends MessageHandler { } } - Emulator.getPluginManager().fireEvent(new UserLoginEvent(habbo, this.client.getChannel().localAddress())); + Emulator.getPluginManager().fireEvent(new UserLoginEvent(habbo, this.client.getHabbo().getHabboInfo().getIpLogin())); if (Emulator.getConfig().getBoolean("hotel.welcome.alert.enabled")) { final Habbo finalHabbo = habbo; @@ -194,6 +201,12 @@ public class SecureLoginEvent extends MessageHandler { }, Emulator.getConfig().getInt("hotel.welcome.alert.delay", 5000)); } + if(SubscriptionHabboClub.HC_PAYDAY_ENABLED) { + SubscriptionHabboClub.processUnclaimed(habbo); + } + + SubscriptionHabboClub.processClubBadge(habbo); + Messenger.checkFriendSizeProgress(habbo); if (!habbo.getHabboStats().hasGottenDefaultSavedSearches) { @@ -208,6 +221,7 @@ public class SecureLoginEvent extends MessageHandler { } } else { Emulator.getGameServer().getGameClientManager().disposeClient(this.client); + LOGGER.warn("Someone tried to login with a non-existing SSO token! Closed connection..."); } } else { Emulator.getGameServer().getGameClientManager().disposeClient(this.client); diff --git a/src/main/java/com/eu/habbo/messages/incoming/handshake/SecureLoginEvent_BACKUP.java b/src/main/java/com/eu/habbo/messages/incoming/handshake/SecureLoginEvent_BACKUP.java deleted file mode 100644 index 881579ba..00000000 --- a/src/main/java/com/eu/habbo/messages/incoming/handshake/SecureLoginEvent_BACKUP.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.eu.habbo.messages.incoming.handshake; - -import com.eu.habbo.Emulator; -import com.eu.habbo.habbohotel.permissions.Permission; -import com.eu.habbo.habbohotel.users.Habbo; -import com.eu.habbo.messages.ServerMessage; -import com.eu.habbo.messages.incoming.MessageHandler; -import com.eu.habbo.messages.outgoing.friends.FriendsComposer; -import com.eu.habbo.messages.outgoing.generic.alerts.GenericAlertComposer; -import com.eu.habbo.messages.outgoing.habboway.nux.NewUserIdentityComposer; -import com.eu.habbo.messages.outgoing.handshake.DebugConsoleComposer; -import com.eu.habbo.messages.outgoing.handshake.SecureLoginOKComposer; -import com.eu.habbo.messages.outgoing.handshake.SessionRightsComposer; -import com.eu.habbo.messages.outgoing.modtool.ModToolComposer; -import com.eu.habbo.messages.outgoing.navigator.*; -import com.eu.habbo.messages.outgoing.users.*; -import com.eu.habbo.plugin.events.users.UserLoginEvent; - -import java.util.ArrayList; - -public class SecureLoginEvent_BACKUP extends MessageHandler { - - - @Override - public void handle() throws Exception { - - if (!Emulator.isReady) - return; - - String sso = this.packet.readString(); - - if (this.client.getHabbo() == null) { - Habbo habbo = Emulator.getGameEnvironment().getHabboManager().loadHabbo(sso); - if (habbo != null) { - habbo.setClient(this.client); - this.client.setHabbo(habbo); - this.client.getHabbo().connect(); - //this.client.sendResponse(new DebugConsoleComposer()); - Emulator.getThreading().run(habbo); - Emulator.getGameEnvironment().getHabboManager().addHabbo(habbo); - - ArrayList messages = new ArrayList<>(); - - - messages.add(new SecureLoginOKComposer().compose()); - messages.add(new UserHomeRoomComposer(this.client.getHabbo().getHabboInfo().getHomeRoom(), 0).compose()); - messages.add(new UserPermissionsComposer(this.client.getHabbo()).compose()); - messages.add(new UserClubComposer(this.client.getHabbo()).compose()); - messages.add(new DebugConsoleComposer(Emulator.debugging).compose()); - messages.add(new UserAchievementScoreComposer(this.client.getHabbo()).compose()); - messages.add(new NewUserIdentityComposer(habbo).compose()); - messages.add(new UserPerksComposer(habbo).compose()); - messages.add(new SessionRightsComposer().compose()); - messages.add(new FavoriteRoomsCountComposer(habbo).compose()); - messages.add(new FriendsComposer(this.client.getHabbo()).compose()); - //messages.add(new NewUserIdentityComposer().compose()); - //messages.add(new UserDataComposer(this.client.getHabbo()).compose()); - //messages.add(new SessionRightsComposer().compose()); - //messages.add(new MinimailCountComposer().compose()); - //messages.add(new MessengerInitComposer(this.client.getHabbo()).compose()); - //messages.add(new FriendsComposer(this.client.getHabbo()).compose()); - - if (this.client.getHabbo().hasPermission(Permission.ACC_SUPPORTTOOL)) { - messages.add(new ModToolComposer(this.client.getHabbo()).compose()); - } - - this.client.sendResponses(messages); - - //Hardcoded - this.client.sendResponse(new NewNavigatorMetaDataComposer()); - this.client.sendResponse(new NewNavigatorLiftedRoomsComposer()); - this.client.sendResponse(new NewNavigatorCollapsedCategoriesComposer()); - this.client.sendResponse(new NewNavigatorSavedSearchesComposer(this.client.getHabbo().getHabboInfo().getSavedSearches())); - this.client.sendResponse(new NewNavigatorEventCategoriesComposer()); - //this.client.sendResponse(new HotelViewComposer()); - //this.client.sendResponse(new UserHomeRoomComposer(this.client.getHabbo().getHabboInfo().getHomeRoom(), this.client.getHabbo().getHabboInfo().getHomeRoom())); - //this.client.sendResponse(new UserEffectsListComposer()); - - - Emulator.getPluginManager().fireEvent(new UserLoginEvent(habbo, this.client.getChannel().localAddress())); - - } else { - this.client.sendResponse(new GenericAlertComposer("Can't connect *sadpanda*")); - - this.client.getChannel().close(); - } - } - } -} diff --git a/src/main/java/com/eu/habbo/messages/incoming/navigator/RequestCanCreateRoomEvent.java b/src/main/java/com/eu/habbo/messages/incoming/navigator/RequestCanCreateRoomEvent.java index ef0b56df..d1ed2bf0 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/navigator/RequestCanCreateRoomEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/navigator/RequestCanCreateRoomEvent.java @@ -9,7 +9,7 @@ public class RequestCanCreateRoomEvent extends MessageHandler { @Override public void handle() throws Exception { int count = Emulator.getGameEnvironment().getRoomManager().getRoomsForHabbo(this.client.getHabbo()).size(); - int max = this.client.getHabbo().getHabboStats().hasActiveClub() ? RoomManager.MAXIMUM_ROOMS_VIP : RoomManager.MAXIMUM_ROOMS_USER; + int max = this.client.getHabbo().getHabboStats().maxRooms; this.client.sendResponse(new CanCreateRoomComposer(count, max)); } } diff --git a/src/main/java/com/eu/habbo/messages/incoming/navigator/RequestCreateRoomEvent.java b/src/main/java/com/eu/habbo/messages/incoming/navigator/RequestCreateRoomEvent.java index 49328abf..d0f8f83a 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/navigator/RequestCreateRoomEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/navigator/RequestCreateRoomEvent.java @@ -48,7 +48,7 @@ public class RequestCreateRoomEvent extends MessageHandler { return; int count = Emulator.getGameEnvironment().getRoomManager().getRoomsForHabbo(this.client.getHabbo()).size(); - int max = this.client.getHabbo().getHabboStats().hasActiveClub() ? RoomManager.MAXIMUM_ROOMS_VIP : RoomManager.MAXIMUM_ROOMS_USER; + int max = this.client.getHabbo().getHabboStats().maxRooms; if (count >= max) { this.client.sendResponse(new CanCreateRoomComposer(count, max)); diff --git a/src/main/java/com/eu/habbo/messages/incoming/navigator/SaveWindowSettingsEvent.java b/src/main/java/com/eu/habbo/messages/incoming/navigator/SaveWindowSettingsEvent.java index c5134207..2910d0c8 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/navigator/SaveWindowSettingsEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/navigator/SaveWindowSettingsEvent.java @@ -14,7 +14,10 @@ public class SaveWindowSettingsEvent extends MessageHandler { windowSettings.width = this.packet.readInt(); windowSettings.height = this.packet.readInt(); - windowSettings.openSearches = this.packet.readBoolean(); - int unknown = this.packet.readInt(); + boolean openSearches = this.packet.readBoolean(); + windowSettings.openSearches = openSearches; + + int unknownVar = this.packet.readInt(); + int unknown = unknownVar; } } diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/AdvertisingSaveEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/AdvertisingSaveEvent.java index 6fb6b0b6..d705f8ff 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/AdvertisingSaveEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/AdvertisingSaveEvent.java @@ -42,6 +42,7 @@ public class AdvertisingSaveEvent extends MessageHandler { item.needsUpdate(true); Emulator.getThreading().run(item); room.updateItem(item); + ((InteractionCustomValues) item).onCustomValuesSaved(room, this.client); } } } diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MannequinSaveLookEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MannequinSaveLookEvent.java index 5def4dee..6713af89 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MannequinSaveLookEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MannequinSaveLookEvent.java @@ -2,15 +2,17 @@ package com.eu.habbo.messages.incoming.rooms.items; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.messages.incoming.MessageHandler; public class MannequinSaveLookEvent extends MessageHandler { @Override public void handle() throws Exception { - Room room = this.client.getHabbo().getHabboInfo().getCurrentRoom(); + Habbo habbo = this.client.getHabbo(); + Room room = habbo.getHabboInfo().getCurrentRoom(); - if (room == null || this.client.getHabbo().getHabboInfo().getId() != room.getOwnerId()) + if (room == null || !room.isOwner(habbo)) return; HabboItem item = room.getHabboItem(this.packet.readInt()); @@ -22,7 +24,7 @@ public class MannequinSaveLookEvent extends MessageHandler { StringBuilder look = new StringBuilder(); - for (String s : this.client.getHabbo().getHabboInfo().getLook().split("\\.")) { + for (String s : habbo.getHabboInfo().getLook().split("\\.")) { if (!s.contains("hr") && !s.contains("hd") && !s.contains("he") && !s.contains("ea") && !s.contains("ha") && !s.contains("fa")) { look.append(s).append("."); } @@ -33,9 +35,9 @@ public class MannequinSaveLookEvent extends MessageHandler { } if (data.length == 3) { - item.setExtradata(this.client.getHabbo().getHabboInfo().getGender().name().toLowerCase() + ":" + look + ":" + data[2]); + item.setExtradata(habbo.getHabboInfo().getGender().name().toLowerCase() + ":" + look + ":" + data[2]); } else { - item.setExtradata(this.client.getHabbo().getHabboInfo().getGender().name().toLowerCase() + ":" + look + ":" + this.client.getHabbo().getHabboInfo().getUsername() + "'s look."); + item.setExtradata(habbo.getHabboInfo().getGender().name().toLowerCase() + ":" + look + ":" + habbo.getHabboInfo().getUsername() + "'s look."); } item.needsUpdate(true); 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/items/MoodLightSaveSettingsEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MoodLightSaveSettingsEvent.java index 04934da6..731e6490 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MoodLightSaveSettingsEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MoodLightSaveSettingsEvent.java @@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionMoodLight; import com.eu.habbo.habbohotel.modtool.ScripterManager; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomMoodlightData; +import com.eu.habbo.habbohotel.rooms.RoomRightLevels; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.messages.incoming.MessageHandler; import com.eu.habbo.messages.outgoing.rooms.items.MoodLightDataComposer; @@ -20,7 +21,7 @@ public class MoodLightSaveSettingsEvent extends MessageHandler { public void handle() throws Exception { Room room = this.client.getHabbo().getHabboInfo().getCurrentRoom(); - if ((room.getGuildId() <= 0 && room.guildRightLevel(this.client.getHabbo()) < 2) && !room.hasRights(this.client.getHabbo())) + if ((room.getGuildId() <= 0 && room.getGuildRightLevel(this.client.getHabbo()).isLessThan(RoomRightLevels.GUILD_RIGHTS)) && !room.hasRights(this.client.getHabbo())) return; int id = this.packet.readInt(); diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MoodLightTurnOnEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MoodLightTurnOnEvent.java index eee75a7b..4f2e8eb5 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MoodLightTurnOnEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MoodLightTurnOnEvent.java @@ -4,6 +4,7 @@ import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.items.interactions.InteractionMoodLight; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomMoodlightData; +import com.eu.habbo.habbohotel.rooms.RoomRightLevels; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.messages.incoming.MessageHandler; @@ -12,7 +13,7 @@ public class MoodLightTurnOnEvent extends MessageHandler { public void handle() throws Exception { Room room = this.client.getHabbo().getHabboInfo().getCurrentRoom(); - if ((room.getGuildId() > 0 && room.guildRightLevel(this.client.getHabbo()) < 2) && !room.hasRights(this.client.getHabbo())) + if ((room.getGuildId() > 0 && room.getGuildRightLevel(this.client.getHabbo()).isLessThan(RoomRightLevels.GUILD_RIGHTS)) && !room.hasRights(this.client.getHabbo())) return; for (HabboItem moodLight : room.getRoomSpecialTypes().getItemsOfType(InteractionMoodLight.class)) { diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MoveWallItemEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MoveWallItemEvent.java index bb260add..10397073 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MoveWallItemEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/MoveWallItemEvent.java @@ -3,6 +3,7 @@ package com.eu.habbo.messages.incoming.rooms.items; import com.eu.habbo.habbohotel.permissions.Permission; import com.eu.habbo.habbohotel.rooms.FurnitureMovementError; import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.rooms.RoomRightLevels; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.messages.incoming.MessageHandler; import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertComposer; @@ -16,7 +17,7 @@ public class MoveWallItemEvent extends MessageHandler { if (room == null) return; - if (!room.hasRights(this.client.getHabbo()) && !this.client.getHabbo().hasPermission(Permission.ACC_PLACEFURNI) && !(room.getGuildId() > 0 && room.guildRightLevel(this.client.getHabbo()) >= 2)) { + if (!room.hasRights(this.client.getHabbo()) && !this.client.getHabbo().hasPermission(Permission.ACC_PLACEFURNI) && !(room.getGuildId() > 0 && room.getGuildRightLevel(this.client.getHabbo()).isEqualOrGreaterThan(RoomRightLevels.GUILD_RIGHTS))) { this.client.sendResponse(new BubbleAlertComposer(BubbleAlertKeys.FURNITURE_PLACEMENT_ERROR.key, FurnitureMovementError.NO_RIGHTS.errorCode)); return; } diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/RedeemClothingEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/RedeemClothingEvent.java index 95382469..20f46659 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/RedeemClothingEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/RedeemClothingEvent.java @@ -53,6 +53,7 @@ public class RedeemClothingEvent extends MessageHandler { } this.client.getHabbo().getInventory().getWardrobeComponent().getClothing().add(clothing.id); + this.client.getHabbo().getInventory().getWardrobeComponent().getClothingSets().addAll(clothing.setId); this.client.sendResponse(new UserClothesComposer(this.client.getHabbo())); this.client.sendResponse(new BubbleAlertComposer(BubbleAlertKeys.FIGURESET_REDEEMED.key)); diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/SetStackHelperHeightEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/SetStackHelperHeightEvent.java index a46bb7d2..dce31447 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/SetStackHelperHeightEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/SetStackHelperHeightEvent.java @@ -34,7 +34,7 @@ public class SetStackHelperHeightEvent extends MessageHandler { } } } else { - stackerHeight = Math.min(Math.max(stackerHeight, itemTile.z * 100), 4000); + stackerHeight = Math.min(Math.max(stackerHeight, itemTile.z * 100), Room.MAXIMUM_FURNI_HEIGHT * 100); } double height = 0; diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/ToggleFloorItemEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/ToggleFloorItemEvent.java index 5b665d79..50376ae8 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/ToggleFloorItemEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/ToggleFloorItemEvent.java @@ -11,6 +11,9 @@ import com.eu.habbo.messages.incoming.MessageHandler; import com.eu.habbo.messages.outgoing.rooms.items.RemoveFloorItemComposer; import com.eu.habbo.messages.outgoing.rooms.pets.PetPackageComposer; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserStatusComposer; +import com.eu.habbo.plugin.Event; +import com.eu.habbo.plugin.events.furniture.FurniturePickedUpEvent; +import com.eu.habbo.plugin.events.furniture.FurnitureToggleEvent; import com.eu.habbo.threading.runnables.QueryDeleteHabboItem; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,6 +37,12 @@ public class ToggleFloorItemEvent extends MessageHandler { if (item == null || item instanceof InteractionDice) return; + Event furnitureToggleEvent = new FurnitureToggleEvent(item, this.client.getHabbo(), state); + Emulator.getPluginManager().fireEvent(furnitureToggleEvent); + + if (furnitureToggleEvent.isCancelled()) + return; + /* if (item.getBaseItem().getName().equalsIgnoreCase("totem_planet")) { THashSet items = room.getItemsAt(room.getLayout().getTile(item.getX(), item.getY())); diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/ToggleWallItemEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/ToggleWallItemEvent.java index 8700940c..d4020edf 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/ToggleWallItemEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/ToggleWallItemEvent.java @@ -4,6 +4,8 @@ import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.messages.incoming.MessageHandler; +import com.eu.habbo.plugin.Event; +import com.eu.habbo.plugin.events.furniture.FurnitureToggleEvent; public class ToggleWallItemEvent extends MessageHandler { @Override @@ -21,6 +23,12 @@ public class ToggleWallItemEvent extends MessageHandler { if (item == null) return; + Event furnitureToggleEvent = new FurnitureToggleEvent(item, this.client.getHabbo(), state); + Emulator.getPluginManager().fireEvent(furnitureToggleEvent); + + if (furnitureToggleEvent.isCancelled()) + return; + if (item.getBaseItem().getName().equalsIgnoreCase("poster")) return; 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/pets/ScratchPetEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/pets/ScratchPetEvent.java index 4621c044..501b6901 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/pets/ScratchPetEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/pets/ScratchPetEvent.java @@ -1,5 +1,6 @@ package com.eu.habbo.messages.incoming.rooms.pets; +import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.pets.MonsterplantPet; import com.eu.habbo.habbohotel.pets.Pet; import com.eu.habbo.messages.incoming.MessageHandler; @@ -22,6 +23,9 @@ public class ScratchPetEvent extends MessageHandler { if (this.client.getHabbo().getHabboStats().petRespectPointsToGive > 0 || pet instanceof MonsterplantPet) { pet.scratched(this.client.getHabbo()); + + // Update the stats to the database. + Emulator.getThreading().run(pet); } } } 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 511f9829..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 @@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.catalog.CatalogItem; import com.eu.habbo.habbohotel.catalog.CatalogPage; import com.eu.habbo.habbohotel.permissions.Permission; import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.rooms.RoomRightLevels; import com.eu.habbo.messages.incoming.MessageHandler; import com.eu.habbo.messages.outgoing.catalog.AlertPurchaseFailedComposer; import com.eu.habbo.messages.outgoing.catalog.PurchaseOKComposer; @@ -20,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(); @@ -29,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.guildRightLevel(this.client.getHabbo()) == 3)) { - 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/rooms/users/RoomUserLookAtPoint.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/users/RoomUserLookAtPoint.java index 24e8004c..f4f7c005 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/users/RoomUserLookAtPoint.java +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/users/RoomUserLookAtPoint.java @@ -51,7 +51,8 @@ public class RoomUserLookAtPoint extends MessageHandler { if (tile != null) { roomUnit.lookAtPoint(tile); - room.sendComposer(new RoomUserStatusComposer(roomUnit).compose()); + roomUnit.statusUpdate(true); + //room.sendComposer(new RoomUserStatusComposer(roomUnit).compose()); } } } diff --git a/src/main/java/com/eu/habbo/messages/incoming/trading/TradeOfferItemEvent.java b/src/main/java/com/eu/habbo/messages/incoming/trading/TradeOfferItemEvent.java index 25fb39cb..85b521d3 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/trading/TradeOfferItemEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/trading/TradeOfferItemEvent.java @@ -17,7 +17,7 @@ public class TradeOfferItemEvent extends MessageHandler { HabboItem item = this.client.getHabbo().getInventory().getItemsComponent().getHabboItem(this.packet.readInt()); - if (item == null) + if (item == null || !item.getBaseItem().allowTrade()) return; trade.offerItem(this.client.getHabbo(), item); 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/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/incoming/users/SaveMottoEvent.java b/src/main/java/com/eu/habbo/messages/incoming/users/SaveMottoEvent.java index d3b2a329..50d0f9a1 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/users/SaveMottoEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/users/SaveMottoEvent.java @@ -13,9 +13,11 @@ public class SaveMottoEvent extends MessageHandler { UserSavedMottoEvent event = new UserSavedMottoEvent(this.client.getHabbo(), this.client.getHabbo().getHabboInfo().getMotto(), motto); Emulator.getPluginManager().fireEvent(event); motto = event.newMotto; - - this.client.getHabbo().getHabboInfo().setMotto(motto); - this.client.getHabbo().getHabboInfo().run(); + + if(motto.length() <= Emulator.getConfig().getInt("motto.max_length", 38)) { + this.client.getHabbo().getHabboInfo().setMotto(motto); + this.client.getHabbo().getHabboInfo().run(); + } if (this.client.getHabbo().getHabboInfo().getCurrentRoom() != null) { this.client.getHabbo().getHabboInfo().getCurrentRoom().sendComposer(new RoomUserDataComposer(this.client.getHabbo()).compose()); 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/incoming/users/UserSaveLookEvent.java b/src/main/java/com/eu/habbo/messages/incoming/users/UserSaveLookEvent.java index 411f24e3..c4c30c5f 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/users/UserSaveLookEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/users/UserSaveLookEvent.java @@ -4,6 +4,7 @@ import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.achievements.AchievementManager; import com.eu.habbo.habbohotel.modtool.ScripterManager; import com.eu.habbo.habbohotel.users.HabboGender; +import com.eu.habbo.habbohotel.users.clothingvalidation.ClothingValidationManager; import com.eu.habbo.messages.incoming.MessageHandler; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDataComposer; import com.eu.habbo.messages.outgoing.users.UpdateUserLookComposer; @@ -35,7 +36,7 @@ public class UserSaveLookEvent extends MessageHandler { if (lookEvent.isCancelled()) return; - this.client.getHabbo().getHabboInfo().setLook(lookEvent.newLook); + this.client.getHabbo().getHabboInfo().setLook(ClothingValidationManager.VALIDATE_ON_CHANGE_LOOKS ? ClothingValidationManager.validateLook(this.client.getHabbo(), lookEvent.newLook, lookEvent.gender.name()) : lookEvent.newLook); this.client.getHabbo().getHabboInfo().setGender(lookEvent.gender); Emulator.getThreading().run(this.client.getHabbo().getHabboInfo()); this.client.sendResponse(new UpdateUserLookComposer(this.client.getHabbo())); diff --git a/src/main/java/com/eu/habbo/messages/incoming/wired/WiredApplySetConditionsEvent.java b/src/main/java/com/eu/habbo/messages/incoming/wired/WiredApplySetConditionsEvent.java new file mode 100644 index 00000000..1d9266f3 --- /dev/null +++ b/src/main/java/com/eu/habbo/messages/incoming/wired/WiredApplySetConditionsEvent.java @@ -0,0 +1,103 @@ +package com.eu.habbo.messages.incoming.wired; + +import com.eu.habbo.habbohotel.items.interactions.wired.interfaces.InteractionWiredMatchFurniSettings; +import com.eu.habbo.habbohotel.rooms.FurnitureMovementError; +import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.rooms.RoomTile; +import com.eu.habbo.habbohotel.rooms.RoomTileState; +import com.eu.habbo.habbohotel.users.HabboItem; +import com.eu.habbo.messages.incoming.MessageHandler; +import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertComposer; +import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertKeys; +import com.eu.habbo.messages.outgoing.rooms.items.FloorItemOnRollerComposer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class WiredApplySetConditionsEvent extends MessageHandler { + + @Override + public int getRatelimit() { + return 500; + } + + @Override + public void handle() throws Exception { + int itemId = this.packet.readInt(); + + // Executing Habbo has to be in a Room + if (!this.client.getHabbo().getRoomUnit().isInRoom()) { + this.client.sendResponse(new BubbleAlertComposer( + BubbleAlertKeys.FURNITURE_PLACEMENT_ERROR.key, + FurnitureMovementError.NO_RIGHTS.errorCode + )); + return; + } + + Room room = this.client.getHabbo().getHabboInfo().getCurrentRoom(); + + if (room != null) { + + // Executing Habbo should be able to edit wireds + if (room.hasRights(this.client.getHabbo()) || room.isOwner(this.client.getHabbo())) { + + List wireds = new ArrayList<>(); + wireds.addAll(room.getRoomSpecialTypes().getConditions()); + wireds.addAll(room.getRoomSpecialTypes().getEffects()); + + // Find the item with the given ID in the room + Optional item = wireds.stream() + .filter(wired -> wired.getId() == itemId) + .findFirst(); + + // If the item exists + if (item.isPresent()) { + HabboItem wiredItem = item.get(); + + // The item should have settings to match furni state, position and rotation + if (wiredItem instanceof InteractionWiredMatchFurniSettings) { + + InteractionWiredMatchFurniSettings wired = (InteractionWiredMatchFurniSettings) wiredItem; + + // Try to apply the set settings to each item + wired.getMatchFurniSettings().forEach(setting -> { + HabboItem matchItem = room.getHabboItem(setting.item_id); + + // Match state + if (wired.shouldMatchState() && matchItem.allowWiredResetState()) { + if (!setting.state.equals(" ") && !matchItem.getExtradata().equals(setting.state)) { + matchItem.setExtradata(setting.state); + room.updateItemState(matchItem); + } + } + + RoomTile oldLocation = room.getLayout().getTile(matchItem.getX(), matchItem.getY()); + double oldZ = matchItem.getZ(); + + // Match Position & Rotation + if(wired.shouldMatchRotation() && !wired.shouldMatchPosition()) { + if(matchItem.getRotation() != setting.rotation && room.furnitureFitsAt(oldLocation, matchItem, setting.rotation, false) == FurnitureMovementError.NONE) { + room.moveFurniTo(matchItem, oldLocation, setting.rotation, null, true); + } + } + else if(wired.shouldMatchPosition()) { + boolean slideAnimation = !wired.shouldMatchRotation() || matchItem.getRotation() == setting.rotation; + RoomTile newLocation = room.getLayout().getTile((short) setting.x, (short) setting.y); + int newRotation = wired.shouldMatchRotation() ? setting.rotation : matchItem.getRotation(); + + if(newLocation != null && newLocation.state != RoomTileState.INVALID && (newLocation != oldLocation || newRotation != matchItem.getRotation()) && room.furnitureFitsAt(newLocation, matchItem, newRotation, true) == FurnitureMovementError.NONE) { + if(room.moveFurniTo(matchItem, newLocation, newRotation, null, !slideAnimation) == FurnitureMovementError.NONE) { + if(slideAnimation) { + room.sendComposer(new FloorItemOnRollerComposer(matchItem, null, oldLocation, oldZ, newLocation, matchItem.getZ(), 0, room).compose()); + } + } + } + } + }); + } + } + } + } + } +} diff --git a/src/main/java/com/eu/habbo/messages/incoming/wired/WiredEffectSaveDataEvent.java b/src/main/java/com/eu/habbo/messages/incoming/wired/WiredEffectSaveDataEvent.java index 98ace187..fbf51226 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/wired/WiredEffectSaveDataEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/wired/WiredEffectSaveDataEvent.java @@ -5,6 +5,8 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect; import com.eu.habbo.habbohotel.permissions.Permission; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.messages.incoming.MessageHandler; +import com.eu.habbo.messages.outgoing.generic.alerts.GenericErrorMessagesComposer; +import com.eu.habbo.messages.outgoing.generic.alerts.UpdateFailedComposer; import com.eu.habbo.messages.outgoing.wired.WiredSavedComposer; public class WiredEffectSaveDataEvent extends MessageHandler { @@ -18,13 +20,19 @@ public class WiredEffectSaveDataEvent extends MessageHandler { if (room.hasRights(this.client.getHabbo()) || room.getOwnerId() == this.client.getHabbo().getHabboInfo().getId() || this.client.getHabbo().hasPermission(Permission.ACC_ANYROOMOWNER) || this.client.getHabbo().hasPermission(Permission.ACC_MOVEROTATE)) { InteractionWiredEffect effect = room.getRoomSpecialTypes().getEffect(itemId); - if (effect != null) { + try { + if (effect == null) + throw new WiredSaveException(String.format("Wired effect with item id %s not found in room", itemId)); + if (effect.saveData(this.packet, this.client)) { this.client.sendResponse(new WiredSavedComposer()); effect.needsUpdate(true); Emulator.getThreading().run(effect); } } + catch (WiredSaveException e) { + this.client.sendResponse(new UpdateFailedComposer(e.getMessage())); + } } } } diff --git a/src/main/java/com/eu/habbo/messages/incoming/wired/WiredSaveException.java b/src/main/java/com/eu/habbo/messages/incoming/wired/WiredSaveException.java new file mode 100644 index 00000000..74feda15 --- /dev/null +++ b/src/main/java/com/eu/habbo/messages/incoming/wired/WiredSaveException.java @@ -0,0 +1,15 @@ +package com.eu.habbo.messages.incoming.wired; + +public class WiredSaveException extends Exception { + + private final String message; + + public WiredSaveException(String message) { + this.message = message; + } + + @Override + public String getMessage() { + return this.message; + } +} 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 c6e299c0..e38663e7 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/Outgoing.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/Outgoing.java @@ -84,7 +84,7 @@ public class Outgoing { public final static int RoomScoreComposer = 482; public final static int DoorbellAddUserComposer = 2309; public final static int SecureLoginOKComposer = 2491; - public final static int SessionRightsComposer = 2033; + public final static int AvailabilityStatusMessageComposer = 2033; public final static int GuildMemberUpdateComposer = 265; public final static int RoomFloorItemsComposer = 1778; public final static int InventoryItemsComposer = 994; @@ -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 @@ -493,7 +493,7 @@ public class Outgoing { public final static int SimplePollAnswerComposer = 2589; - public final static int SomeConnectionComposer = 3928; + public final static int PingComposer = 3928; public final static int TradingWaitingConfirmComposer = 2720; public final static int BaseJumpJoinQueueComposer = 2260; public final static int ClubCenterDataComposer = 3277; diff --git a/src/main/java/com/eu/habbo/messages/outgoing/catalog/ClubCenterDataComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/catalog/ClubCenterDataComposer.java index 28b1472c..64e4a3f0 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/catalog/ClubCenterDataComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/catalog/ClubCenterDataComposer.java @@ -1,40 +1,54 @@ package com.eu.habbo.messages.outgoing.catalog; +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.messages.ServerMessage; import com.eu.habbo.messages.outgoing.MessageComposer; import com.eu.habbo.messages.outgoing.Outgoing; -public class ClubCenterDataComposer extends MessageComposer { - private final int streakDuration; - private final String joinDate; - private final double percentage; - private final int creditsSpend; - private final int creditsBonus; - private final int spendBonus; - private final int delay; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; - public ClubCenterDataComposer(int streakDuration, String joinDate, double percentage, int creditsSpend, int creditsBonus, int spendBonus, int delay) { - this.streakDuration = streakDuration; - this.joinDate = joinDate; - this.percentage = percentage; - this.creditsSpend = creditsSpend; - this.creditsBonus = creditsBonus; - this.spendBonus = spendBonus; - this.delay = delay; +public class ClubCenterDataComposer extends MessageComposer { + public final int currentHcStreak; + public final String firstSubDate; + public final double kickbackPercentage; + public final int totalCreditsMissed; + public final int totalCreditsRewarded; + public final int totalCreditsSpent; + public final int creditRewardForStreakBonus; + public final int creditRewardForMonthlySpent; + public final int timeUntilPayday; + + public ClubCenterDataComposer(int currentHcStreak, String firstSubDate, double kickbackPercentage, int totalCreditsMissed, int totalCreditsRewarded, int totalCreditsSpent, int creditRewardForStreakBonus, int creditRewardForMonthlySpent, int timeUntilPayday) { + this.currentHcStreak = currentHcStreak; + this.firstSubDate = firstSubDate; + this.kickbackPercentage = kickbackPercentage; + this.totalCreditsMissed = totalCreditsMissed; + this.totalCreditsRewarded = totalCreditsRewarded; + this.totalCreditsSpent = totalCreditsSpent; + this.creditRewardForStreakBonus = creditRewardForStreakBonus; + this.creditRewardForMonthlySpent = creditRewardForMonthlySpent; + this.timeUntilPayday = timeUntilPayday; } @Override protected ServerMessage composeInternal() { this.response.init(Outgoing.ClubCenterDataComposer); - this.response.appendInt(this.streakDuration); //streakduration in days - this.response.appendString(this.joinDate); //joindate - this.response.appendDouble(this.percentage); //percentage - this.response.appendInt(0); //Unused - this.response.appendInt(0); //unused - this.response.appendInt(this.creditsSpend); //Amount credits spend - this.response.appendInt(this.creditsBonus); //Credits bonus - this.response.appendInt(this.spendBonus); //Spend bonus - this.response.appendInt(this.delay); //next pay in minutes + this.response.appendInt(this.currentHcStreak); // currentHcStreak (days) + this.response.appendString(this.firstSubDate); // firstSubscriptionDate (dd-mm-yyyy) + this.response.appendDouble(this.kickbackPercentage); // kickbackPercentage (e.g. 0.1 for 10%) + this.response.appendInt(this.totalCreditsMissed); // (not used) + this.response.appendInt(this.totalCreditsRewarded); // (not used) + this.response.appendInt(this.totalCreditsSpent); + this.response.appendInt(this.creditRewardForStreakBonus); + this.response.appendInt(this.creditRewardForMonthlySpent); + this.response.appendInt(this.timeUntilPayday); // timeUntilPayday (minutes) return this.response; } + + } \ No newline at end of file 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..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 @@ -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(daysRequired); + this.response.appendBoolean(daysRequired <= daysAsHc); } } else { this.response.appendInt(0); diff --git a/src/main/java/com/eu/habbo/messages/outgoing/friends/FriendRequestErrorComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/friends/FriendRequestErrorComposer.java index 751dbc77..84ebe13b 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/friends/FriendRequestErrorComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/friends/FriendRequestErrorComposer.java @@ -6,6 +6,7 @@ import com.eu.habbo.messages.outgoing.Outgoing; public class FriendRequestErrorComposer extends MessageComposer { public static final int FRIEND_LIST_OWN_FULL = 1; + public static final int FRIEND_LIST_TARGET_FULL = 2; public static final int TARGET_NOT_ACCEPTING_REQUESTS = 3; public static final int TARGET_NOT_FOUND = 4; diff --git a/src/main/java/com/eu/habbo/messages/outgoing/friends/FriendsComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/friends/FriendsComposer.java index 0253f33f..2fd69a9a 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/friends/FriendsComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/friends/FriendsComposer.java @@ -1,24 +1,28 @@ package com.eu.habbo.messages.outgoing.friends; -import com.eu.habbo.habbohotel.messenger.Messenger; import com.eu.habbo.habbohotel.messenger.MessengerBuddy; -import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboGender; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.outgoing.MessageComposer; import com.eu.habbo.messages.outgoing.Outgoing; +import gnu.trove.set.hash.THashSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Map; +import java.util.ArrayList; +import java.util.Collection; public class FriendsComposer extends MessageComposer { private static final Logger LOGGER = LoggerFactory.getLogger(FriendsComposer.class); - private final Habbo habbo; + private final int totalPages; + private final int pageIndex; + private final Collection friends; - public FriendsComposer(Habbo habbo) { - this.habbo = habbo; + public FriendsComposer(int totalPages, int pageIndex, Collection friends) { + this.totalPages = totalPages; + this.pageIndex = pageIndex; + this.friends = friends; } @Override @@ -26,52 +30,54 @@ public class FriendsComposer extends MessageComposer { try { this.response.init(Outgoing.FriendsComposer); - //this.response.appendInt(300); - //this.response.appendInt(300); - //this.response.appendInt(3); //Club level - this.response.appendInt(this.habbo.hasPermission("acc_infinite_friends") ? Integer.MAX_VALUE : Messenger.MAXIMUM_FRIENDS); - this.response.appendInt(this.habbo.hasPermission("acc_infinite_friends") ? Integer.MAX_VALUE : Messenger.MAXIMUM_FRIENDS); - this.response.appendInt(this.habbo.getMessenger().getFriends().size()/* + (this.habbo.hasPermission("acc_staff_chat") ? 1 : 0)*/); + this.response.appendInt(this.totalPages); + this.response.appendInt(this.pageIndex); + this.response.appendInt(this.friends.size()); - for (Map.Entry row : this.habbo.getMessenger().getFriends().entrySet()) { - this.response.appendInt(row.getKey()); - this.response.appendString(row.getValue().getUsername()); - this.response.appendInt(row.getValue().getGender().equals(HabboGender.M) ? 0 : 1); - this.response.appendBoolean(row.getValue().getOnline() == 1); - this.response.appendBoolean(row.getValue().inRoom()); //IN ROOM - this.response.appendString(row.getValue().getOnline() == 1 ? row.getValue().getLook() : ""); + for (MessengerBuddy row : this.friends) { + this.response.appendInt(row.getId()); + this.response.appendString(row.getUsername()); + this.response.appendInt(row.getGender().equals(HabboGender.M) ? 0 : 1); + this.response.appendBoolean(row.getOnline() == 1); + this.response.appendBoolean(row.inRoom()); //IN ROOM + this.response.appendString(row.getOnline() == 1 ? row.getLook() : ""); this.response.appendInt(0); - this.response.appendString(row.getValue().getMotto()); + this.response.appendString(row.getMotto()); this.response.appendString(""); this.response.appendString(""); this.response.appendBoolean(false); //Offline messaging. this.response.appendBoolean(false); this.response.appendBoolean(false); - this.response.appendShort(row.getValue().getRelation()); + this.response.appendShort(row.getRelation()); } - - /*if(this.habbo.hasPermission("acc_staff_chat")) - { - this.response.appendInt(-1); - this.response.appendString("Staff Chat"); - this.response.appendInt(this.habbo.getHabboInfo().getGender().equals(HabboGender.M) ? 0 : 1); - this.response.appendBoolean(true); - this.response.appendBoolean(false); //IN ROOM - this.response.appendString("ADM"); - this.response.appendInt(0); - this.response.appendString(""); - this.response.appendString(""); - this.response.appendString(""); - this.response.appendBoolean(true); //Offline messaging. - this.response.appendBoolean(false); - this.response.appendBoolean(false); - this.response.appendShort(0); - }*/ - return this.response; } catch (Exception e) { LOGGER.error("Caught exception", e); } return null; } + + public static ArrayList getMessagesForBuddyList(Collection buddies) { + ArrayList messages = new ArrayList(); + THashSet friends = new THashSet(); + + int totalPages = (int)Math.ceil(buddies.size() / 750.0); + int page = 0; + + for(MessengerBuddy buddy : buddies) { + friends.add(buddy); + + if(friends.size() == 750) { + messages.add(new FriendsComposer(totalPages, page, friends).compose()); + friends.clear(); + page++; + } + } + + if(page == 0 || friends.size() > 0) { + messages.add(new FriendsComposer(totalPages, page, friends).compose()); + } + + return messages; + } } \ No newline at end of file diff --git a/src/main/java/com/eu/habbo/messages/outgoing/guilds/GuildFavoriteRoomUserUpdateComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/guilds/GuildFavoriteRoomUserUpdateComposer.java index 48d9c556..37df2118 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/guilds/GuildFavoriteRoomUserUpdateComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/guilds/GuildFavoriteRoomUserUpdateComposer.java @@ -19,9 +19,9 @@ public class GuildFavoriteRoomUserUpdateComposer extends MessageComposer { protected ServerMessage composeInternal() { this.response.init(Outgoing.GuildFavoriteRoomUserUpdateComposer); this.response.appendInt(this.roomUnit.getId()); - this.response.appendInt(this.guild.getId()); - this.response.appendInt(this.guild.getState().state); - this.response.appendString(this.guild.getName()); + this.response.appendInt(this.guild != null ? this.guild.getId() : 0); + this.response.appendInt(this.guild != null ? this.guild.getState().state : 3); + this.response.appendString(this.guild != null ? this.guild.getName() : ""); return this.response; } } diff --git a/src/main/java/com/eu/habbo/messages/outgoing/handshake/AvailabilityStatusMessageComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/handshake/AvailabilityStatusMessageComposer.java new file mode 100644 index 00000000..d65cc78c --- /dev/null +++ b/src/main/java/com/eu/habbo/messages/outgoing/handshake/AvailabilityStatusMessageComposer.java @@ -0,0 +1,27 @@ +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 AvailabilityStatusMessageComposer extends MessageComposer { + private final boolean isOpen; + private final boolean isShuttingDown; + private final boolean isAuthenticHabbo; + + public AvailabilityStatusMessageComposer(boolean isOpen, boolean isShuttingDown, boolean isAuthenticHabbo) { + this.isOpen = isOpen; + this.isShuttingDown = isShuttingDown; + this.isAuthenticHabbo = isAuthenticHabbo; + } + + @Override + protected ServerMessage composeInternal() { + this.response.init(Outgoing.AvailabilityStatusMessageComposer); + + this.response.appendBoolean(isOpen);//isOpen + this.response.appendBoolean(isShuttingDown);//onShutdown + this.response.appendBoolean(isAuthenticHabbo);//isAuthenticHabbo + return this.response; + } +} 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/handshake/SomeConnectionComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/handshake/PingComposer.java similarity index 70% rename from src/main/java/com/eu/habbo/messages/outgoing/handshake/SomeConnectionComposer.java rename to src/main/java/com/eu/habbo/messages/outgoing/handshake/PingComposer.java index 5a1e6724..a8300686 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/handshake/SomeConnectionComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/handshake/PingComposer.java @@ -4,10 +4,10 @@ import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.outgoing.MessageComposer; import com.eu.habbo.messages.outgoing.Outgoing; -public class SomeConnectionComposer extends MessageComposer { +public class PingComposer extends MessageComposer { @Override protected ServerMessage composeInternal() { - this.response.init(Outgoing.SomeConnectionComposer); + this.response.init(Outgoing.PingComposer); return this.response; } } \ No newline at end of file diff --git a/src/main/java/com/eu/habbo/messages/outgoing/handshake/SessionRightsComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/handshake/SessionRightsComposer.java deleted file mode 100644 index b442e4e0..00000000 --- a/src/main/java/com/eu/habbo/messages/outgoing/handshake/SessionRightsComposer.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 SessionRightsComposer extends MessageComposer { - private static final boolean unknownBooleanOne = true; //true - private static final boolean unknownBooleanTwo = false; - - @Override - protected ServerMessage composeInternal() { - this.response.init(Outgoing.SessionRightsComposer); - - this.response.appendBoolean(unknownBooleanOne); - this.response.appendBoolean(true); - this.response.appendBoolean(true); - 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/messages/outgoing/rooms/FreezeLivesComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/rooms/FreezeLivesComposer.java index 1afbc939..c4bf6d91 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/rooms/FreezeLivesComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/rooms/FreezeLivesComposer.java @@ -15,7 +15,7 @@ public class FreezeLivesComposer extends MessageComposer { @Override protected ServerMessage composeInternal() { this.response.init(Outgoing.FreezeLivesComposer); - this.response.appendInt(this.gamePlayer.getHabbo().getHabboInfo().getId()); + this.response.appendInt(this.gamePlayer.getHabbo().getRoomUnit().getId()); this.response.appendInt(this.gamePlayer.getLives()); return this.response; } diff --git a/src/main/java/com/eu/habbo/messages/outgoing/rooms/items/FloorItemOnRollerComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/rooms/items/FloorItemOnRollerComposer.java index abf2eee4..878b9490 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/rooms/items/FloorItemOnRollerComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/rooms/items/FloorItemOnRollerComposer.java @@ -8,12 +8,16 @@ import com.eu.habbo.messages.outgoing.MessageComposer; import com.eu.habbo.messages.outgoing.Outgoing; import com.eu.habbo.messages.outgoing.rooms.UpdateStackHeightComposer; import gnu.trove.set.hash.THashSet; +import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; public class FloorItemOnRollerComposer extends MessageComposer { private final HabboItem item; private final HabboItem roller; + private final RoomTile oldLocation; private final RoomTile newLocation; private final double heightOffset; + private final double oldZ; + private final double newZ; private final Room room; public FloorItemOnRollerComposer(HabboItem item, HabboItem roller, RoomTile newLocation, double heightOffset, Room room) { @@ -22,6 +26,20 @@ public class FloorItemOnRollerComposer extends MessageComposer { this.newLocation = newLocation; this.heightOffset = heightOffset; this.room = room; + this.oldLocation = null; + this.oldZ = -1; + this.newZ = -1; + } + + public FloorItemOnRollerComposer(HabboItem item, HabboItem roller, RoomTile oldLocation, double oldZ, RoomTile newLocation, double newZ, double heightOffset, Room room) { + this.item = item; + this.roller = roller; + this.oldLocation = oldLocation; + this.oldZ = oldZ; + this.newLocation = newLocation; + this.newZ = newZ; + this.heightOffset = heightOffset; + this.room = room; } @Override @@ -30,30 +48,32 @@ public class FloorItemOnRollerComposer extends MessageComposer { short oldY = this.item.getY(); this.response.init(Outgoing.ObjectOnRollerComposer); - this.response.appendInt(this.item.getX()); - this.response.appendInt(this.item.getY()); + this.response.appendInt(this.oldLocation != null ? this.oldLocation.x : this.item.getX()); + this.response.appendInt(this.oldLocation != null ? this.oldLocation.y : this.item.getY()); this.response.appendInt(this.newLocation.x); this.response.appendInt(this.newLocation.y); this.response.appendInt(1); this.response.appendInt(this.item.getId()); - this.response.appendString(Double.toString(this.item.getZ())); - this.response.appendString(Double.toString(this.item.getZ() + this.heightOffset)); + this.response.appendString(Double.toString(this.oldLocation != null ? this.oldZ : this.item.getZ())); + this.response.appendString(Double.toString(this.oldLocation != null ? this.newZ : (this.item.getZ() + this.heightOffset))); this.response.appendInt(this.roller != null ? this.roller.getId() : -1); - this.item.onMove(this.room, this.room.getLayout().getTile(this.item.getX(), this.item.getY()), this.newLocation); - this.item.setX(this.newLocation.x); - this.item.setY(this.newLocation.y); - this.item.setZ(this.item.getZ() + this.heightOffset); - this.item.needsUpdate(true); + if(this.oldLocation == null) { + this.item.onMove(this.room, this.room.getLayout().getTile(this.item.getX(), this.item.getY()), this.newLocation); + this.item.setX(this.newLocation.x); + this.item.setY(this.newLocation.y); + this.item.setZ(this.item.getZ() + this.heightOffset); + this.item.needsUpdate(true); - //TODO This is bad - // - THashSet tiles = this.room.getLayout().getTilesAt(this.room.getLayout().getTile(oldX, oldY), this.item.getBaseItem().getWidth(), this.item.getBaseItem().getLength(), this.item.getRotation()); - tiles.addAll(this.room.getLayout().getTilesAt(this.room.getLayout().getTile(this.item.getX(), this.item.getY()), this.item.getBaseItem().getWidth(), this.item.getBaseItem().getLength(), this.item.getRotation())); - this.room.updateTiles(tiles); - this.room.sendComposer(new UpdateStackHeightComposer(oldX, oldY, this.room.getStackHeight(oldX, oldY, true)).compose()); - // - //this.room.updateHabbosAt(RoomLayout.getRectangle(this.item.getX(), this.item.getY(), this.item.getBaseItem().getWidth(), this.item.getBaseItem().getLength(), this.item.getRotation())); + //TODO This is bad + // + THashSet tiles = this.room.getLayout().getTilesAt(this.room.getLayout().getTile(oldX, oldY), this.item.getBaseItem().getWidth(), this.item.getBaseItem().getLength(), this.item.getRotation()); + tiles.addAll(this.room.getLayout().getTilesAt(this.room.getLayout().getTile(this.item.getX(), this.item.getY()), this.item.getBaseItem().getWidth(), this.item.getBaseItem().getLength(), this.item.getRotation())); + this.room.updateTiles(tiles); + //this.room.sendComposer(new UpdateStackHeightComposer(oldX, oldY, this.room.getStackHeight(oldX, oldY, true)).compose()); + // + //this.room.updateHabbosAt(RoomLayout.getRectangle(this.item.getX(), this.item.getY(), this.item.getBaseItem().getWidth(), this.item.getBaseItem().getLength(), this.item.getRotation())); + } return this.response; } diff --git a/src/main/java/com/eu/habbo/messages/outgoing/rooms/users/RoomUnitOnRollerComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/rooms/users/RoomUnitOnRollerComposer.java index 863792d7..70df0b1c 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/rooms/users/RoomUnitOnRollerComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/rooms/users/RoomUnitOnRollerComposer.java @@ -5,10 +5,12 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionRoller; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomTile; import com.eu.habbo.habbohotel.rooms.RoomUnit; +import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.outgoing.MessageComposer; import com.eu.habbo.messages.outgoing.Outgoing; +import gnu.trove.set.hash.THashSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,6 +25,7 @@ public class RoomUnitOnRollerComposer extends MessageComposer { private final Room room; private int x; private int y; + private HabboItem oldTopItem; public RoomUnitOnRollerComposer(RoomUnit roomUnit, HabboItem roller, RoomTile oldLocation, double oldZ, RoomTile newLocation, double newZ, Room room) { this.roomUnit = roomUnit; @@ -32,6 +35,7 @@ public class RoomUnitOnRollerComposer extends MessageComposer { this.newLocation = newLocation; this.newZ = newZ; this.room = room; + oldTopItem = this.room.getTopItemAt(oldLocation.x, oldLocation.y); } public RoomUnitOnRollerComposer(RoomUnit roomUnit, RoomTile newLocation, Room room) { @@ -42,6 +46,7 @@ public class RoomUnitOnRollerComposer extends MessageComposer { this.newLocation = newLocation; this.newZ = this.newLocation.getStackHeight(); this.room = room; + this.oldTopItem = null; } @Override @@ -62,25 +67,53 @@ public class RoomUnitOnRollerComposer extends MessageComposer { this.response.appendString(this.newZ + ""); if (this.roller != null && room.getLayout() != null) { - RoomTile rollerTile = room.getLayout().getTile(this.roller.getX(), this.roller.getY()); - HabboItem topItem = this.room.getTopItemAt(this.roomUnit.getCurrentLocation().x, this.roomUnit.getCurrentLocation().y); - if (topItem != null) { - try { - topItem.onWalkOff(this.roomUnit, this.room, new Object[]{this}); - } catch (Exception e) { - LOGGER.error("Caught exception", e); - } - } Emulator.getThreading().run(() -> { - if (RoomUnitOnRollerComposer.this.oldLocation == rollerTile && RoomUnitOnRollerComposer.this.roomUnit.getGoal() == rollerTile) { - RoomUnitOnRollerComposer.this.roomUnit.setLocation(room.getLayout().getTile(newLocation.x, newLocation.y)); - RoomUnitOnRollerComposer.this.roomUnit.setPreviousLocationZ(RoomUnitOnRollerComposer.this.newLocation.getStackHeight()); - RoomUnitOnRollerComposer.this.roomUnit.setZ(RoomUnitOnRollerComposer.this.newLocation.getStackHeight()); - RoomUnitOnRollerComposer.this.roomUnit.sitUpdate = true; + if(!this.roomUnit.isWalking() && this.roomUnit.getCurrentLocation() == this.oldLocation) { + HabboItem topItem = this.room.getTopItemAt(this.oldLocation.x, this.oldLocation.y); + HabboItem topItemNewLocation = this.room.getTopItemAt(this.newLocation.x, this.newLocation.y); + if (topItem != null && (oldTopItem == null || oldTopItem != topItemNewLocation)) { + try { + topItem.onWalkOff(this.roomUnit, this.room, new Object[]{this}); + } catch (Exception e) { + LOGGER.error("Caught exception", e); + } + } + + this.roomUnit.setLocation(this.newLocation); + this.roomUnit.setZ(this.newLocation.getStackHeight()); + this.roomUnit.setPreviousLocationZ(this.newLocation.getStackHeight()); + + if (topItemNewLocation != null && topItemNewLocation != roller && oldTopItem != topItemNewLocation) { + try { + topItemNewLocation.onWalkOn(this.roomUnit, this.room, new Object[]{this}); + } catch (Exception e) { + LOGGER.error("Caught exception", e); + } + } } - }, this.room.getRollerSpeed() == 0 ? 250 : InteractionRoller.DELAY); + /* + RoomTile rollerTile = room.getLayout().getTile(this.roller.getX(), this.roller.getY()); + Emulator.getThreading().run(() -> { + if (this.oldLocation == rollerTile && this.roomUnit.getGoal() == rollerTile) { + this.roomUnit.setLocation(newLocation); + this.roomUnit.setGoalLocation(newLocation); + this.roomUnit.setPreviousLocationZ(newLocation.getStackHeight()); + this.roomUnit.setZ(newLocation.getStackHeight()); + this.roomUnit.sitUpdate = true; + + HabboItem topItem = this.room.getTopItemAt(this.roomUnit.getCurrentLocation().x, this.roomUnit.getCurrentLocation().y); + if (topItem != null && topItem != roller && oldTopItem != topItem) { + try { + topItem.onWalkOff(this.roomUnit, this.room, new Object[]{this}); + } catch (Exception e) { + LOGGER.error("Caught exception", e); + } + } + } + }, this.room.getRollerSpeed() == 0 ? 250 : InteractionRoller.DELAY); + */ } else { this.roomUnit.setLocation(this.newLocation); this.roomUnit.setZ(this.newZ); 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 6e5f60bc..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 @@ -2,23 +2,118 @@ 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; +import java.time.Period; +import java.util.Date; +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()); + 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(); + days = (int) Math.floor(timeRemaining / 86400.0); + minutes = (int) Math.ceil(timeRemaining / 60.0); + + if(days < 1 && minutes > 0) { + days = 1; + } + } + + 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(responseType); // responseType + this.response.appendBoolean(pastTimeAsHC > 0); // hasEverBeenMember + this.response.appendBoolean(true); // isVIP + this.response.appendInt(0); // pastClubDays + 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(); + + // int - daysToPeriodEnd + // int - memberPeriods + // int - periodsSubscribedAhead + // int - responseType + // bool - hasEverBeenMember + // bool - isVIP + // int - pastClubDays + // int - pastVIPdays + // 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(); int now = Emulator.getIntUnixTimestamp(); @@ -48,6 +143,7 @@ public class UserClubComposer extends MessageComposer { this.response.appendInt(0); this.response.appendInt(1); } + this.response.appendBoolean(true); this.response.appendBoolean(true); this.response.appendInt(0); @@ -60,6 +156,7 @@ public class UserClubComposer extends MessageComposer { } else { this.response.appendInt((int) remaining); } + */ return this.response; } 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/messages/rcon/RCONMessage.java b/src/main/java/com/eu/habbo/messages/rcon/RCONMessage.java index 8650144e..736625f7 100644 --- a/src/main/java/com/eu/habbo/messages/rcon/RCONMessage.java +++ b/src/main/java/com/eu/habbo/messages/rcon/RCONMessage.java @@ -32,6 +32,7 @@ public abstract class RCONMessage { public abstract void handle(Gson gson, T json); public static class RCONMessageSerializer implements JsonSerializer { + @Override public JsonElement serialize(final RCONMessage rconMessage, final Type type, final JsonSerializationContext context) { JsonObject result = new JsonObject(); result.add("status", new JsonPrimitive(rconMessage.status)); 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 90514484..98647cc7 100644 --- a/src/main/java/com/eu/habbo/networking/gameserver/GameServer.java +++ b/src/main/java/com/eu/habbo/networking/gameserver/GameServer.java @@ -7,9 +7,11 @@ import com.eu.habbo.networking.Server; import com.eu.habbo.networking.gameserver.decoders.*; import com.eu.habbo.networking.gameserver.encoders.GameServerMessageEncoder; import com.eu.habbo.networking.gameserver.encoders.GameServerMessageLogger; +import com.eu.habbo.networking.gameserver.handlers.IdleTimeoutHandler; import io.netty.channel.ChannelInitializer; import io.netty.channel.socket.SocketChannel; import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.timeout.IdleStateHandler; public class GameServer extends Server { private final PacketManager packetManager; @@ -38,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/decoders/GameByteDecryption.java b/src/main/java/com/eu/habbo/networking/gameserver/decoders/GameByteDecryption.java index 6881e17f..b1c91b7c 100644 --- a/src/main/java/com/eu/habbo/networking/gameserver/decoders/GameByteDecryption.java +++ b/src/main/java/com/eu/habbo/networking/gameserver/decoders/GameByteDecryption.java @@ -17,13 +17,13 @@ public class GameByteDecryption extends ByteToMessageDecoder { @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { // Read all available bytes. - byte[] data = in.readBytes(in.readableBytes()).array(); + ByteBuf data = in.readBytes(in.readableBytes()); // Decrypt. - ctx.channel().attr(GameServerAttributes.CRYPTO_CLIENT).get().parse(data); + ctx.channel().attr(GameServerAttributes.CRYPTO_CLIENT).get().parse(data.array()); // Continue in the pipeline. - out.add(Unpooled.wrappedBuffer(data)); + out.add(data); } } diff --git a/src/main/java/com/eu/habbo/networking/gameserver/decoders/GameMessageHandler.java b/src/main/java/com/eu/habbo/networking/gameserver/decoders/GameMessageHandler.java index 2da3032e..c85f3315 100644 --- a/src/main/java/com/eu/habbo/networking/gameserver/decoders/GameMessageHandler.java +++ b/src/main/java/com/eu/habbo/networking/gameserver/decoders/GameMessageHandler.java @@ -59,13 +59,13 @@ public class GameMessageHandler extends ChannelInboundHandlerAdapter { ctx.channel().close(); return; } - - if (cause instanceof TooLongFrameException) { - LOGGER.error("Disconnecting client, reason: \"" + cause.getMessage() + "\"."); - } else { - LOGGER.error("Disconnecting client, exception in GameMessageHander.", cause); + if (Emulator.getConfig().getBoolean("debug.mode")) { + if (cause instanceof TooLongFrameException) { + LOGGER.error("Disconnecting client, reason: \"" + cause.getMessage() + "\"."); + } else { + LOGGER.error("Disconnecting client, exception in GameMessageHander.", cause); + } } - ctx.channel().close(); } diff --git a/src/main/java/com/eu/habbo/networking/gameserver/encoders/GameByteEncryption.java b/src/main/java/com/eu/habbo/networking/gameserver/encoders/GameByteEncryption.java index 895addd0..0c20b977 100644 --- a/src/main/java/com/eu/habbo/networking/gameserver/encoders/GameByteEncryption.java +++ b/src/main/java/com/eu/habbo/networking/gameserver/encoders/GameByteEncryption.java @@ -6,28 +6,25 @@ import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelOutboundHandlerAdapter; import io.netty.channel.ChannelPromise; +import io.netty.util.ReferenceCountUtil; public class GameByteEncryption extends ChannelOutboundHandlerAdapter { @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - // Convert msg to ByteBuf. - ByteBuf out = (ByteBuf) msg; + // convert to Bytebuf + ByteBuf in = (ByteBuf) msg; - // Read all available bytes. - byte[] data; + // read available bytes + ByteBuf data = (in).readBytes(in.readableBytes()); - if (out.hasArray()) { - data = out.array(); - } else { - data = out.readBytes(out.readableBytes()).array(); - } + //release old object + ReferenceCountUtil.release(in); // Encrypt. - ctx.channel().attr(GameServerAttributes.CRYPTO_SERVER).get().parse(data); + ctx.channel().attr(GameServerAttributes.CRYPTO_SERVER).get().parse(data.array()); // Continue in the pipeline. - ctx.write(Unpooled.wrappedBuffer(data)); + ctx.write(data, promise); } - } 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 new file mode 100644 index 00000000..26c55666 --- /dev/null +++ b/src/main/java/com/eu/habbo/networking/gameserver/handlers/IdleTimeoutHandler.java @@ -0,0 +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 java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +public class IdleTimeoutHandler extends ChannelDuplexHandler { + 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/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 52df1e66..a7d60270 100644 --- a/src/main/java/com/eu/habbo/plugin/PluginManager.java +++ b/src/main/java/com/eu/habbo/plugin/PluginManager.java @@ -21,8 +21,11 @@ import com.eu.habbo.habbohotel.navigation.EventCategory; import com.eu.habbo.habbohotel.navigation.NavigatorManager; import com.eu.habbo.habbohotel.pets.PetManager; import com.eu.habbo.habbohotel.rooms.*; +import com.eu.habbo.habbohotel.users.clothingvalidation.ClothingValidationManager; import com.eu.habbo.habbohotel.users.HabboInventory; import com.eu.habbo.habbohotel.users.HabboManager; +import com.eu.habbo.habbohotel.users.subscriptions.SubscriptionHabboClub; +import com.eu.habbo.habbohotel.users.subscriptions.SubscriptionManager; import com.eu.habbo.habbohotel.wired.WiredHandler; import com.eu.habbo.habbohotel.wired.highscores.WiredHighscoreManager; import com.eu.habbo.messages.PacketManager; @@ -59,6 +62,7 @@ import java.net.URLClassLoader; import java.util.Arrays; import java.util.NoSuchElementException; import java.util.Objects; +import java.util.regex.Pattern; import java.util.stream.Collectors; public class PluginManager { @@ -78,6 +82,7 @@ public class PluginManager { PacketManager.DEBUG_SHOW_PACKETS = Emulator.getConfig().getBoolean("debug.show.packets"); PacketManager.MULTI_THREADED_PACKET_HANDLING = Emulator.getConfig().getBoolean("io.client.multithreaded.handler"); Room.HABBO_CHAT_DELAY = Emulator.getConfig().getBoolean("room.chat.delay", false); + Room.MUTEAREA_CAN_WHISPER = Emulator.getConfig().getBoolean("room.chat.mutearea.allow_whisper", false); RoomChatMessage.SAVE_ROOM_CHATS = Emulator.getConfig().getBoolean("save.room.chats", false); RoomLayout.MAXIMUM_STEP_HEIGHT = Emulator.getConfig().getDouble("pathfinder.step.maximum.height", 1.1); RoomLayout.ALLOW_FALLING = Emulator.getConfig().getBoolean("pathfinder.step.allow.falling", true); @@ -97,8 +102,8 @@ public class PluginManager { Bot.PLACEMENT_MESSAGES = Emulator.getConfig().getValue("hotel.bot.placement.messages", "Yo!;Hello I'm a real party animal!;Hello!").split(";"); HabboInventory.MAXIMUM_ITEMS = Emulator.getConfig().getInt("hotel.inventory.max.items"); - Messenger.MAXIMUM_FRIENDS = Emulator.getConfig().getInt("hotel.max.friends"); - Messenger.MAXIMUM_FRIENDS_HC = Emulator.getConfig().getInt("hotel.max.friends.hc"); + Messenger.MAXIMUM_FRIENDS = Emulator.getConfig().getInt("hotel.users.max.friends", 300); + Messenger.MAXIMUM_FRIENDS_HC = Emulator.getConfig().getInt("hotel.users.max.friends.hc", 1100); Room.MAXIMUM_BOTS = Emulator.getConfig().getInt("hotel.max.bots.room"); Room.MAXIMUM_PETS = Emulator.getConfig().getInt("hotel.pets.max.room"); Room.MAXIMUM_FURNI = Emulator.getConfig().getInt("hotel.room.furni.max", 2500); @@ -107,8 +112,8 @@ public class PluginManager { Room.IDLE_CYCLES = Emulator.getConfig().getInt("hotel.roomuser.idle.cycles", 240); Room.IDLE_CYCLES_KICK = Emulator.getConfig().getInt("hotel.roomuser.idle.cycles.kick", 480); Room.ROLLERS_MAXIMUM_ROLL_AVATARS = Emulator.getConfig().getInt("hotel.room.rollers.roll_avatars.max", 1); - RoomManager.MAXIMUM_ROOMS_VIP = Emulator.getConfig().getInt("hotel.max.rooms.vip"); - RoomManager.MAXIMUM_ROOMS_USER = Emulator.getConfig().getInt("hotel.max.rooms.user"); + RoomManager.MAXIMUM_ROOMS_USER = Emulator.getConfig().getInt("hotel.users.max.rooms", 50); + RoomManager.MAXIMUM_ROOMS_HC = Emulator.getConfig().getInt("hotel.users.max.rooms.hc", 75); RoomManager.HOME_ROOM_ID = Emulator.getConfig().getInt("hotel.home.room"); WiredHandler.MAXIMUM_FURNI_SELECTION = Emulator.getConfig().getInt("hotel.wired.furni.selection.count"); WiredHandler.TELEPORT_DELAY = Emulator.getConfig().getInt("wired.effect.teleport.delay", 500); @@ -162,6 +167,52 @@ public class PluginManager { PetManager.MAXIMUM_PET_INVENTORY_SIZE = Emulator.getConfig().getInt("hotel.pets.max.inventory"); + SubscriptionHabboClub.HC_PAYDAY_ENABLED = Emulator.getConfig().getBoolean("subscriptions.hc.payday.enabled", false); + + try { + SubscriptionHabboClub.HC_PAYDAY_NEXT_DATE = (int) (Emulator.stringToDate(Emulator.getConfig().getValue("subscriptions.hc.payday.next_date")).getTime() / 1000); + } + catch(Exception e) { SubscriptionHabboClub.HC_PAYDAY_NEXT_DATE = Integer.MAX_VALUE; } + + SubscriptionHabboClub.HC_PAYDAY_INTERVAL = Emulator.getConfig().getValue("subscriptions.hc.payday.interval"); + SubscriptionHabboClub.HC_PAYDAY_QUERY = Emulator.getConfig().getValue("subscriptions.hc.payday.query"); + 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(";"))) { + if(streak.contains("=")) { + SubscriptionHabboClub.HC_PAYDAY_STREAK.put(Integer.parseInt(streak.split(Pattern.quote("="))[0]), Integer.parseInt(streak.split(Pattern.quote("="))[1])); + } + } + + ClothingValidationManager.VALIDATE_ON_HC_EXPIRE = Emulator.getConfig().getBoolean("hotel.users.clothingvalidation.onhcexpired", false); + ClothingValidationManager.VALIDATE_ON_LOGIN = Emulator.getConfig().getBoolean("hotel.users.clothingvalidation.onlogin", false); + ClothingValidationManager.VALIDATE_ON_CHANGE_LOOKS = Emulator.getConfig().getBoolean("hotel.users.clothingvalidation.onchangelooks", false); + ClothingValidationManager.VALIDATE_ON_MIMIC = Emulator.getConfig().getBoolean("hotel.users.clothingvalidation.onmimic", false); + ClothingValidationManager.VALIDATE_ON_MANNEQUIN = Emulator.getConfig().getBoolean("hotel.users.clothingvalidation.onmannequin", false); + ClothingValidationManager.VALIDATE_ON_FBALLGATE = Emulator.getConfig().getBoolean("hotel.users.clothingvalidation.onfballgate", false); + + String newUrl = Emulator.getConfig().getValue("gamedata.figuredata.url"); + if(!ClothingValidationManager.FIGUREDATA_URL.equals(newUrl)) { + ClothingValidationManager.FIGUREDATA_URL = newUrl; + ClothingValidationManager.reloadFiguredata(newUrl); + } + + if(newUrl.isEmpty()) { + ClothingValidationManager.VALIDATE_ON_HC_EXPIRE = false; + ClothingValidationManager.VALIDATE_ON_LOGIN = false; + ClothingValidationManager.VALIDATE_ON_CHANGE_LOOKS = false; + ClothingValidationManager.VALIDATE_ON_MIMIC = false; + ClothingValidationManager.VALIDATE_ON_MANNEQUIN = false; + ClothingValidationManager.VALIDATE_ON_FBALLGATE = false; + } + + NewNavigatorEventCategoriesComposer.CATEGORIES.clear(); for (String category : Emulator.getConfig().getValue("navigator.eventcategories", "").split(";")) { try { @@ -179,6 +230,7 @@ public class PluginManager { Emulator.getGameEnvironment().getPointsScheduler().reloadConfig(); Emulator.getGameEnvironment().getPixelScheduler().reloadConfig(); Emulator.getGameEnvironment().getGotwPointsScheduler().reloadConfig(); + Emulator.getGameEnvironment().subscriptionScheduler.reloadConfig(); } } diff --git a/src/main/java/com/eu/habbo/plugin/events/furniture/FurnitureMovedEvent.java b/src/main/java/com/eu/habbo/plugin/events/furniture/FurnitureMovedEvent.java index 13ce67e0..cbf4e1e5 100644 --- a/src/main/java/com/eu/habbo/plugin/events/furniture/FurnitureMovedEvent.java +++ b/src/main/java/com/eu/habbo/plugin/events/furniture/FurnitureMovedEvent.java @@ -7,9 +7,8 @@ import com.eu.habbo.habbohotel.users.HabboItem; public class FurnitureMovedEvent extends FurnitureUserEvent { public final RoomTile oldPosition; - - public final RoomTile newPosition; + private boolean pluginHelper; public FurnitureMovedEvent(HabboItem furniture, Habbo habbo, RoomTile oldPosition, RoomTile newPosition) { @@ -17,5 +16,14 @@ public class FurnitureMovedEvent extends FurnitureUserEvent { this.oldPosition = oldPosition; this.newPosition = newPosition; + this.pluginHelper = false; + } + + public void setPluginHelper(boolean helper) { + this.pluginHelper = helper; + } + + public boolean hasPluginHelper() { + return this.pluginHelper; } } diff --git a/src/main/java/com/eu/habbo/plugin/events/furniture/FurniturePlacedEvent.java b/src/main/java/com/eu/habbo/plugin/events/furniture/FurniturePlacedEvent.java index 10308ebb..6af5747e 100644 --- a/src/main/java/com/eu/habbo/plugin/events/furniture/FurniturePlacedEvent.java +++ b/src/main/java/com/eu/habbo/plugin/events/furniture/FurniturePlacedEvent.java @@ -7,11 +7,20 @@ import com.eu.habbo.habbohotel.users.HabboItem; public class FurniturePlacedEvent extends FurnitureUserEvent { public final RoomTile location; - + private boolean pluginHelper; public FurniturePlacedEvent(HabboItem furniture, Habbo habbo, RoomTile location) { super(furniture, habbo); this.location = location; + this.pluginHelper = false; + } + + public void setPluginHelper(boolean helper) { + this.pluginHelper = helper; + } + + public boolean hasPluginHelper() { + return this.pluginHelper; } } diff --git a/src/main/java/com/eu/habbo/plugin/events/furniture/FurnitureRedeemedEvent.java b/src/main/java/com/eu/habbo/plugin/events/furniture/FurnitureRedeemedEvent.java index dbf63128..ce2dd0dc 100644 --- a/src/main/java/com/eu/habbo/plugin/events/furniture/FurnitureRedeemedEvent.java +++ b/src/main/java/com/eu/habbo/plugin/events/furniture/FurnitureRedeemedEvent.java @@ -4,17 +4,13 @@ import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboItem; public class FurnitureRedeemedEvent extends FurnitureUserEvent { - public static final int CREDITS = 0; - public static final int PIXELS = 1; + public static final int CREDITS = -1; + public static final int PIXELS = 0; public static final int DIAMONDS = 5; - public final int amount; - - public final int currencyID; - public FurnitureRedeemedEvent(HabboItem furniture, Habbo habbo, int amount, int currencyID) { super(furniture, habbo); diff --git a/src/main/java/com/eu/habbo/plugin/events/furniture/FurnitureStackHeightEvent.java b/src/main/java/com/eu/habbo/plugin/events/furniture/FurnitureStackHeightEvent.java new file mode 100644 index 00000000..80bb8e82 --- /dev/null +++ b/src/main/java/com/eu/habbo/plugin/events/furniture/FurnitureStackHeightEvent.java @@ -0,0 +1,37 @@ +package com.eu.habbo.plugin.events.furniture; + +import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.plugin.Event; + +public class FurnitureStackHeightEvent extends Event { + + public final short x; + public final short y; + public final Room room; + private boolean pluginHelper; + private Double height; + + public FurnitureStackHeightEvent(short x, short y, Room room) { + this.x = x; + this.y = y; + this.room = room; + this.pluginHelper = false; + this.height = 0.0D; + } + + public void setPluginHelper(boolean helper) { + this.pluginHelper = helper; + } + + public boolean hasPluginHelper() { + return this.pluginHelper; + } + + public void setHeight(Double height) { + this.height = height; + } + + public Double getHeight() { + return this.height; + } +} diff --git a/src/main/java/com/eu/habbo/plugin/events/furniture/FurnitureToggleEvent.java b/src/main/java/com/eu/habbo/plugin/events/furniture/FurnitureToggleEvent.java new file mode 100644 index 00000000..01dd9c92 --- /dev/null +++ b/src/main/java/com/eu/habbo/plugin/events/furniture/FurnitureToggleEvent.java @@ -0,0 +1,14 @@ +package com.eu.habbo.plugin.events.furniture; + +import com.eu.habbo.habbohotel.users.Habbo; +import com.eu.habbo.habbohotel.users.HabboItem; + +public class FurnitureToggleEvent extends FurnitureUserEvent { + public int state; + + public FurnitureToggleEvent(HabboItem furniture, Habbo habbo, int state) { + super(furniture, habbo); + + this.state = state; + } +} diff --git a/src/main/java/com/eu/habbo/plugin/events/trading/TradeConfirmEvent.java b/src/main/java/com/eu/habbo/plugin/events/trading/TradeConfirmEvent.java new file mode 100644 index 00000000..ee42fd2f --- /dev/null +++ b/src/main/java/com/eu/habbo/plugin/events/trading/TradeConfirmEvent.java @@ -0,0 +1,14 @@ +package com.eu.habbo.plugin.events.trading; + +import com.eu.habbo.habbohotel.rooms.RoomTradeUser; +import com.eu.habbo.plugin.Event; + +public class TradeConfirmEvent extends Event { + public final RoomTradeUser userOne; + public final RoomTradeUser userTwo; + + public TradeConfirmEvent(RoomTradeUser userOne, RoomTradeUser userTwo) { + this.userOne = userOne; + this.userTwo = userTwo; + } +} diff --git a/src/main/java/com/eu/habbo/plugin/events/users/UserExecuteCommandEvent.java b/src/main/java/com/eu/habbo/plugin/events/users/UserExecuteCommandEvent.java index b70999e4..2da7d345 100644 --- a/src/main/java/com/eu/habbo/plugin/events/users/UserExecuteCommandEvent.java +++ b/src/main/java/com/eu/habbo/plugin/events/users/UserExecuteCommandEvent.java @@ -6,15 +6,22 @@ import com.eu.habbo.habbohotel.users.Habbo; public class UserExecuteCommandEvent extends UserEvent { public final Command command; - - public final String[] params; - + private boolean success; public UserExecuteCommandEvent(Habbo habbo, Command command, String[] params) { super(habbo); this.command = command; this.params = params; + this.success = true; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public boolean isSuccess() { + return success; } } diff --git a/src/main/java/com/eu/habbo/plugin/events/users/UserGetIPAddressEvent.java b/src/main/java/com/eu/habbo/plugin/events/users/UserGetIPAddressEvent.java new file mode 100644 index 00000000..c77b3639 --- /dev/null +++ b/src/main/java/com/eu/habbo/plugin/events/users/UserGetIPAddressEvent.java @@ -0,0 +1,28 @@ +package com.eu.habbo.plugin.events.users; + +import com.eu.habbo.habbohotel.users.Habbo; + +public class UserGetIPAddressEvent extends UserEvent{ + public final String oldIp; + + private String updatedIp; + private boolean changedIP = false; + + public UserGetIPAddressEvent(Habbo habbo, String ip) { + super(habbo); + this.oldIp = ip; + } + + public void setUpdatedIp(String updatedIp) { + this.updatedIp = updatedIp; + this.changedIP = true; + } + + public boolean hasChangedIP() { + return changedIP; + } + + public String getUpdatedIp() { + return updatedIp; + } +} diff --git a/src/main/java/com/eu/habbo/plugin/events/users/UserLoginEvent.java b/src/main/java/com/eu/habbo/plugin/events/users/UserLoginEvent.java index 15268bcb..d864a5fb 100644 --- a/src/main/java/com/eu/habbo/plugin/events/users/UserLoginEvent.java +++ b/src/main/java/com/eu/habbo/plugin/events/users/UserLoginEvent.java @@ -6,10 +6,9 @@ import java.net.SocketAddress; public class UserLoginEvent extends UserEvent { - public final SocketAddress ip; + public final String ip; - - public UserLoginEvent(Habbo habbo, SocketAddress ip) { + public UserLoginEvent(Habbo habbo, String ip) { super(habbo); this.ip = ip; diff --git a/src/main/java/com/eu/habbo/plugin/events/users/subscriptions/UserSubscriptionCreatedEvent.java b/src/main/java/com/eu/habbo/plugin/events/users/subscriptions/UserSubscriptionCreatedEvent.java new file mode 100644 index 00000000..6a6ce5ee --- /dev/null +++ b/src/main/java/com/eu/habbo/plugin/events/users/subscriptions/UserSubscriptionCreatedEvent.java @@ -0,0 +1,17 @@ +package com.eu.habbo.plugin.events.users.subscriptions; + +import com.eu.habbo.plugin.Event; + +public class UserSubscriptionCreatedEvent extends Event { + public final int userId; + public final String subscriptionType; + public final int duration; + + public UserSubscriptionCreatedEvent(int userId, String subscriptionType, int duration) { + super(); + + this.userId = userId; + this.subscriptionType = subscriptionType; + this.duration = duration; + } +} diff --git a/src/main/java/com/eu/habbo/plugin/events/users/subscriptions/UserSubscriptionExpiredEvent.java b/src/main/java/com/eu/habbo/plugin/events/users/subscriptions/UserSubscriptionExpiredEvent.java new file mode 100644 index 00000000..7090066c --- /dev/null +++ b/src/main/java/com/eu/habbo/plugin/events/users/subscriptions/UserSubscriptionExpiredEvent.java @@ -0,0 +1,16 @@ +package com.eu.habbo.plugin.events.users.subscriptions; + +import com.eu.habbo.habbohotel.users.subscriptions.Subscription; +import com.eu.habbo.plugin.Event; + +public class UserSubscriptionExpiredEvent extends Event { + public final int userId; + public final Subscription subscription; + + public UserSubscriptionExpiredEvent(int userId, Subscription subscription) { + super(); + + this.userId = userId; + this.subscription = subscription; + } +} diff --git a/src/main/java/com/eu/habbo/plugin/events/users/subscriptions/UserSubscriptionExtendedEvent.java b/src/main/java/com/eu/habbo/plugin/events/users/subscriptions/UserSubscriptionExtendedEvent.java new file mode 100644 index 00000000..3e1c24e0 --- /dev/null +++ b/src/main/java/com/eu/habbo/plugin/events/users/subscriptions/UserSubscriptionExtendedEvent.java @@ -0,0 +1,17 @@ +package com.eu.habbo.plugin.events.users.subscriptions; + +import com.eu.habbo.habbohotel.users.subscriptions.Subscription; +import com.eu.habbo.plugin.Event; + +public class UserSubscriptionExtendedEvent extends Event { + public final int userId; + public final Subscription subscription; + public final int duration; + + public UserSubscriptionExtendedEvent(int userId, Subscription subscription, int duration) { + super(); + this.userId = userId; + this.subscription = subscription; + this.duration = duration; + } +} diff --git a/src/main/java/com/eu/habbo/threading/runnables/BanzaiRandomTeleport.java b/src/main/java/com/eu/habbo/threading/runnables/BanzaiRandomTeleport.java index c372652a..d559daed 100644 --- a/src/main/java/com/eu/habbo/threading/runnables/BanzaiRandomTeleport.java +++ b/src/main/java/com/eu/habbo/threading/runnables/BanzaiRandomTeleport.java @@ -2,9 +2,11 @@ package com.eu.habbo.threading.runnables; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.habbohotel.rooms.RoomTile; import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.rooms.RoomUserRotation; import com.eu.habbo.habbohotel.users.HabboItem; +import org.slf4j.LoggerFactory; public class BanzaiRandomTeleport implements Runnable { private final HabboItem item; @@ -21,12 +23,52 @@ public class BanzaiRandomTeleport implements Runnable { @Override public void run() { - this.habbo.setCanWalk(true); - this.item.setExtradata("0"); - this.toItem.setExtradata("0"); - this.room.updateItem(this.item); - this.room.updateItem(this.toItem); - this.habbo.setRotation(RoomUserRotation.fromValue(Emulator.getRandom().nextInt(8))); - this.room.teleportRoomUnitToItem(this.habbo, this.toItem); + HabboItem topItemNow = this.room.getTopItemAt(this.habbo.getX(), this.habbo.getY()); + RoomTile lastLocation = this.habbo.getCurrentLocation(); + RoomTile newLocation = this.room.getLayout().getTile(toItem.getX(), toItem.getY()); + + if(topItemNow != null) { + try { + topItemNow.onWalkOff(this.habbo, this.room, new Object[] { lastLocation, newLocation, this }); + } catch (Exception e) { + LoggerFactory.getLogger(BanzaiRandomTeleport.class).error("BanzaiRandomTeleport exception", e); + } + } + + Emulator.getThreading().run(() -> { + if (this.item.getExtradata().equals("1")) { + this.item.setExtradata("0"); + this.room.updateItemState(this.item); + } + }, 500); + + if(!this.toItem.getExtradata().equals("1")) { + this.toItem.setExtradata("1"); + this.room.updateItemState(this.toItem); + } + + Emulator.getThreading().run(() -> { + this.habbo.setCanWalk(true); + HabboItem topItemNext = this.room.getTopItemAt(this.habbo.getX(), this.habbo.getY()); + + if(topItemNext != null) { + try { + topItemNext.onWalkOn(this.habbo, this.room, new Object[] { lastLocation, newLocation, this }); + } catch (Exception e) { + LoggerFactory.getLogger(BanzaiRandomTeleport.class).error("BanzaiRandomTeleport exception", e); + } + } + + if (this.toItem.getExtradata().equals("1")) { + this.toItem.setExtradata("0"); + this.room.updateItemState(this.toItem); + } + }, 750); + + Emulator.getThreading().run(() -> { + this.habbo.setRotation(RoomUserRotation.fromValue(Emulator.getRandom().nextInt(8))); + this.room.teleportRoomUnitToLocation(this.habbo, newLocation.x, newLocation.y, newLocation.getStackHeight()); + }, 250); + } } diff --git a/src/main/java/com/eu/habbo/threading/runnables/BattleBanzaiTilesFlicker.java b/src/main/java/com/eu/habbo/threading/runnables/BattleBanzaiTilesFlicker.java index 77eb02ef..0993c1b3 100644 --- a/src/main/java/com/eu/habbo/threading/runnables/BattleBanzaiTilesFlicker.java +++ b/src/main/java/com/eu/habbo/threading/runnables/BattleBanzaiTilesFlicker.java @@ -41,7 +41,7 @@ public class BattleBanzaiTilesFlicker implements Runnable { this.room.sendComposer(new ItemsDataUpdateComposer(this.items).compose()); - if (this.count == 5) { + if (this.count == 9) { for (HabboItem item : this.room.getRoomSpecialTypes().getItemsOfType(InteractionBattleBanzaiSphere.class)) { item.setExtradata("0"); this.room.updateItemState(item); diff --git a/src/main/java/com/eu/habbo/threading/runnables/BotFollowHabbo.java b/src/main/java/com/eu/habbo/threading/runnables/BotFollowHabbo.java index b6926f62..11642074 100644 --- a/src/main/java/com/eu/habbo/threading/runnables/BotFollowHabbo.java +++ b/src/main/java/com/eu/habbo/threading/runnables/BotFollowHabbo.java @@ -5,16 +5,20 @@ import com.eu.habbo.habbohotel.bots.Bot; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomTile; import com.eu.habbo.habbohotel.users.Habbo; +import com.eu.habbo.habbohotel.wired.WiredHandler; +import com.eu.habbo.habbohotel.wired.WiredTriggerType; public class BotFollowHabbo implements Runnable { private final Bot bot; private final Habbo habbo; private final Room room; + private boolean hasReached; public BotFollowHabbo(Bot bot, Habbo habbo, Room room) { this.bot = bot; this.habbo = habbo; this.room = room; + this.hasReached = false; } @Override @@ -30,6 +34,16 @@ public class BotFollowHabbo implements Runnable { if (target.x < 0 || target.y < 0) target = this.room.getLayout().getTileInFront(this.habbo.getRoomUnit().getCurrentLocation(), this.habbo.getRoomUnit().getBodyRotation().getValue()); + if(this.habbo.getRoomUnit().getCurrentLocation().distance(this.bot.getRoomUnit().getCurrentLocation()) < 2) { + if(!hasReached) { + WiredHandler.handle(WiredTriggerType.BOT_REACHED_AVTR, bot.getRoomUnit(), room, new Object[]{}); + hasReached = true; + } + } + else { + hasReached = false; + } + if (target.x >= 0 && target.y >= 0) { this.bot.getRoomUnit().setGoalLocation(target); this.bot.getRoomUnit().setCanWalk(true); diff --git a/src/main/java/com/eu/habbo/threading/runnables/CloseGate.java b/src/main/java/com/eu/habbo/threading/runnables/CloseGate.java index f63e6f47..1637bc7f 100644 --- a/src/main/java/com/eu/habbo/threading/runnables/CloseGate.java +++ b/src/main/java/com/eu/habbo/threading/runnables/CloseGate.java @@ -4,22 +4,22 @@ import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.users.HabboItem; public class CloseGate implements Runnable { - private final HabboItem guildGate; + private final HabboItem gate; private final Room room; - public CloseGate(HabboItem guildGate, Room room) { - this.guildGate = guildGate; + public CloseGate(HabboItem gate, Room room) { + this.gate = gate; this.room = room; } @Override public void run() { - if (this.guildGate.getRoomId() == this.room.getId()) { + if (this.gate.getRoomId() == this.room.getId()) { if (this.room.isLoaded()) { - if (this.room.getHabbosAt(this.guildGate.getX(), this.guildGate.getY()).isEmpty()) { - this.guildGate.setExtradata("0"); - this.room.updateItem(this.guildGate); - this.guildGate.needsUpdate(true); + if (this.room.getHabbosAt(this.gate.getX(), this.gate.getY()).isEmpty()) { + this.gate.setExtradata("0"); + this.room.updateItem(this.gate); + this.gate.needsUpdate(true); } } } diff --git a/src/main/java/com/eu/habbo/threading/runnables/KickBallAction.java b/src/main/java/com/eu/habbo/threading/runnables/KickBallAction.java index d4f5b1bf..0bc85056 100644 --- a/src/main/java/com/eu/habbo/threading/runnables/KickBallAction.java +++ b/src/main/java/com/eu/habbo/threading/runnables/KickBallAction.java @@ -18,14 +18,16 @@ public class KickBallAction implements Runnable { public boolean dead = false; //When true the run() function will not execute. Used when another user kicks the ball whilst it is arleady moving. private RoomUserRotation currentDirection; //The current direction the item is moving in private int currentStep; //The current step of the move sequence + public final boolean isDrag; - public KickBallAction(InteractionPushable ball, Room room, RoomUnit kicker, RoomUserRotation direction, int steps) { + public KickBallAction(InteractionPushable ball, Room room, RoomUnit kicker, RoomUserRotation direction, int steps, boolean isDrag) { this.ball = ball; this.room = room; this.kicker = kicker; this.currentDirection = direction; this.totalSteps = steps; this.currentStep = 0; + this.isDrag = isDrag; } @Override @@ -39,7 +41,10 @@ public class KickBallAction implements Runnable { if (next == null || !this.ball.validMove(this.room, this.room.getLayout().getTile(this.ball.getX(), this.ball.getY()), next)) { RoomUserRotation oldDirection = this.currentDirection; - this.currentDirection = this.ball.getBounceDirection(this.room, this.currentDirection); + + if(!this.isDrag) { + this.currentDirection = this.ball.getBounceDirection(this.room, this.currentDirection); + } if (this.currentDirection != oldDirection) { this.ball.onBounce(this.room, oldDirection, this.currentDirection, this.kicker); diff --git a/src/main/java/com/eu/habbo/threading/runnables/RoomUnitTeleport.java b/src/main/java/com/eu/habbo/threading/runnables/RoomUnitTeleport.java index 9228596a..9cbe83c6 100644 --- a/src/main/java/com/eu/habbo/threading/runnables/RoomUnitTeleport.java +++ b/src/main/java/com/eu/habbo/threading/runnables/RoomUnitTeleport.java @@ -30,15 +30,15 @@ public class RoomUnitTeleport implements Runnable { this.y = y; this.z = z; this.newEffect = newEffect; - roomUnit.isWiredTeleporting = true; } @Override public void run() { - if (roomUnit == null || roomUnit.getRoom() == null || room.getLayout() == null) + if (roomUnit == null || roomUnit.getRoom() == null || room.getLayout() == null || roomUnit.isLeavingTeleporter) return; - - RoomTile t = this.room.getLayout().getTile((short) this.x, (short) this.y); + + RoomTile lastLocation = this.roomUnit.getCurrentLocation(); + RoomTile newLocation = this.room.getLayout().getTile((short) this.x, (short) this.y); HabboItem topItem = this.room.getTopItemAt(this.roomUnit.getCurrentLocation().x, this.roomUnit.getCurrentLocation().y); if (topItem != null) { @@ -49,23 +49,24 @@ public class RoomUnitTeleport implements Runnable { } } this.roomUnit.setPath(new LinkedList<>()); - this.roomUnit.setCurrentLocation(t); - this.roomUnit.setPreviousLocation(t); + this.roomUnit.setCurrentLocation(newLocation); + this.roomUnit.setPreviousLocation(newLocation); this.roomUnit.setZ(this.z); this.roomUnit.setPreviousLocationZ(this.z); this.roomUnit.removeStatus(RoomUnitStatus.MOVE); - ServerMessage teleportMessage = new RoomUnitOnRollerComposer(this.roomUnit, t, this.room).compose(); - this.roomUnit.setLocation(t); - this.room.sendComposer(teleportMessage); + //ServerMessage teleportMessage = new RoomUnitOnRollerComposer(this.roomUnit, newLocation, this.room).compose(); + this.roomUnit.setLocation(newLocation); + //this.room.sendComposer(teleportMessage); + this.roomUnit.statusUpdate(true); roomUnit.isWiredTeleporting = false; - this.room.updateHabbosAt(t.x, t.y); - this.room.updateBotsAt(t.x, t.y); + this.room.updateHabbosAt(newLocation.x, newLocation.y); + this.room.updateBotsAt(newLocation.x, newLocation.y); topItem = room.getTopItemAt(x, y); if (topItem != null && roomUnit.getCurrentLocation().equals(room.getLayout().getTile((short) x, (short) y))) { try { - topItem.onWalkOn(roomUnit, room, new Object[]{}); + topItem.onWalkOn(roomUnit, room, new Object[]{ lastLocation, newLocation, this }); } catch (Exception e) { } } diff --git a/src/main/java/com/eu/habbo/threading/runnables/RoomUnitWalkToLocation.java b/src/main/java/com/eu/habbo/threading/runnables/RoomUnitWalkToLocation.java index 7a648ff0..a2f65db7 100644 --- a/src/main/java/com/eu/habbo/threading/runnables/RoomUnitWalkToLocation.java +++ b/src/main/java/com/eu/habbo/threading/runnables/RoomUnitWalkToLocation.java @@ -4,6 +4,7 @@ import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.rooms.RoomTile; import com.eu.habbo.habbohotel.rooms.RoomUnit; +import com.eu.habbo.habbohotel.rooms.RoomUnitStatus; import java.util.ArrayList; import java.util.List; @@ -47,7 +48,7 @@ public class RoomUnitWalkToLocation implements Runnable { return; } - if (!this.walker.getGoal().equals(this.goalTile)) { + if (!this.walker.getGoal().equals(this.goalTile) || (this.walker.getPath().size() == 0 && !this.walker.hasStatus(RoomUnitStatus.MOVE))) { onFail(); return; } diff --git a/src/main/java/com/eu/habbo/threading/runnables/RoomUnitWalkToRoomUnit.java b/src/main/java/com/eu/habbo/threading/runnables/RoomUnitWalkToRoomUnit.java index 296490e7..3ff6ae37 100644 --- a/src/main/java/com/eu/habbo/threading/runnables/RoomUnitWalkToRoomUnit.java +++ b/src/main/java/com/eu/habbo/threading/runnables/RoomUnitWalkToRoomUnit.java @@ -42,17 +42,15 @@ public class RoomUnitWalkToRoomUnit implements Runnable { if (this.goalTile == null) { this.findNewLocation(); Emulator.getThreading().run(this, 500); - } - - if (this.goalTile == null) return; + } if (this.walker.getGoal().equals(this.goalTile)) { // check that the action hasn't been cancelled by changing the goal if (this.walker.getCurrentLocation().distance(this.goalTile) <= this.minDistance) { for (Runnable r : this.targetReached) { Emulator.getThreading().run(r); - WiredHandler.handle(WiredTriggerType.BOT_REACHED_AVTR, this.target, this.room, new Object[]{this.walker}); + WiredHandler.handle(WiredTriggerType.BOT_REACHED_AVTR, this.target, this.room, new Object[]{ this.walker }); } } else { Emulator.getThreading().run(this, 500); 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); + } +} diff --git a/src/main/java/com/eu/habbo/threading/runnables/teleport/TeleportActionFive.java b/src/main/java/com/eu/habbo/threading/runnables/teleport/TeleportActionFive.java index 674dfba3..9072a33d 100644 --- a/src/main/java/com/eu/habbo/threading/runnables/teleport/TeleportActionFive.java +++ b/src/main/java/com/eu/habbo/threading/runnables/teleport/TeleportActionFive.java @@ -3,11 +3,10 @@ package com.eu.habbo.threading.runnables.teleport; import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.gameclients.GameClient; import com.eu.habbo.habbohotel.items.interactions.InteractionTeleportTile; -import com.eu.habbo.habbohotel.rooms.Room; -import com.eu.habbo.habbohotel.rooms.RoomTile; -import com.eu.habbo.habbohotel.rooms.RoomUnit; +import com.eu.habbo.habbohotel.rooms.*; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboItem; +import com.eu.habbo.messages.outgoing.rooms.users.RoomUserStatusComposer; import com.eu.habbo.threading.runnables.HabboItemNewState; import com.eu.habbo.threading.runnables.RoomUnitWalkToLocation; @@ -29,6 +28,7 @@ class TeleportActionFive implements Runnable { public void run() { RoomUnit unit = this.client.getHabbo().getRoomUnit(); + unit.isLeavingTeleporter = false; unit.isTeleporting = false; unit.setCanWalk(true); @@ -46,11 +46,16 @@ class TeleportActionFive implements Runnable { List onSuccess = new ArrayList(); onSuccess.add(() -> { unit.setCanLeaveRoomByDoor(true); + + Emulator.getThreading().run(() -> { + unit.isLeavingTeleporter = false; + }, 300); }); unit.setCanLeaveRoomByDoor(false); unit.setGoalLocation(tile); unit.statusUpdate(true); + unit.isLeavingTeleporter = true; Emulator.getThreading().run(new RoomUnitWalkToLocation(unit, tile, room, onSuccess, onSuccess)); } diff --git a/src/main/java/com/eu/habbo/threading/runnables/teleport/TeleportActionFour.java b/src/main/java/com/eu/habbo/threading/runnables/teleport/TeleportActionFour.java index cd2adb5f..6379fa98 100644 --- a/src/main/java/com/eu/habbo/threading/runnables/teleport/TeleportActionFour.java +++ b/src/main/java/com/eu/habbo/threading/runnables/teleport/TeleportActionFour.java @@ -25,6 +25,10 @@ class TeleportActionFour implements Runnable { return; } + if(this.client.getHabbo().getRoomUnit() != null) { + this.client.getHabbo().getRoomUnit().isLeavingTeleporter = true; + } + Emulator.getThreading().run(new TeleportActionFive(this.currentTeleport, this.room, this.client), 500); } } diff --git a/src/main/java/com/eu/habbo/threading/runnables/teleport/TeleportActionThree.java b/src/main/java/com/eu/habbo/threading/runnables/teleport/TeleportActionThree.java index 2a54060a..521c2f54 100644 --- a/src/main/java/com/eu/habbo/threading/runnables/teleport/TeleportActionThree.java +++ b/src/main/java/com/eu/habbo/threading/runnables/teleport/TeleportActionThree.java @@ -54,15 +54,17 @@ class TeleportActionThree implements Runnable { this.client.getHabbo().getRoomUnit().setLocation(teleportLocation); this.client.getHabbo().getRoomUnit().getPath().clear(); this.client.getHabbo().getRoomUnit().removeStatus(RoomUnitStatus.MOVE); - this.client.getHabbo().getRoomUnit().setZ(targetTeleport.getZ()); - this.client.getHabbo().getRoomUnit().setPreviousLocationZ(targetTeleport.getZ()); - this.client.getHabbo().getRoomUnit().setRotation(RoomUserRotation.values()[targetTeleport.getRotation() % 8]); + this.client.getHabbo().getRoomUnit().setZ(teleportLocation.getStackHeight()); + this.client.getHabbo().getRoomUnit().setPreviousLocationZ(teleportLocation.getStackHeight()); if (targetRoom != this.room) { this.room.removeHabbo(this.client.getHabbo(), false); Emulator.getGameEnvironment().getRoomManager().enterRoom(this.client.getHabbo(), targetRoom.getId(), "", Emulator.getConfig().getBoolean("hotel.teleport.locked.allowed"), teleportLocation); } + this.client.getHabbo().getRoomUnit().setRotation(RoomUserRotation.values()[targetTeleport.getRotation() % 8]); + this.client.getHabbo().getRoomUnit().statusUpdate(true); + targetTeleport.setExtradata("2"); targetRoom.updateItem(targetTeleport); //targetRoom.updateHabbo(this.client.getHabbo());