You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-20 07:26:18 +00:00
@@ -0,0 +1,3 @@
|
||||
INSERT INTO emulator_settings (`key`, `value`) VALUES ('packet.global.rate.limit', '50');
|
||||
|
||||
ALTER TABLE `rooms` ADD COLUMN IF NOT EXISTS `youtube_enabled` TINYINT(1) NOT NULL DEFAULT 0;
|
||||
@@ -175,7 +175,35 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
||||
private volatile boolean muted;
|
||||
private RoomSpecialTypes roomSpecialTypes;
|
||||
private TraxManager traxManager;
|
||||
|
||||
|
||||
// YouTube room broadcast state: tracks the current video being broadcast
|
||||
// by the room owner, the owner's playlist, and which users have the player open.
|
||||
private boolean youtubeEnabled = false;
|
||||
private String youtubeCurrentVideo = "";
|
||||
private String youtubeSenderName = "";
|
||||
private final java.util.List<String> youtubePlaylist = new java.util.concurrent.CopyOnWriteArrayList<>();
|
||||
private final java.util.Set<Integer> youtubeWatchers = java.util.concurrent.ConcurrentHashMap.newKeySet();
|
||||
|
||||
public boolean isYoutubeEnabled() { return this.youtubeEnabled; }
|
||||
public void setYoutubeEnabled(boolean enabled) { this.youtubeEnabled = enabled; }
|
||||
public String getYoutubeCurrentVideo() { return this.youtubeCurrentVideo; }
|
||||
public String getYoutubeSenderName() { return this.youtubeSenderName; }
|
||||
public java.util.List<String> getYoutubePlaylist() { return this.youtubePlaylist; }
|
||||
public java.util.Set<Integer> getYoutubeWatchers() { return this.youtubeWatchers; }
|
||||
|
||||
public void setYoutubeVideo(String videoId, String senderName, java.util.List<String> playlist) {
|
||||
this.youtubeCurrentVideo = videoId;
|
||||
this.youtubeSenderName = senderName;
|
||||
this.youtubePlaylist.clear();
|
||||
if (playlist != null) this.youtubePlaylist.addAll(playlist);
|
||||
}
|
||||
|
||||
public void clearYoutubeVideo() {
|
||||
this.youtubeCurrentVideo = "";
|
||||
this.youtubeSenderName = "";
|
||||
this.youtubePlaylist.clear();
|
||||
}
|
||||
|
||||
public final THashMap<String, Object> cache;
|
||||
|
||||
public Room(ResultSet set) throws SQLException {
|
||||
@@ -203,6 +231,7 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
||||
this.allowPetsEat = set.getBoolean("allow_other_pets_eat");
|
||||
this.allowWalkthrough = set.getBoolean("allow_walkthrough");
|
||||
this.hideWall = set.getBoolean("allow_hidewall");
|
||||
try { this.youtubeEnabled = set.getBoolean("youtube_enabled"); } catch (Exception e) { this.youtubeEnabled = false; }
|
||||
this.chatMode = set.getInt("chat_mode");
|
||||
this.chatWeight = set.getInt("chat_weight");
|
||||
this.chatSpeed = set.getInt("chat_speed");
|
||||
@@ -1095,7 +1124,7 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
||||
if (this.needsUpdate) {
|
||||
try (Connection connection = Emulator.getDatabase().getDataSource()
|
||||
.getConnection(); PreparedStatement statement = connection.prepareStatement(
|
||||
"UPDATE rooms SET name = ?, description = ?, password = ?, state = ?, users_max = ?, category = ?, score = ?, paper_floor = ?, paper_wall = ?, paper_landscape = ?, thickness_wall = ?, wall_height = ?, thickness_floor = ?, moodlight_data = ?, tags = ?, allow_other_pets = ?, allow_other_pets_eat = ?, allow_walkthrough = ?, allow_hidewall = ?, chat_mode = ?, chat_weight = ?, chat_speed = ?, chat_hearing_distance = ?, chat_protection =?, who_can_mute = ?, who_can_kick = ?, who_can_ban = ?, poll_id = ?, guild_id = ?, roller_speed = ?, override_model = ?, is_staff_picked = ?, promoted = ?, trade_mode = ?, move_diagonally = ?, owner_id = ?, owner_name = ?, jukebox_active = ?, hidewired = ?, allow_underpass = ? WHERE id = ?")) {
|
||||
"UPDATE rooms SET name = ?, description = ?, password = ?, state = ?, users_max = ?, category = ?, score = ?, paper_floor = ?, paper_wall = ?, paper_landscape = ?, thickness_wall = ?, wall_height = ?, thickness_floor = ?, moodlight_data = ?, tags = ?, allow_other_pets = ?, allow_other_pets_eat = ?, allow_walkthrough = ?, allow_hidewall = ?, chat_mode = ?, chat_weight = ?, chat_speed = ?, chat_hearing_distance = ?, chat_protection =?, who_can_mute = ?, who_can_kick = ?, who_can_ban = ?, poll_id = ?, guild_id = ?, roller_speed = ?, override_model = ?, is_staff_picked = ?, promoted = ?, trade_mode = ?, move_diagonally = ?, owner_id = ?, owner_name = ?, jukebox_active = ?, hidewired = ?, allow_underpass = ?, youtube_enabled = ? WHERE id = ?")) {
|
||||
statement.setString(1, this.name);
|
||||
statement.setString(2, this.description);
|
||||
statement.setString(3, this.password);
|
||||
@@ -1145,7 +1174,8 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
||||
statement.setString(38, this.jukeboxActive ? "1" : "0");
|
||||
statement.setString(39, this.hideWired ? "1" : "0");
|
||||
statement.setString(40, this.allowUnderpass ? "1" : "0");
|
||||
statement.setInt(41, this.id);
|
||||
statement.setString(41, this.youtubeEnabled ? "1" : "0");
|
||||
statement.setInt(42, this.id);
|
||||
statement.executeUpdate();
|
||||
this.needsUpdate = false;
|
||||
} catch (SQLException e) {
|
||||
@@ -1774,13 +1804,31 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
||||
}
|
||||
|
||||
public void removeHabbo(Habbo habbo) {
|
||||
this.cleanupYoutubeWatcher(habbo);
|
||||
this.unitManager.removeHabbo(habbo);
|
||||
}
|
||||
|
||||
public void removeHabbo(Habbo habbo, boolean sendRemovePacket) {
|
||||
this.cleanupYoutubeWatcher(habbo);
|
||||
this.unitManager.removeHabbo(habbo, sendRemovePacket);
|
||||
}
|
||||
|
||||
private void cleanupYoutubeWatcher(Habbo habbo) {
|
||||
if (habbo == null) return;
|
||||
int userId = habbo.getHabboInfo().getId();
|
||||
|
||||
// If the broadcast sender leaves, stop the broadcast for everyone
|
||||
if (!this.youtubeCurrentVideo.isEmpty()
|
||||
&& habbo.getHabboInfo().getUsername().equals(this.youtubeSenderName)) {
|
||||
this.clearYoutubeVideo();
|
||||
this.sendComposer(new com.eu.habbo.messages.outgoing.rooms.youtube.YouTubeRoomBroadcastComposer("", "", java.util.Collections.emptyList()).compose());
|
||||
}
|
||||
|
||||
if (this.youtubeWatchers.remove(userId)) {
|
||||
this.sendComposer(new com.eu.habbo.messages.outgoing.rooms.youtube.YouTubeRoomWatchersComposer(this.youtubeWatchers).compose());
|
||||
}
|
||||
}
|
||||
|
||||
public void addBot(Bot bot) {
|
||||
this.unitManager.addBot(bot);
|
||||
}
|
||||
|
||||
@@ -790,7 +790,6 @@ public class RoomManager {
|
||||
habbo.getRoomUnit().setInvisible(false);
|
||||
room.addHabbo(habbo);
|
||||
|
||||
// Pre-send own wearing badges so the client cache is populated before the user clicks themselves
|
||||
habbo.getClient().sendResponse(new UserBadgesComposer(habbo.getInventory().getBadgesComponent().getWearingBadges(), habbo.getHabboInfo().getId()));
|
||||
|
||||
List<Habbo> habbos = new ArrayList<>();
|
||||
@@ -987,6 +986,20 @@ public class RoomManager {
|
||||
}
|
||||
}
|
||||
|
||||
habbo.getClient().sendResponse(new com.eu.habbo.messages.outgoing.rooms.youtube.YouTubeRoomSettingsComposer(
|
||||
room.isYoutubeEnabled()).compose());
|
||||
|
||||
if (!room.getYoutubeCurrentVideo().isEmpty()) {
|
||||
habbo.getClient().sendResponse(new com.eu.habbo.messages.outgoing.rooms.youtube.YouTubeRoomBroadcastComposer(
|
||||
room.getYoutubeCurrentVideo(),
|
||||
room.getYoutubeSenderName(),
|
||||
room.getYoutubePlaylist()).compose());
|
||||
}
|
||||
if (!room.getYoutubeWatchers().isEmpty()) {
|
||||
habbo.getClient().sendResponse(new com.eu.habbo.messages.outgoing.rooms.youtube.YouTubeRoomWatchersComposer(
|
||||
room.getYoutubeWatchers()).compose());
|
||||
}
|
||||
|
||||
WiredManager.triggerUserEntersRoom(room, habbo.getRoomUnit());
|
||||
room.habboEntered(habbo);
|
||||
|
||||
|
||||
@@ -677,5 +677,10 @@ public class PacketManager {
|
||||
this.registerHandler(Incoming.GameCenterLeaveGameEvent, GameCenterLeaveGameEvent.class);
|
||||
this.registerHandler(Incoming.GameCenterEvent, GameCenterEvent.class);
|
||||
this.registerHandler(Incoming.GameCenterRequestGameStatusEvent, GameCenterRequestGameStatusEvent.class);
|
||||
|
||||
// YouTube Room Broadcast
|
||||
this.registerHandler(Incoming.YouTubeRoomPlayEvent, com.eu.habbo.messages.incoming.rooms.youtube.YouTubeRoomPlayEvent.class);
|
||||
this.registerHandler(Incoming.YouTubeRoomWatchingEvent, com.eu.habbo.messages.incoming.rooms.youtube.YouTubeRoomWatchingEvent.class);
|
||||
this.registerHandler(Incoming.YouTubeRoomSettingsEvent, com.eu.habbo.messages.incoming.rooms.youtube.YouTubeRoomSettingsEvent.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -436,4 +436,9 @@ public class Incoming {
|
||||
public static final int SetActivePrefixEvent = 7012;
|
||||
public static final int DeletePrefixEvent = 7013;
|
||||
public static final int PurchasePrefixEvent = 7014;
|
||||
|
||||
// YouTube Room Broadcast
|
||||
public static final int YouTubeRoomPlayEvent = 8001;
|
||||
public static final int YouTubeRoomWatchingEvent = 8002;
|
||||
public static final int YouTubeRoomSettingsEvent = 8003;
|
||||
}
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package com.eu.habbo.messages.incoming.rooms.youtube;
|
||||
|
||||
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.rooms.youtube.YouTubeRoomBroadcastComposer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class YouTubeRoomPlayEvent extends MessageHandler {
|
||||
|
||||
private static final int MAX_VIDEO_ID_LENGTH = 100;
|
||||
private static final int MAX_PLAYLIST_ITEM_LENGTH = 200;
|
||||
private static final int MAX_PLAYLIST_SIZE = 50;
|
||||
|
||||
@Override
|
||||
public int getRatelimit() {
|
||||
// Max 1 broadcast every 2 seconds per client
|
||||
return 2000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle() throws Exception {
|
||||
Habbo habbo = this.client.getHabbo();
|
||||
if (habbo == null) return;
|
||||
|
||||
Room room = habbo.getHabboInfo().getCurrentRoom();
|
||||
if (room == null) return;
|
||||
if (!room.isYoutubeEnabled()) return;
|
||||
if (!room.isOwner(habbo) && !room.hasRights(habbo)) return;
|
||||
|
||||
String videoId = this.packet.readString();
|
||||
if (videoId.length() > MAX_VIDEO_ID_LENGTH) {
|
||||
videoId = videoId.substring(0, MAX_VIDEO_ID_LENGTH);
|
||||
}
|
||||
|
||||
int playlistCount = this.packet.readInt();
|
||||
if (playlistCount > MAX_PLAYLIST_SIZE) playlistCount = MAX_PLAYLIST_SIZE;
|
||||
if (playlistCount < 0) playlistCount = 0;
|
||||
|
||||
List<String> playlist = new ArrayList<>();
|
||||
for (int i = 0; i < playlistCount; i++) {
|
||||
String item = this.packet.readString();
|
||||
if (item.length() > MAX_PLAYLIST_ITEM_LENGTH) {
|
||||
item = item.substring(0, MAX_PLAYLIST_ITEM_LENGTH);
|
||||
}
|
||||
playlist.add(item);
|
||||
}
|
||||
|
||||
// Store the current video + playlist on the room, or clear if empty
|
||||
if (videoId.isEmpty()) {
|
||||
room.clearYoutubeVideo();
|
||||
} else {
|
||||
room.setYoutubeVideo(videoId, habbo.getHabboInfo().getUsername(), playlist);
|
||||
}
|
||||
|
||||
// Broadcast to everyone in the room (empty videoId = stop)
|
||||
room.sendComposer(
|
||||
new YouTubeRoomBroadcastComposer(videoId, habbo.getHabboInfo().getUsername(), playlist).compose()
|
||||
);
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.eu.habbo.messages.incoming.rooms.youtube;
|
||||
|
||||
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.rooms.youtube.YouTubeRoomBroadcastComposer;
|
||||
import com.eu.habbo.messages.outgoing.rooms.youtube.YouTubeRoomSettingsComposer;
|
||||
|
||||
public class YouTubeRoomSettingsEvent extends MessageHandler {
|
||||
|
||||
@Override
|
||||
public int getRatelimit() {
|
||||
return 200;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle() throws Exception {
|
||||
Habbo habbo = this.client.getHabbo();
|
||||
if (habbo == null) return;
|
||||
|
||||
Room room = habbo.getHabboInfo().getCurrentRoom();
|
||||
if (room == null) return;
|
||||
if (!room.isOwner(habbo)) return;
|
||||
|
||||
boolean enabled = this.packet.readInt() == 1;
|
||||
room.setYoutubeEnabled(enabled);
|
||||
room.setNeedsUpdate(true);
|
||||
room.sendComposer(new YouTubeRoomSettingsComposer(enabled).compose());
|
||||
|
||||
if (!enabled && !room.getYoutubeCurrentVideo().isEmpty()) {
|
||||
room.clearYoutubeVideo();
|
||||
room.sendComposer(new YouTubeRoomBroadcastComposer("", "", java.util.Collections.emptyList()).compose());
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package com.eu.habbo.messages.incoming.rooms.youtube;
|
||||
|
||||
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.rooms.youtube.YouTubeRoomWatchersComposer;
|
||||
|
||||
public class YouTubeRoomWatchingEvent extends MessageHandler {
|
||||
|
||||
@Override
|
||||
public int getRatelimit() {
|
||||
return 500;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle() throws Exception {
|
||||
Habbo habbo = this.client.getHabbo();
|
||||
if (habbo == null) return;
|
||||
|
||||
Room room = habbo.getHabboInfo().getCurrentRoom();
|
||||
if (room == null) return;
|
||||
|
||||
boolean watching = this.packet.readInt() == 1;
|
||||
int userId = habbo.getHabboInfo().getId();
|
||||
|
||||
boolean changed;
|
||||
if (watching) {
|
||||
changed = room.getYoutubeWatchers().add(userId);
|
||||
} else {
|
||||
changed = room.getYoutubeWatchers().remove(userId);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
room.sendComposer(
|
||||
new YouTubeRoomWatchersComposer(room.getYoutubeWatchers()).compose()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -571,4 +571,9 @@ public class Outgoing {
|
||||
public static final int ActivePrefixUpdatedComposer = 7003;
|
||||
public static final int AvailableCommandsComposer = 4050;
|
||||
|
||||
// YouTube Room Broadcast
|
||||
public static final int YouTubeRoomBroadcastComposer = 8001;
|
||||
public static final int YouTubeRoomWatchersComposer = 8002;
|
||||
public static final int YouTubeRoomSettingsComposer = 8003;
|
||||
|
||||
}
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.eu.habbo.messages.outgoing.rooms.youtube;
|
||||
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.outgoing.MessageComposer;
|
||||
import com.eu.habbo.messages.outgoing.Outgoing;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class YouTubeRoomBroadcastComposer extends MessageComposer {
|
||||
private final String videoId;
|
||||
private final String senderName;
|
||||
private final List<String> playlist;
|
||||
|
||||
public YouTubeRoomBroadcastComposer(String videoId, String senderName, List<String> playlist) {
|
||||
this.videoId = videoId;
|
||||
this.senderName = senderName;
|
||||
this.playlist = playlist;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ServerMessage composeInternal() {
|
||||
this.response.init(Outgoing.YouTubeRoomBroadcastComposer);
|
||||
this.response.appendString(this.videoId);
|
||||
this.response.appendString(this.senderName);
|
||||
this.response.appendInt(this.playlist.size());
|
||||
for (String id : this.playlist) {
|
||||
this.response.appendString(id);
|
||||
}
|
||||
return this.response;
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.eu.habbo.messages.outgoing.rooms.youtube;
|
||||
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.outgoing.MessageComposer;
|
||||
import com.eu.habbo.messages.outgoing.Outgoing;
|
||||
|
||||
public class YouTubeRoomSettingsComposer extends MessageComposer {
|
||||
private final boolean youtubeEnabled;
|
||||
|
||||
public YouTubeRoomSettingsComposer(boolean youtubeEnabled) {
|
||||
this.youtubeEnabled = youtubeEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ServerMessage composeInternal() {
|
||||
this.response.init(Outgoing.YouTubeRoomSettingsComposer);
|
||||
this.response.appendInt(this.youtubeEnabled ? 1 : 0);
|
||||
return this.response;
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.eu.habbo.messages.outgoing.rooms.youtube;
|
||||
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.outgoing.MessageComposer;
|
||||
import com.eu.habbo.messages.outgoing.Outgoing;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class YouTubeRoomWatchersComposer extends MessageComposer {
|
||||
private final Set<Integer> watcherIds;
|
||||
|
||||
public YouTubeRoomWatchersComposer(Set<Integer> watcherIds) {
|
||||
this.watcherIds = watcherIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ServerMessage composeInternal() {
|
||||
this.response.init(Outgoing.YouTubeRoomWatchersComposer);
|
||||
this.response.appendInt(this.watcherIds.size());
|
||||
for (int id : this.watcherIds) {
|
||||
this.response.appendInt(id);
|
||||
}
|
||||
return this.response;
|
||||
}
|
||||
}
|
||||
+20
-5
@@ -6,13 +6,18 @@ import com.eu.habbo.messages.ClientMessage;
|
||||
import com.eu.habbo.networking.gameserver.GameServerAttributes;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GameMessageRateLimit extends MessageToMessageDecoder<ClientMessage> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(GameMessageRateLimit.class);
|
||||
|
||||
private static final int RESET_TIME = 1;
|
||||
private static final int MAX_COUNTER = 10;
|
||||
private static final int DEFAULT_GLOBAL_MAX = 50;
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ClientMessage message, List<Object> out) throws Exception {
|
||||
@@ -23,26 +28,36 @@ public class GameMessageRateLimit extends MessageToMessageDecoder<ClientMessage>
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
int globalCount = 0;
|
||||
|
||||
// Check if reset time has passed.
|
||||
int timestamp = Emulator.getIntUnixTimestamp();
|
||||
if (timestamp - client.lastPacketCounterCleared > RESET_TIME) {
|
||||
// Reset counter.
|
||||
client.incomingPacketCounter.clear();
|
||||
client.lastPacketCounterCleared = timestamp;
|
||||
} else {
|
||||
// Get stored count for message id.
|
||||
count = client.incomingPacketCounter.getOrDefault(message.getMessageId(), 0);
|
||||
for (int c : client.incomingPacketCounter.values()) {
|
||||
globalCount += c;
|
||||
}
|
||||
}
|
||||
|
||||
// If we exceeded the counter, drop the packet.
|
||||
if (count > MAX_COUNTER) {
|
||||
return;
|
||||
}
|
||||
|
||||
int globalMax = Emulator.getConfig().getInt("packet.global.rate.limit", DEFAULT_GLOBAL_MAX);
|
||||
if (globalCount > globalMax) {
|
||||
if (globalCount == globalMax + 1) {
|
||||
String username = (client.getHabbo() != null && client.getHabbo().getHabboInfo() != null)
|
||||
? client.getHabbo().getHabboInfo().getUsername() : "unauthenticated";
|
||||
LOGGER.warn("Global packet rate limit exceeded for {} ({} packets/sec) — dropping excess packets",
|
||||
username, globalCount);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
client.incomingPacketCounter.put(message.getMessageId(), ++count);
|
||||
|
||||
// Continue processing.
|
||||
out.add(message);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user