diff --git a/sqlupdates/2_0_0_TO_2_1_0-RC-1.sql b/sqlupdates/2_0_0_TO_2_1_0-RC-1.sql index 547b1ada..e65f64fc 100644 --- a/sqlupdates/2_0_0_TO_2_1_0-RC-1.sql +++ b/sqlupdates/2_0_0_TO_2_1_0-RC-1.sql @@ -23,3 +23,49 @@ ADD COLUMN `can_swim` enum('1','0') NULL DEFAULT '0' AFTER `random_actions`; UPDATE `pet_actions` SET `can_swim` = '1' WHERE `pet_type` = 9 OR `pet_type` = 14 OR `pet_type` = 23 OR `pet_type` = 24 OR `pet_type` = 25 OR `pet_type` = 28 OR `pet_type` = 29 OR `pet_type` = 30 OR `pet_type` = 32; UPDATE `items_base` SET `customparams` = '30,60,120,180,300,600', `interaction_type` = 'game_timer', `interaction_modes_count` = 1 WHERE `item_name` IN ('fball_counter','bb_counter','es_counter'); + +ALTER TABLE `youtube_playlists` +DROP COLUMN `order`, +CHANGE COLUMN `video_id` `playlist_id` varchar(255) NOT NULL COMMENT 'YouTube playlist ID' AFTER `item_id`; + +DROP TABLE `youtube_items`; + +TRUNCATE TABLE `youtube_playlists`; + +DROP PROCEDURE IF EXISTS DEFAULT_YTTV_PLAYLISTS; +DELIMITER ;; + +CREATE PROCEDURE DEFAULT_YTTV_PLAYLISTS() +BEGIN + DECLARE n INT DEFAULT 0; + DECLARE i INT DEFAULT 0; + DECLARE a INT DEFAULT 0; + DECLARE itemId INT default 0; + SELECT COUNT(*) FROM `items_base` WHERE `interaction_type` = 'youtube' INTO n; + SET i=0; + + SET @defaultPlaylistIds = '["PL4YfV2mXS8WXOkxFly7YsGL8cKtqp873p","PL4F5KzcUTpEdux38c8CYunT9uNh_k2NPt","PL4F5KzcUTpEcO-1iw3P6gavJ_ALTxqNHn","PL4F5KzcUTpEfpHad_B7j_MulB3-cwtLFh","PL4F5KzcUTpEekJPbcVOaNYVV6VLSo9zRB","PL80F08DAE1B614BA9","PL4F5KzcUTpEfeS5t7EiEIYbpplZivDZTL","PL4ACB18CA629E650A","PL4F5KzcUTpEfyRBCOVKQ4qxlSoHsGDZ82","PL4F5KzcUTpEet7EMwhw0ge5n2oNMr7JY8","PL4F5KzcUTpEfTW4fkX9vrt497MEvWorwK","PL4F5KzcUTpEcit3i1q55-IFFndmo_dsR8","PL4F5KzcUTpEeJleVUhO1MWRJyYDWWp9Do","PL4F5KzcUTpEcFzCpH2_EXtwzKQH8mJGd9","PL4F5KzcUTpEcIiSOH2x3sg2jwACNbSIm9","PL4F5KzcUTpEfRxBiXwTBA7oiybPqoZD_j","PL4YfV2mXS8WUo09aevZX-b47k4PD08-i8","PL4F5KzcUTpEcFzCpH2_EXtwzKQH8mJGd9"]'; + + WHILE i < n DO + SET itemId = (SELECT id FROM `items_base` WHERE `interaction_type` = 'youtube' LIMIT i, 1); + + WHILE a> playLists = new THashMap<>(); - public THashMap videos = new THashMap<>(); + public class YoutubeVideo { + private final String id; + private final int duration; + + YoutubeVideo(String id, int duration) { + this.id = id; + this.duration = duration; + } + + public String getId() { + return id; + } + + public int getDuration() { + return duration; + } + } + + public class YoutubePlaylist { + private final String id; + private final String name; + private final String description; + private final ArrayList videos; + + YoutubePlaylist(String id, String name, String description, ArrayList videos) { + this.id = id; + this.name = name; + this.description = description; + this.videos = videos; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public ArrayList getVideos() { + return videos; + } + } + + private THashMap> playlists = new THashMap<>(); + private THashMap playlistCache = new THashMap<>(); public void load() { - this.videos.clear(); - this.playLists.clear(); + this.playlists.clear(); + this.playlistCache.clear(); - try (Connection connection = Emulator.getDatabase().getDataSource().getConnection()) { - try (Statement statement = connection.createStatement()) { - try (ResultSet set = statement.executeQuery("SELECT * FROM youtube_items")) { - while (set.next()) { - this.videos.put(set.getInt("id"), new YoutubeItem(set)); - } - } + long millis = System.currentTimeMillis(); - try (ResultSet set = statement.executeQuery("SELECT * FROM youtube_playlists ORDER BY `order` ASC")) { - while (set.next()) { - if (!this.playLists.containsKey(set.getInt("item_id"))) { - this.playLists.put(set.getInt("item_id"), new ArrayList<>()); + ExecutorService youtubeDataLoaderPool = Executors.newFixedThreadPool(10); + + Emulator.getLogging().logStart("YouTube Manager -> Loading..."); + + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT * FROM youtube_playlists")) { + try (ResultSet set = statement.executeQuery()) { + while (set.next()) { + final int itemId = set.getInt("item_id"); + final String playlistId = set.getString("playlist_id"); + + youtubeDataLoaderPool.submit(() -> { + ArrayList playlists = this.playlists.getOrDefault(itemId, new ArrayList<>()); + + YoutubePlaylist playlist = this.playlistCache.containsKey(playlistId) ? this.playlistCache.get(playlistId) : this.getPlaylistDataById(playlistId); + if (playlist != null) { + playlists.add(playlist); + + this.playlistCache.put(playlistId, playlist); + } else { + Emulator.getLogging().logErrorLine("Failed to load YouTube playlist: " + playlistId); } - YoutubeItem item = this.videos.get(set.getInt("video_id")); - - if (item != null) { - this.playLists.get(set.getInt("item_id")).add(item); - } - } + this.playlists.put(itemId, playlists); + }); } } } catch (SQLException e) { Emulator.getLogging().logSQLException(e); } - } - public ArrayList getPlaylist(Item item) { - if (this.playLists.containsKey(item.getId())) { - return this.playLists.get(item.getId()); + youtubeDataLoaderPool.shutdown(); + try { + youtubeDataLoaderPool.awaitTermination(60, TimeUnit.SECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); } - return new ArrayList<>(); + Emulator.getLogging().logStart("YouTube Manager -> Loaded! (" + (System.currentTimeMillis() - millis) + " MS)"); } - public YoutubeItem getVideo(Item item, String video) { - if (this.playLists.contains(item.getId())) { - for (YoutubeItem v : this.playLists.get(item.getId())) { - if (v.video.equalsIgnoreCase(video)) { - return v; + private YoutubePlaylist getPlaylistDataById(String playlistId) { + try { + URL myUrl = new URL("https://www.youtube.com/playlist?list=" + playlistId); + + HttpsURLConnection conn = (HttpsURLConnection) myUrl.openConnection(); + conn.setRequestProperty("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"); + conn.setRequestProperty("accept-language", "en-GB,en-US;q=0.9,en;q=0.8"); + conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3731.0 Safari/537.36"); + + InputStream is = conn.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + + YoutubePlaylist playlist = null; + + String inputLine; + while ((inputLine = br.readLine()) != null) { + if (inputLine.contains("window[\"ytInitialData\"]")) { + JsonObject obj = new JsonParser().parse(inputLine.substring(inputLine.indexOf("{")).replace(";", "")).getAsJsonObject(); + + JsonObject meta = obj.get("microformat").getAsJsonObject().get("microformatDataRenderer").getAsJsonObject(); + String name = meta.get("title").getAsString(); + String description = meta.get("description").getAsString(); + + ArrayList videos = new ArrayList<>(); + + JsonArray rawVideos = obj.get("contents").getAsJsonObject().get("twoColumnBrowseResultsRenderer").getAsJsonObject().get("tabs").getAsJsonArray().get(0).getAsJsonObject().get("tabRenderer").getAsJsonObject().get("content").getAsJsonObject().get("sectionListRenderer").getAsJsonObject().get("contents").getAsJsonArray().get(0).getAsJsonObject().get("itemSectionRenderer").getAsJsonObject().get("contents").getAsJsonArray().get(0).getAsJsonObject().get("playlistVideoListRenderer").getAsJsonObject().get("contents").getAsJsonArray(); + + for (JsonElement rawVideo : rawVideos) { + JsonObject videoData = rawVideo.getAsJsonObject().get("playlistVideoRenderer").getAsJsonObject(); + if (!videoData.has("lengthSeconds")) continue; // removed videos + videos.add(new YoutubeVideo(videoData.get("videoId").getAsString(), Integer.valueOf(videoData.get("lengthSeconds").getAsString()))); + } + + playlist = new YoutubePlaylist(playlistId, name, description, videos); + + break; } } + + br.close(); + + return playlist; + } catch (java.io.IOException e) { + e.printStackTrace(); } return null; } - public String getPreviewImage(Item item) { - if (this.playLists.contains(item.getId())) { - if (!this.playLists.get(item.getId()).isEmpty()) { - return this.playLists.get(item.getId()).get(0).video; - } - } - - return ""; - } - - public YoutubeItem getVideo(Item item, int index) { - if (this.playLists.containsKey(item.getId())) { - return this.playLists.get(item.getId()).get(index); - } - - return null; - } - - public class YoutubeItem { - public final int id; - public final String video; - public final String title; - public final String description; - public final int startTime; - public final int endTime; - - public YoutubeItem(ResultSet set) throws SQLException { - this.id = set.getInt("id"); - this.video = set.getString("video"); - this.title = set.getString("title"); - this.description = set.getString("description"); - this.startTime = set.getInt("start_time"); - this.endTime = set.getInt("end_time"); - } + public ArrayList getPlaylistsForItemId(int itemId) { + return this.playlists.get(itemId); } } \ No newline at end of file diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionYoutubeTV.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionYoutubeTV.java index 438025a0..47bbbb10 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionYoutubeTV.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionYoutubeTV.java @@ -1,16 +1,27 @@ 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.YoutubeManager; 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.messages.ServerMessage; +import com.eu.habbo.messages.outgoing.rooms.items.youtube.YoutubeVideoComposer; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.concurrent.ScheduledFuture; public class InteractionYoutubeTV extends HabboItem { + public YoutubeManager.YoutubePlaylist currentPlaylist = null; + public YoutubeManager.YoutubeVideo currentVideo = null; + public int startedWatchingAt = 0; + public int offset = 0; + public boolean playing = true; + public ScheduledFuture autoAdvance = null; + public InteractionYoutubeTV(ResultSet set, Item baseItem) throws SQLException { super(set, baseItem); } @@ -42,8 +53,44 @@ public class InteractionYoutubeTV extends HabboItem { serverMessage.appendInt(1 + (this.isLimited() ? 256 : 0)); serverMessage.appendInt(1); serverMessage.appendString("THUMBNAIL_URL"); - serverMessage.appendString(Emulator.getConfig().getValue("imager.url.youtube").replace("%video%", Emulator.getGameEnvironment().getItemManager().getYoutubeManager().getPreviewImage(this.getBaseItem()))); + if (this.currentVideo == null) { + serverMessage.appendString(""); + } else { + serverMessage.appendString(Emulator.getConfig().getValue("imager.url.youtube").replace("%video%", this.currentVideo.getId())); + } super.serializeExtradata(serverMessage); } + + @Override + public void onPickUp(Room room) { + super.onPickUp(room); + + if (this.autoAdvance != null) { + this.cancelAdvancement(); + } + + this.currentVideo = null; + this.currentPlaylist = null; + this.startedWatchingAt = 0; + this.offset = 0; + } + + public void cancelAdvancement() { + if (this.autoAdvance == null) return; + + this.autoAdvance.cancel(true); + this.autoAdvance = null; + } + + @Override + public void onClick(GameClient client, Room room, Object[] objects) throws Exception { + super.onClick(client, room, objects); + + if (this.currentVideo != null) { + int startTime = this.offset; + if (this.playing) startTime += Emulator.getIntUnixTimestamp() - this.startedWatchingAt; + client.sendResponse(new YoutubeVideoComposer(this.getId(), this.currentVideo, this.playing, startTime)); + } + } } \ No newline at end of file diff --git a/src/main/java/com/eu/habbo/messages/PacketManager.java b/src/main/java/com/eu/habbo/messages/PacketManager.java index f92cd743..c49fe1b3 100644 --- a/src/main/java/com/eu/habbo/messages/PacketManager.java +++ b/src/main/java/com/eu/habbo/messages/PacketManager.java @@ -52,9 +52,9 @@ import com.eu.habbo.messages.incoming.rooms.items.jukebox.*; import com.eu.habbo.messages.incoming.rooms.items.lovelock.LoveLockStartConfirmEvent; import com.eu.habbo.messages.incoming.rooms.items.rentablespace.RentSpaceCancelEvent; import com.eu.habbo.messages.incoming.rooms.items.rentablespace.RentSpaceEvent; -import com.eu.habbo.messages.incoming.rooms.items.youtube.YoutubeRequestNextVideoEvent; -import com.eu.habbo.messages.incoming.rooms.items.youtube.YoutubeRequestPlayListEvent; -import com.eu.habbo.messages.incoming.rooms.items.youtube.YoutubeRequestVideoDataEvent; +import com.eu.habbo.messages.incoming.rooms.items.youtube.YoutubeRequestStateChange; +import com.eu.habbo.messages.incoming.rooms.items.youtube.YoutubeRequestPlaylists; +import com.eu.habbo.messages.incoming.rooms.items.youtube.YoutubeRequestPlaylistChange; import com.eu.habbo.messages.incoming.rooms.pets.*; import com.eu.habbo.messages.incoming.rooms.promotions.BuyRoomPromotionEvent; import com.eu.habbo.messages.incoming.rooms.promotions.RequestPromotionRoomsEvent; @@ -424,9 +424,9 @@ public class PacketManager { this.registerHandler(Incoming.RoomUserBanEvent, RoomUserBanEvent.class); this.registerHandler(Incoming.UnbanRoomUserEvent, UnbanRoomUserEvent.class); this.registerHandler(Incoming.RequestRoomUserTagsEvent, RequestRoomUserTagsEvent.class); - this.registerHandler(Incoming.YoutubeRequestPlayListEvent, YoutubeRequestPlayListEvent.class); - this.registerHandler(Incoming.YoutubeRequestNextVideoEvent, YoutubeRequestNextVideoEvent.class); - this.registerHandler(Incoming.YoutubeRequestVideoDataEvent, YoutubeRequestVideoDataEvent.class); + this.registerHandler(Incoming.YoutubeRequestPlaylists, YoutubeRequestPlaylists.class); + this.registerHandler(Incoming.YoutubeRequestStateChange, YoutubeRequestStateChange.class); + this.registerHandler(Incoming.YoutubeRequestPlaylistChange, YoutubeRequestPlaylistChange.class); this.registerHandler(Incoming.RoomFavoriteEvent, RoomFavoriteEvent.class); this.registerHandler(Incoming.LoveLockStartConfirmEvent, LoveLockStartConfirmEvent.class); this.registerHandler(Incoming.RoomUnFavoriteEvent, RoomUnFavoriteEvent.class); 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 ba2e48b7..ee4ed6d5 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/Incoming.java +++ b/src/main/java/com/eu/habbo/messages/incoming/Incoming.java @@ -305,9 +305,9 @@ public class Incoming { public static final int RoomFavoriteEvent = 3817; public static final int RoomUnFavoriteEvent = 309; - public static final int YoutubeRequestPlayListEvent = 336; - public static final int YoutubeRequestNextVideoEvent = 3005; - public static final int YoutubeRequestVideoDataEvent = 2069; + public static final int YoutubeRequestPlaylists = 336; + public static final int YoutubeRequestStateChange = 3005; + public static final int YoutubeRequestPlaylistChange = 2069; public static final int EditRoomPromotionMessageEvent = 3707; public static final int HotelViewRequestBadgeRewardEvent = 2318; diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestNextVideoEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestNextVideoEvent.java deleted file mode 100644 index 3a3d505a..00000000 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestNextVideoEvent.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.eu.habbo.messages.incoming.rooms.items.youtube; - -import com.eu.habbo.Emulator; -import com.eu.habbo.habbohotel.items.YoutubeManager; -import com.eu.habbo.habbohotel.items.interactions.InteractionYoutubeTV; -import com.eu.habbo.habbohotel.users.HabboItem; -import com.eu.habbo.messages.incoming.MessageHandler; -import com.eu.habbo.messages.outgoing.rooms.items.youtube.YoutubeVideoComposer; - -public class YoutubeRequestNextVideoEvent extends MessageHandler { - @Override - public void handle() throws Exception { - int itemId = this.packet.readInt(); - int next = this.packet.readInt(); - - if (this.client.getHabbo().getHabboInfo().getCurrentRoom() != null) { - HabboItem item = this.client.getHabbo().getHabboInfo().getCurrentRoom().getHabboItem(itemId); - - if (item instanceof InteractionYoutubeTV) { - YoutubeManager.YoutubeItem video = Emulator.getGameEnvironment().getItemManager().getYoutubeManager().getVideo(item.getBaseItem(), next); - - if (video != null) { - this.client.sendResponse(new YoutubeVideoComposer(itemId, video)); - } - } - } - } -} \ No newline at end of file diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestPlaylistChange.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestPlaylistChange.java new file mode 100644 index 00000000..3a367dfe --- /dev/null +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestPlaylistChange.java @@ -0,0 +1,55 @@ +package com.eu.habbo.messages.incoming.rooms.items.youtube; + +import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.items.YoutubeManager; +import com.eu.habbo.habbohotel.items.interactions.InteractionYoutubeTV; +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.habbohotel.users.HabboItem; +import com.eu.habbo.messages.incoming.MessageHandler; +import com.eu.habbo.messages.outgoing.rooms.items.youtube.YoutubeVideoComposer; +import com.eu.habbo.threading.runnables.YoutubeAdvanceVideo; + +import java.util.Optional; + +public class YoutubeRequestPlaylistChange extends MessageHandler { + @Override + public void handle() throws Exception { + int itemId = this.packet.readInt(); + String playlistId = this.packet.readString(); + + Habbo habbo = this.client.getHabbo(); + + if (habbo == null) return; + + + Room room = habbo.getHabboInfo().getCurrentRoom(); + + if (room == null) return; + if (!room.isOwner(habbo) && !habbo.hasPermission(Permission.ACC_ANYROOMOWNER)) return; + + + HabboItem item = this.client.getHabbo().getHabboInfo().getCurrentRoom().getHabboItem(itemId); + + if (item == null || !(item instanceof InteractionYoutubeTV)) return; + + Optional playlist = Emulator.getGameEnvironment().getItemManager().getYoutubeManager().getPlaylistsForItemId(item.getBaseItem().getId()).stream().filter(p -> p.getId().equals(playlistId)).findAny(); + + if (playlist.isPresent()) { + YoutubeManager.YoutubeVideo video = playlist.get().getVideos().get(0); + if (video == null) return; + + ((InteractionYoutubeTV) item).currentVideo = video; + ((InteractionYoutubeTV) item).currentPlaylist = playlist.get(); + + ((InteractionYoutubeTV) item).cancelAdvancement(); + + room.updateItem(item); + room.sendComposer(new YoutubeVideoComposer(itemId, video, true, 0).compose()); + ((InteractionYoutubeTV) item).autoAdvance = Emulator.getThreading().run(new YoutubeAdvanceVideo((InteractionYoutubeTV) item), video.getDuration() * 1000); + + item.needsUpdate(true); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestPlayListEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestPlaylists.java similarity index 79% rename from src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestPlayListEvent.java rename to src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestPlaylists.java index d997a683..469861d0 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestPlayListEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestPlaylists.java @@ -6,7 +6,7 @@ import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.messages.incoming.MessageHandler; import com.eu.habbo.messages.outgoing.rooms.items.youtube.YoutubeDisplayListComposer; -public class YoutubeRequestPlayListEvent extends MessageHandler { +public class YoutubeRequestPlaylists extends MessageHandler { @Override public void handle() throws Exception { int itemId = this.packet.readInt(); @@ -15,7 +15,9 @@ public class YoutubeRequestPlayListEvent extends MessageHandler { HabboItem item = this.client.getHabbo().getHabboInfo().getCurrentRoom().getHabboItem(itemId); if (item instanceof InteractionYoutubeTV) { - this.client.sendResponse(new YoutubeDisplayListComposer(itemId, Emulator.getGameEnvironment().getItemManager().getYoutubeManager().getPlaylist(item.getBaseItem()))); + InteractionYoutubeTV tv = (InteractionYoutubeTV) item; + + this.client.sendResponse(new YoutubeDisplayListComposer(itemId, Emulator.getGameEnvironment().getItemManager().getYoutubeManager().getPlaylistsForItemId(item.getBaseItem().getId()), tv.currentPlaylist)); } } } diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestStateChange.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestStateChange.java new file mode 100644 index 00000000..c0f23ebf --- /dev/null +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestStateChange.java @@ -0,0 +1,108 @@ +package com.eu.habbo.messages.incoming.rooms.items.youtube; + +import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.items.YoutubeManager; +import com.eu.habbo.habbohotel.items.interactions.InteractionYoutubeTV; +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.habbohotel.users.HabboItem; +import com.eu.habbo.messages.incoming.MessageHandler; +import com.eu.habbo.messages.outgoing.rooms.items.youtube.YoutubeStateChangeComposer; +import com.eu.habbo.messages.outgoing.rooms.items.youtube.YoutubeVideoComposer; +import com.eu.habbo.threading.runnables.YoutubeAdvanceVideo; + +public class YoutubeRequestStateChange extends MessageHandler { + public enum YoutubeState { + PREVIOUS(0), + NEXT(1), + PAUSE(2), + RESUME(3); + + private int state; + + YoutubeState(int state) { + this.state = state; + } + + public int getState() { + return state; + } + + public static YoutubeState getByState(int state) { + switch (state) { + case 0: + return PREVIOUS; + case 1: + return NEXT; + case 2: + return PAUSE; + case 3: + return RESUME; + default: + return null; + } + } + } + + @Override + public void handle() throws Exception { + int itemId = this.packet.readInt(); + YoutubeState state = YoutubeState.getByState(this.packet.readInt()); + + if (state == null) return; + + Habbo habbo = this.client.getHabbo(); + + if (habbo == null) return; + + + Room room = habbo.getHabboInfo().getCurrentRoom(); + + if (room == null) return; + if (!room.isOwner(habbo) && !habbo.hasPermission(Permission.ACC_ANYROOMOWNER)) return; + + + HabboItem item = this.client.getHabbo().getHabboInfo().getCurrentRoom().getHabboItem(itemId); + + if (item == null || !(item instanceof InteractionYoutubeTV)) return; + + InteractionYoutubeTV tv = (InteractionYoutubeTV) item; + + switch (state) { + case PAUSE: + tv.playing = false; + tv.offset += Emulator.getIntUnixTimestamp() - tv.startedWatchingAt; + if (tv.autoAdvance != null) tv.autoAdvance.cancel(true); + room.sendComposer(new YoutubeStateChangeComposer(tv.getId(), 2).compose()); + break; + case RESUME: + tv.playing = true; + tv.startedWatchingAt = Emulator.getIntUnixTimestamp(); + tv.autoAdvance = Emulator.getThreading().run(new YoutubeAdvanceVideo(tv), (tv.currentVideo.getDuration() - tv.offset) * 1000); + room.sendComposer(new YoutubeStateChangeComposer(tv.getId(), 1).compose()); + break; + case PREVIOUS: + int previousIndex = tv.currentPlaylist.getVideos().indexOf(tv.currentVideo) - 1; + if (previousIndex < 0) previousIndex = tv.currentPlaylist.getVideos().size() - 1; + tv.currentVideo = tv.currentPlaylist.getVideos().get(previousIndex); + break; + case NEXT: + int nextIndex = tv.currentPlaylist.getVideos().indexOf(tv.currentVideo) + 1; + if (nextIndex >= tv.currentPlaylist.getVideos().size()) nextIndex = 0; + tv.currentVideo = tv.currentPlaylist.getVideos().get(nextIndex); + break; + } + + if (state == YoutubeState.PREVIOUS || state == YoutubeState.NEXT) { + room.sendComposer(new YoutubeVideoComposer(tv.getId(), tv.currentVideo, true, 0).compose()); + + tv.cancelAdvancement(); + tv.autoAdvance = Emulator.getThreading().run(new YoutubeAdvanceVideo(tv), tv.currentVideo.getDuration() * 1000); + tv.startedWatchingAt = Emulator.getIntUnixTimestamp(); + tv.offset = 0; + tv.playing = true; + room.updateItem(tv); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestVideoDataEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestVideoDataEvent.java deleted file mode 100644 index 0e1623c7..00000000 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/youtube/YoutubeRequestVideoDataEvent.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.eu.habbo.messages.incoming.rooms.items.youtube; - -import com.eu.habbo.Emulator; -import com.eu.habbo.habbohotel.items.YoutubeManager; -import com.eu.habbo.habbohotel.items.interactions.InteractionYoutubeTV; -import com.eu.habbo.habbohotel.users.HabboItem; -import com.eu.habbo.messages.incoming.MessageHandler; -import com.eu.habbo.messages.outgoing.rooms.items.youtube.YoutubeVideoComposer; - -public class YoutubeRequestVideoDataEvent extends MessageHandler { - @Override - public void handle() throws Exception { - int itemId = this.packet.readInt(); - String videoId = this.packet.readString(); - - if (this.client.getHabbo().getHabboInfo().getCurrentRoom() != null) { - HabboItem item = this.client.getHabbo().getHabboInfo().getCurrentRoom().getHabboItem(itemId); - - if (item instanceof InteractionYoutubeTV) { - YoutubeManager.YoutubeItem videoItem = Emulator.getGameEnvironment().getItemManager().getYoutubeManager().getVideo(item.getBaseItem(), videoId); - - if (videoItem != null) { - this.client.sendResponse(new YoutubeVideoComposer(itemId, videoItem)); - } - } - } - } -} \ No newline at end of file diff --git a/src/main/java/com/eu/habbo/messages/outgoing/rooms/items/youtube/YoutubeDisplayListComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/rooms/items/youtube/YoutubeDisplayListComposer.java index ef92a8dd..9cab7508 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/rooms/items/youtube/YoutubeDisplayListComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/rooms/items/youtube/YoutubeDisplayListComposer.java @@ -8,27 +8,29 @@ import com.eu.habbo.messages.outgoing.Outgoing; import java.util.ArrayList; public class YoutubeDisplayListComposer extends MessageComposer { - public final int itemId; - public final ArrayList items; + private final int itemId; + private final ArrayList playlists; + private final YoutubeManager.YoutubePlaylist currentPlaylist; - public YoutubeDisplayListComposer(int itemId, ArrayList items) { + public YoutubeDisplayListComposer(int itemId, ArrayList playlists, YoutubeManager.YoutubePlaylist currentPlaylist) { this.itemId = itemId; - this.items = items; + this.playlists = playlists; + this.currentPlaylist = currentPlaylist; } @Override public ServerMessage compose() { this.response.init(Outgoing.YoutubeDisplayListComposer); this.response.appendInt(this.itemId); - this.response.appendInt(this.items.size()); + this.response.appendInt(this.playlists.size()); - for (YoutubeManager.YoutubeItem item : this.items) { - this.response.appendString(item.video); - this.response.appendString(item.title); - this.response.appendString(item.description); + for (YoutubeManager.YoutubePlaylist item : this.playlists) { + this.response.appendString(item.getId()); // playlist ID + this.response.appendString(item.getName()); // playlist title + this.response.appendString(item.getDescription()); // playlist description } - this.response.appendString(""); + this.response.appendString(this.currentPlaylist == null ? "" : this.currentPlaylist.getId()); // current playlist ID return this.response; } } \ No newline at end of file diff --git a/src/main/java/com/eu/habbo/messages/outgoing/rooms/items/youtube/YoutubeStateChangeComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/rooms/items/youtube/YoutubeStateChangeComposer.java new file mode 100644 index 00000000..1014715e --- /dev/null +++ b/src/main/java/com/eu/habbo/messages/outgoing/rooms/items/youtube/YoutubeStateChangeComposer.java @@ -0,0 +1,24 @@ +package com.eu.habbo.messages.outgoing.rooms.items.youtube; + +import com.eu.habbo.messages.ServerMessage; +import com.eu.habbo.messages.outgoing.MessageComposer; +import com.eu.habbo.messages.outgoing.Outgoing; + +public class YoutubeStateChangeComposer extends MessageComposer { + private final int furniId; + private final int state; + + public YoutubeStateChangeComposer(int furniId, int state) { + this.furniId = furniId; + this.state = state; + } + + @Override + public ServerMessage compose() { + this.response.init(Outgoing.YoutubeMessageComposer3); + this.response.appendInt(this.furniId); + this.response.appendInt(this.state); + + return this.response; + } +} diff --git a/src/main/java/com/eu/habbo/messages/outgoing/rooms/items/youtube/YoutubeVideoComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/rooms/items/youtube/YoutubeVideoComposer.java index be386b06..62a56781 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/rooms/items/youtube/YoutubeVideoComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/rooms/items/youtube/YoutubeVideoComposer.java @@ -6,22 +6,26 @@ import com.eu.habbo.messages.outgoing.MessageComposer; import com.eu.habbo.messages.outgoing.Outgoing; public class YoutubeVideoComposer extends MessageComposer { - public final int itemId; - public final YoutubeManager.YoutubeItem item; + private final int itemId; + private final YoutubeManager.YoutubeVideo video; + private final boolean playing; + private final int startTime; - public YoutubeVideoComposer(int itemId, YoutubeManager.YoutubeItem item) { + public YoutubeVideoComposer(int itemId, YoutubeManager.YoutubeVideo video, boolean playing, int startTime) { this.itemId = itemId; - this.item = item; + this.video = video; + this.playing = playing; + this.startTime = startTime; } @Override public ServerMessage compose() { this.response.init(Outgoing.YoutubeMessageComposer2); this.response.appendInt(this.itemId); - this.response.appendString(this.item.video); - this.response.appendInt(this.item.startTime); - this.response.appendInt(this.item.endTime); - this.response.appendInt(0); + this.response.appendString(this.video.getId()); + this.response.appendInt(this.startTime); + this.response.appendInt(this.video.getDuration()); + this.response.appendInt(this.playing ? 1 : 2); return this.response; } } \ No newline at end of file diff --git a/src/main/java/com/eu/habbo/threading/runnables/YoutubeAdvanceVideo.java b/src/main/java/com/eu/habbo/threading/runnables/YoutubeAdvanceVideo.java new file mode 100644 index 00000000..0a140643 --- /dev/null +++ b/src/main/java/com/eu/habbo/threading/runnables/YoutubeAdvanceVideo.java @@ -0,0 +1,33 @@ +package com.eu.habbo.threading.runnables; + +import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.items.interactions.InteractionYoutubeTV; +import com.eu.habbo.habbohotel.rooms.Room; +import com.eu.habbo.messages.outgoing.rooms.items.youtube.YoutubeVideoComposer; + +public class YoutubeAdvanceVideo implements Runnable { + private final InteractionYoutubeTV tv; + + public YoutubeAdvanceVideo(InteractionYoutubeTV tv) { + this.tv = tv; + } + + @Override + public void run() { + if (this.tv.autoAdvance == null) return; + + Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.tv.getRoomId()); + + if (room == null) return; + + int nextIndex = tv.currentPlaylist.getVideos().indexOf(tv.currentVideo) + 1; + if (nextIndex >= tv.currentPlaylist.getVideos().size()) nextIndex = 0; + tv.currentVideo = tv.currentPlaylist.getVideos().get(nextIndex); + tv.startedWatchingAt = Emulator.getIntUnixTimestamp(); + tv.offset = 0; + room.updateItem(this.tv); + room.sendComposer(new YoutubeVideoComposer(tv.getId(), tv.currentVideo, true, 0).compose()); + + tv.autoAdvance = Emulator.getThreading().run(new YoutubeAdvanceVideo(this.tv), tv.currentVideo.getDuration() * 1000); + } +}