diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/db_installer/sql/game/collection_favorites.sql b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/db_installer/sql/game/collection_favorites.sql
new file mode 100644
index 0000000000..7571da448f
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/db_installer/sql/game/collection_favorites.sql
@@ -0,0 +1,6 @@
+DROP TABLE IF EXISTS `collection_favorites`;
+CREATE TABLE IF NOT EXISTS `collection_favorites` (
+ `accountName` VARCHAR(45) NOT NULL DEFAULT '',
+ `collectionId` int(3) UNSIGNED NOT NULL DEFAULT 0,
+ PRIMARY KEY (`accountName`,`collectionId`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/db_installer/sql/game/collections.sql b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/db_installer/sql/game/collections.sql
new file mode 100644
index 0000000000..8c0fafc9fd
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/db_installer/sql/game/collections.sql
@@ -0,0 +1,8 @@
+DROP TABLE IF EXISTS `collections`;
+CREATE TABLE IF NOT EXISTS `collections` (
+ `accountName` VARCHAR(45) NOT NULL DEFAULT '',
+ `itemId` int(11) UNSIGNED NOT NULL DEFAULT 0,
+ `collectionId` int(3) UNSIGNED NOT NULL DEFAULT 0,
+ `index` tinyint(3) UNSIGNED NOT NULL DEFAULT 0,
+ PRIMARY KEY (`accountName`,`collectionId`,`index`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/CollectionData.xml b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/CollectionData.xml
new file mode 100644
index 0000000000..15b867ca51
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/CollectionData.xml
@@ -0,0 +1,658 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/xsd/CollectionData.xsd b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/xsd/CollectionData.xsd
new file mode 100644
index 0000000000..814f7bbe29
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/xsd/CollectionData.xsd
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/GameServer.java
index 9a74a0e016..f471b93fa4 100644
--- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/GameServer.java
@@ -59,6 +59,7 @@ import org.l2jmobius.gameserver.data.xml.ClanHallData;
import org.l2jmobius.gameserver.data.xml.ClanMasteryData;
import org.l2jmobius.gameserver.data.xml.ClanShopData;
import org.l2jmobius.gameserver.data.xml.ClassListData;
+import org.l2jmobius.gameserver.data.xml.CollectionData;
import org.l2jmobius.gameserver.data.xml.CombinationItemsData;
import org.l2jmobius.gameserver.data.xml.CubicData;
import org.l2jmobius.gameserver.data.xml.DailyMissionData;
@@ -283,6 +284,7 @@ public class GameServer
FishingData.getInstance();
HennaData.getInstance();
PrimeShopData.getInstance();
+ CollectionData.getInstance();
PcCafePointsManager.getInstance();
AppearanceItemData.getInstance();
AlchemyData.getInstance();
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/data/xml/CollectionData.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/data/xml/CollectionData.java
new file mode 100644
index 0000000000..020d270f53
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/data/xml/CollectionData.java
@@ -0,0 +1,136 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.data.xml;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.data.ItemTable;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.holders.CollectionDataHolder;
+import org.l2jmobius.gameserver.model.holders.ItemCollectionData;
+import org.l2jmobius.gameserver.model.items.Item;
+
+/**
+ * Written by Berezkin Nikolay, on 04.05.2021
+ */
+public class CollectionData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(CollectionData.class.getName());
+
+ private static final Map _collections = new HashMap<>();
+
+ protected CollectionData()
+ {
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ _collections.clear();
+ parseDatapackFile("data/CollectionData.xml");
+
+ if (!_collections.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _collections.size() + " collections.");
+ }
+ else
+ {
+ LOGGER.info(getClass().getSimpleName() + ": System is disabled.");
+ }
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
+ {
+ if ("list".equalsIgnoreCase(n.getNodeName()))
+ {
+ for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
+ {
+ if ("collection".equalsIgnoreCase(d.getNodeName()))
+ {
+ NamedNodeMap attrs = d.getAttributes();
+ Node att;
+ final StatSet set = new StatSet();
+ for (int i = 0; i < attrs.getLength(); i++)
+ {
+ att = attrs.item(i);
+ set.set(att.getNodeName(), att.getNodeValue());
+ }
+
+ final int id = parseInteger(attrs, "id");
+ final int optionId = parseInteger(attrs, "optionId");
+ final int category = parseInteger(attrs, "category");
+ List items = new ArrayList<>();
+ for (Node b = d.getFirstChild(); b != null; b = b.getNextSibling())
+ {
+ attrs = b.getAttributes();
+ if ("item".equalsIgnoreCase(b.getNodeName()))
+ {
+ final int itemId = parseInteger(attrs, "id");
+ final long itemCount = parseLong(attrs, "count", 1L);
+ final int itemEnchantLevel = parseInteger(attrs, "enchant_level", 0);
+ final Item item = ItemTable.getInstance().getTemplate(itemId);
+ if (item == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Item template null for itemId: " + itemId + " collection item: " + id);
+ continue;
+ }
+ items.add(new ItemCollectionData(itemId, itemCount, itemEnchantLevel));
+ }
+ }
+
+ _collections.put(id, new CollectionDataHolder(id, optionId, category, items));
+ }
+ }
+ }
+ }
+ }
+
+ public CollectionDataHolder getCollection(int id)
+ {
+ return _collections.get(id);
+ }
+
+ public Collection getCollections()
+ {
+ return _collections.values();
+ }
+
+ public static CollectionData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final CollectionData INSTANCE = new CollectionData();
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
index df54a691eb..4d278d44b5 100644
--- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
@@ -68,10 +68,12 @@ import org.l2jmobius.gameserver.data.xml.AdminData;
import org.l2jmobius.gameserver.data.xml.AttendanceRewardData;
import org.l2jmobius.gameserver.data.xml.CategoryData;
import org.l2jmobius.gameserver.data.xml.ClassListData;
+import org.l2jmobius.gameserver.data.xml.CollectionData;
import org.l2jmobius.gameserver.data.xml.ExperienceData;
import org.l2jmobius.gameserver.data.xml.HennaData;
import org.l2jmobius.gameserver.data.xml.NpcData;
import org.l2jmobius.gameserver.data.xml.NpcNameLocalisationData;
+import org.l2jmobius.gameserver.data.xml.OptionData;
import org.l2jmobius.gameserver.data.xml.PetDataTable;
import org.l2jmobius.gameserver.data.xml.PlayerTemplateData;
import org.l2jmobius.gameserver.data.xml.PlayerXpPercentLostData;
@@ -218,10 +220,12 @@ import org.l2jmobius.gameserver.model.fishing.Fishing;
import org.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
import org.l2jmobius.gameserver.model.holders.AutoPlaySettingsHolder;
import org.l2jmobius.gameserver.model.holders.AutoUseSettingsHolder;
+import org.l2jmobius.gameserver.model.holders.CollectionDataHolder;
import org.l2jmobius.gameserver.model.holders.DamageTakenHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.ItemSkillHolder;
import org.l2jmobius.gameserver.model.holders.MovieHolder;
+import org.l2jmobius.gameserver.model.holders.PlayerCollectionData;
import org.l2jmobius.gameserver.model.holders.PlayerEventHolder;
import org.l2jmobius.gameserver.model.holders.PreparedMultisellListHolder;
import org.l2jmobius.gameserver.model.holders.RecipeHolder;
@@ -253,6 +257,7 @@ import org.l2jmobius.gameserver.model.olympiad.Hero;
import org.l2jmobius.gameserver.model.olympiad.OlympiadGameManager;
import org.l2jmobius.gameserver.model.olympiad.OlympiadGameTask;
import org.l2jmobius.gameserver.model.olympiad.OlympiadManager;
+import org.l2jmobius.gameserver.model.options.Options;
import org.l2jmobius.gameserver.model.punishment.PunishmentAffect;
import org.l2jmobius.gameserver.model.punishment.PunishmentTask;
import org.l2jmobius.gameserver.model.punishment.PunishmentType;
@@ -415,6 +420,14 @@ public class PlayerInstance extends Playable
// Character Shortcut SQL String Definitions:
private static final String DELETE_CHAR_SHORTCUTS = "DELETE FROM character_shortcuts WHERE charId=? AND class_index=?";
+ // Character Collections list
+ private static final String DELETE_COLLECTION = "DELETE FROM collections WHERE accountName=?";
+ private static final String INSERT_COLLECTION = "REPLACE INTO collections (`accountName`, `itemId`, `collectionId`, `index`) VALUES (?, ?, ?, ?)";
+ private static final String RESTORE_COLLECTION = "SELECT * FROM collections WHERE accountName=? ORDER BY `index`";
+ private static final String DELETE_COLLECTION_FAVORITE = "DELETE FROM collection_favorites WHERE accountName=?";
+ private static final String INSERT_COLLECTION_FAVORITE = "REPLACE INTO collection_favorites (`accountName`, `collectionId`) VALUES (?, ?)";
+ private static final String RESTORE_COLLECTION_FAVORITE = "SELECT * FROM collection_favorites WHERE accountName=?";
+
// Character Recipe List Save
private static final String DELETE_CHAR_RECIPE_SHOP = "DELETE FROM character_recipeshoplist WHERE charId=?";
private static final String INSERT_CHAR_RECIPE_SHOP = "REPLACE INTO character_recipeshoplist (`charId`, `recipeId`, `price`, `index`) VALUES (?, ?, ?, ?)";
@@ -889,6 +902,9 @@ public class PlayerInstance extends Playable
private int _homunculusDefBonus;
private float _homunculusCritBonus;
+ private final List _collections = new ArrayList<>();
+ private final List _collectionFavorites = new ArrayList<>();
+
private final List _questTimers = new ArrayList<>();
private final List> _timerHolders = new ArrayList<>();
@@ -6944,6 +6960,11 @@ public class PlayerInstance extends Playable
restoreRecipeShopList();
}
+ // Restore collections.
+ restoreCollections();
+ restoreCollectionBonuses();
+ restoreCollectionFavorites();
+
// Load Premium Item List.
loadPremiumItemList();
@@ -7091,6 +7112,10 @@ public class PlayerInstance extends Playable
storeRecipeShopList();
}
+ // Store collections.
+ storeCollections();
+ storeCollectionFavorites();
+
final PlayerVariables vars = getScript(PlayerVariables.class);
if (vars != null)
{
@@ -14400,6 +14425,165 @@ public class PlayerInstance extends Playable
return Math.max(getVariables().getLong(PlayerVariables.HUNTING_ZONE_ENTRY + zoneId, 0), 0);
}
+ public List getCollections()
+ {
+ return _collections;
+ }
+
+ public List getCollectionFavorites()
+ {
+ return _collectionFavorites;
+ }
+
+ public void addCollectionFavorite(Integer id)
+ {
+ _collectionFavorites.add(id);
+ }
+
+ public void removeCollectionFavorite(Integer id)
+ {
+ _collectionFavorites.remove(id);
+ }
+
+ public void storeCollections()
+ {
+ try (Connection con = DatabaseFactory.getConnection())
+ {
+ try (PreparedStatement st = con.prepareStatement(DELETE_COLLECTION))
+ {
+ st.setString(1, getAccountNamePlayer());
+ st.execute();
+ }
+
+ try (PreparedStatement st = con.prepareStatement(INSERT_COLLECTION))
+ {
+ _collections.forEach(data ->
+ {
+ try
+ {
+ st.setString(1, getAccountNamePlayer());
+ st.setInt(2, data.getItemId());
+ st.setInt(3, data.getCollectionId());
+ st.setInt(4, data.getIndex());
+ st.addBatch();
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.SEVERE, "Could not store collection for playerId " + getObjectId() + ": ", e);
+ }
+ });
+ st.executeBatch();
+ con.commit();
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.SEVERE, "Could not store collection for playerId " + getObjectId() + ": ", e);
+ }
+ }
+
+ public void storeCollectionFavorites()
+ {
+ try (Connection con = DatabaseFactory.getConnection())
+ {
+ try (PreparedStatement st = con.prepareStatement(DELETE_COLLECTION_FAVORITE))
+ {
+ st.setString(1, getAccountNamePlayer());
+ st.execute();
+ }
+
+ try (PreparedStatement st = con.prepareStatement(INSERT_COLLECTION_FAVORITE))
+ {
+ _collectionFavorites.forEach(data ->
+ {
+ try
+ {
+ st.setString(1, getAccountNamePlayer());
+ st.setInt(2, data);
+ st.addBatch();
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.SEVERE, "Could not store collection favorite for playerId " + getObjectId() + ": ", e);
+ }
+ });
+ st.executeBatch();
+ con.commit();
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.SEVERE, "Could not store collection favorite for playerId " + getObjectId() + ": ", e);
+ }
+ }
+
+ private void restoreCollections()
+ {
+ if (_collections != null)
+ {
+ _collections.clear();
+ }
+
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement statement = con.prepareStatement(RESTORE_COLLECTION))
+ {
+ statement.setString(1, getAccountNamePlayer());
+ try (ResultSet rset = statement.executeQuery())
+ {
+ while (rset.next())
+ {
+ _collections.add(new PlayerCollectionData(rset.getInt("collectionId"), rset.getInt("itemId"), rset.getInt("index")));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.SEVERE, "Could not restore collection list data for playerId: " + getObjectId(), e);
+ }
+ }
+
+ private void restoreCollectionBonuses()
+ {
+ getCollections().stream().map(PlayerCollectionData::getCollectionId).collect(Collectors.toSet()).forEach(uniqueCollection ->
+ {
+ final List currentProgress = getCollections().stream().filter(it -> it.getCollectionId() == uniqueCollection).collect(Collectors.toList());
+ final CollectionDataHolder template = CollectionData.getInstance().getCollection(uniqueCollection);
+ if (currentProgress.size() == template.getItems().size())
+ {
+ final Options options = OptionData.getInstance().getOptions(template.getOptionId());
+ if (options != null)
+ {
+ options.apply(this);
+ }
+ }
+ });
+ }
+
+ private void restoreCollectionFavorites()
+ {
+ if (_collectionFavorites != null)
+ {
+ _collectionFavorites.clear();
+ }
+
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement statement = con.prepareStatement(RESTORE_COLLECTION_FAVORITE))
+ {
+ statement.setString(1, getAccountNamePlayer());
+ try (ResultSet rset = statement.executeQuery())
+ {
+ while (rset.next())
+ {
+ _collectionFavorites.add(rset.getInt("collectionId"));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.SEVERE, "Could not restore collection favorite list data for playerId: " + getObjectId(), e);
+ }
+ }
+
public int getHomunculusHpBonus()
{
return _homunculusHpBonus;
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/CollectionDataHolder.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/CollectionDataHolder.java
new file mode 100644
index 0000000000..9d6629d241
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/CollectionDataHolder.java
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.holders;
+
+import java.util.List;
+
+/**
+ * Written by Berezkin Nikolay, on 04.05.2021
+ */
+public class CollectionDataHolder
+{
+ private final int _collectionId;
+ private final int _optionId;
+ private final int _category;
+ private final List _items;
+
+ public CollectionDataHolder(int collectionId, int optionId, int category, List items)
+ {
+ _collectionId = collectionId;
+ _optionId = optionId;
+ _category = category;
+ _items = items;
+ }
+
+ public int getCollectionId()
+ {
+ return _collectionId;
+ }
+
+ public int getOptionId()
+ {
+ return _optionId;
+ }
+
+ public int getCategory()
+ {
+ return _category;
+ }
+
+ public List getItems()
+ {
+ return _items;
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/ItemCollectionData.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/ItemCollectionData.java
new file mode 100644
index 0000000000..b4b9f1df43
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/ItemCollectionData.java
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.holders;
+
+/**
+ * Written by Berezkin Nikolay, on 04.05.2021
+ */
+public class ItemCollectionData
+{
+ private final int _enchantLevel;
+ private final int _itemId;
+ private final long _count;
+
+ public ItemCollectionData(int itemId, long count, int enchantLevel)
+ {
+ _itemId = itemId;
+ _count = count;
+ _enchantLevel = enchantLevel;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public int getEnchantLevel()
+ {
+ return _enchantLevel;
+ }
+
+ public long getCount()
+ {
+ return _count;
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/PlayerCollectionData.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/PlayerCollectionData.java
new file mode 100644
index 0000000000..da221d8055
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/PlayerCollectionData.java
@@ -0,0 +1,26 @@
+package org.l2jmobius.gameserver.model.holders;
+
+/**
+ * Written by Berezkin Nikolay, on 04.05.2021
+ */
+public class PlayerCollectionData {
+ public int getCollectionId() {
+ return collectionId;
+ }
+
+ public int getItemId() {
+ return itemId;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ private final int collectionId, itemId, index;
+
+ public PlayerCollectionData(int collectionId, int itemId, int index) {
+ this.collectionId = collectionId;
+ this.itemId = itemId;
+ this.index = index;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index 31cc6ebf42..0bdbc1ec73 100644
--- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -52,6 +52,13 @@ import org.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestCan
import org.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestCuriousHouseHtml;
import org.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestJoinCuriousHouse;
import org.l2jmobius.gameserver.network.clientpackets.classchange.ExRequestClassChange;
+import org.l2jmobius.gameserver.network.clientpackets.collection.RequestExCollectionOpenUI;
+import org.l2jmobius.gameserver.network.clientpackets.collection.RequestCollectionCloseUI;
+import org.l2jmobius.gameserver.network.clientpackets.collection.RequestCollectionFavoriteList;
+import org.l2jmobius.gameserver.network.clientpackets.collection.RequestCollectionReceiveReward;
+import org.l2jmobius.gameserver.network.clientpackets.collection.RequestCollectionRegister;
+import org.l2jmobius.gameserver.network.clientpackets.collection.RequestCollectionUpdateFavorite;
+import org.l2jmobius.gameserver.network.clientpackets.collection.RequestExCollectionList;
import org.l2jmobius.gameserver.network.clientpackets.commission.RequestCommissionBuyInfo;
import org.l2jmobius.gameserver.network.clientpackets.commission.RequestCommissionBuyItem;
import org.l2jmobius.gameserver.network.clientpackets.commission.RequestCommissionCancel;
@@ -615,14 +622,14 @@ public enum ExIncomingPackets implements IIncomingPackets
EX_STEADY_GET_REWARD(0x1D7, null, ConnectionState.IN_GAME),
EX_PET_RANKING_MY_INFO(0x1D8, null, ConnectionState.IN_GAME),
EX_PET_RANKING_LIST(0x1D9, null, ConnectionState.IN_GAME),
- EX_COLLECTION_OPEN_UI(0x1DA, null, ConnectionState.IN_GAME),
- EX_COLLECTION_CLOSE_UI(0x1DB, null, ConnectionState.IN_GAME),
- EX_COLLECTION_LIST(0x1DC, null, ConnectionState.IN_GAME),
- EX_COLLECTION_UPDATE_FAVORITE(0x1DD, null, ConnectionState.IN_GAME),
- EX_COLLECTION_FAVORITE_LIST(0x1DE, null, ConnectionState.IN_GAME),
+ EX_COLLECTION_OPEN_UI(0x1DA, RequestExCollectionOpenUI::new, ConnectionState.IN_GAME),
+ EX_COLLECTION_CLOSE_UI(0x1DB, RequestCollectionCloseUI::new, ConnectionState.IN_GAME),
+ EX_COLLECTION_LIST(0x1DC, RequestExCollectionList::new, ConnectionState.IN_GAME),
+ EX_COLLECTION_UPDATE_FAVORITE(0x1DD, RequestCollectionUpdateFavorite::new, ConnectionState.IN_GAME),
+ EX_COLLECTION_FAVORITE_LIST(0x1DE, RequestCollectionFavoriteList::new, ConnectionState.IN_GAME),
EX_COLLECTION_SUMMARY(0x1DF, null, ConnectionState.IN_GAME),
- EX_COLLECTION_REGISTER(0x1E0, null, ConnectionState.IN_GAME),
- EX_COLLECTION_RECEIVE_REWARD(0x1E1, null, ConnectionState.IN_GAME),
+ EX_COLLECTION_REGISTER(0x1E0, RequestCollectionRegister::new, ConnectionState.IN_GAME),
+ EX_COLLECTION_RECEIVE_REWARD(0x1E1, RequestCollectionReceiveReward::new, ConnectionState.IN_GAME),
EX_PVPBOOK_SHARE_REVENGE_LIST(0x1E2, null, ConnectionState.IN_GAME),
EX_PVPBOOK_SHARE_REVENGE_REQ_SHARE_REVENGEINFO(0x1E3, null, ConnectionState.IN_GAME),
EX_PVPBOOK_SHARE_REVENGE_KILLER_LOCATION(0x1E4, null, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionCloseUI.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionCloseUI.java
new file mode 100644
index 0000000000..ab3be0f645
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionCloseUI.java
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.collection;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.collection.ExCollectionCloseUI;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class RequestCollectionCloseUI implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.sendPacket(new ExCollectionCloseUI());
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionFavoriteList.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionFavoriteList.java
new file mode 100644
index 0000000000..5767b06c91
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionFavoriteList.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.collection;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.collection.ExCollectionFavoriteList;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class RequestCollectionFavoriteList implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ packet.readC(); // ?
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.sendPacket(new ExCollectionFavoriteList());
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionReceiveReward.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionReceiveReward.java
new file mode 100644
index 0000000000..82ebe4b022
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionReceiveReward.java
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.collection;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 13.04.2021
+ */
+public class RequestCollectionReceiveReward implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionRegister.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionRegister.java
new file mode 100644
index 0000000000..a1cd4ef2ff
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionRegister.java
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.collection;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.data.xml.CollectionData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.PlayerCollectionData;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.collection.ExCollectionComplete;
+import org.l2jmobius.gameserver.network.serverpackets.collection.ExCollectionRegister;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class RequestCollectionRegister implements IClientIncomingPacket
+{
+ private int _collectionId;
+ private int _index;
+ private int _itemObjId;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _collectionId = packet.readH();
+ _index = packet.readD();
+ _itemObjId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+ final ItemInstance item = player.getInventory().getItemByObjectId(_itemObjId);
+
+ if (item == null)
+ {
+ player.sendMessage("Item not found.");
+ return;
+ }
+
+ player.destroyItemByItemId("Collection", item.getId(), 1, player, true);
+
+ player.sendPacket(new ExCollectionRegister(_collectionId, _index, item));
+
+ player.getCollections().add(new PlayerCollectionData(_collectionId, item.getId(), _index));
+
+ if (CollectionData.getInstance().getCollection(_collectionId).getItems().size() == player.getCollections().stream().filter(it -> it.getCollectionId() == _collectionId).count())
+ {
+ player.sendPacket(new ExCollectionComplete(_collectionId));
+ }
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionUpdateFavorite.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionUpdateFavorite.java
new file mode 100644
index 0000000000..654e31872c
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionUpdateFavorite.java
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.collection;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.collection.ExCollectionUpdateFavorite;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class RequestCollectionUpdateFavorite implements IClientIncomingPacket
+{
+ private int _isAdd;
+ private int _collectionId;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _isAdd = packet.readC();
+ _collectionId = packet.readH();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+ if (_isAdd == 1)
+ {
+ player.addCollectionFavorite(_collectionId);
+ }
+ else
+ {
+ player.removeCollectionFavorite(_collectionId);
+ }
+ player.sendPacket(new ExCollectionUpdateFavorite(_isAdd, _collectionId));
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestExCollectionList.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestExCollectionList.java
new file mode 100644
index 0000000000..2bcbc3385a
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestExCollectionList.java
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.collection;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.collection.ExCollectionList;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class RequestExCollectionList implements IClientIncomingPacket
+{
+ private int _category;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _category = packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.sendPacket(new ExCollectionList(_category));
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestExCollectionOpenUI.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestExCollectionOpenUI.java
new file mode 100644
index 0000000000..0da390b1c7
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestExCollectionOpenUI.java
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.collection;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.collection.ExCollectionOpenUI;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class RequestExCollectionOpenUI implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ packet.readC(); // 1 = isClosed
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.setTarget(null);
+ player.sendPacket(new ExCollectionOpenUI());
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionCloseUI.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionCloseUI.java
new file mode 100644
index 0000000000..494a5464a2
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionCloseUI.java
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.collection;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class ExCollectionCloseUI implements IClientOutgoingPacket
+{
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_COLLECTION_CLOSE_UI.writeId(packet);
+ packet.writeC(0x00);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionComplete.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionComplete.java
new file mode 100644
index 0000000000..664309481f
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionComplete.java
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.collection;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 13.04.2021
+ */
+public class ExCollectionComplete implements IClientOutgoingPacket
+{
+ private final int _collectionId;
+
+ public ExCollectionComplete(int collectionId)
+ {
+ _collectionId = collectionId;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_COLLECTION_COMPLETE.writeId(packet);
+ packet.writeH(_collectionId);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionFavoriteList.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionFavoriteList.java
new file mode 100644
index 0000000000..7c441b7681
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionFavoriteList.java
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.collection;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class ExCollectionFavoriteList implements IClientOutgoingPacket
+{
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_COLLECTION_FAVORITE_LIST.writeId(packet);
+ packet.writeD(0x00);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionInfo.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionInfo.java
new file mode 100644
index 0000000000..8ff97440ca
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionInfo.java
@@ -0,0 +1,84 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.collection;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.CollectionData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.PlayerCollectionData;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class ExCollectionInfo implements IClientOutgoingPacket
+{
+ final PlayerInstance _playerInstance;
+ final List _categoryList;
+ final Set _collections;
+ final List _favoriteList;
+ final int _category;
+
+ public ExCollectionInfo(PlayerInstance playerInstance, int category)
+ {
+ _playerInstance = playerInstance;
+ _categoryList = playerInstance.getCollections().stream().filter(it -> CollectionData.getInstance().getCollection(it.getCollectionId()).getCategory() == category).collect(Collectors.toList());
+ _collections = _categoryList.stream().map(PlayerCollectionData::getCollectionId).collect(Collectors.toSet());
+ _favoriteList = playerInstance.getCollectionFavorites();
+ _category = category;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_COLLECTION_INFO.writeId(packet);
+ packet.writeD(_collections.size()); // size
+ for (Integer collection : _collections)
+ {
+ final List collectionCurrent = _categoryList.stream().filter(it -> it.getCollectionId() == collection).collect(Collectors.toList());
+ packet.writeD(collectionCurrent.size());
+ for (PlayerCollectionData current : collectionCurrent)
+ {
+ packet.writeC(current.getIndex());
+ packet.writeD(current.getItemId());
+ packet.writeH(CollectionData.getInstance().getCollection(collection).getItems().get(current.getIndex()).getEnchantLevel()); // enchant level
+ packet.writeC(0); // unk flag for item
+ packet.writeD(1); // count
+ }
+ packet.writeH(collection);
+ }
+ packet.writeD(_favoriteList.size()); // favourite size
+ for (int favoriteCollection : _favoriteList)
+ {
+ packet.writeH(favoriteCollection);
+ }
+ packet.writeD(0);
+ // loop unk
+ // 1 h
+ // d
+ // h
+ // loop end
+ packet.writeC(_category);
+ packet.writeH(0);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionList.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionList.java
new file mode 100644
index 0000000000..272533c8d2
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionList.java
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.collection;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class ExCollectionList implements IClientOutgoingPacket
+{
+ private final int _category;
+
+ public ExCollectionList(int category)
+ {
+ _category = category;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_COLLECTION_LIST.writeId(packet);
+ packet.writeC(_category);
+ packet.writeD(0);// size & loop body
+ return true;
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionOpenUI.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionOpenUI.java
new file mode 100644
index 0000000000..1ed6b08793
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionOpenUI.java
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.collection;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class ExCollectionOpenUI implements IClientOutgoingPacket
+{
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_COLLECTION_OPEN_UI.writeId(packet);
+ packet.writeC(0);// unk and may be unk D too
+ return true;
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionRegister.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionRegister.java
new file mode 100644
index 0000000000..daf1cc574e
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionRegister.java
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.collection;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class ExCollectionRegister implements IClientOutgoingPacket
+{
+ private final int _collectionId;
+ private final int _index;
+ private final ItemInstance _item;
+
+ public ExCollectionRegister(int collectionId, int index, ItemInstance item)
+ {
+ _collectionId = collectionId;
+ _index = index;
+ _item = item;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_COLLECTION_REGISTER.writeId(packet);
+ packet.writeH(_collectionId);
+ packet.writeC(1);
+ packet.writeC(0x0E);
+ packet.writeC(0);
+ packet.writeC(_index);
+ packet.writeD(_item.getId());
+ packet.writeH(0);
+ packet.writeC(0);
+ packet.writeD(0);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionUpdateFavorite.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionUpdateFavorite.java
new file mode 100644
index 0000000000..74755ddf90
--- /dev/null
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionUpdateFavorite.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.collection;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class ExCollectionUpdateFavorite implements IClientOutgoingPacket
+{
+ private final int _isAdd;
+ private final int _collectionId;
+
+ public ExCollectionUpdateFavorite(int isAdd, int collectionId)
+ {
+ _isAdd = isAdd;
+ _collectionId = collectionId;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_COLLECTION_UPDATE_FAVORITE.writeId(packet);
+ packet.writeC(_isAdd);
+ packet.writeH(_collectionId);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/readme.txt b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/readme.txt
index c81d43c4f2..9085e525f7 100644
--- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/readme.txt
+++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/readme.txt
@@ -116,7 +116,7 @@ Homunculus Ch. 2: https://eu.4game.com/patchnotes/lineage2/270/
-New augment system
Return of the Queen Ant: https://eu.4game.com/patchnotes/lineage2/293/
--Login support
+-Collection system
Events:
-Birth of Draco
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/db_installer/sql/game/collection_favorites.sql b/L2J_Mobius_Essence_5.0_Sylph/dist/db_installer/sql/game/collection_favorites.sql
new file mode 100644
index 0000000000..7571da448f
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/db_installer/sql/game/collection_favorites.sql
@@ -0,0 +1,6 @@
+DROP TABLE IF EXISTS `collection_favorites`;
+CREATE TABLE IF NOT EXISTS `collection_favorites` (
+ `accountName` VARCHAR(45) NOT NULL DEFAULT '',
+ `collectionId` int(3) UNSIGNED NOT NULL DEFAULT 0,
+ PRIMARY KEY (`accountName`,`collectionId`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/db_installer/sql/game/collections.sql b/L2J_Mobius_Essence_5.0_Sylph/dist/db_installer/sql/game/collections.sql
new file mode 100644
index 0000000000..8c0fafc9fd
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/db_installer/sql/game/collections.sql
@@ -0,0 +1,8 @@
+DROP TABLE IF EXISTS `collections`;
+CREATE TABLE IF NOT EXISTS `collections` (
+ `accountName` VARCHAR(45) NOT NULL DEFAULT '',
+ `itemId` int(11) UNSIGNED NOT NULL DEFAULT 0,
+ `collectionId` int(3) UNSIGNED NOT NULL DEFAULT 0,
+ `index` tinyint(3) UNSIGNED NOT NULL DEFAULT 0,
+ PRIMARY KEY (`accountName`,`collectionId`,`index`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/CollectionData.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/CollectionData.xml
new file mode 100644
index 0000000000..a553bb2dc5
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/CollectionData.xml
@@ -0,0 +1,1762 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/xsd/CollectionData.xsd b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/xsd/CollectionData.xsd
new file mode 100644
index 0000000000..814f7bbe29
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/xsd/CollectionData.xsd
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/GameServer.java
index 760a4191e2..231931f82e 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/GameServer.java
@@ -58,6 +58,7 @@ import org.l2jmobius.gameserver.data.xml.CategoryData;
import org.l2jmobius.gameserver.data.xml.ClanHallData;
import org.l2jmobius.gameserver.data.xml.ClanRewardData;
import org.l2jmobius.gameserver.data.xml.ClassListData;
+import org.l2jmobius.gameserver.data.xml.CollectionData;
import org.l2jmobius.gameserver.data.xml.CombinationItemsData;
import org.l2jmobius.gameserver.data.xml.CubicData;
import org.l2jmobius.gameserver.data.xml.DailyMissionData;
@@ -293,6 +294,7 @@ public class GameServer
LimitShopData.getInstance();
LimitShopCraftData.getInstance();
LimitShopClanData.getInstance();
+ CollectionData.getInstance();
PcCafePointsManager.getInstance();
AppearanceItemData.getInstance();
CommissionManager.getInstance();
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/data/xml/CollectionData.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/data/xml/CollectionData.java
new file mode 100644
index 0000000000..020d270f53
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/data/xml/CollectionData.java
@@ -0,0 +1,136 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.data.xml;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.data.ItemTable;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.holders.CollectionDataHolder;
+import org.l2jmobius.gameserver.model.holders.ItemCollectionData;
+import org.l2jmobius.gameserver.model.items.Item;
+
+/**
+ * Written by Berezkin Nikolay, on 04.05.2021
+ */
+public class CollectionData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(CollectionData.class.getName());
+
+ private static final Map _collections = new HashMap<>();
+
+ protected CollectionData()
+ {
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ _collections.clear();
+ parseDatapackFile("data/CollectionData.xml");
+
+ if (!_collections.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _collections.size() + " collections.");
+ }
+ else
+ {
+ LOGGER.info(getClass().getSimpleName() + ": System is disabled.");
+ }
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
+ {
+ if ("list".equalsIgnoreCase(n.getNodeName()))
+ {
+ for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
+ {
+ if ("collection".equalsIgnoreCase(d.getNodeName()))
+ {
+ NamedNodeMap attrs = d.getAttributes();
+ Node att;
+ final StatSet set = new StatSet();
+ for (int i = 0; i < attrs.getLength(); i++)
+ {
+ att = attrs.item(i);
+ set.set(att.getNodeName(), att.getNodeValue());
+ }
+
+ final int id = parseInteger(attrs, "id");
+ final int optionId = parseInteger(attrs, "optionId");
+ final int category = parseInteger(attrs, "category");
+ List items = new ArrayList<>();
+ for (Node b = d.getFirstChild(); b != null; b = b.getNextSibling())
+ {
+ attrs = b.getAttributes();
+ if ("item".equalsIgnoreCase(b.getNodeName()))
+ {
+ final int itemId = parseInteger(attrs, "id");
+ final long itemCount = parseLong(attrs, "count", 1L);
+ final int itemEnchantLevel = parseInteger(attrs, "enchant_level", 0);
+ final Item item = ItemTable.getInstance().getTemplate(itemId);
+ if (item == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Item template null for itemId: " + itemId + " collection item: " + id);
+ continue;
+ }
+ items.add(new ItemCollectionData(itemId, itemCount, itemEnchantLevel));
+ }
+ }
+
+ _collections.put(id, new CollectionDataHolder(id, optionId, category, items));
+ }
+ }
+ }
+ }
+ }
+
+ public CollectionDataHolder getCollection(int id)
+ {
+ return _collections.get(id);
+ }
+
+ public Collection getCollections()
+ {
+ return _collections.values();
+ }
+
+ public static CollectionData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final CollectionData INSTANCE = new CollectionData();
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
index 096d943ab8..cc7c0b338a 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
@@ -71,10 +71,12 @@ import org.l2jmobius.gameserver.data.xml.AdminData;
import org.l2jmobius.gameserver.data.xml.AttendanceRewardData;
import org.l2jmobius.gameserver.data.xml.CategoryData;
import org.l2jmobius.gameserver.data.xml.ClassListData;
+import org.l2jmobius.gameserver.data.xml.CollectionData;
import org.l2jmobius.gameserver.data.xml.ExperienceData;
import org.l2jmobius.gameserver.data.xml.HennaData;
import org.l2jmobius.gameserver.data.xml.NpcData;
import org.l2jmobius.gameserver.data.xml.NpcNameLocalisationData;
+import org.l2jmobius.gameserver.data.xml.OptionData;
import org.l2jmobius.gameserver.data.xml.PetDataTable;
import org.l2jmobius.gameserver.data.xml.PlayerTemplateData;
import org.l2jmobius.gameserver.data.xml.PlayerXpPercentLostData;
@@ -225,11 +227,13 @@ import org.l2jmobius.gameserver.model.fishing.Fishing;
import org.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
import org.l2jmobius.gameserver.model.holders.AutoPlaySettingsHolder;
import org.l2jmobius.gameserver.model.holders.AutoUseSettingsHolder;
+import org.l2jmobius.gameserver.model.holders.CollectionDataHolder;
import org.l2jmobius.gameserver.model.holders.DamageTakenHolder;
import org.l2jmobius.gameserver.model.holders.ElementalSpiritDataHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.ItemSkillHolder;
import org.l2jmobius.gameserver.model.holders.MovieHolder;
+import org.l2jmobius.gameserver.model.holders.PlayerCollectionData;
import org.l2jmobius.gameserver.model.holders.PlayerEventHolder;
import org.l2jmobius.gameserver.model.holders.PreparedMultisellListHolder;
import org.l2jmobius.gameserver.model.holders.SellBuffHolder;
@@ -261,6 +265,7 @@ import org.l2jmobius.gameserver.model.olympiad.Hero;
import org.l2jmobius.gameserver.model.olympiad.OlympiadGameManager;
import org.l2jmobius.gameserver.model.olympiad.OlympiadGameTask;
import org.l2jmobius.gameserver.model.olympiad.OlympiadManager;
+import org.l2jmobius.gameserver.model.options.Options;
import org.l2jmobius.gameserver.model.punishment.PunishmentAffect;
import org.l2jmobius.gameserver.model.punishment.PunishmentTask;
import org.l2jmobius.gameserver.model.punishment.PunishmentType;
@@ -428,6 +433,14 @@ public class PlayerInstance extends Playable
// Character Shortcut SQL String Definitions:
private static final String DELETE_CHAR_SHORTCUTS = "DELETE FROM character_shortcuts WHERE charId=? AND class_index=?";
+ // Character Collections list:
+ private static final String DELETE_COLLECTION = "DELETE FROM collections WHERE accountName=?";
+ private static final String INSERT_COLLECTION = "REPLACE INTO collections (`accountName`, `itemId`, `collectionId`, `index`) VALUES (?, ?, ?, ?)";
+ private static final String RESTORE_COLLECTION = "SELECT * FROM collections WHERE accountName=? ORDER BY `index`";
+ private static final String DELETE_COLLECTION_FAVORITE = "DELETE FROM collection_favorites WHERE accountName=?";
+ private static final String INSERT_COLLECTION_FAVORITE = "REPLACE INTO collection_favorites (`accountName`, `collectionId`) VALUES (?, ?)";
+ private static final String RESTORE_COLLECTION_FAVORITE = "SELECT * FROM collection_favorites WHERE accountName=?";
+
// Character Recipe List Save:
private static final String DELETE_CHAR_RECIPE_SHOP = "DELETE FROM character_recipeshoplist WHERE charId=?";
private static final String INSERT_CHAR_RECIPE_SHOP = "REPLACE INTO character_recipeshoplist (`charId`, `recipeId`, `price`, `index`) VALUES (?, ?, ?, ?)";
@@ -899,6 +912,9 @@ public class PlayerInstance extends Playable
private PlayerRandomCraft _randomCraft = null;
+ private final List _collections = new ArrayList<>();
+ private final List _collectionFavorites = new ArrayList<>();
+
private final List _questTimers = new ArrayList<>();
private final List> _timerHolders = new ArrayList<>();
@@ -6912,6 +6928,11 @@ public class PlayerInstance extends Playable
restoreRecipeShopList();
}
+ // Restore collections.
+ restoreCollections();
+ restoreCollectionBonuses();
+ restoreCollectionFavorites();
+
// Load Premium Item List.
loadPremiumItemList();
@@ -7059,6 +7080,10 @@ public class PlayerInstance extends Playable
storeRecipeShopList();
}
+ // Store collections.
+ storeCollections();
+ storeCollectionFavorites();
+
final PlayerVariables vars = getScript(PlayerVariables.class);
if (vars != null)
{
@@ -14577,4 +14602,163 @@ public class PlayerInstance extends Playable
{
return _randomCraft;
}
+
+ public List getCollections()
+ {
+ return _collections;
+ }
+
+ public List getCollectionFavorites()
+ {
+ return _collectionFavorites;
+ }
+
+ public void addCollectionFavorite(Integer id)
+ {
+ _collectionFavorites.add(id);
+ }
+
+ public void removeCollectionFavorite(Integer id)
+ {
+ _collectionFavorites.remove(id);
+ }
+
+ public void storeCollections()
+ {
+ try (Connection con = DatabaseFactory.getConnection())
+ {
+ try (PreparedStatement st = con.prepareStatement(DELETE_COLLECTION))
+ {
+ st.setString(1, getAccountNamePlayer());
+ st.execute();
+ }
+
+ try (PreparedStatement st = con.prepareStatement(INSERT_COLLECTION))
+ {
+ _collections.forEach(data ->
+ {
+ try
+ {
+ st.setString(1, getAccountNamePlayer());
+ st.setInt(2, data.getItemId());
+ st.setInt(3, data.getCollectionId());
+ st.setInt(4, data.getIndex());
+ st.addBatch();
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.SEVERE, "Could not store collection for playerId " + getObjectId() + ": ", e);
+ }
+ });
+ st.executeBatch();
+ con.commit();
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.SEVERE, "Could not store collection for playerId " + getObjectId() + ": ", e);
+ }
+ }
+
+ public void storeCollectionFavorites()
+ {
+ try (Connection con = DatabaseFactory.getConnection())
+ {
+ try (PreparedStatement st = con.prepareStatement(DELETE_COLLECTION_FAVORITE))
+ {
+ st.setString(1, getAccountNamePlayer());
+ st.execute();
+ }
+
+ try (PreparedStatement st = con.prepareStatement(INSERT_COLLECTION_FAVORITE))
+ {
+ _collectionFavorites.forEach(data ->
+ {
+ try
+ {
+ st.setString(1, getAccountNamePlayer());
+ st.setInt(2, data);
+ st.addBatch();
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.SEVERE, "Could not store collection favorite for playerId " + getObjectId() + ": ", e);
+ }
+ });
+ st.executeBatch();
+ con.commit();
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.SEVERE, "Could not store collection favorite for playerId " + getObjectId() + ": ", e);
+ }
+ }
+
+ private void restoreCollections()
+ {
+ if (_collections != null)
+ {
+ _collections.clear();
+ }
+
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement statement = con.prepareStatement(RESTORE_COLLECTION))
+ {
+ statement.setString(1, getAccountNamePlayer());
+ try (ResultSet rset = statement.executeQuery())
+ {
+ while (rset.next())
+ {
+ _collections.add(new PlayerCollectionData(rset.getInt("collectionId"), rset.getInt("itemId"), rset.getInt("index")));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.SEVERE, "Could not restore collection list data for playerId: " + getObjectId(), e);
+ }
+ }
+
+ private void restoreCollectionBonuses()
+ {
+ getCollections().stream().map(PlayerCollectionData::getCollectionId).collect(Collectors.toSet()).forEach(uniqueCollection ->
+ {
+ final List currentProgress = getCollections().stream().filter(it -> it.getCollectionId() == uniqueCollection).collect(Collectors.toList());
+ final CollectionDataHolder template = CollectionData.getInstance().getCollection(uniqueCollection);
+ if (currentProgress.size() == template.getItems().size())
+ {
+ final Options options = OptionData.getInstance().getOptions(template.getOptionId());
+ if (options != null)
+ {
+ options.apply(this);
+ }
+ }
+ });
+ }
+
+ private void restoreCollectionFavorites()
+ {
+ if (_collectionFavorites != null)
+ {
+ _collectionFavorites.clear();
+ }
+
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement statement = con.prepareStatement(RESTORE_COLLECTION_FAVORITE))
+ {
+ statement.setString(1, getAccountNamePlayer());
+ try (ResultSet rset = statement.executeQuery())
+ {
+ while (rset.next())
+ {
+ _collectionFavorites.add(rset.getInt("collectionId"));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.SEVERE, "Could not restore collection favorite list data for playerId: " + getObjectId(), e);
+ }
+ }
}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/holders/CollectionDataHolder.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/holders/CollectionDataHolder.java
new file mode 100644
index 0000000000..9d6629d241
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/holders/CollectionDataHolder.java
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.holders;
+
+import java.util.List;
+
+/**
+ * Written by Berezkin Nikolay, on 04.05.2021
+ */
+public class CollectionDataHolder
+{
+ private final int _collectionId;
+ private final int _optionId;
+ private final int _category;
+ private final List _items;
+
+ public CollectionDataHolder(int collectionId, int optionId, int category, List items)
+ {
+ _collectionId = collectionId;
+ _optionId = optionId;
+ _category = category;
+ _items = items;
+ }
+
+ public int getCollectionId()
+ {
+ return _collectionId;
+ }
+
+ public int getOptionId()
+ {
+ return _optionId;
+ }
+
+ public int getCategory()
+ {
+ return _category;
+ }
+
+ public List getItems()
+ {
+ return _items;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/holders/ItemCollectionData.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/holders/ItemCollectionData.java
new file mode 100644
index 0000000000..b4b9f1df43
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/holders/ItemCollectionData.java
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.holders;
+
+/**
+ * Written by Berezkin Nikolay, on 04.05.2021
+ */
+public class ItemCollectionData
+{
+ private final int _enchantLevel;
+ private final int _itemId;
+ private final long _count;
+
+ public ItemCollectionData(int itemId, long count, int enchantLevel)
+ {
+ _itemId = itemId;
+ _count = count;
+ _enchantLevel = enchantLevel;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public int getEnchantLevel()
+ {
+ return _enchantLevel;
+ }
+
+ public long getCount()
+ {
+ return _count;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/holders/PlayerCollectionData.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/holders/PlayerCollectionData.java
new file mode 100644
index 0000000000..da221d8055
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/holders/PlayerCollectionData.java
@@ -0,0 +1,26 @@
+package org.l2jmobius.gameserver.model.holders;
+
+/**
+ * Written by Berezkin Nikolay, on 04.05.2021
+ */
+public class PlayerCollectionData {
+ public int getCollectionId() {
+ return collectionId;
+ }
+
+ public int getItemId() {
+ return itemId;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ private final int collectionId, itemId, index;
+
+ public PlayerCollectionData(int collectionId, int itemId, int index) {
+ this.collectionId = collectionId;
+ this.itemId = itemId;
+ this.index = index;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index cb67b9cd28..7f7177b1fd 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -46,6 +46,13 @@ import org.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestCan
import org.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestCuriousHouseHtml;
import org.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestJoinCuriousHouse;
import org.l2jmobius.gameserver.network.clientpackets.classchange.ExRequestClassChange;
+import org.l2jmobius.gameserver.network.clientpackets.collection.RequestExCollectionOpenUI;
+import org.l2jmobius.gameserver.network.clientpackets.collection.RequestCollectionCloseUI;
+import org.l2jmobius.gameserver.network.clientpackets.collection.RequestCollectionFavoriteList;
+import org.l2jmobius.gameserver.network.clientpackets.collection.RequestCollectionReceiveReward;
+import org.l2jmobius.gameserver.network.clientpackets.collection.RequestCollectionRegister;
+import org.l2jmobius.gameserver.network.clientpackets.collection.RequestCollectionUpdateFavorite;
+import org.l2jmobius.gameserver.network.clientpackets.collection.RequestExCollectionList;
import org.l2jmobius.gameserver.network.clientpackets.commission.RequestCommissionBuyInfo;
import org.l2jmobius.gameserver.network.clientpackets.commission.RequestCommissionBuyItem;
import org.l2jmobius.gameserver.network.clientpackets.commission.RequestCommissionCancel;
@@ -616,14 +623,14 @@ public enum ExIncomingPackets implements IIncomingPackets
EX_STEADY_GET_REWARD(0x1D7, null, ConnectionState.IN_GAME),
EX_PET_RANKING_MY_INFO(0x1D8, null, ConnectionState.IN_GAME),
EX_PET_RANKING_LIST(0x1D9, null, ConnectionState.IN_GAME),
- EX_COLLECTION_OPEN_UI(0x1DA, null, ConnectionState.IN_GAME),
- EX_COLLECTION_CLOSE_UI(0x1DB, null, ConnectionState.IN_GAME),
- EX_COLLECTION_LIST(0x1DC, null, ConnectionState.IN_GAME),
- EX_COLLECTION_UPDATE_FAVORITE(0x1DD, null, ConnectionState.IN_GAME),
- EX_COLLECTION_FAVORITE_LIST(0x1DE, null, ConnectionState.IN_GAME),
+ EX_COLLECTION_OPEN_UI(0x1DA, RequestExCollectionOpenUI::new, ConnectionState.IN_GAME),
+ EX_COLLECTION_CLOSE_UI(0x1DB, RequestCollectionCloseUI::new, ConnectionState.IN_GAME),
+ EX_COLLECTION_LIST(0x1DC, RequestExCollectionList::new, ConnectionState.IN_GAME),
+ EX_COLLECTION_UPDATE_FAVORITE(0x1DD, RequestCollectionUpdateFavorite::new, ConnectionState.IN_GAME),
+ EX_COLLECTION_FAVORITE_LIST(0x1DE, RequestCollectionFavoriteList::new, ConnectionState.IN_GAME),
EX_COLLECTION_SUMMARY(0x1DF, null, ConnectionState.IN_GAME),
- EX_COLLECTION_REGISTER(0x1E0, null, ConnectionState.IN_GAME),
- EX_COLLECTION_RECEIVE_REWARD(0x1E1, null, ConnectionState.IN_GAME),
+ EX_COLLECTION_REGISTER(0x1E0, RequestCollectionRegister::new, ConnectionState.IN_GAME),
+ EX_COLLECTION_RECEIVE_REWARD(0x1E1, RequestCollectionReceiveReward::new, ConnectionState.IN_GAME),
EX_PVPBOOK_SHARE_REVENGE_LIST(0x1E2, null, ConnectionState.IN_GAME),
EX_PVPBOOK_SHARE_REVENGE_REQ_SHARE_REVENGEINFO(0x1E3, null, ConnectionState.IN_GAME),
EX_PVPBOOK_SHARE_REVENGE_KILLER_LOCATION(0x1E4, null, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionCloseUI.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionCloseUI.java
new file mode 100644
index 0000000000..ab3be0f645
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionCloseUI.java
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.collection;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.collection.ExCollectionCloseUI;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class RequestCollectionCloseUI implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.sendPacket(new ExCollectionCloseUI());
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionFavoriteList.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionFavoriteList.java
new file mode 100644
index 0000000000..5767b06c91
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionFavoriteList.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.collection;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.collection.ExCollectionFavoriteList;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class RequestCollectionFavoriteList implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ packet.readC(); // ?
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.sendPacket(new ExCollectionFavoriteList());
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionReceiveReward.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionReceiveReward.java
new file mode 100644
index 0000000000..82ebe4b022
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionReceiveReward.java
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.collection;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 13.04.2021
+ */
+public class RequestCollectionReceiveReward implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionRegister.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionRegister.java
new file mode 100644
index 0000000000..a1cd4ef2ff
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionRegister.java
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.collection;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.data.xml.CollectionData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.PlayerCollectionData;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.collection.ExCollectionComplete;
+import org.l2jmobius.gameserver.network.serverpackets.collection.ExCollectionRegister;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class RequestCollectionRegister implements IClientIncomingPacket
+{
+ private int _collectionId;
+ private int _index;
+ private int _itemObjId;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _collectionId = packet.readH();
+ _index = packet.readD();
+ _itemObjId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+ final ItemInstance item = player.getInventory().getItemByObjectId(_itemObjId);
+
+ if (item == null)
+ {
+ player.sendMessage("Item not found.");
+ return;
+ }
+
+ player.destroyItemByItemId("Collection", item.getId(), 1, player, true);
+
+ player.sendPacket(new ExCollectionRegister(_collectionId, _index, item));
+
+ player.getCollections().add(new PlayerCollectionData(_collectionId, item.getId(), _index));
+
+ if (CollectionData.getInstance().getCollection(_collectionId).getItems().size() == player.getCollections().stream().filter(it -> it.getCollectionId() == _collectionId).count())
+ {
+ player.sendPacket(new ExCollectionComplete(_collectionId));
+ }
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionUpdateFavorite.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionUpdateFavorite.java
new file mode 100644
index 0000000000..654e31872c
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestCollectionUpdateFavorite.java
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.collection;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.collection.ExCollectionUpdateFavorite;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class RequestCollectionUpdateFavorite implements IClientIncomingPacket
+{
+ private int _isAdd;
+ private int _collectionId;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _isAdd = packet.readC();
+ _collectionId = packet.readH();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+ if (_isAdd == 1)
+ {
+ player.addCollectionFavorite(_collectionId);
+ }
+ else
+ {
+ player.removeCollectionFavorite(_collectionId);
+ }
+ player.sendPacket(new ExCollectionUpdateFavorite(_isAdd, _collectionId));
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestExCollectionList.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestExCollectionList.java
new file mode 100644
index 0000000000..2bcbc3385a
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestExCollectionList.java
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.collection;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.collection.ExCollectionList;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class RequestExCollectionList implements IClientIncomingPacket
+{
+ private int _category;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _category = packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.sendPacket(new ExCollectionList(_category));
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestExCollectionOpenUI.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestExCollectionOpenUI.java
new file mode 100644
index 0000000000..0da390b1c7
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/collection/RequestExCollectionOpenUI.java
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.collection;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.collection.ExCollectionOpenUI;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class RequestExCollectionOpenUI implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ packet.readC(); // 1 = isClosed
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.setTarget(null);
+ player.sendPacket(new ExCollectionOpenUI());
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionCloseUI.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionCloseUI.java
new file mode 100644
index 0000000000..494a5464a2
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionCloseUI.java
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.collection;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class ExCollectionCloseUI implements IClientOutgoingPacket
+{
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_COLLECTION_CLOSE_UI.writeId(packet);
+ packet.writeC(0x00);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionComplete.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionComplete.java
new file mode 100644
index 0000000000..664309481f
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionComplete.java
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.collection;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 13.04.2021
+ */
+public class ExCollectionComplete implements IClientOutgoingPacket
+{
+ private final int _collectionId;
+
+ public ExCollectionComplete(int collectionId)
+ {
+ _collectionId = collectionId;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_COLLECTION_COMPLETE.writeId(packet);
+ packet.writeH(_collectionId);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionFavoriteList.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionFavoriteList.java
new file mode 100644
index 0000000000..7c441b7681
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionFavoriteList.java
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.collection;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class ExCollectionFavoriteList implements IClientOutgoingPacket
+{
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_COLLECTION_FAVORITE_LIST.writeId(packet);
+ packet.writeD(0x00);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionInfo.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionInfo.java
new file mode 100644
index 0000000000..8ff97440ca
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionInfo.java
@@ -0,0 +1,84 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.collection;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.CollectionData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.PlayerCollectionData;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class ExCollectionInfo implements IClientOutgoingPacket
+{
+ final PlayerInstance _playerInstance;
+ final List _categoryList;
+ final Set _collections;
+ final List _favoriteList;
+ final int _category;
+
+ public ExCollectionInfo(PlayerInstance playerInstance, int category)
+ {
+ _playerInstance = playerInstance;
+ _categoryList = playerInstance.getCollections().stream().filter(it -> CollectionData.getInstance().getCollection(it.getCollectionId()).getCategory() == category).collect(Collectors.toList());
+ _collections = _categoryList.stream().map(PlayerCollectionData::getCollectionId).collect(Collectors.toSet());
+ _favoriteList = playerInstance.getCollectionFavorites();
+ _category = category;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_COLLECTION_INFO.writeId(packet);
+ packet.writeD(_collections.size()); // size
+ for (Integer collection : _collections)
+ {
+ final List collectionCurrent = _categoryList.stream().filter(it -> it.getCollectionId() == collection).collect(Collectors.toList());
+ packet.writeD(collectionCurrent.size());
+ for (PlayerCollectionData current : collectionCurrent)
+ {
+ packet.writeC(current.getIndex());
+ packet.writeD(current.getItemId());
+ packet.writeH(CollectionData.getInstance().getCollection(collection).getItems().get(current.getIndex()).getEnchantLevel()); // enchant level
+ packet.writeC(0); // unk flag for item
+ packet.writeD(1); // count
+ }
+ packet.writeH(collection);
+ }
+ packet.writeD(_favoriteList.size()); // favourite size
+ for (int favoriteCollection : _favoriteList)
+ {
+ packet.writeH(favoriteCollection);
+ }
+ packet.writeD(0);
+ // loop unk
+ // 1 h
+ // d
+ // h
+ // loop end
+ packet.writeC(_category);
+ packet.writeH(0);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionList.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionList.java
new file mode 100644
index 0000000000..272533c8d2
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionList.java
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.collection;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class ExCollectionList implements IClientOutgoingPacket
+{
+ private final int _category;
+
+ public ExCollectionList(int category)
+ {
+ _category = category;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_COLLECTION_LIST.writeId(packet);
+ packet.writeC(_category);
+ packet.writeD(0);// size & loop body
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionOpenUI.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionOpenUI.java
new file mode 100644
index 0000000000..1ed6b08793
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionOpenUI.java
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.collection;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class ExCollectionOpenUI implements IClientOutgoingPacket
+{
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_COLLECTION_OPEN_UI.writeId(packet);
+ packet.writeC(0);// unk and may be unk D too
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionRegister.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionRegister.java
new file mode 100644
index 0000000000..daf1cc574e
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionRegister.java
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.collection;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class ExCollectionRegister implements IClientOutgoingPacket
+{
+ private final int _collectionId;
+ private final int _index;
+ private final ItemInstance _item;
+
+ public ExCollectionRegister(int collectionId, int index, ItemInstance item)
+ {
+ _collectionId = collectionId;
+ _index = index;
+ _item = item;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_COLLECTION_REGISTER.writeId(packet);
+ packet.writeH(_collectionId);
+ packet.writeC(1);
+ packet.writeC(0x0E);
+ packet.writeC(0);
+ packet.writeC(_index);
+ packet.writeD(_item.getId());
+ packet.writeH(0);
+ packet.writeC(0);
+ packet.writeD(0);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionUpdateFavorite.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionUpdateFavorite.java
new file mode 100644
index 0000000000..74755ddf90
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/collection/ExCollectionUpdateFavorite.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.collection;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * Written by Berezkin Nikolay, on 12.04.2021
+ */
+public class ExCollectionUpdateFavorite implements IClientOutgoingPacket
+{
+ private final int _isAdd;
+ private final int _collectionId;
+
+ public ExCollectionUpdateFavorite(int isAdd, int collectionId)
+ {
+ _isAdd = isAdd;
+ _collectionId = collectionId;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_COLLECTION_UPDATE_FAVORITE.writeId(packet);
+ packet.writeC(_isAdd);
+ packet.writeH(_collectionId);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/readme.txt b/L2J_Mobius_Essence_5.0_Sylph/readme.txt
index 8ebb398aaa..d819070897 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/readme.txt
+++ b/L2J_Mobius_Essence_5.0_Sylph/readme.txt
@@ -124,6 +124,7 @@ Dwelling of Spirits: https://eu.4game.com/patchnotes/lineage2essence/261/
Sylph: https://eu.4game.com/patchnotes/lineage2essence/281/
-Sylph creation support
+-Collection system
Customs:
-Newbie Helper NPC location info