diff --git a/README.md b/README.md index 877e6bfb..1f0a1c0f 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,8 @@ If we ever are to make paid features or plugins, we will not prevent or discoura - Thijmen - Brenoepic - Stankman + - Laynester + diff --git a/sqlupdates/3_0_0 to 3_0_1.sql b/sqlupdates/3_0_0 to 3_0_1.sql index 42ace602..248827a8 100644 --- a/sqlupdates/3_0_0 to 3_0_1.sql +++ b/sqlupdates/3_0_0 to 3_0_1.sql @@ -11,6 +11,18 @@ INSERT INTO `emulator_settings` (`key`, `value`) VALUES ('youtube.apikey', ''); INSERT INTO `emulator_settings` (`key`, `value`) VALUES ('hotel.gifts.length.max', '300'); +-- Add friendship categories table +CREATE TABLE `messenger_categories` ( + `id` int NOT NULL AUTO_INCREMENT, + `name` varchar(25) NOT NULL, + `user_id` int NOT NULL, + UNIQUE KEY `identifier` (`id`) +); + +-- Set an ID (int) from category list items +ALTER TABLE messenger_friendships ADD category int NOT NULL DEFAULT '0' AFTER friends_since; + + -- ---------------------------- -- Table structure for calendar_campaigns -- ---------------------------- diff --git a/src/main/java/com/eu/habbo/habbohotel/catalog/marketplace/MarketPlace.java b/src/main/java/com/eu/habbo/habbohotel/catalog/marketplace/MarketPlace.java index 9801eae2..7ac720d8 100644 --- a/src/main/java/com/eu/habbo/habbohotel/catalog/marketplace/MarketPlace.java +++ b/src/main/java/com/eu/habbo/habbohotel/catalog/marketplace/MarketPlace.java @@ -67,7 +67,7 @@ public class MarketPlace { if (offer != null && habbo.getInventory().getMarketplaceItems().contains(offer)) { RequestOffersEvent.cachedResults.clear(); try (Connection connection = Emulator.getDatabase().getDataSource().getConnection()) { - try (PreparedStatement ownerCheck = connection.prepareStatement("SELECT user_id FROM marketplace_items WHERE id = ?")) { + try (PreparedStatement ownerCheck = connection.prepareStatement("SELECT user_id FROM marketplace_items WHERE id = ?", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) { ownerCheck.setInt(1, offer.getOfferId()); try (ResultSet ownerSet = ownerCheck.executeQuery()) { ownerSet.last(); diff --git a/src/main/java/com/eu/habbo/habbohotel/commands/EmptyInventoryCommand.java b/src/main/java/com/eu/habbo/habbohotel/commands/EmptyInventoryCommand.java index 779dd3e5..a7a205a8 100644 --- a/src/main/java/com/eu/habbo/habbohotel/commands/EmptyInventoryCommand.java +++ b/src/main/java/com/eu/habbo/habbohotel/commands/EmptyInventoryCommand.java @@ -42,7 +42,6 @@ public class EmptyInventoryCommand extends Command { Emulator.getThreading().run(new QueryDeleteHabboItems(items)); habbo.getClient().sendResponse(new InventoryRefreshComposer()); - habbo.getClient().sendResponse(new InventoryItemsComposer(0, 1, gameClient.getHabbo().getInventory().getItemsComponent().getItems())); gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.succes.cmd_empty.cleared").replace("%username%", habbo.getHabboInfo().getUsername()), RoomChatMessageBubbles.ALERT); } else { 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 f702d68c..e62b1f0a 100644 --- a/src/main/java/com/eu/habbo/habbohotel/items/ItemManager.java +++ b/src/main/java/com/eu/habbo/habbohotel/items/ItemManager.java @@ -161,6 +161,7 @@ public class ItemManager { this.interactionsList.add(new ItemInteraction("viking_cotie", InteractionVikingCotie.class)); this.interactionsList.add(new ItemInteraction("tile_fxprovider_nfs", InteractionTileEffectProvider.class)); this.interactionsList.add(new ItemInteraction("mutearea", InteractionMuteArea.class)); + this.interactionsList.add(new ItemInteraction("buildarea", InteractionBuildArea.class)); this.interactionsList.add(new ItemInteraction("information_terminal", InteractionInformationTerminal.class)); this.interactionsList.add(new ItemInteraction("external_image", InteractionExternalImage.class)); this.interactionsList.add(new ItemInteraction("youtube", InteractionYoutubeTV.class)); diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionBuildArea.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionBuildArea.java new file mode 100644 index 00000000..015ab451 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionBuildArea.java @@ -0,0 +1,253 @@ +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.Habbo; +import com.eu.habbo.habbohotel.users.HabboInfo; +import com.eu.habbo.habbohotel.users.HabboItem; +import com.eu.habbo.habbohotel.users.HabboManager; +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.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; + +public class InteractionBuildArea extends InteractionCustomValues { + public static THashMap defaultValues = new THashMap() { + { + this.put("tilesLeft", "0"); + } + + { + this.put("tilesRight", "0"); + } + + { + this.put("tilesFront", "0"); + } + + { + this.put("tilesBack", "0"); + } + + { + this.put("builders", ""); + } + }; + + private THashSet tiles; + + public InteractionBuildArea(ResultSet set, Item baseItem) throws SQLException { + super(set, baseItem, defaultValues); + tiles = new THashSet<>(); + } + + public InteractionBuildArea(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 onPlace(Room room) { + super.onPlace(room); + this.regenAffectedTiles(room); + } + + @Override + public void onPickUp(Room room) { + super.onPickUp(room); + + ArrayList builderNames = new ArrayList<>(Arrays.asList(this.values.get("builders").split(";"))); + THashSet canBuild = new THashSet<>(); + + for (String builderName : builderNames) { + Habbo builder = Emulator.getGameEnvironment().getHabboManager().getHabbo(builderName); + HabboInfo builderInfo; + if (builder != null) { + builderInfo = builder.getHabboInfo(); + } else { + builderInfo = HabboManager.getOfflineHabboInfo(builderName); + } + if (builderInfo != null) { + canBuild.add(builderInfo.getId()); + } + } + + if (!canBuild.isEmpty()) { + for (RoomTile tile : this.tiles) { + THashSet tileItems = room.getItemsAt(tile); + for (HabboItem tileItem : tileItems) { + if (canBuild.contains(tileItem.getUserId()) && tileItem != this) { + room.pickUpItem(tileItem, null); + } + } + } + } + + this.tiles.clear(); + } + + @Override + public void onMove(Room room, RoomTile oldLocation, RoomTile newLocation) { + super.onMove(room, oldLocation, newLocation); + + ArrayList builderNames = new ArrayList<>(Arrays.asList(this.values.get("builders").split(";"))); + THashSet canBuild = new THashSet<>(); + + for (String builderName : builderNames) { + Habbo builder = Emulator.getGameEnvironment().getHabboManager().getHabbo(builderName); + HabboInfo builderInfo; + if (builder != null) { + builderInfo = builder.getHabboInfo(); + } else { + builderInfo = HabboManager.getOfflineHabboInfo(builderName); + } + if (builderInfo != null) { + canBuild.add(builderInfo.getId()); + } + } + + THashSet oldTiles = this.tiles; + THashSet newTiles = new THashSet<>(); + + int minX = Math.max(0, newLocation.x - Integer.parseInt(this.values.get("tilesBack"))); + int minY = Math.max(0, newLocation.y - Integer.parseInt(this.values.get("tilesRight"))); + int maxX = Math.min(room.getLayout().getMapSizeX(), newLocation.x + Integer.parseInt(this.values.get("tilesFront"))); + int maxY = Math.min(room.getLayout().getMapSizeY(), newLocation.y + Integer.parseInt(this.values.get("tilesLeft"))); + + 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) + newTiles.add(tile); + } + } + + if (!canBuild.isEmpty()) { + for (RoomTile tile : oldTiles) { + THashSet tileItems = room.getItemsAt(tile); + if(newTiles.contains(tile)) continue; + for (HabboItem tileItem : tileItems) { + if (canBuild.contains(tileItem.getUserId()) && tileItem != this) { + room.pickUpItem(tileItem, null); + } + } + } + } + this.regenAffectedTiles(room); + } + + public boolean inSquare(RoomTile location) { + Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()); + + if (room != null && this.tiles.size() == 0) { + regenAffectedTiles(room); + } + + return this.tiles.contains(location); + + } + + 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, THashMap oldValues) { + regenAffectedTiles(room); + ArrayList builderNames = new ArrayList<>(Arrays.asList(this.values.get("builders").split(";"))); + THashSet canBuild = new THashSet<>(); + + for (String builderName : builderNames) { + Habbo builder = Emulator.getGameEnvironment().getHabboManager().getHabbo(builderName); + HabboInfo builderInfo; + if (builder != null) { + builderInfo = builder.getHabboInfo(); + } else { + builderInfo = HabboManager.getOfflineHabboInfo(builderName); + } + if (builderInfo != null) { + canBuild.add(builderInfo.getId()); + } + } + + THashSet oldTiles = new THashSet<>(); + + int minX = Math.max(0, this.getX() - Integer.parseInt(oldValues.get("tilesBack"))); + int minY = Math.max(0, this.getY() - Integer.parseInt(oldValues.get("tilesRight"))); + int maxX = Math.min(room.getLayout().getMapSizeX(), this.getX() + Integer.parseInt(oldValues.get("tilesFront"))); + int maxY = Math.min(room.getLayout().getMapSizeY(), this.getY() + Integer.parseInt(oldValues.get("tilesLeft"))); + + 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.contains(tile)) + oldTiles.add(tile); + } + } + if (!canBuild.isEmpty()) { + for (RoomTile tile : oldTiles) { + THashSet tileItems = room.getItemsAt(tile); + for (HabboItem tileItem : tileItems) { + if (canBuild.contains(tileItem.getUserId()) && tileItem != this) { + room.pickUpItem(tileItem, null); + } + } + } + } + + // 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); + } + } + + public boolean isBuilder(String Username){ + return Arrays.asList(this.values.get("builders").split(";")).contains(Username); + } +} 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 9ef005bc..5a275c28 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 @@ -80,7 +80,7 @@ public abstract class InteractionCustomValues extends HabboItem { super.serializeExtradata(serverMessage); } - public void onCustomValuesSaved(Room room, GameClient client) { + public void onCustomValuesSaved(Room room, GameClient client, THashMap oldValues) { } } 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 29a7c0ac..beed1131 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 @@ -17,7 +17,6 @@ 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; import java.sql.SQLException; @@ -125,8 +124,8 @@ public class InteractionMuteArea extends InteractionCustomValues { } @Override - public void onCustomValuesSaved(Room room, GameClient client) { - super.onCustomValuesSaved(room, client); + public void onCustomValuesSaved(Room room, GameClient client, THashMap oldValues) { + super.onCustomValuesSaved(room, client, oldValues); this.regenAffectedTiles(room); 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 b1d3eb25..fa4603cf 100644 --- a/src/main/java/com/eu/habbo/habbohotel/messenger/Messenger.java +++ b/src/main/java/com/eu/habbo/habbohotel/messenger/Messenger.java @@ -302,7 +302,7 @@ public class Messenger { buddy.setLook(owner.getHabboInfo().getLook()); buddy.setGender(owner.getHabboInfo().getGender()); buddy.setUsername(owner.getHabboInfo().getUsername()); - habbo.getClient().sendResponse(new UpdateFriendComposer(buddy)); + habbo.getClient().sendResponse(new UpdateFriendComposer(habbo, buddy, 0)); } } } @@ -368,12 +368,12 @@ public class Messenger { return; } - habboTo.getClient().sendResponse(new UpdateFriendComposer(to)); - habboFrom.getClient().sendResponse(new UpdateFriendComposer(from)); + habboTo.getClient().sendResponse(new UpdateFriendComposer(habboTo, to, 1)); + habboFrom.getClient().sendResponse(new UpdateFriendComposer(habboFrom, from, 1)); } else if (habboTo != null) { - habboTo.getClient().sendResponse(new UpdateFriendComposer(this.loadFriend(habboTo, userFrom))); + habboTo.getClient().sendResponse(new UpdateFriendComposer(habboTo, this.loadFriend(habboTo, userFrom), 1)); } else if (habboFrom != null) { - habboFrom.getClient().sendResponse(new UpdateFriendComposer(this.loadFriend(habboFrom, userTo))); + habboFrom.getClient().sendResponse(new UpdateFriendComposer(habboFrom, this.loadFriend(habboFrom, userTo), 1)); } } } diff --git a/src/main/java/com/eu/habbo/habbohotel/messenger/MessengerBuddy.java b/src/main/java/com/eu/habbo/habbohotel/messenger/MessengerBuddy.java index e68eefb5..d879d004 100644 --- a/src/main/java/com/eu/habbo/habbohotel/messenger/MessengerBuddy.java +++ b/src/main/java/com/eu/habbo/habbohotel/messenger/MessengerBuddy.java @@ -25,6 +25,7 @@ public class MessengerBuddy implements Runnable, ISerialize { private String look = ""; private String motto = ""; private short relation; + private int categoryId = 0; private boolean inRoom; private int userOne = 0; @@ -37,6 +38,7 @@ public class MessengerBuddy implements Runnable, ISerialize { this.motto = set.getString("motto"); this.look = set.getString("look"); this.relation = (short) set.getInt("relation"); + this.categoryId = set.getInt("category"); this.userOne = set.getInt("user_one_id"); this.inRoom = false; if (this.online == 1) { @@ -136,6 +138,8 @@ public class MessengerBuddy implements Runnable, ISerialize { Emulator.getThreading().run(this); } + public int getCategoryId() { return this.categoryId; } + public boolean inRoom() { return this.inRoom; } @@ -181,7 +185,7 @@ public class MessengerBuddy implements Runnable, ISerialize { message.appendBoolean(this.online == 1); message.appendBoolean(this.inRoom); //IN ROOM message.appendString(this.look); - message.appendInt(0); // Friends category ID + message.appendInt(this.categoryId); // Friends category ID message.appendString(this.motto); message.appendString(""); //Last seen as DATETIMESTRING message.appendString(""); // Realname or Facebookame as String diff --git a/src/main/java/com/eu/habbo/habbohotel/messenger/MessengerCategory.java b/src/main/java/com/eu/habbo/habbohotel/messenger/MessengerCategory.java new file mode 100644 index 00000000..b19a43b0 --- /dev/null +++ b/src/main/java/com/eu/habbo/habbohotel/messenger/MessengerCategory.java @@ -0,0 +1,31 @@ +package com.eu.habbo.habbohotel.messenger; + +public class MessengerCategory { + private int user_id; + private String name; + private int id; + + public MessengerCategory(String name, int user_id, int id) { + this.name = name; + this.user_id = user_id; + this.id = id; + } + + public String getName() { + return name; + } + + public int getUserId() { + return user_id; + } + + public int getId() { + return id; + } + + public void setName(String name) { + this.name = name; + } + public void setId(int id) { this.id = id; } +} + diff --git a/src/main/java/com/eu/habbo/habbohotel/navigation/NavigatorManager.java b/src/main/java/com/eu/habbo/habbohotel/navigation/NavigatorManager.java index 5745834d..5c16598e 100644 --- a/src/main/java/com/eu/habbo/habbohotel/navigation/NavigatorManager.java +++ b/src/main/java/com/eu/habbo/habbohotel/navigation/NavigatorManager.java @@ -80,7 +80,7 @@ public class NavigatorManager { Class clazz = Room.class; if (set.getString("field").contains(".")) { - for (String s : (set.getString("field")).split(".")) { + for (String s : (set.getString("field")).split("\\.")) { try { field = clazz.getDeclaredMethod(s); clazz = field.getReturnType(); 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 af82a1ae..09c54558 100644 --- a/src/main/java/com/eu/habbo/habbohotel/rooms/Room.java +++ b/src/main/java/com/eu/habbo/habbohotel/rooms/Room.java @@ -2407,6 +2407,8 @@ public class Room implements Comparable, ISerialize, Runnable { this.roomSpecialTypes.addUndefined(item); } else if (item instanceof InteractionMuteArea) { this.roomSpecialTypes.addUndefined(item); + } else if (item instanceof InteractionBuildArea) { + this.roomSpecialTypes.addUndefined(item); } else if (item instanceof InteractionTagPole) { this.roomSpecialTypes.addUndefined(item); } else if (item instanceof InteractionTagField) { @@ -4487,6 +4489,12 @@ public class Room implements Comparable, ISerialize, Runnable { } } + for (HabboItem area : this.getRoomSpecialTypes().getItemsOfType(InteractionBuildArea.class)) { + if (((InteractionBuildArea) area).inSquare(tile) && ((InteractionBuildArea) area).isBuilder(habbo.getHabboInfo().getUsername())) { + return FurnitureMovementError.NONE; + } + } + return FurnitureMovementError.NO_RIGHTS; } diff --git a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomChatMessage.java b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomChatMessage.java index ba845ba4..294d2749 100644 --- a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomChatMessage.java +++ b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomChatMessage.java @@ -56,6 +56,7 @@ public class RoomChatMessage implements Runnable, ISerialize, DatabaseLoggable { for (Integer i : RoomChatMessage.BANNED_BUBBLES) { if (i == this.bubble.getType()) { this.bubble = RoomChatMessageBubbles.NORMAL; + break; } } } diff --git a/src/main/java/com/eu/habbo/habbohotel/users/HabboBadge.java b/src/main/java/com/eu/habbo/habbohotel/users/HabboBadge.java index 5903cdc5..18176593 100644 --- a/src/main/java/com/eu/habbo/habbohotel/users/HabboBadge.java +++ b/src/main/java/com/eu/habbo/habbohotel/users/HabboBadge.java @@ -57,6 +57,9 @@ public class HabboBadge implements Runnable { public void run() { try { if (this.needsInsert) { + if (this.habbo.getInventory().getBadgesComponent().hasBadge(this.code)) + return; + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("INSERT INTO users_badges (user_id, slot_id, badge_code) VALUES (?, ?, ?)", Statement.RETURN_GENERATED_KEYS)) { statement.setInt(1, this.habbo.getHabboInfo().getId()); statement.setInt(2, this.slot); diff --git a/src/main/java/com/eu/habbo/habbohotel/users/HabboInfo.java b/src/main/java/com/eu/habbo/habbohotel/users/HabboInfo.java index a7fd28a5..8c166631 100644 --- a/src/main/java/com/eu/habbo/habbohotel/users/HabboInfo.java +++ b/src/main/java/com/eu/habbo/habbohotel/users/HabboInfo.java @@ -4,6 +4,7 @@ import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.catalog.CatalogItem; import com.eu.habbo.habbohotel.games.Game; import com.eu.habbo.habbohotel.games.GamePlayer; +import com.eu.habbo.habbohotel.messenger.MessengerCategory; import com.eu.habbo.habbohotel.navigation.NavigatorSavedSearch; import com.eu.habbo.habbohotel.permissions.Rank; import com.eu.habbo.habbohotel.pets.PetTasks; @@ -55,6 +56,7 @@ public class HabboInfo implements Runnable { private int webPublishTimestamp; private String machineID; private List savedSearches = new ArrayList<>(); + private List messengerCategories = new ArrayList<>(); public HabboInfo(ResultSet set) { try { @@ -88,6 +90,7 @@ public class HabboInfo implements Runnable { this.loadCurrencies(); this.loadSavedSearches(); + this.loadMessengerCategories(); } private void loadCurrencies() { @@ -179,6 +182,56 @@ public class HabboInfo implements Runnable { } } + private void loadMessengerCategories() { + this.messengerCategories = new ArrayList<>(); + + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT * FROM messenger_categories WHERE user_id = ?")) { + statement.setInt(1, this.id); + try (ResultSet set = statement.executeQuery()) { + while (set.next()) { + this.messengerCategories.add(new MessengerCategory(set.getString("name"), set.getInt("user_id"), set.getInt("id"))); + } + } + } catch (SQLException e) { + LOGGER.error("Caught SQL exception", e); + } + } + + public void addMessengerCategory(MessengerCategory category) { + this.messengerCategories.add(category); + + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("INSERT INTO messenger_categories (name, user_id) VALUES (?, ?)", Statement.RETURN_GENERATED_KEYS)) { + statement.setString(1, category.getName()); + statement.setInt(2, this.id); + int affectedRows = statement.executeUpdate(); + + if (affectedRows == 0) { + throw new SQLException("Creating messenger category failed, no rows affected."); + } + + try (ResultSet generatedKeys = statement.getGeneratedKeys()) { + if (generatedKeys.next()) { + category.setId(generatedKeys.getInt(1)); + } else { + throw new SQLException("Creating messenger category failed, no ID found."); + } + } + } catch (SQLException e) { + LOGGER.error("Caught SQL exception", e); + } + } + + public void deleteMessengerCategory(MessengerCategory category) { + this.messengerCategories.remove(category); + + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("DELETE FROM messenger_categories WHERE id = ?")) { + statement.setInt(1, category.getId()); + statement.execute(); + } catch (SQLException e) { + LOGGER.error("Caught SQL exception", e); + } + } + public int getCurrencyAmount(int type) { return this.currencies.get(type); } @@ -478,6 +531,8 @@ public class HabboInfo implements Runnable { return this.savedSearches; } + public List getMessengerCategories() { return this.messengerCategories; } + @Override public void run() { this.saveCurrencies(); diff --git a/src/main/java/com/eu/habbo/habbohotel/users/inventory/BadgesComponent.java b/src/main/java/com/eu/habbo/habbohotel/users/inventory/BadgesComponent.java index 02573ff4..845ba2cb 100644 --- a/src/main/java/com/eu/habbo/habbohotel/users/inventory/BadgesComponent.java +++ b/src/main/java/com/eu/habbo/habbohotel/users/inventory/BadgesComponent.java @@ -160,7 +160,8 @@ public class BadgesComponent { public void addBadge(HabboBadge badge) { synchronized (this.badges) { - this.badges.add(badge); + if (!this.hasBadge(badge.getCode())) + this.badges.add(badge); } } 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 1cb10037..14a7915e 100644 --- a/src/main/java/com/eu/habbo/habbohotel/wired/WiredHandler.java +++ b/src/main/java/com/eu/habbo/habbohotel/wired/WiredHandler.java @@ -374,7 +374,7 @@ public class WiredHandler { } } - try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT COUNT(*) as row_count, wired_rewards_given.* FROM wired_rewards_given WHERE user_id = ? AND wired_item = ? ORDER BY timestamp DESC LIMIT ?")) { + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT COUNT(*) as row_count, wired_rewards_given.* FROM wired_rewards_given WHERE user_id = ? AND wired_item = ? ORDER BY timestamp DESC LIMIT ?", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) { statement.setInt(1, habbo.getHabboInfo().getId()); statement.setInt(2, wiredBox.getId()); statement.setInt(3, wiredBox.rewardItems.size()); diff --git a/src/main/java/com/eu/habbo/messages/incoming/friends/ChangeRelationEvent.java b/src/main/java/com/eu/habbo/messages/incoming/friends/ChangeRelationEvent.java index cb02842f..d2790194 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/friends/ChangeRelationEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/friends/ChangeRelationEvent.java @@ -16,7 +16,7 @@ public class ChangeRelationEvent extends MessageHandler { UserRelationShipEvent event = new UserRelationShipEvent(this.client.getHabbo(), buddy, relationId); if (!event.isCancelled()) { buddy.setRelation(event.relationShip); - this.client.sendResponse(new UpdateFriendComposer(buddy)); + this.client.sendResponse(new UpdateFriendComposer(this.client.getHabbo(), buddy, 0)); } } } diff --git a/src/main/java/com/eu/habbo/messages/incoming/inventory/RequestInventoryItemsEvent.java b/src/main/java/com/eu/habbo/messages/incoming/inventory/RequestInventoryItemsEvent.java index 2b9641cb..f5047b72 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/inventory/RequestInventoryItemsEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/inventory/RequestInventoryItemsEvent.java @@ -17,20 +17,23 @@ public class RequestInventoryItemsEvent extends MessageHandler { @Override public void handle() throws Exception { int totalItems = this.client.getHabbo().getInventory().getItemsComponent().getItems().size(); - int pages = (int) Math.ceil((double) totalItems / 1000.0); + int totalFragments = (int) Math.ceil((double) totalItems / 1000.0); - if (pages == 0) { - pages = 1; + if (totalFragments == 0) { + totalFragments = 1; } synchronized (this.client.getHabbo().getInventory().getItemsComponent().getItems()) { TIntObjectMap items = new TIntObjectHashMap<>(); TIntObjectIterator iterator = this.client.getHabbo().getInventory().getItemsComponent().getItems().iterator(); + int count = 0; - int page = 0; + int fragmentNumber = 0; + for (int i = this.client.getHabbo().getInventory().getItemsComponent().getItems().size(); i-- > 0; ) { + if (count == 0) { - page++; + fragmentNumber++; } try { @@ -43,13 +46,13 @@ public class RequestInventoryItemsEvent extends MessageHandler { } if (count == 1000) { - this.client.sendResponse(new InventoryItemsComposer(page, pages, items)); + this.client.sendResponse(new InventoryItemsComposer(fragmentNumber, totalFragments, items)); count = 0; items.clear(); } } - this.client.sendResponse(new InventoryItemsComposer(page, pages, items)); + if(count > 0 && items.size() > 0) this.client.sendResponse(new InventoryItemsComposer(fragmentNumber, totalFragments, items)); } } } 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 d705f8ff..b25f3792 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 @@ -6,6 +6,9 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionRoomAds; import com.eu.habbo.habbohotel.rooms.Room; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.messages.incoming.MessageHandler; +import gnu.trove.map.hash.THashMap; + +import java.util.Map; public class AdvertisingSaveEvent extends MessageHandler { @Override @@ -26,6 +29,7 @@ public class AdvertisingSaveEvent extends MessageHandler { return; } if (item instanceof InteractionCustomValues) { + THashMap oldValues = new THashMap<>(((InteractionCustomValues) item).values); int count = this.packet.readInt(); for (int i = 0; i < count / 2; i++) { String key = this.packet.readString(); @@ -42,7 +46,7 @@ public class AdvertisingSaveEvent extends MessageHandler { item.needsUpdate(true); Emulator.getThreading().run(item); room.updateItem(item); - ((InteractionCustomValues) item).onCustomValuesSaved(room, this.client); + ((InteractionCustomValues) item).onCustomValuesSaved(room, this.client, oldValues); } } } diff --git a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/RoomPlaceItemEvent.java b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/RoomPlaceItemEvent.java index 8cdeb7d0..0f293184 100644 --- a/src/main/java/com/eu/habbo/messages/incoming/rooms/items/RoomPlaceItemEvent.java +++ b/src/main/java/com/eu/habbo/messages/incoming/rooms/items/RoomPlaceItemEvent.java @@ -3,10 +3,7 @@ package com.eu.habbo.messages.incoming.rooms.items; import com.eu.habbo.habbohotel.items.FurnitureType; import com.eu.habbo.habbohotel.items.interactions.*; import com.eu.habbo.habbohotel.modtool.ScripterManager; -import com.eu.habbo.habbohotel.rooms.FurnitureMovementError; -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.*; import com.eu.habbo.habbohotel.users.HabboItem; import com.eu.habbo.messages.incoming.MessageHandler; import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertComposer; @@ -20,7 +17,7 @@ public class RoomPlaceItemEvent extends MessageHandler { int itemId = -1; - if (values.length != 0) itemId = Integer.valueOf(values[0]); + if (values.length != 0) itemId = Integer.parseInt(values[0]); if (!this.client.getHabbo().getRoomUnit().isInRoom()) { this.client.sendResponse(new BubbleAlertComposer(BubbleAlertKeys.FURNITURE_PLACEMENT_ERROR.key, FurnitureMovementError.NO_RIGHTS.errorCode)); @@ -56,27 +53,9 @@ public class RoomPlaceItemEvent extends MessageHandler { } if (item.getBaseItem().getType() == FurnitureType.FLOOR) { - short x = Short.valueOf(values[1]); - short y = Short.valueOf(values[2]); - int rotation = Integer.valueOf(values[3]); - if (rentSpace != null && !room.hasRights(this.client.getHabbo())) { - if (item instanceof InteractionRoller || - item instanceof InteractionStackHelper || - item instanceof InteractionWired || - item instanceof InteractionBackgroundToner || - item instanceof InteractionRoomAds || - item instanceof InteractionCannon || - item instanceof InteractionPuzzleBox || - item.getBaseItem().getType() == FurnitureType.WALL) { - this.client.sendResponse(new BubbleAlertComposer(BubbleAlertKeys.FURNITURE_PLACEMENT_ERROR.key, FurnitureMovementError.NO_RIGHTS.errorCode)); - return; - } - - if (!RoomLayout.squareInSquare(RoomLayout.getRectangle(rentSpace.getX(), rentSpace.getY(), rentSpace.getBaseItem().getWidth(), rentSpace.getBaseItem().getLength(), rentSpace.getRotation()), RoomLayout.getRectangle(x, y, item.getBaseItem().getWidth(), item.getBaseItem().getLength(), rotation))) { - this.client.sendResponse(new BubbleAlertComposer(BubbleAlertKeys.FURNITURE_PLACEMENT_ERROR.key, FurnitureMovementError.NO_RIGHTS.errorCode)); - return; - } - } + short x = Short.parseShort(values[1]); + short y = Short.parseShort(values[2]); + int rotation = Integer.parseInt(values[3]); RoomTile tile = room.getLayout().getTile(x, y); @@ -88,6 +67,30 @@ public class RoomPlaceItemEvent extends MessageHandler { return; } + HabboItem buildArea = null; + for (HabboItem area : room.getRoomSpecialTypes().getItemsOfType(InteractionBuildArea.class)) { + if (((InteractionBuildArea) area).inSquare(tile)) { + buildArea = area; + } + } + + if ((rentSpace != null || buildArea != null) && !room.hasRights(this.client.getHabbo())) { + if (item instanceof InteractionRoller || + item instanceof InteractionStackHelper || + item instanceof InteractionWired || + item instanceof InteractionBackgroundToner || + item instanceof InteractionRoomAds || + item instanceof InteractionCannon || + item instanceof InteractionPuzzleBox || + item.getBaseItem().getType() == FurnitureType.WALL) { + this.client.sendResponse(new BubbleAlertComposer(BubbleAlertKeys.FURNITURE_PLACEMENT_ERROR.key, FurnitureMovementError.NO_RIGHTS.errorCode)); + return; + } + if (rentSpace != null && !RoomLayout.squareInSquare(RoomLayout.getRectangle(rentSpace.getX(), rentSpace.getY(), rentSpace.getBaseItem().getWidth(), rentSpace.getBaseItem().getLength(), rentSpace.getRotation()), RoomLayout.getRectangle(x, y, item.getBaseItem().getWidth(), item.getBaseItem().getLength(), rotation))) { + this.client.sendResponse(new BubbleAlertComposer(BubbleAlertKeys.FURNITURE_PLACEMENT_ERROR.key, FurnitureMovementError.NO_RIGHTS.errorCode)); + return; + } + } FurnitureMovementError error = room.canPlaceFurnitureAt(item, this.client.getHabbo(), tile, rotation); if (!error.equals(FurnitureMovementError.NONE)) { 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 2fd69a9a..287e87cb 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 @@ -41,10 +41,10 @@ public class FriendsComposer extends MessageComposer { 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.appendInt(row.getCategoryId()); //Friends category this.response.appendString(row.getMotto()); - this.response.appendString(""); - this.response.appendString(""); + this.response.appendString(""); //Last seen as DATETIMESTRING + this.response.appendString(""); //Realname or Facebookame as String this.response.appendBoolean(false); //Offline messaging. this.response.appendBoolean(false); this.response.appendBoolean(false); diff --git a/src/main/java/com/eu/habbo/messages/outgoing/friends/MessengerInitComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/friends/MessengerInitComposer.java index a48e6e65..de3b9206 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/friends/MessengerInitComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/friends/MessengerInitComposer.java @@ -1,11 +1,15 @@ package com.eu.habbo.messages.outgoing.friends; +import com.eu.habbo.Emulator; import com.eu.habbo.habbohotel.messenger.Messenger; +import com.eu.habbo.habbohotel.messenger.MessengerCategory; 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.List; + public class MessengerInitComposer extends MessageComposer { private final Habbo habbo; @@ -15,6 +19,7 @@ public class MessengerInitComposer extends MessageComposer { @Override protected ServerMessage composeInternal() { + this.response.init(Outgoing.MessengerInitComposer); if (this.habbo.hasPermission("acc_infinite_friends")) { this.response.appendInt(Integer.MAX_VALUE); @@ -25,9 +30,19 @@ public class MessengerInitComposer extends MessageComposer { this.response.appendInt(1337); this.response.appendInt(Messenger.MAXIMUM_FRIENDS_HC); } + if (!this.habbo.getHabboInfo().getMessengerCategories().isEmpty()) { - //this.response.appendInt(1000); - this.response.appendInt(0); + List messengerCategories = this.habbo.getHabboInfo().getMessengerCategories(); + this.response.appendInt(messengerCategories.size()); + + for (MessengerCategory mc : messengerCategories) { + this.response.appendInt(mc.getId()); + this.response.appendString(mc.getName()); + } + } else { + this.response.appendInt(0); + } return this.response; } } + diff --git a/src/main/java/com/eu/habbo/messages/outgoing/friends/UpdateFriendComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/friends/UpdateFriendComposer.java index 907fa9a0..1be0b1ac 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/friends/UpdateFriendComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/friends/UpdateFriendComposer.java @@ -1,6 +1,11 @@ package com.eu.habbo.messages.outgoing.friends; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + import com.eu.habbo.habbohotel.messenger.MessengerBuddy; +import com.eu.habbo.habbohotel.messenger.MessengerCategory; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboGender; import com.eu.habbo.messages.ServerMessage; @@ -8,60 +13,65 @@ import com.eu.habbo.messages.outgoing.MessageComposer; import com.eu.habbo.messages.outgoing.Outgoing; public class UpdateFriendComposer extends MessageComposer { - private MessengerBuddy buddy; + private Collection buddies; private Habbo habbo; + private int action; - public UpdateFriendComposer(MessengerBuddy buddy) { - this.buddy = buddy; + public UpdateFriendComposer(Habbo habbo, MessengerBuddy buddy, Integer action) { + this.habbo = habbo; + this.buddies = Collections.singletonList(buddy); + this.action = action; } - - public UpdateFriendComposer(Habbo habbo) { + public UpdateFriendComposer(Habbo habbo, Collection buddies, Integer action) { this.habbo = habbo; + this.buddies = buddies; + this.action = action; } @Override protected ServerMessage composeInternal() { this.response.init(Outgoing.UpdateFriendComposer); - if (this.buddy != null) { - this.response.appendInt(0); - this.response.appendInt(1); - this.response.appendInt(0); - this.response.appendInt(this.buddy.getId()); - this.response.appendString(this.buddy.getUsername()); - this.response.appendInt(this.buddy.getGender().equals(HabboGender.M) ? 0 : 1); - this.response.appendBoolean(this.buddy.getOnline() == 1); - this.response.appendBoolean(this.buddy.inRoom()); //In room - this.response.appendString(this.buddy.getLook()); - this.response.appendInt(0); - this.response.appendString(this.buddy.getMotto()); - this.response.appendString(""); - this.response.appendString(""); - this.response.appendBoolean(false); - this.response.appendBoolean(false); - this.response.appendBoolean(false); - this.response.appendShort(this.buddy.getRelation()); + if (this.habbo != null && !this.habbo.getHabboInfo().getMessengerCategories().isEmpty()) { + + List messengerCategories = this.habbo.getHabboInfo().getMessengerCategories(); + this.response.appendInt(messengerCategories.size()); + + for (MessengerCategory mc : messengerCategories) { + this.response.appendInt(mc.getId()); + this.response.appendString(mc.getName()); + } } else { this.response.appendInt(0); - this.response.appendInt(1); - this.response.appendInt(0); - this.response.appendInt(-1); - this.response.appendString("Staff Chat"); - this.response.appendInt(0); - this.response.appendBoolean(true); - this.response.appendBoolean(false); //In room - this.response.appendString(this.habbo.getHabboInfo().getLook()); - this.response.appendInt(0); - this.response.appendString(""); - this.response.appendString(""); - this.response.appendString(""); - this.response.appendBoolean(false); - this.response.appendBoolean(false); - this.response.appendBoolean(false); - this.response.appendShort(0); } + + this.response.appendInt(buddies.size()); // totalbuddies + + for(MessengerBuddy buddy : buddies){ + + if (buddy != null) { + this.response.appendInt(this.action); // -1 = removed friendId / 0 = updated friend / 1 = added friend + this.response.appendInt(buddy.getId()); + if (this.action == -1) { + continue; + } + this.response.appendString(buddy.getUsername()); + this.response.appendInt(buddy.getGender().equals(HabboGender.M) ? 0 : 1); + this.response.appendBoolean(buddy.getOnline() == 1); + this.response.appendBoolean(buddy.inRoom()); //In room + this.response.appendString(buddy.getLook()); + this.response.appendInt(buddy.getCategoryId()); + this.response.appendString(buddy.getMotto()); + this.response.appendString(""); //Last seen as DATETIMESTRING + this.response.appendString(""); //Realname or Facebookame as String + this.response.appendBoolean(false); //Offline messaging. + this.response.appendBoolean(false); + this.response.appendBoolean(false); + this.response.appendShort(buddy.getRelation()); + } + } return this.response; } } diff --git a/src/main/java/com/eu/habbo/messages/outgoing/inventory/InventoryItemsComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/inventory/InventoryItemsComposer.java index 258ce1a9..a8a24ed0 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/inventory/InventoryItemsComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/inventory/InventoryItemsComposer.java @@ -14,13 +14,13 @@ import org.slf4j.LoggerFactory; public class InventoryItemsComposer extends MessageComposer implements TIntObjectProcedure { private static final Logger LOGGER = LoggerFactory.getLogger(InventoryItemsComposer.class); - private final int page; - private final int out; + private final int fragmentNumber; + private final int totalFragments; private final TIntObjectMap items; - public InventoryItemsComposer(int page, int out, TIntObjectMap items) { - this.page = page; - this.out = out; + public InventoryItemsComposer(int fragmentNumber, int totalFragments, TIntObjectMap items) { + this.fragmentNumber = fragmentNumber; + this.totalFragments = totalFragments; this.items = items; } @@ -28,8 +28,8 @@ public class InventoryItemsComposer extends MessageComposer implements TIntObjec protected ServerMessage composeInternal() { try { this.response.init(Outgoing.InventoryItemsComposer); - this.response.appendInt(this.out); - this.response.appendInt(this.page - 1); + this.response.appendInt(this.totalFragments); + this.response.appendInt(this.fragmentNumber - 1); this.response.appendInt(this.items.size()); this.items.forEachEntry(this); diff --git a/src/main/java/com/eu/habbo/messages/outgoing/rooms/RoomDataComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/rooms/RoomDataComposer.java index 7dea5e9f..895cacc6 100644 --- a/src/main/java/com/eu/habbo/messages/outgoing/rooms/RoomDataComposer.java +++ b/src/main/java/com/eu/habbo/messages/outgoing/rooms/RoomDataComposer.java @@ -39,8 +39,8 @@ public class RoomDataComposer extends MessageComposer { this.response.appendInt(this.room.getUsersMax()); this.response.appendString(this.room.getDescription()); this.response.appendInt(this.room.getTradeMode()); - this.response.appendInt(2); this.response.appendInt(this.room.getScore()); + this.response.appendInt(2);//Top rated room rank this.response.appendInt(this.room.getCategory()); if (!this.room.getTags().isEmpty()) {