From 1a1241957f4f1cffb1f753ba2218f3ea19dc6186 Mon Sep 17 00:00:00 2001
From: MobiusDevelopment <8391001+MobiusDevelopment@users.noreply.github.com>
Date: Sat, 4 Jul 2020 00:26:44 +0000
Subject: [PATCH] Addition of paperdoll cache. Contributed by Sahar.
---
.../gameserver/cache/PaperdollCache.java | 127 ++++++++++++++++++
.../model/itemcontainer/Inventory.java | 36 +++--
.../gameserver/model/stats/BaseStat.java | 4 +-
.../gameserver/model/stats/IStatFunction.java | 5 +-
.../stats/finalizers/BaseStatFinalizer.java | 17 +--
.../clientpackets/RequestEnchantItem.java | 1 +
.../gameserver/cache/PaperdollCache.java | 127 ++++++++++++++++++
.../model/itemcontainer/Inventory.java | 36 +++--
.../gameserver/model/stats/BaseStat.java | 4 +-
.../gameserver/model/stats/IStatFunction.java | 5 +-
.../stats/finalizers/BaseStatFinalizer.java | 17 +--
.../clientpackets/RequestEnchantItem.java | 1 +
.../gameserver/cache/PaperdollCache.java | 127 ++++++++++++++++++
.../model/itemcontainer/Inventory.java | 36 +++--
.../gameserver/model/stats/BaseStat.java | 4 +-
.../gameserver/model/stats/IStatFunction.java | 5 +-
.../stats/finalizers/BaseStatFinalizer.java | 17 +--
.../clientpackets/RequestEnchantItem.java | 1 +
.../gameserver/cache/PaperdollCache.java | 127 ++++++++++++++++++
.../model/itemcontainer/Inventory.java | 36 +++--
.../gameserver/model/stats/BaseStat.java | 4 +-
.../gameserver/model/stats/IStatFunction.java | 5 +-
.../stats/finalizers/BaseStatFinalizer.java | 17 +--
.../clientpackets/RequestEnchantItem.java | 1 +
.../gameserver/cache/PaperdollCache.java | 127 ++++++++++++++++++
.../model/itemcontainer/Inventory.java | 36 +++--
.../gameserver/model/stats/BaseStat.java | 4 +-
.../gameserver/model/stats/IStatFunction.java | 5 +-
.../stats/finalizers/BaseStatFinalizer.java | 17 +--
.../clientpackets/RequestEnchantItem.java | 1 +
.../gameserver/cache/PaperdollCache.java | 127 ++++++++++++++++++
.../model/itemcontainer/Inventory.java | 36 +++--
.../gameserver/model/stats/BaseStat.java | 4 +-
.../gameserver/model/stats/IStatFunction.java | 5 +-
.../stats/finalizers/BaseStatFinalizer.java | 17 +--
.../clientpackets/RequestEnchantItem.java | 1 +
.../gameserver/cache/PaperdollCache.java | 127 ++++++++++++++++++
.../model/itemcontainer/Inventory.java | 36 +++--
.../gameserver/model/stats/BaseStat.java | 4 +-
.../gameserver/model/stats/IStatFunction.java | 5 +-
.../stats/finalizers/BaseStatFinalizer.java | 17 +--
.../clientpackets/RequestEnchantItem.java | 1 +
.../gameserver/cache/PaperdollCache.java | 127 ++++++++++++++++++
.../model/itemcontainer/Inventory.java | 36 +++--
.../gameserver/model/stats/BaseStat.java | 4 +-
.../gameserver/model/stats/IStatFunction.java | 5 +-
.../stats/finalizers/BaseStatFinalizer.java | 17 +--
.../clientpackets/RequestEnchantItem.java | 1 +
.../gameserver/cache/PaperdollCache.java | 127 ++++++++++++++++++
.../model/itemcontainer/Inventory.java | 36 +++--
.../gameserver/model/stats/BaseStat.java | 4 +-
.../gameserver/model/stats/IStatFunction.java | 5 +-
.../stats/finalizers/BaseStatFinalizer.java | 17 +--
.../clientpackets/RequestEnchantItem.java | 1 +
.../gameserver/cache/PaperdollCache.java | 127 ++++++++++++++++++
.../model/itemcontainer/Inventory.java | 36 +++--
.../gameserver/model/stats/BaseStat.java | 4 +-
.../gameserver/model/stats/IStatFunction.java | 5 +-
.../stats/finalizers/BaseStatFinalizer.java | 17 +--
.../clientpackets/RequestEnchantItem.java | 1 +
.../gameserver/cache/PaperdollCache.java | 127 ++++++++++++++++++
.../model/itemcontainer/Inventory.java | 36 +++--
.../gameserver/model/stats/BaseStat.java | 4 +-
.../gameserver/model/stats/IStatFunction.java | 5 +-
.../stats/finalizers/BaseStatFinalizer.java | 17 +--
.../clientpackets/RequestEnchantItem.java | 1 +
.../gameserver/cache/PaperdollCache.java | 127 ++++++++++++++++++
.../model/itemcontainer/Inventory.java | 36 +++--
.../gameserver/model/stats/BaseStat.java | 4 +-
.../gameserver/model/stats/IStatFunction.java | 5 +-
.../stats/finalizers/BaseStatFinalizer.java | 17 +--
.../clientpackets/RequestEnchantItem.java | 1 +
.../gameserver/cache/PaperdollCache.java | 127 ++++++++++++++++++
.../model/itemcontainer/Inventory.java | 36 +++--
.../gameserver/model/stats/BaseStat.java | 4 +-
.../gameserver/model/stats/IStatFunction.java | 5 +-
.../stats/finalizers/BaseStatFinalizer.java | 17 +--
.../clientpackets/RequestEnchantItem.java | 1 +
.../gameserver/cache/PaperdollCache.java | 127 ++++++++++++++++++
.../model/itemcontainer/Inventory.java | 36 +++--
.../gameserver/model/stats/BaseStat.java | 4 +-
.../gameserver/model/stats/IStatFunction.java | 5 +-
.../stats/finalizers/BaseStatFinalizer.java | 17 +--
.../clientpackets/RequestEnchantItem.java | 1 +
.../gameserver/cache/PaperdollCache.java | 127 ++++++++++++++++++
.../model/itemcontainer/Inventory.java | 36 +++--
.../gameserver/model/stats/BaseStat.java | 4 +-
.../gameserver/model/stats/IStatFunction.java | 5 +-
.../stats/finalizers/BaseStatFinalizer.java | 17 +--
.../clientpackets/RequestEnchantItem.java | 1 +
90 files changed, 2340 insertions(+), 510 deletions(-)
create mode 100644 L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
create mode 100644 L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
create mode 100644 L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
create mode 100644 L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
create mode 100644 L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
create mode 100644 L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
create mode 100644 L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
create mode 100644 L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
create mode 100644 L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
diff --git a/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/cache/PaperdollCache.java b/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
new file mode 100644
index 0000000000..c908c4434d
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
@@ -0,0 +1,127 @@
+/*
+ * 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.cache;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
+import org.l2jmobius.gameserver.model.ArmorSet;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.stats.BaseStat;
+import org.l2jmobius.gameserver.model.stats.Stat;
+
+/**
+ * @author Sahar
+ */
+public final class PaperdollCache
+{
+ private final Set _paperdollItems = ConcurrentHashMap.newKeySet();
+
+ private final Map _baseStatValues = new ConcurrentHashMap<>();
+ private final Map _statValues = new ConcurrentHashMap<>();
+ private int _maxSetEnchant = -1;
+
+ public Set getPaperdollItems()
+ {
+ return _paperdollItems;
+ }
+
+ public void clearCachedStats()
+ {
+ _baseStatValues.clear();
+ _statValues.clear();
+
+ clearMaxSetEnchant();
+ }
+
+ public void clearMaxSetEnchant()
+ {
+ _maxSetEnchant = -1;
+ }
+
+ public double getBaseStatValue(PlayerInstance player, final BaseStat stat)
+ {
+ final Double baseStatValue = _baseStatValues.get(stat);
+ if (baseStatValue != null)
+ {
+ return baseStatValue;
+ }
+
+ final Set appliedSets = new HashSet<>(2);
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
+ {
+ value += set.getStatsBonus(stat);
+ }
+ }
+ }
+
+ _baseStatValues.put(stat, value);
+ return value;
+ }
+
+ public int getMaxSetEnchant(PlayerInstance player)
+ {
+ int maxSetEnchant = _maxSetEnchant;
+ if (maxSetEnchant >= 0)
+ {
+ return maxSetEnchant;
+ }
+
+ maxSetEnchant = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ final int enchantEffect = set.getLowestSetEnchant(player);
+ if (enchantEffect > maxSetEnchant)
+ {
+ maxSetEnchant = enchantEffect;
+ }
+ }
+ }
+
+ _maxSetEnchant = maxSetEnchant;
+ return maxSetEnchant;
+ }
+
+ public double getStats(Stat stat)
+ {
+ final Double statValue = _statValues.get(stat);
+ if (statValue != null)
+ {
+ return statValue;
+ }
+
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ value += item.getItem().getStats(stat, 0);
+ }
+
+ _statValues.put(stat, value);
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index 599ca25c08..cd4a5de684 100644
--- a/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.cache.PaperdollCache;
import org.l2jmobius.gameserver.data.xml.impl.AppearanceItemData;
import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
import org.l2jmobius.gameserver.datatables.ItemTable;
@@ -123,6 +124,7 @@ public abstract class Inventory extends ItemContainer
private final ItemInstance[] _paperdoll;
private final List _paperdollListeners;
+ private final PaperdollCache _paperdollCache = new PaperdollCache();
// protected to be accessed from child classes only
protected int _totalWeight;
@@ -1203,6 +1205,8 @@ public abstract class Inventory extends ItemContainer
if (old != null)
{
_paperdoll[slot] = null;
+ _paperdollCache.getPaperdollItems().remove(old);
+
// Put old item from paperdoll slot to base location
old.setItemLocation(getBaseLocation());
old.setLastChange(ItemInstance.MODIFIED);
@@ -1233,6 +1237,8 @@ public abstract class Inventory extends ItemContainer
if (item != null)
{
_paperdoll[slot] = item;
+ _paperdollCache.getPaperdollItems().add(item);
+
item.setItemLocation(getEquipLocation(), slot);
item.setLastChange(ItemInstance.MODIFIED);
_wearedMask |= item.getItem().getItemMask();
@@ -1248,6 +1254,7 @@ public abstract class Inventory extends ItemContainer
item.updateDatabase();
}
+ _paperdollCache.clearCachedStats();
getOwner().getStat().recalculateStats(!getOwner().isPlayer());
if (getOwner().isPlayer())
@@ -2120,19 +2127,7 @@ public abstract class Inventory extends ItemContainer
}
final PlayerInstance player = getOwner().getActingPlayer();
- int maxSetEnchant = 0;
- for (ItemInstance item : getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- final int enchantEffect = set.getLowestSetEnchant(player);
- if (enchantEffect > maxSetEnchant)
- {
- maxSetEnchant = enchantEffect;
- }
- }
- }
- return maxSetEnchant;
+ return _paperdollCache.getMaxSetEnchant(player);
}
public int getWeaponEnchant()
@@ -2196,6 +2191,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final Collection getPaperdollItems(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2216,6 +2216,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems().size();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2232,4 +2237,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
+
+ public PaperdollCache getPaperdollCache()
+ {
+ return _paperdollCache;
+ }
}
diff --git a/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/stats/BaseStat.java b/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
index ea1f76bbb6..3b2a441178 100644
--- a/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
+++ b/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
@@ -40,6 +40,8 @@ public enum BaseStat
CHA(Stat.STAT_CHA),
LUC(Stat.STAT_LUC);
+ private static final BaseStat[] VALUES = BaseStat.values();
+
public static final int MAX_STAT_VALUE = 201;
private final double[] _bonus = new double[MAX_STAT_VALUE];
@@ -92,7 +94,7 @@ public enum BaseStat
public static BaseStat valueOf(Stat stat)
{
- for (BaseStat baseStat : values())
+ for (BaseStat baseStat : VALUES)
{
if (baseStat.getStat() == stat)
{
diff --git a/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java b/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
index 9da29a9c79..00e2ff03fd 100644
--- a/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
+++ b/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
@@ -92,10 +92,7 @@ public interface IStatFunction
final Inventory inv = creature.getInventory();
if (inv != null)
{
- for (ItemInstance item : inv.getPaperdollItems())
- {
- baseValue += item.getItem().getStats(stat, 0);
- }
+ baseValue += inv.getPaperdollCache().getStats(stat);
}
}
diff --git a/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java b/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
index 58369ad827..1355065c58 100644
--- a/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
+++ b/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
@@ -16,15 +16,10 @@
*/
package org.l2jmobius.gameserver.model.stats.finalizers;
-import java.util.HashSet;
import java.util.OptionalDouble;
-import java.util.Set;
-import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
-import org.l2jmobius.gameserver.model.ArmorSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
-import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.stats.BaseStat;
import org.l2jmobius.gameserver.model.stats.IStatFunction;
import org.l2jmobius.gameserver.model.stats.Stat;
@@ -46,19 +41,9 @@ public class BaseStatFinalizer implements IStatFunction
if (creature.isPlayer())
{
final PlayerInstance player = creature.getActingPlayer();
- final Set appliedSets = new HashSet<>(2);
// Armor sets calculation
- for (ItemInstance item : player.getInventory().getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
- {
- baseValue += set.getStatsBonus(BaseStat.valueOf(stat));
- }
- }
- }
+ baseValue += player.getInventory().getPaperdollCache().getBaseStatValue(player, BaseStat.valueOf(stat));
// Henna calculation
baseValue += player.getHennaValue(BaseStat.valueOf(stat));
diff --git a/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java b/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
index 1ab8980f37..a45f7b8b9b 100644
--- a/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
+++ b/L2J_Mobius_1.0_Ertheia/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
@@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
+ player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;
diff --git a/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/cache/PaperdollCache.java b/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
new file mode 100644
index 0000000000..c908c4434d
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
@@ -0,0 +1,127 @@
+/*
+ * 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.cache;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
+import org.l2jmobius.gameserver.model.ArmorSet;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.stats.BaseStat;
+import org.l2jmobius.gameserver.model.stats.Stat;
+
+/**
+ * @author Sahar
+ */
+public final class PaperdollCache
+{
+ private final Set _paperdollItems = ConcurrentHashMap.newKeySet();
+
+ private final Map _baseStatValues = new ConcurrentHashMap<>();
+ private final Map _statValues = new ConcurrentHashMap<>();
+ private int _maxSetEnchant = -1;
+
+ public Set getPaperdollItems()
+ {
+ return _paperdollItems;
+ }
+
+ public void clearCachedStats()
+ {
+ _baseStatValues.clear();
+ _statValues.clear();
+
+ clearMaxSetEnchant();
+ }
+
+ public void clearMaxSetEnchant()
+ {
+ _maxSetEnchant = -1;
+ }
+
+ public double getBaseStatValue(PlayerInstance player, final BaseStat stat)
+ {
+ final Double baseStatValue = _baseStatValues.get(stat);
+ if (baseStatValue != null)
+ {
+ return baseStatValue;
+ }
+
+ final Set appliedSets = new HashSet<>(2);
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
+ {
+ value += set.getStatsBonus(stat);
+ }
+ }
+ }
+
+ _baseStatValues.put(stat, value);
+ return value;
+ }
+
+ public int getMaxSetEnchant(PlayerInstance player)
+ {
+ int maxSetEnchant = _maxSetEnchant;
+ if (maxSetEnchant >= 0)
+ {
+ return maxSetEnchant;
+ }
+
+ maxSetEnchant = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ final int enchantEffect = set.getLowestSetEnchant(player);
+ if (enchantEffect > maxSetEnchant)
+ {
+ maxSetEnchant = enchantEffect;
+ }
+ }
+ }
+
+ _maxSetEnchant = maxSetEnchant;
+ return maxSetEnchant;
+ }
+
+ public double getStats(Stat stat)
+ {
+ final Double statValue = _statValues.get(stat);
+ if (statValue != null)
+ {
+ return statValue;
+ }
+
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ value += item.getItem().getStats(stat, 0);
+ }
+
+ _statValues.put(stat, value);
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index 5228ad8a48..93e45bf372 100644
--- a/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.cache.PaperdollCache;
import org.l2jmobius.gameserver.data.xml.impl.AppearanceItemData;
import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
import org.l2jmobius.gameserver.datatables.ItemTable;
@@ -123,6 +124,7 @@ public abstract class Inventory extends ItemContainer
private final ItemInstance[] _paperdoll;
private final List _paperdollListeners;
+ private final PaperdollCache _paperdollCache = new PaperdollCache();
// protected to be accessed from child classes only
protected int _totalWeight;
@@ -1209,6 +1211,8 @@ public abstract class Inventory extends ItemContainer
if (old != null)
{
_paperdoll[slot] = null;
+ _paperdollCache.getPaperdollItems().remove(old);
+
// Put old item from paperdoll slot to base location
old.setItemLocation(getBaseLocation());
old.setLastChange(ItemInstance.MODIFIED);
@@ -1239,6 +1243,8 @@ public abstract class Inventory extends ItemContainer
if (item != null)
{
_paperdoll[slot] = item;
+ _paperdollCache.getPaperdollItems().add(item);
+
item.setItemLocation(getEquipLocation(), slot);
item.setLastChange(ItemInstance.MODIFIED);
_wearedMask |= item.getItem().getItemMask();
@@ -1254,6 +1260,7 @@ public abstract class Inventory extends ItemContainer
item.updateDatabase();
}
+ _paperdollCache.clearCachedStats();
getOwner().getStat().recalculateStats(!getOwner().isPlayer());
if (getOwner().isPlayer())
@@ -2126,19 +2133,7 @@ public abstract class Inventory extends ItemContainer
}
final PlayerInstance player = getOwner().getActingPlayer();
- int maxSetEnchant = 0;
- for (ItemInstance item : getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- final int enchantEffect = set.getLowestSetEnchant(player);
- if (enchantEffect > maxSetEnchant)
- {
- maxSetEnchant = enchantEffect;
- }
- }
- }
- return maxSetEnchant;
+ return _paperdollCache.getMaxSetEnchant(player);
}
public int getWeaponEnchant()
@@ -2202,6 +2197,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final Collection getPaperdollItems(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2222,6 +2222,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems().size();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2238,4 +2243,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
+
+ public PaperdollCache getPaperdollCache()
+ {
+ return _paperdollCache;
+ }
}
diff --git a/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/stats/BaseStat.java b/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
index ea1f76bbb6..3b2a441178 100644
--- a/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
+++ b/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
@@ -40,6 +40,8 @@ public enum BaseStat
CHA(Stat.STAT_CHA),
LUC(Stat.STAT_LUC);
+ private static final BaseStat[] VALUES = BaseStat.values();
+
public static final int MAX_STAT_VALUE = 201;
private final double[] _bonus = new double[MAX_STAT_VALUE];
@@ -92,7 +94,7 @@ public enum BaseStat
public static BaseStat valueOf(Stat stat)
{
- for (BaseStat baseStat : values())
+ for (BaseStat baseStat : VALUES)
{
if (baseStat.getStat() == stat)
{
diff --git a/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java b/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
index 9da29a9c79..00e2ff03fd 100644
--- a/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
+++ b/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
@@ -92,10 +92,7 @@ public interface IStatFunction
final Inventory inv = creature.getInventory();
if (inv != null)
{
- for (ItemInstance item : inv.getPaperdollItems())
- {
- baseValue += item.getItem().getStats(stat, 0);
- }
+ baseValue += inv.getPaperdollCache().getStats(stat);
}
}
diff --git a/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java b/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
index 58369ad827..1355065c58 100644
--- a/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
+++ b/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
@@ -16,15 +16,10 @@
*/
package org.l2jmobius.gameserver.model.stats.finalizers;
-import java.util.HashSet;
import java.util.OptionalDouble;
-import java.util.Set;
-import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
-import org.l2jmobius.gameserver.model.ArmorSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
-import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.stats.BaseStat;
import org.l2jmobius.gameserver.model.stats.IStatFunction;
import org.l2jmobius.gameserver.model.stats.Stat;
@@ -46,19 +41,9 @@ public class BaseStatFinalizer implements IStatFunction
if (creature.isPlayer())
{
final PlayerInstance player = creature.getActingPlayer();
- final Set appliedSets = new HashSet<>(2);
// Armor sets calculation
- for (ItemInstance item : player.getInventory().getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
- {
- baseValue += set.getStatsBonus(BaseStat.valueOf(stat));
- }
- }
- }
+ baseValue += player.getInventory().getPaperdollCache().getBaseStatValue(player, BaseStat.valueOf(stat));
// Henna calculation
baseValue += player.getHennaValue(BaseStat.valueOf(stat));
diff --git a/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java b/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
index 8482dee4e0..5664c5292a 100644
--- a/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
+++ b/L2J_Mobius_2.5_Underground/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
@@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
+ player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;
diff --git a/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/cache/PaperdollCache.java b/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
new file mode 100644
index 0000000000..c908c4434d
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
@@ -0,0 +1,127 @@
+/*
+ * 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.cache;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
+import org.l2jmobius.gameserver.model.ArmorSet;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.stats.BaseStat;
+import org.l2jmobius.gameserver.model.stats.Stat;
+
+/**
+ * @author Sahar
+ */
+public final class PaperdollCache
+{
+ private final Set _paperdollItems = ConcurrentHashMap.newKeySet();
+
+ private final Map _baseStatValues = new ConcurrentHashMap<>();
+ private final Map _statValues = new ConcurrentHashMap<>();
+ private int _maxSetEnchant = -1;
+
+ public Set getPaperdollItems()
+ {
+ return _paperdollItems;
+ }
+
+ public void clearCachedStats()
+ {
+ _baseStatValues.clear();
+ _statValues.clear();
+
+ clearMaxSetEnchant();
+ }
+
+ public void clearMaxSetEnchant()
+ {
+ _maxSetEnchant = -1;
+ }
+
+ public double getBaseStatValue(PlayerInstance player, final BaseStat stat)
+ {
+ final Double baseStatValue = _baseStatValues.get(stat);
+ if (baseStatValue != null)
+ {
+ return baseStatValue;
+ }
+
+ final Set appliedSets = new HashSet<>(2);
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
+ {
+ value += set.getStatsBonus(stat);
+ }
+ }
+ }
+
+ _baseStatValues.put(stat, value);
+ return value;
+ }
+
+ public int getMaxSetEnchant(PlayerInstance player)
+ {
+ int maxSetEnchant = _maxSetEnchant;
+ if (maxSetEnchant >= 0)
+ {
+ return maxSetEnchant;
+ }
+
+ maxSetEnchant = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ final int enchantEffect = set.getLowestSetEnchant(player);
+ if (enchantEffect > maxSetEnchant)
+ {
+ maxSetEnchant = enchantEffect;
+ }
+ }
+ }
+
+ _maxSetEnchant = maxSetEnchant;
+ return maxSetEnchant;
+ }
+
+ public double getStats(Stat stat)
+ {
+ final Double statValue = _statValues.get(stat);
+ if (statValue != null)
+ {
+ return statValue;
+ }
+
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ value += item.getItem().getStats(stat, 0);
+ }
+
+ _statValues.put(stat, value);
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index 5228ad8a48..93e45bf372 100644
--- a/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.cache.PaperdollCache;
import org.l2jmobius.gameserver.data.xml.impl.AppearanceItemData;
import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
import org.l2jmobius.gameserver.datatables.ItemTable;
@@ -123,6 +124,7 @@ public abstract class Inventory extends ItemContainer
private final ItemInstance[] _paperdoll;
private final List _paperdollListeners;
+ private final PaperdollCache _paperdollCache = new PaperdollCache();
// protected to be accessed from child classes only
protected int _totalWeight;
@@ -1209,6 +1211,8 @@ public abstract class Inventory extends ItemContainer
if (old != null)
{
_paperdoll[slot] = null;
+ _paperdollCache.getPaperdollItems().remove(old);
+
// Put old item from paperdoll slot to base location
old.setItemLocation(getBaseLocation());
old.setLastChange(ItemInstance.MODIFIED);
@@ -1239,6 +1243,8 @@ public abstract class Inventory extends ItemContainer
if (item != null)
{
_paperdoll[slot] = item;
+ _paperdollCache.getPaperdollItems().add(item);
+
item.setItemLocation(getEquipLocation(), slot);
item.setLastChange(ItemInstance.MODIFIED);
_wearedMask |= item.getItem().getItemMask();
@@ -1254,6 +1260,7 @@ public abstract class Inventory extends ItemContainer
item.updateDatabase();
}
+ _paperdollCache.clearCachedStats();
getOwner().getStat().recalculateStats(!getOwner().isPlayer());
if (getOwner().isPlayer())
@@ -2126,19 +2133,7 @@ public abstract class Inventory extends ItemContainer
}
final PlayerInstance player = getOwner().getActingPlayer();
- int maxSetEnchant = 0;
- for (ItemInstance item : getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- final int enchantEffect = set.getLowestSetEnchant(player);
- if (enchantEffect > maxSetEnchant)
- {
- maxSetEnchant = enchantEffect;
- }
- }
- }
- return maxSetEnchant;
+ return _paperdollCache.getMaxSetEnchant(player);
}
public int getWeaponEnchant()
@@ -2202,6 +2197,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final Collection getPaperdollItems(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2222,6 +2222,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems().size();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2238,4 +2243,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
+
+ public PaperdollCache getPaperdollCache()
+ {
+ return _paperdollCache;
+ }
}
diff --git a/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/stats/BaseStat.java b/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
index ea1f76bbb6..3b2a441178 100644
--- a/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
+++ b/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
@@ -40,6 +40,8 @@ public enum BaseStat
CHA(Stat.STAT_CHA),
LUC(Stat.STAT_LUC);
+ private static final BaseStat[] VALUES = BaseStat.values();
+
public static final int MAX_STAT_VALUE = 201;
private final double[] _bonus = new double[MAX_STAT_VALUE];
@@ -92,7 +94,7 @@ public enum BaseStat
public static BaseStat valueOf(Stat stat)
{
- for (BaseStat baseStat : values())
+ for (BaseStat baseStat : VALUES)
{
if (baseStat.getStat() == stat)
{
diff --git a/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java b/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
index 9da29a9c79..00e2ff03fd 100644
--- a/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
+++ b/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
@@ -92,10 +92,7 @@ public interface IStatFunction
final Inventory inv = creature.getInventory();
if (inv != null)
{
- for (ItemInstance item : inv.getPaperdollItems())
- {
- baseValue += item.getItem().getStats(stat, 0);
- }
+ baseValue += inv.getPaperdollCache().getStats(stat);
}
}
diff --git a/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java b/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
index 58369ad827..1355065c58 100644
--- a/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
+++ b/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
@@ -16,15 +16,10 @@
*/
package org.l2jmobius.gameserver.model.stats.finalizers;
-import java.util.HashSet;
import java.util.OptionalDouble;
-import java.util.Set;
-import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
-import org.l2jmobius.gameserver.model.ArmorSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
-import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.stats.BaseStat;
import org.l2jmobius.gameserver.model.stats.IStatFunction;
import org.l2jmobius.gameserver.model.stats.Stat;
@@ -46,19 +41,9 @@ public class BaseStatFinalizer implements IStatFunction
if (creature.isPlayer())
{
final PlayerInstance player = creature.getActingPlayer();
- final Set appliedSets = new HashSet<>(2);
// Armor sets calculation
- for (ItemInstance item : player.getInventory().getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
- {
- baseValue += set.getStatsBonus(BaseStat.valueOf(stat));
- }
- }
- }
+ baseValue += player.getInventory().getPaperdollCache().getBaseStatValue(player, BaseStat.valueOf(stat));
// Henna calculation
baseValue += player.getHennaValue(BaseStat.valueOf(stat));
diff --git a/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java b/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
index 8482dee4e0..5664c5292a 100644
--- a/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
+++ b/L2J_Mobius_3.0_Helios/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
@@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
+ player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;
diff --git a/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/cache/PaperdollCache.java b/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
new file mode 100644
index 0000000000..c908c4434d
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
@@ -0,0 +1,127 @@
+/*
+ * 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.cache;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
+import org.l2jmobius.gameserver.model.ArmorSet;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.stats.BaseStat;
+import org.l2jmobius.gameserver.model.stats.Stat;
+
+/**
+ * @author Sahar
+ */
+public final class PaperdollCache
+{
+ private final Set _paperdollItems = ConcurrentHashMap.newKeySet();
+
+ private final Map _baseStatValues = new ConcurrentHashMap<>();
+ private final Map _statValues = new ConcurrentHashMap<>();
+ private int _maxSetEnchant = -1;
+
+ public Set getPaperdollItems()
+ {
+ return _paperdollItems;
+ }
+
+ public void clearCachedStats()
+ {
+ _baseStatValues.clear();
+ _statValues.clear();
+
+ clearMaxSetEnchant();
+ }
+
+ public void clearMaxSetEnchant()
+ {
+ _maxSetEnchant = -1;
+ }
+
+ public double getBaseStatValue(PlayerInstance player, final BaseStat stat)
+ {
+ final Double baseStatValue = _baseStatValues.get(stat);
+ if (baseStatValue != null)
+ {
+ return baseStatValue;
+ }
+
+ final Set appliedSets = new HashSet<>(2);
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
+ {
+ value += set.getStatsBonus(stat);
+ }
+ }
+ }
+
+ _baseStatValues.put(stat, value);
+ return value;
+ }
+
+ public int getMaxSetEnchant(PlayerInstance player)
+ {
+ int maxSetEnchant = _maxSetEnchant;
+ if (maxSetEnchant >= 0)
+ {
+ return maxSetEnchant;
+ }
+
+ maxSetEnchant = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ final int enchantEffect = set.getLowestSetEnchant(player);
+ if (enchantEffect > maxSetEnchant)
+ {
+ maxSetEnchant = enchantEffect;
+ }
+ }
+ }
+
+ _maxSetEnchant = maxSetEnchant;
+ return maxSetEnchant;
+ }
+
+ public double getStats(Stat stat)
+ {
+ final Double statValue = _statValues.get(stat);
+ if (statValue != null)
+ {
+ return statValue;
+ }
+
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ value += item.getItem().getStats(stat, 0);
+ }
+
+ _statValues.put(stat, value);
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index 31006fa918..56a8b6a30f 100644
--- a/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.cache.PaperdollCache;
import org.l2jmobius.gameserver.data.xml.impl.AppearanceItemData;
import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
import org.l2jmobius.gameserver.datatables.ItemTable;
@@ -123,6 +124,7 @@ public abstract class Inventory extends ItemContainer
private final ItemInstance[] _paperdoll;
private final List _paperdollListeners;
+ private final PaperdollCache _paperdollCache = new PaperdollCache();
// protected to be accessed from child classes only
protected int _totalWeight;
@@ -1209,6 +1211,8 @@ public abstract class Inventory extends ItemContainer
if (old != null)
{
_paperdoll[slot] = null;
+ _paperdollCache.getPaperdollItems().remove(old);
+
// Put old item from paperdoll slot to base location
old.setItemLocation(getBaseLocation());
old.setLastChange(ItemInstance.MODIFIED);
@@ -1239,6 +1243,8 @@ public abstract class Inventory extends ItemContainer
if (item != null)
{
_paperdoll[slot] = item;
+ _paperdollCache.getPaperdollItems().add(item);
+
item.setItemLocation(getEquipLocation(), slot);
item.setLastChange(ItemInstance.MODIFIED);
_wearedMask |= item.getItem().getItemMask();
@@ -1254,6 +1260,7 @@ public abstract class Inventory extends ItemContainer
item.updateDatabase();
}
+ _paperdollCache.clearCachedStats();
getOwner().getStat().recalculateStats(!getOwner().isPlayer());
if (getOwner().isPlayer())
@@ -2126,19 +2133,7 @@ public abstract class Inventory extends ItemContainer
}
final PlayerInstance player = getOwner().getActingPlayer();
- int maxSetEnchant = 0;
- for (ItemInstance item : getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- final int enchantEffect = set.getLowestSetEnchant(player);
- if (enchantEffect > maxSetEnchant)
- {
- maxSetEnchant = enchantEffect;
- }
- }
- }
- return maxSetEnchant;
+ return _paperdollCache.getMaxSetEnchant(player);
}
public int getWeaponEnchant()
@@ -2202,6 +2197,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final Collection getPaperdollItems(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2222,6 +2222,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems().size();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2238,4 +2243,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
+
+ public PaperdollCache getPaperdollCache()
+ {
+ return _paperdollCache;
+ }
}
diff --git a/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/stats/BaseStat.java b/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
index ea1f76bbb6..3b2a441178 100644
--- a/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
+++ b/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
@@ -40,6 +40,8 @@ public enum BaseStat
CHA(Stat.STAT_CHA),
LUC(Stat.STAT_LUC);
+ private static final BaseStat[] VALUES = BaseStat.values();
+
public static final int MAX_STAT_VALUE = 201;
private final double[] _bonus = new double[MAX_STAT_VALUE];
@@ -92,7 +94,7 @@ public enum BaseStat
public static BaseStat valueOf(Stat stat)
{
- for (BaseStat baseStat : values())
+ for (BaseStat baseStat : VALUES)
{
if (baseStat.getStat() == stat)
{
diff --git a/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java b/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
index 9da29a9c79..00e2ff03fd 100644
--- a/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
+++ b/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
@@ -92,10 +92,7 @@ public interface IStatFunction
final Inventory inv = creature.getInventory();
if (inv != null)
{
- for (ItemInstance item : inv.getPaperdollItems())
- {
- baseValue += item.getItem().getStats(stat, 0);
- }
+ baseValue += inv.getPaperdollCache().getStats(stat);
}
}
diff --git a/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java b/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
index 58369ad827..1355065c58 100644
--- a/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
+++ b/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
@@ -16,15 +16,10 @@
*/
package org.l2jmobius.gameserver.model.stats.finalizers;
-import java.util.HashSet;
import java.util.OptionalDouble;
-import java.util.Set;
-import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
-import org.l2jmobius.gameserver.model.ArmorSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
-import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.stats.BaseStat;
import org.l2jmobius.gameserver.model.stats.IStatFunction;
import org.l2jmobius.gameserver.model.stats.Stat;
@@ -46,19 +41,9 @@ public class BaseStatFinalizer implements IStatFunction
if (creature.isPlayer())
{
final PlayerInstance player = creature.getActingPlayer();
- final Set appliedSets = new HashSet<>(2);
// Armor sets calculation
- for (ItemInstance item : player.getInventory().getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
- {
- baseValue += set.getStatsBonus(BaseStat.valueOf(stat));
- }
- }
- }
+ baseValue += player.getInventory().getPaperdollCache().getBaseStatValue(player, BaseStat.valueOf(stat));
// Henna calculation
baseValue += player.getHennaValue(BaseStat.valueOf(stat));
diff --git a/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java b/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
index 8482dee4e0..5664c5292a 100644
--- a/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
+++ b/L2J_Mobius_4.0_GrandCrusade/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
@@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
+ player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;
diff --git a/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/cache/PaperdollCache.java b/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
new file mode 100644
index 0000000000..c908c4434d
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
@@ -0,0 +1,127 @@
+/*
+ * 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.cache;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
+import org.l2jmobius.gameserver.model.ArmorSet;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.stats.BaseStat;
+import org.l2jmobius.gameserver.model.stats.Stat;
+
+/**
+ * @author Sahar
+ */
+public final class PaperdollCache
+{
+ private final Set _paperdollItems = ConcurrentHashMap.newKeySet();
+
+ private final Map _baseStatValues = new ConcurrentHashMap<>();
+ private final Map _statValues = new ConcurrentHashMap<>();
+ private int _maxSetEnchant = -1;
+
+ public Set getPaperdollItems()
+ {
+ return _paperdollItems;
+ }
+
+ public void clearCachedStats()
+ {
+ _baseStatValues.clear();
+ _statValues.clear();
+
+ clearMaxSetEnchant();
+ }
+
+ public void clearMaxSetEnchant()
+ {
+ _maxSetEnchant = -1;
+ }
+
+ public double getBaseStatValue(PlayerInstance player, final BaseStat stat)
+ {
+ final Double baseStatValue = _baseStatValues.get(stat);
+ if (baseStatValue != null)
+ {
+ return baseStatValue;
+ }
+
+ final Set appliedSets = new HashSet<>(2);
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
+ {
+ value += set.getStatsBonus(stat);
+ }
+ }
+ }
+
+ _baseStatValues.put(stat, value);
+ return value;
+ }
+
+ public int getMaxSetEnchant(PlayerInstance player)
+ {
+ int maxSetEnchant = _maxSetEnchant;
+ if (maxSetEnchant >= 0)
+ {
+ return maxSetEnchant;
+ }
+
+ maxSetEnchant = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ final int enchantEffect = set.getLowestSetEnchant(player);
+ if (enchantEffect > maxSetEnchant)
+ {
+ maxSetEnchant = enchantEffect;
+ }
+ }
+ }
+
+ _maxSetEnchant = maxSetEnchant;
+ return maxSetEnchant;
+ }
+
+ public double getStats(Stat stat)
+ {
+ final Double statValue = _statValues.get(stat);
+ if (statValue != null)
+ {
+ return statValue;
+ }
+
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ value += item.getItem().getStats(stat, 0);
+ }
+
+ _statValues.put(stat, value);
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index aa7934b96c..d085094609 100644
--- a/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.cache.PaperdollCache;
import org.l2jmobius.gameserver.data.xml.impl.AppearanceItemData;
import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
import org.l2jmobius.gameserver.datatables.ItemTable;
@@ -128,6 +129,7 @@ public abstract class Inventory extends ItemContainer
private final ItemInstance[] _paperdoll;
private final List _paperdollListeners;
+ private final PaperdollCache _paperdollCache = new PaperdollCache();
// protected to be accessed from child classes only
protected int _totalWeight;
@@ -1238,6 +1240,8 @@ public abstract class Inventory extends ItemContainer
if (old != null)
{
_paperdoll[slot] = null;
+ _paperdollCache.getPaperdollItems().remove(old);
+
// Put old item from paperdoll slot to base location
old.setItemLocation(getBaseLocation());
old.setLastChange(ItemInstance.MODIFIED);
@@ -1268,6 +1272,8 @@ public abstract class Inventory extends ItemContainer
if (item != null)
{
_paperdoll[slot] = item;
+ _paperdollCache.getPaperdollItems().add(item);
+
item.setItemLocation(getEquipLocation(), slot);
item.setLastChange(ItemInstance.MODIFIED);
_wearedMask |= item.getItem().getItemMask();
@@ -1283,6 +1289,7 @@ public abstract class Inventory extends ItemContainer
item.updateDatabase();
}
+ _paperdollCache.clearCachedStats();
getOwner().getStat().recalculateStats(!getOwner().isPlayer());
if (getOwner().isPlayer())
@@ -2139,19 +2146,7 @@ public abstract class Inventory extends ItemContainer
}
final PlayerInstance player = getOwner().getActingPlayer();
- int maxSetEnchant = 0;
- for (ItemInstance item : getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- final int enchantEffect = set.getLowestSetEnchant(player);
- if (enchantEffect > maxSetEnchant)
- {
- maxSetEnchant = enchantEffect;
- }
- }
- }
- return maxSetEnchant;
+ return _paperdollCache.getMaxSetEnchant(player);
}
public int getWeaponEnchant()
@@ -2215,6 +2210,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final Collection getPaperdollItems(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2235,6 +2235,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems().size();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2251,4 +2256,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
+
+ public PaperdollCache getPaperdollCache()
+ {
+ return _paperdollCache;
+ }
}
diff --git a/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/stats/BaseStat.java b/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
index ea1f76bbb6..3b2a441178 100644
--- a/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
+++ b/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
@@ -40,6 +40,8 @@ public enum BaseStat
CHA(Stat.STAT_CHA),
LUC(Stat.STAT_LUC);
+ private static final BaseStat[] VALUES = BaseStat.values();
+
public static final int MAX_STAT_VALUE = 201;
private final double[] _bonus = new double[MAX_STAT_VALUE];
@@ -92,7 +94,7 @@ public enum BaseStat
public static BaseStat valueOf(Stat stat)
{
- for (BaseStat baseStat : values())
+ for (BaseStat baseStat : VALUES)
{
if (baseStat.getStat() == stat)
{
diff --git a/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java b/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
index 3286b91bf0..9026f10ca6 100644
--- a/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
+++ b/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
@@ -92,10 +92,7 @@ public interface IStatFunction
final Inventory inv = creature.getInventory();
if (inv != null)
{
- for (ItemInstance item : inv.getPaperdollItems())
- {
- baseValue += item.getItem().getStats(stat, 0);
- }
+ baseValue += inv.getPaperdollCache().getStats(stat);
}
}
diff --git a/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java b/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
index 58369ad827..1355065c58 100644
--- a/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
+++ b/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
@@ -16,15 +16,10 @@
*/
package org.l2jmobius.gameserver.model.stats.finalizers;
-import java.util.HashSet;
import java.util.OptionalDouble;
-import java.util.Set;
-import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
-import org.l2jmobius.gameserver.model.ArmorSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
-import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.stats.BaseStat;
import org.l2jmobius.gameserver.model.stats.IStatFunction;
import org.l2jmobius.gameserver.model.stats.Stat;
@@ -46,19 +41,9 @@ public class BaseStatFinalizer implements IStatFunction
if (creature.isPlayer())
{
final PlayerInstance player = creature.getActingPlayer();
- final Set appliedSets = new HashSet<>(2);
// Armor sets calculation
- for (ItemInstance item : player.getInventory().getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
- {
- baseValue += set.getStatsBonus(BaseStat.valueOf(stat));
- }
- }
- }
+ baseValue += player.getInventory().getPaperdollCache().getBaseStatValue(player, BaseStat.valueOf(stat));
// Henna calculation
baseValue += player.getHennaValue(BaseStat.valueOf(stat));
diff --git a/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java b/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
index c13244d61b..fd0688a9f7 100644
--- a/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
+++ b/L2J_Mobius_5.0_Salvation/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
@@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
+ player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;
diff --git a/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/cache/PaperdollCache.java b/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
new file mode 100644
index 0000000000..c908c4434d
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
@@ -0,0 +1,127 @@
+/*
+ * 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.cache;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
+import org.l2jmobius.gameserver.model.ArmorSet;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.stats.BaseStat;
+import org.l2jmobius.gameserver.model.stats.Stat;
+
+/**
+ * @author Sahar
+ */
+public final class PaperdollCache
+{
+ private final Set _paperdollItems = ConcurrentHashMap.newKeySet();
+
+ private final Map _baseStatValues = new ConcurrentHashMap<>();
+ private final Map _statValues = new ConcurrentHashMap<>();
+ private int _maxSetEnchant = -1;
+
+ public Set getPaperdollItems()
+ {
+ return _paperdollItems;
+ }
+
+ public void clearCachedStats()
+ {
+ _baseStatValues.clear();
+ _statValues.clear();
+
+ clearMaxSetEnchant();
+ }
+
+ public void clearMaxSetEnchant()
+ {
+ _maxSetEnchant = -1;
+ }
+
+ public double getBaseStatValue(PlayerInstance player, final BaseStat stat)
+ {
+ final Double baseStatValue = _baseStatValues.get(stat);
+ if (baseStatValue != null)
+ {
+ return baseStatValue;
+ }
+
+ final Set appliedSets = new HashSet<>(2);
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
+ {
+ value += set.getStatsBonus(stat);
+ }
+ }
+ }
+
+ _baseStatValues.put(stat, value);
+ return value;
+ }
+
+ public int getMaxSetEnchant(PlayerInstance player)
+ {
+ int maxSetEnchant = _maxSetEnchant;
+ if (maxSetEnchant >= 0)
+ {
+ return maxSetEnchant;
+ }
+
+ maxSetEnchant = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ final int enchantEffect = set.getLowestSetEnchant(player);
+ if (enchantEffect > maxSetEnchant)
+ {
+ maxSetEnchant = enchantEffect;
+ }
+ }
+ }
+
+ _maxSetEnchant = maxSetEnchant;
+ return maxSetEnchant;
+ }
+
+ public double getStats(Stat stat)
+ {
+ final Double statValue = _statValues.get(stat);
+ if (statValue != null)
+ {
+ return statValue;
+ }
+
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ value += item.getItem().getStats(stat, 0);
+ }
+
+ _statValues.put(stat, value);
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index f0b29ddde3..d6d712d153 100644
--- a/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.cache.PaperdollCache;
import org.l2jmobius.gameserver.data.xml.impl.AppearanceItemData;
import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
import org.l2jmobius.gameserver.datatables.ItemTable;
@@ -151,6 +152,7 @@ public abstract class Inventory extends ItemContainer
private final ItemInstance[] _paperdoll;
private final List _paperdollListeners;
+ private final PaperdollCache _paperdollCache = new PaperdollCache();
// protected to be accessed from child classes only
protected int _totalWeight;
@@ -1314,6 +1316,8 @@ public abstract class Inventory extends ItemContainer
if (old != null)
{
_paperdoll[slot] = null;
+ _paperdollCache.getPaperdollItems().remove(old);
+
// Put old item from paperdoll slot to base location
old.setItemLocation(getBaseLocation());
old.setLastChange(ItemInstance.MODIFIED);
@@ -1344,6 +1348,8 @@ public abstract class Inventory extends ItemContainer
if (item != null)
{
_paperdoll[slot] = item;
+ _paperdollCache.getPaperdollItems().add(item);
+
item.setItemLocation(getEquipLocation(), slot);
item.setLastChange(ItemInstance.MODIFIED);
_wearedMask |= item.getItem().getItemMask();
@@ -1359,6 +1365,7 @@ public abstract class Inventory extends ItemContainer
item.updateDatabase();
}
+ _paperdollCache.clearCachedStats();
getOwner().getStat().recalculateStats(!getOwner().isPlayer());
if (getOwner().isPlayer())
@@ -2436,19 +2443,7 @@ public abstract class Inventory extends ItemContainer
}
final PlayerInstance player = getOwner().getActingPlayer();
- int maxSetEnchant = 0;
- for (ItemInstance item : getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- final int enchantEffect = set.getLowestSetEnchant(player);
- if (enchantEffect > maxSetEnchant)
- {
- maxSetEnchant = enchantEffect;
- }
- }
- }
- return maxSetEnchant;
+ return _paperdollCache.getMaxSetEnchant(player);
}
public int getWeaponEnchant()
@@ -2512,6 +2507,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final Collection getPaperdollItems(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2532,6 +2532,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems().size();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2548,4 +2553,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
+
+ public PaperdollCache getPaperdollCache()
+ {
+ return _paperdollCache;
+ }
}
diff --git a/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/stats/BaseStat.java b/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
index ea1f76bbb6..3b2a441178 100644
--- a/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
+++ b/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
@@ -40,6 +40,8 @@ public enum BaseStat
CHA(Stat.STAT_CHA),
LUC(Stat.STAT_LUC);
+ private static final BaseStat[] VALUES = BaseStat.values();
+
public static final int MAX_STAT_VALUE = 201;
private final double[] _bonus = new double[MAX_STAT_VALUE];
@@ -92,7 +94,7 @@ public enum BaseStat
public static BaseStat valueOf(Stat stat)
{
- for (BaseStat baseStat : values())
+ for (BaseStat baseStat : VALUES)
{
if (baseStat.getStat() == stat)
{
diff --git a/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java b/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
index 3286b91bf0..9026f10ca6 100644
--- a/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
+++ b/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
@@ -92,10 +92,7 @@ public interface IStatFunction
final Inventory inv = creature.getInventory();
if (inv != null)
{
- for (ItemInstance item : inv.getPaperdollItems())
- {
- baseValue += item.getItem().getStats(stat, 0);
- }
+ baseValue += inv.getPaperdollCache().getStats(stat);
}
}
diff --git a/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java b/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
index 58369ad827..1355065c58 100644
--- a/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
+++ b/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
@@ -16,15 +16,10 @@
*/
package org.l2jmobius.gameserver.model.stats.finalizers;
-import java.util.HashSet;
import java.util.OptionalDouble;
-import java.util.Set;
-import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
-import org.l2jmobius.gameserver.model.ArmorSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
-import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.stats.BaseStat;
import org.l2jmobius.gameserver.model.stats.IStatFunction;
import org.l2jmobius.gameserver.model.stats.Stat;
@@ -46,19 +41,9 @@ public class BaseStatFinalizer implements IStatFunction
if (creature.isPlayer())
{
final PlayerInstance player = creature.getActingPlayer();
- final Set appliedSets = new HashSet<>(2);
// Armor sets calculation
- for (ItemInstance item : player.getInventory().getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
- {
- baseValue += set.getStatsBonus(BaseStat.valueOf(stat));
- }
- }
- }
+ baseValue += player.getInventory().getPaperdollCache().getBaseStatValue(player, BaseStat.valueOf(stat));
// Henna calculation
baseValue += player.getHennaValue(BaseStat.valueOf(stat));
diff --git a/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java b/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
index c13244d61b..fd0688a9f7 100644
--- a/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
+++ b/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
@@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
+ player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;
diff --git a/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/cache/PaperdollCache.java b/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
new file mode 100644
index 0000000000..c908c4434d
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
@@ -0,0 +1,127 @@
+/*
+ * 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.cache;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
+import org.l2jmobius.gameserver.model.ArmorSet;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.stats.BaseStat;
+import org.l2jmobius.gameserver.model.stats.Stat;
+
+/**
+ * @author Sahar
+ */
+public final class PaperdollCache
+{
+ private final Set _paperdollItems = ConcurrentHashMap.newKeySet();
+
+ private final Map _baseStatValues = new ConcurrentHashMap<>();
+ private final Map _statValues = new ConcurrentHashMap<>();
+ private int _maxSetEnchant = -1;
+
+ public Set getPaperdollItems()
+ {
+ return _paperdollItems;
+ }
+
+ public void clearCachedStats()
+ {
+ _baseStatValues.clear();
+ _statValues.clear();
+
+ clearMaxSetEnchant();
+ }
+
+ public void clearMaxSetEnchant()
+ {
+ _maxSetEnchant = -1;
+ }
+
+ public double getBaseStatValue(PlayerInstance player, final BaseStat stat)
+ {
+ final Double baseStatValue = _baseStatValues.get(stat);
+ if (baseStatValue != null)
+ {
+ return baseStatValue;
+ }
+
+ final Set appliedSets = new HashSet<>(2);
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
+ {
+ value += set.getStatsBonus(stat);
+ }
+ }
+ }
+
+ _baseStatValues.put(stat, value);
+ return value;
+ }
+
+ public int getMaxSetEnchant(PlayerInstance player)
+ {
+ int maxSetEnchant = _maxSetEnchant;
+ if (maxSetEnchant >= 0)
+ {
+ return maxSetEnchant;
+ }
+
+ maxSetEnchant = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ final int enchantEffect = set.getLowestSetEnchant(player);
+ if (enchantEffect > maxSetEnchant)
+ {
+ maxSetEnchant = enchantEffect;
+ }
+ }
+ }
+
+ _maxSetEnchant = maxSetEnchant;
+ return maxSetEnchant;
+ }
+
+ public double getStats(Stat stat)
+ {
+ final Double statValue = _statValues.get(stat);
+ if (statValue != null)
+ {
+ return statValue;
+ }
+
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ value += item.getItem().getStats(stat, 0);
+ }
+
+ _statValues.put(stat, value);
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index f0b29ddde3..d6d712d153 100644
--- a/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.cache.PaperdollCache;
import org.l2jmobius.gameserver.data.xml.impl.AppearanceItemData;
import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
import org.l2jmobius.gameserver.datatables.ItemTable;
@@ -151,6 +152,7 @@ public abstract class Inventory extends ItemContainer
private final ItemInstance[] _paperdoll;
private final List _paperdollListeners;
+ private final PaperdollCache _paperdollCache = new PaperdollCache();
// protected to be accessed from child classes only
protected int _totalWeight;
@@ -1314,6 +1316,8 @@ public abstract class Inventory extends ItemContainer
if (old != null)
{
_paperdoll[slot] = null;
+ _paperdollCache.getPaperdollItems().remove(old);
+
// Put old item from paperdoll slot to base location
old.setItemLocation(getBaseLocation());
old.setLastChange(ItemInstance.MODIFIED);
@@ -1344,6 +1348,8 @@ public abstract class Inventory extends ItemContainer
if (item != null)
{
_paperdoll[slot] = item;
+ _paperdollCache.getPaperdollItems().add(item);
+
item.setItemLocation(getEquipLocation(), slot);
item.setLastChange(ItemInstance.MODIFIED);
_wearedMask |= item.getItem().getItemMask();
@@ -1359,6 +1365,7 @@ public abstract class Inventory extends ItemContainer
item.updateDatabase();
}
+ _paperdollCache.clearCachedStats();
getOwner().getStat().recalculateStats(!getOwner().isPlayer());
if (getOwner().isPlayer())
@@ -2436,19 +2443,7 @@ public abstract class Inventory extends ItemContainer
}
final PlayerInstance player = getOwner().getActingPlayer();
- int maxSetEnchant = 0;
- for (ItemInstance item : getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- final int enchantEffect = set.getLowestSetEnchant(player);
- if (enchantEffect > maxSetEnchant)
- {
- maxSetEnchant = enchantEffect;
- }
- }
- }
- return maxSetEnchant;
+ return _paperdollCache.getMaxSetEnchant(player);
}
public int getWeaponEnchant()
@@ -2512,6 +2507,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final Collection getPaperdollItems(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2532,6 +2532,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems().size();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2548,4 +2553,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
+
+ public PaperdollCache getPaperdollCache()
+ {
+ return _paperdollCache;
+ }
}
diff --git a/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/stats/BaseStat.java b/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
index ea1f76bbb6..3b2a441178 100644
--- a/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
+++ b/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
@@ -40,6 +40,8 @@ public enum BaseStat
CHA(Stat.STAT_CHA),
LUC(Stat.STAT_LUC);
+ private static final BaseStat[] VALUES = BaseStat.values();
+
public static final int MAX_STAT_VALUE = 201;
private final double[] _bonus = new double[MAX_STAT_VALUE];
@@ -92,7 +94,7 @@ public enum BaseStat
public static BaseStat valueOf(Stat stat)
{
- for (BaseStat baseStat : values())
+ for (BaseStat baseStat : VALUES)
{
if (baseStat.getStat() == stat)
{
diff --git a/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java b/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
index 3286b91bf0..9026f10ca6 100644
--- a/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
+++ b/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
@@ -92,10 +92,7 @@ public interface IStatFunction
final Inventory inv = creature.getInventory();
if (inv != null)
{
- for (ItemInstance item : inv.getPaperdollItems())
- {
- baseValue += item.getItem().getStats(stat, 0);
- }
+ baseValue += inv.getPaperdollCache().getStats(stat);
}
}
diff --git a/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java b/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
index 58369ad827..1355065c58 100644
--- a/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
+++ b/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
@@ -16,15 +16,10 @@
*/
package org.l2jmobius.gameserver.model.stats.finalizers;
-import java.util.HashSet;
import java.util.OptionalDouble;
-import java.util.Set;
-import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
-import org.l2jmobius.gameserver.model.ArmorSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
-import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.stats.BaseStat;
import org.l2jmobius.gameserver.model.stats.IStatFunction;
import org.l2jmobius.gameserver.model.stats.Stat;
@@ -46,19 +41,9 @@ public class BaseStatFinalizer implements IStatFunction
if (creature.isPlayer())
{
final PlayerInstance player = creature.getActingPlayer();
- final Set appliedSets = new HashSet<>(2);
// Armor sets calculation
- for (ItemInstance item : player.getInventory().getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
- {
- baseValue += set.getStatsBonus(BaseStat.valueOf(stat));
- }
- }
- }
+ baseValue += player.getInventory().getPaperdollCache().getBaseStatValue(player, BaseStat.valueOf(stat));
// Henna calculation
baseValue += player.getHennaValue(BaseStat.valueOf(stat));
diff --git a/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java b/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
index fef586aecb..9bf90b6310 100644
--- a/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
+++ b/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
@@ -257,6 +257,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
+ player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;
diff --git a/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/cache/PaperdollCache.java b/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
new file mode 100644
index 0000000000..c908c4434d
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
@@ -0,0 +1,127 @@
+/*
+ * 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.cache;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
+import org.l2jmobius.gameserver.model.ArmorSet;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.stats.BaseStat;
+import org.l2jmobius.gameserver.model.stats.Stat;
+
+/**
+ * @author Sahar
+ */
+public final class PaperdollCache
+{
+ private final Set _paperdollItems = ConcurrentHashMap.newKeySet();
+
+ private final Map _baseStatValues = new ConcurrentHashMap<>();
+ private final Map _statValues = new ConcurrentHashMap<>();
+ private int _maxSetEnchant = -1;
+
+ public Set getPaperdollItems()
+ {
+ return _paperdollItems;
+ }
+
+ public void clearCachedStats()
+ {
+ _baseStatValues.clear();
+ _statValues.clear();
+
+ clearMaxSetEnchant();
+ }
+
+ public void clearMaxSetEnchant()
+ {
+ _maxSetEnchant = -1;
+ }
+
+ public double getBaseStatValue(PlayerInstance player, final BaseStat stat)
+ {
+ final Double baseStatValue = _baseStatValues.get(stat);
+ if (baseStatValue != null)
+ {
+ return baseStatValue;
+ }
+
+ final Set appliedSets = new HashSet<>(2);
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
+ {
+ value += set.getStatsBonus(stat);
+ }
+ }
+ }
+
+ _baseStatValues.put(stat, value);
+ return value;
+ }
+
+ public int getMaxSetEnchant(PlayerInstance player)
+ {
+ int maxSetEnchant = _maxSetEnchant;
+ if (maxSetEnchant >= 0)
+ {
+ return maxSetEnchant;
+ }
+
+ maxSetEnchant = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ final int enchantEffect = set.getLowestSetEnchant(player);
+ if (enchantEffect > maxSetEnchant)
+ {
+ maxSetEnchant = enchantEffect;
+ }
+ }
+ }
+
+ _maxSetEnchant = maxSetEnchant;
+ return maxSetEnchant;
+ }
+
+ public double getStats(Stat stat)
+ {
+ final Double statValue = _statValues.get(stat);
+ if (statValue != null)
+ {
+ return statValue;
+ }
+
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ value += item.getItem().getStats(stat, 0);
+ }
+
+ _statValues.put(stat, value);
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index a9d7b3c4d6..da95a4aac5 100644
--- a/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.cache.PaperdollCache;
import org.l2jmobius.gameserver.data.xml.impl.AppearanceItemData;
import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
import org.l2jmobius.gameserver.datatables.ItemTable;
@@ -151,6 +152,7 @@ public abstract class Inventory extends ItemContainer
private final ItemInstance[] _paperdoll;
private final List _paperdollListeners;
+ private final PaperdollCache _paperdollCache = new PaperdollCache();
// protected to be accessed from child classes only
protected int _totalWeight;
@@ -1307,6 +1309,8 @@ public abstract class Inventory extends ItemContainer
if (old != null)
{
_paperdoll[slot] = null;
+ _paperdollCache.getPaperdollItems().remove(old);
+
// Put old item from paperdoll slot to base location
old.setItemLocation(getBaseLocation());
old.setLastChange(ItemInstance.MODIFIED);
@@ -1337,6 +1341,8 @@ public abstract class Inventory extends ItemContainer
if (item != null)
{
_paperdoll[slot] = item;
+ _paperdollCache.getPaperdollItems().add(item);
+
item.setItemLocation(getEquipLocation(), slot);
item.setLastChange(ItemInstance.MODIFIED);
_wearedMask |= item.getItem().getItemMask();
@@ -1352,6 +1358,7 @@ public abstract class Inventory extends ItemContainer
item.updateDatabase();
}
+ _paperdollCache.clearCachedStats();
getOwner().getStat().recalculateStats(!getOwner().isPlayer());
if (getOwner().isPlayer())
@@ -2420,19 +2427,7 @@ public abstract class Inventory extends ItemContainer
}
final PlayerInstance player = getOwner().getActingPlayer();
- int maxSetEnchant = 0;
- for (ItemInstance item : getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- final int enchantEffect = set.getLowestSetEnchant(player);
- if (enchantEffect > maxSetEnchant)
- {
- maxSetEnchant = enchantEffect;
- }
- }
- }
- return maxSetEnchant;
+ return _paperdollCache.getMaxSetEnchant(player);
}
public int getWeaponEnchant()
@@ -2496,6 +2491,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final Collection getPaperdollItems(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2516,6 +2516,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems().size();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2532,4 +2537,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
+
+ public PaperdollCache getPaperdollCache()
+ {
+ return _paperdollCache;
+ }
}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/stats/BaseStat.java b/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
index ea1f76bbb6..3b2a441178 100644
--- a/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
+++ b/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
@@ -40,6 +40,8 @@ public enum BaseStat
CHA(Stat.STAT_CHA),
LUC(Stat.STAT_LUC);
+ private static final BaseStat[] VALUES = BaseStat.values();
+
public static final int MAX_STAT_VALUE = 201;
private final double[] _bonus = new double[MAX_STAT_VALUE];
@@ -92,7 +94,7 @@ public enum BaseStat
public static BaseStat valueOf(Stat stat)
{
- for (BaseStat baseStat : values())
+ for (BaseStat baseStat : VALUES)
{
if (baseStat.getStat() == stat)
{
diff --git a/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java b/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
index 3286b91bf0..9026f10ca6 100644
--- a/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
+++ b/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
@@ -92,10 +92,7 @@ public interface IStatFunction
final Inventory inv = creature.getInventory();
if (inv != null)
{
- for (ItemInstance item : inv.getPaperdollItems())
- {
- baseValue += item.getItem().getStats(stat, 0);
- }
+ baseValue += inv.getPaperdollCache().getStats(stat);
}
}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java b/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
index 58369ad827..1355065c58 100644
--- a/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
+++ b/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
@@ -16,15 +16,10 @@
*/
package org.l2jmobius.gameserver.model.stats.finalizers;
-import java.util.HashSet;
import java.util.OptionalDouble;
-import java.util.Set;
-import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
-import org.l2jmobius.gameserver.model.ArmorSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
-import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.stats.BaseStat;
import org.l2jmobius.gameserver.model.stats.IStatFunction;
import org.l2jmobius.gameserver.model.stats.Stat;
@@ -46,19 +41,9 @@ public class BaseStatFinalizer implements IStatFunction
if (creature.isPlayer())
{
final PlayerInstance player = creature.getActingPlayer();
- final Set appliedSets = new HashSet<>(2);
// Armor sets calculation
- for (ItemInstance item : player.getInventory().getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
- {
- baseValue += set.getStatsBonus(BaseStat.valueOf(stat));
- }
- }
- }
+ baseValue += player.getInventory().getPaperdollCache().getBaseStatValue(player, BaseStat.valueOf(stat));
// Henna calculation
baseValue += player.getHennaValue(BaseStat.valueOf(stat));
diff --git a/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java b/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
index a6385c03f1..52db3e4fb8 100644
--- a/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
+++ b/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
@@ -257,6 +257,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
+ player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/cache/PaperdollCache.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
new file mode 100644
index 0000000000..c908c4434d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
@@ -0,0 +1,127 @@
+/*
+ * 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.cache;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
+import org.l2jmobius.gameserver.model.ArmorSet;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.stats.BaseStat;
+import org.l2jmobius.gameserver.model.stats.Stat;
+
+/**
+ * @author Sahar
+ */
+public final class PaperdollCache
+{
+ private final Set _paperdollItems = ConcurrentHashMap.newKeySet();
+
+ private final Map _baseStatValues = new ConcurrentHashMap<>();
+ private final Map _statValues = new ConcurrentHashMap<>();
+ private int _maxSetEnchant = -1;
+
+ public Set getPaperdollItems()
+ {
+ return _paperdollItems;
+ }
+
+ public void clearCachedStats()
+ {
+ _baseStatValues.clear();
+ _statValues.clear();
+
+ clearMaxSetEnchant();
+ }
+
+ public void clearMaxSetEnchant()
+ {
+ _maxSetEnchant = -1;
+ }
+
+ public double getBaseStatValue(PlayerInstance player, final BaseStat stat)
+ {
+ final Double baseStatValue = _baseStatValues.get(stat);
+ if (baseStatValue != null)
+ {
+ return baseStatValue;
+ }
+
+ final Set appliedSets = new HashSet<>(2);
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
+ {
+ value += set.getStatsBonus(stat);
+ }
+ }
+ }
+
+ _baseStatValues.put(stat, value);
+ return value;
+ }
+
+ public int getMaxSetEnchant(PlayerInstance player)
+ {
+ int maxSetEnchant = _maxSetEnchant;
+ if (maxSetEnchant >= 0)
+ {
+ return maxSetEnchant;
+ }
+
+ maxSetEnchant = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ final int enchantEffect = set.getLowestSetEnchant(player);
+ if (enchantEffect > maxSetEnchant)
+ {
+ maxSetEnchant = enchantEffect;
+ }
+ }
+ }
+
+ _maxSetEnchant = maxSetEnchant;
+ return maxSetEnchant;
+ }
+
+ public double getStats(Stat stat)
+ {
+ final Double statValue = _statValues.get(stat);
+ if (statValue != null)
+ {
+ return statValue;
+ }
+
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ value += item.getItem().getStats(stat, 0);
+ }
+
+ _statValues.put(stat, value);
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index 5228ad8a48..93e45bf372 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.cache.PaperdollCache;
import org.l2jmobius.gameserver.data.xml.impl.AppearanceItemData;
import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
import org.l2jmobius.gameserver.datatables.ItemTable;
@@ -123,6 +124,7 @@ public abstract class Inventory extends ItemContainer
private final ItemInstance[] _paperdoll;
private final List _paperdollListeners;
+ private final PaperdollCache _paperdollCache = new PaperdollCache();
// protected to be accessed from child classes only
protected int _totalWeight;
@@ -1209,6 +1211,8 @@ public abstract class Inventory extends ItemContainer
if (old != null)
{
_paperdoll[slot] = null;
+ _paperdollCache.getPaperdollItems().remove(old);
+
// Put old item from paperdoll slot to base location
old.setItemLocation(getBaseLocation());
old.setLastChange(ItemInstance.MODIFIED);
@@ -1239,6 +1243,8 @@ public abstract class Inventory extends ItemContainer
if (item != null)
{
_paperdoll[slot] = item;
+ _paperdollCache.getPaperdollItems().add(item);
+
item.setItemLocation(getEquipLocation(), slot);
item.setLastChange(ItemInstance.MODIFIED);
_wearedMask |= item.getItem().getItemMask();
@@ -1254,6 +1260,7 @@ public abstract class Inventory extends ItemContainer
item.updateDatabase();
}
+ _paperdollCache.clearCachedStats();
getOwner().getStat().recalculateStats(!getOwner().isPlayer());
if (getOwner().isPlayer())
@@ -2126,19 +2133,7 @@ public abstract class Inventory extends ItemContainer
}
final PlayerInstance player = getOwner().getActingPlayer();
- int maxSetEnchant = 0;
- for (ItemInstance item : getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- final int enchantEffect = set.getLowestSetEnchant(player);
- if (enchantEffect > maxSetEnchant)
- {
- maxSetEnchant = enchantEffect;
- }
- }
- }
- return maxSetEnchant;
+ return _paperdollCache.getMaxSetEnchant(player);
}
public int getWeaponEnchant()
@@ -2202,6 +2197,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final Collection getPaperdollItems(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2222,6 +2222,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems().size();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2238,4 +2243,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
+
+ public PaperdollCache getPaperdollCache()
+ {
+ return _paperdollCache;
+ }
}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/stats/BaseStat.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
index 861b619297..dc0b1c6109 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
@@ -38,6 +38,8 @@ public enum BaseStat
CON(Stat.STAT_CON),
MEN(Stat.STAT_MEN);
+ private static final BaseStat[] VALUES = BaseStat.values();
+
public static final int MAX_STAT_VALUE = 201;
private final double[] _bonus = new double[MAX_STAT_VALUE];
@@ -90,7 +92,7 @@ public enum BaseStat
public static BaseStat valueOf(Stat stat)
{
- for (BaseStat baseStat : values())
+ for (BaseStat baseStat : VALUES)
{
if (baseStat.getStat() == stat)
{
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
index 9da29a9c79..00e2ff03fd 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
@@ -92,10 +92,7 @@ public interface IStatFunction
final Inventory inv = creature.getInventory();
if (inv != null)
{
- for (ItemInstance item : inv.getPaperdollItems())
- {
- baseValue += item.getItem().getStats(stat, 0);
- }
+ baseValue += inv.getPaperdollCache().getStats(stat);
}
}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
index 58369ad827..1355065c58 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
@@ -16,15 +16,10 @@
*/
package org.l2jmobius.gameserver.model.stats.finalizers;
-import java.util.HashSet;
import java.util.OptionalDouble;
-import java.util.Set;
-import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
-import org.l2jmobius.gameserver.model.ArmorSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
-import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.stats.BaseStat;
import org.l2jmobius.gameserver.model.stats.IStatFunction;
import org.l2jmobius.gameserver.model.stats.Stat;
@@ -46,19 +41,9 @@ public class BaseStatFinalizer implements IStatFunction
if (creature.isPlayer())
{
final PlayerInstance player = creature.getActingPlayer();
- final Set appliedSets = new HashSet<>(2);
// Armor sets calculation
- for (ItemInstance item : player.getInventory().getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
- {
- baseValue += set.getStatsBonus(BaseStat.valueOf(stat));
- }
- }
- }
+ baseValue += player.getInventory().getPaperdollCache().getBaseStatValue(player, BaseStat.valueOf(stat));
// Henna calculation
baseValue += player.getHennaValue(BaseStat.valueOf(stat));
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
index 1ab8980f37..a45f7b8b9b 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
@@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
+ player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/cache/PaperdollCache.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
new file mode 100644
index 0000000000..c908c4434d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
@@ -0,0 +1,127 @@
+/*
+ * 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.cache;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
+import org.l2jmobius.gameserver.model.ArmorSet;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.stats.BaseStat;
+import org.l2jmobius.gameserver.model.stats.Stat;
+
+/**
+ * @author Sahar
+ */
+public final class PaperdollCache
+{
+ private final Set _paperdollItems = ConcurrentHashMap.newKeySet();
+
+ private final Map _baseStatValues = new ConcurrentHashMap<>();
+ private final Map _statValues = new ConcurrentHashMap<>();
+ private int _maxSetEnchant = -1;
+
+ public Set getPaperdollItems()
+ {
+ return _paperdollItems;
+ }
+
+ public void clearCachedStats()
+ {
+ _baseStatValues.clear();
+ _statValues.clear();
+
+ clearMaxSetEnchant();
+ }
+
+ public void clearMaxSetEnchant()
+ {
+ _maxSetEnchant = -1;
+ }
+
+ public double getBaseStatValue(PlayerInstance player, final BaseStat stat)
+ {
+ final Double baseStatValue = _baseStatValues.get(stat);
+ if (baseStatValue != null)
+ {
+ return baseStatValue;
+ }
+
+ final Set appliedSets = new HashSet<>(2);
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
+ {
+ value += set.getStatsBonus(stat);
+ }
+ }
+ }
+
+ _baseStatValues.put(stat, value);
+ return value;
+ }
+
+ public int getMaxSetEnchant(PlayerInstance player)
+ {
+ int maxSetEnchant = _maxSetEnchant;
+ if (maxSetEnchant >= 0)
+ {
+ return maxSetEnchant;
+ }
+
+ maxSetEnchant = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ final int enchantEffect = set.getLowestSetEnchant(player);
+ if (enchantEffect > maxSetEnchant)
+ {
+ maxSetEnchant = enchantEffect;
+ }
+ }
+ }
+
+ _maxSetEnchant = maxSetEnchant;
+ return maxSetEnchant;
+ }
+
+ public double getStats(Stat stat)
+ {
+ final Double statValue = _statValues.get(stat);
+ if (statValue != null)
+ {
+ return statValue;
+ }
+
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ value += item.getItem().getStats(stat, 0);
+ }
+
+ _statValues.put(stat, value);
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index 5228ad8a48..93e45bf372 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.cache.PaperdollCache;
import org.l2jmobius.gameserver.data.xml.impl.AppearanceItemData;
import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
import org.l2jmobius.gameserver.datatables.ItemTable;
@@ -123,6 +124,7 @@ public abstract class Inventory extends ItemContainer
private final ItemInstance[] _paperdoll;
private final List _paperdollListeners;
+ private final PaperdollCache _paperdollCache = new PaperdollCache();
// protected to be accessed from child classes only
protected int _totalWeight;
@@ -1209,6 +1211,8 @@ public abstract class Inventory extends ItemContainer
if (old != null)
{
_paperdoll[slot] = null;
+ _paperdollCache.getPaperdollItems().remove(old);
+
// Put old item from paperdoll slot to base location
old.setItemLocation(getBaseLocation());
old.setLastChange(ItemInstance.MODIFIED);
@@ -1239,6 +1243,8 @@ public abstract class Inventory extends ItemContainer
if (item != null)
{
_paperdoll[slot] = item;
+ _paperdollCache.getPaperdollItems().add(item);
+
item.setItemLocation(getEquipLocation(), slot);
item.setLastChange(ItemInstance.MODIFIED);
_wearedMask |= item.getItem().getItemMask();
@@ -1254,6 +1260,7 @@ public abstract class Inventory extends ItemContainer
item.updateDatabase();
}
+ _paperdollCache.clearCachedStats();
getOwner().getStat().recalculateStats(!getOwner().isPlayer());
if (getOwner().isPlayer())
@@ -2126,19 +2133,7 @@ public abstract class Inventory extends ItemContainer
}
final PlayerInstance player = getOwner().getActingPlayer();
- int maxSetEnchant = 0;
- for (ItemInstance item : getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- final int enchantEffect = set.getLowestSetEnchant(player);
- if (enchantEffect > maxSetEnchant)
- {
- maxSetEnchant = enchantEffect;
- }
- }
- }
- return maxSetEnchant;
+ return _paperdollCache.getMaxSetEnchant(player);
}
public int getWeaponEnchant()
@@ -2202,6 +2197,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final Collection getPaperdollItems(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2222,6 +2222,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems().size();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2238,4 +2243,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
+
+ public PaperdollCache getPaperdollCache()
+ {
+ return _paperdollCache;
+ }
}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/stats/BaseStat.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
index 861b619297..dc0b1c6109 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
@@ -38,6 +38,8 @@ public enum BaseStat
CON(Stat.STAT_CON),
MEN(Stat.STAT_MEN);
+ private static final BaseStat[] VALUES = BaseStat.values();
+
public static final int MAX_STAT_VALUE = 201;
private final double[] _bonus = new double[MAX_STAT_VALUE];
@@ -90,7 +92,7 @@ public enum BaseStat
public static BaseStat valueOf(Stat stat)
{
- for (BaseStat baseStat : values())
+ for (BaseStat baseStat : VALUES)
{
if (baseStat.getStat() == stat)
{
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
index 9da29a9c79..00e2ff03fd 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
@@ -92,10 +92,7 @@ public interface IStatFunction
final Inventory inv = creature.getInventory();
if (inv != null)
{
- for (ItemInstance item : inv.getPaperdollItems())
- {
- baseValue += item.getItem().getStats(stat, 0);
- }
+ baseValue += inv.getPaperdollCache().getStats(stat);
}
}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
index 58369ad827..1355065c58 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
@@ -16,15 +16,10 @@
*/
package org.l2jmobius.gameserver.model.stats.finalizers;
-import java.util.HashSet;
import java.util.OptionalDouble;
-import java.util.Set;
-import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
-import org.l2jmobius.gameserver.model.ArmorSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
-import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.stats.BaseStat;
import org.l2jmobius.gameserver.model.stats.IStatFunction;
import org.l2jmobius.gameserver.model.stats.Stat;
@@ -46,19 +41,9 @@ public class BaseStatFinalizer implements IStatFunction
if (creature.isPlayer())
{
final PlayerInstance player = creature.getActingPlayer();
- final Set appliedSets = new HashSet<>(2);
// Armor sets calculation
- for (ItemInstance item : player.getInventory().getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
- {
- baseValue += set.getStatsBonus(BaseStat.valueOf(stat));
- }
- }
- }
+ baseValue += player.getInventory().getPaperdollCache().getBaseStatValue(player, BaseStat.valueOf(stat));
// Henna calculation
baseValue += player.getHennaValue(BaseStat.valueOf(stat));
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
index 1ab8980f37..a45f7b8b9b 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
@@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
+ player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/cache/PaperdollCache.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
new file mode 100644
index 0000000000..c908c4434d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
@@ -0,0 +1,127 @@
+/*
+ * 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.cache;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
+import org.l2jmobius.gameserver.model.ArmorSet;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.stats.BaseStat;
+import org.l2jmobius.gameserver.model.stats.Stat;
+
+/**
+ * @author Sahar
+ */
+public final class PaperdollCache
+{
+ private final Set _paperdollItems = ConcurrentHashMap.newKeySet();
+
+ private final Map _baseStatValues = new ConcurrentHashMap<>();
+ private final Map _statValues = new ConcurrentHashMap<>();
+ private int _maxSetEnchant = -1;
+
+ public Set getPaperdollItems()
+ {
+ return _paperdollItems;
+ }
+
+ public void clearCachedStats()
+ {
+ _baseStatValues.clear();
+ _statValues.clear();
+
+ clearMaxSetEnchant();
+ }
+
+ public void clearMaxSetEnchant()
+ {
+ _maxSetEnchant = -1;
+ }
+
+ public double getBaseStatValue(PlayerInstance player, final BaseStat stat)
+ {
+ final Double baseStatValue = _baseStatValues.get(stat);
+ if (baseStatValue != null)
+ {
+ return baseStatValue;
+ }
+
+ final Set appliedSets = new HashSet<>(2);
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
+ {
+ value += set.getStatsBonus(stat);
+ }
+ }
+ }
+
+ _baseStatValues.put(stat, value);
+ return value;
+ }
+
+ public int getMaxSetEnchant(PlayerInstance player)
+ {
+ int maxSetEnchant = _maxSetEnchant;
+ if (maxSetEnchant >= 0)
+ {
+ return maxSetEnchant;
+ }
+
+ maxSetEnchant = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ final int enchantEffect = set.getLowestSetEnchant(player);
+ if (enchantEffect > maxSetEnchant)
+ {
+ maxSetEnchant = enchantEffect;
+ }
+ }
+ }
+
+ _maxSetEnchant = maxSetEnchant;
+ return maxSetEnchant;
+ }
+
+ public double getStats(Stat stat)
+ {
+ final Double statValue = _statValues.get(stat);
+ if (statValue != null)
+ {
+ return statValue;
+ }
+
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ value += item.getItem().getStats(stat, 0);
+ }
+
+ _statValues.put(stat, value);
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index 8d7ff1545f..37e44ceaab 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.cache.PaperdollCache;
import org.l2jmobius.gameserver.data.xml.impl.AppearanceItemData;
import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
import org.l2jmobius.gameserver.datatables.ItemTable;
@@ -128,6 +129,7 @@ public abstract class Inventory extends ItemContainer
private final ItemInstance[] _paperdoll;
private final List _paperdollListeners;
+ private final PaperdollCache _paperdollCache = new PaperdollCache();
// protected to be accessed from child classes only
protected int _totalWeight;
@@ -1238,6 +1240,8 @@ public abstract class Inventory extends ItemContainer
if (old != null)
{
_paperdoll[slot] = null;
+ _paperdollCache.getPaperdollItems().remove(old);
+
// Put old item from paperdoll slot to base location
old.setItemLocation(getBaseLocation());
old.setLastChange(ItemInstance.MODIFIED);
@@ -1268,6 +1272,8 @@ public abstract class Inventory extends ItemContainer
if (item != null)
{
_paperdoll[slot] = item;
+ _paperdollCache.getPaperdollItems().add(item);
+
item.setItemLocation(getEquipLocation(), slot);
item.setLastChange(ItemInstance.MODIFIED);
_wearedMask |= item.getItem().getItemMask();
@@ -1283,6 +1289,7 @@ public abstract class Inventory extends ItemContainer
item.updateDatabase();
}
+ _paperdollCache.clearCachedStats();
getOwner().getStat().recalculateStats(!getOwner().isPlayer());
if (getOwner().isPlayer())
@@ -2145,19 +2152,7 @@ public abstract class Inventory extends ItemContainer
}
final PlayerInstance player = getOwner().getActingPlayer();
- int maxSetEnchant = 0;
- for (ItemInstance item : getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- final int enchantEffect = set.getLowestSetEnchant(player);
- if (enchantEffect > maxSetEnchant)
- {
- maxSetEnchant = enchantEffect;
- }
- }
- }
- return maxSetEnchant;
+ return _paperdollCache.getMaxSetEnchant(player);
}
public int getWeaponEnchant()
@@ -2221,6 +2216,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final Collection getPaperdollItems(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2241,6 +2241,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems().size();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2257,4 +2262,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
+
+ public PaperdollCache getPaperdollCache()
+ {
+ return _paperdollCache;
+ }
}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/stats/BaseStat.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
index 861b619297..dc0b1c6109 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
@@ -38,6 +38,8 @@ public enum BaseStat
CON(Stat.STAT_CON),
MEN(Stat.STAT_MEN);
+ private static final BaseStat[] VALUES = BaseStat.values();
+
public static final int MAX_STAT_VALUE = 201;
private final double[] _bonus = new double[MAX_STAT_VALUE];
@@ -90,7 +92,7 @@ public enum BaseStat
public static BaseStat valueOf(Stat stat)
{
- for (BaseStat baseStat : values())
+ for (BaseStat baseStat : VALUES)
{
if (baseStat.getStat() == stat)
{
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
index 3286b91bf0..9026f10ca6 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
@@ -92,10 +92,7 @@ public interface IStatFunction
final Inventory inv = creature.getInventory();
if (inv != null)
{
- for (ItemInstance item : inv.getPaperdollItems())
- {
- baseValue += item.getItem().getStats(stat, 0);
- }
+ baseValue += inv.getPaperdollCache().getStats(stat);
}
}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
index 58369ad827..1355065c58 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
@@ -16,15 +16,10 @@
*/
package org.l2jmobius.gameserver.model.stats.finalizers;
-import java.util.HashSet;
import java.util.OptionalDouble;
-import java.util.Set;
-import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
-import org.l2jmobius.gameserver.model.ArmorSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
-import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.stats.BaseStat;
import org.l2jmobius.gameserver.model.stats.IStatFunction;
import org.l2jmobius.gameserver.model.stats.Stat;
@@ -46,19 +41,9 @@ public class BaseStatFinalizer implements IStatFunction
if (creature.isPlayer())
{
final PlayerInstance player = creature.getActingPlayer();
- final Set appliedSets = new HashSet<>(2);
// Armor sets calculation
- for (ItemInstance item : player.getInventory().getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
- {
- baseValue += set.getStatsBonus(BaseStat.valueOf(stat));
- }
- }
- }
+ baseValue += player.getInventory().getPaperdollCache().getBaseStatValue(player, BaseStat.valueOf(stat));
// Henna calculation
baseValue += player.getHennaValue(BaseStat.valueOf(stat));
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
index 0db62326a9..32a6f75639 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
@@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
+ player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/cache/PaperdollCache.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
new file mode 100644
index 0000000000..c908c4434d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
@@ -0,0 +1,127 @@
+/*
+ * 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.cache;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
+import org.l2jmobius.gameserver.model.ArmorSet;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.stats.BaseStat;
+import org.l2jmobius.gameserver.model.stats.Stat;
+
+/**
+ * @author Sahar
+ */
+public final class PaperdollCache
+{
+ private final Set _paperdollItems = ConcurrentHashMap.newKeySet();
+
+ private final Map _baseStatValues = new ConcurrentHashMap<>();
+ private final Map _statValues = new ConcurrentHashMap<>();
+ private int _maxSetEnchant = -1;
+
+ public Set getPaperdollItems()
+ {
+ return _paperdollItems;
+ }
+
+ public void clearCachedStats()
+ {
+ _baseStatValues.clear();
+ _statValues.clear();
+
+ clearMaxSetEnchant();
+ }
+
+ public void clearMaxSetEnchant()
+ {
+ _maxSetEnchant = -1;
+ }
+
+ public double getBaseStatValue(PlayerInstance player, final BaseStat stat)
+ {
+ final Double baseStatValue = _baseStatValues.get(stat);
+ if (baseStatValue != null)
+ {
+ return baseStatValue;
+ }
+
+ final Set appliedSets = new HashSet<>(2);
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
+ {
+ value += set.getStatsBonus(stat);
+ }
+ }
+ }
+
+ _baseStatValues.put(stat, value);
+ return value;
+ }
+
+ public int getMaxSetEnchant(PlayerInstance player)
+ {
+ int maxSetEnchant = _maxSetEnchant;
+ if (maxSetEnchant >= 0)
+ {
+ return maxSetEnchant;
+ }
+
+ maxSetEnchant = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ final int enchantEffect = set.getLowestSetEnchant(player);
+ if (enchantEffect > maxSetEnchant)
+ {
+ maxSetEnchant = enchantEffect;
+ }
+ }
+ }
+
+ _maxSetEnchant = maxSetEnchant;
+ return maxSetEnchant;
+ }
+
+ public double getStats(Stat stat)
+ {
+ final Double statValue = _statValues.get(stat);
+ if (statValue != null)
+ {
+ return statValue;
+ }
+
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ value += item.getItem().getStats(stat, 0);
+ }
+
+ _statValues.put(stat, value);
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index bb2d048efd..7ac140f2e4 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.cache.PaperdollCache;
import org.l2jmobius.gameserver.data.xml.impl.AppearanceItemData;
import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
import org.l2jmobius.gameserver.datatables.ItemTable;
@@ -151,6 +152,7 @@ public abstract class Inventory extends ItemContainer
private final ItemInstance[] _paperdoll;
private final List _paperdollListeners;
+ private final PaperdollCache _paperdollCache = new PaperdollCache();
// protected to be accessed from child classes only
protected int _totalWeight;
@@ -1314,6 +1316,8 @@ public abstract class Inventory extends ItemContainer
if (old != null)
{
_paperdoll[slot] = null;
+ _paperdollCache.getPaperdollItems().remove(old);
+
// Put old item from paperdoll slot to base location
old.setItemLocation(getBaseLocation());
old.setLastChange(ItemInstance.MODIFIED);
@@ -1344,6 +1348,8 @@ public abstract class Inventory extends ItemContainer
if (item != null)
{
_paperdoll[slot] = item;
+ _paperdollCache.getPaperdollItems().add(item);
+
item.setItemLocation(getEquipLocation(), slot);
item.setLastChange(ItemInstance.MODIFIED);
_wearedMask |= item.getItem().getItemMask();
@@ -1359,6 +1365,7 @@ public abstract class Inventory extends ItemContainer
item.updateDatabase();
}
+ _paperdollCache.clearCachedStats();
getOwner().getStat().recalculateStats(!getOwner().isPlayer());
if (getOwner().isPlayer())
@@ -2436,19 +2443,7 @@ public abstract class Inventory extends ItemContainer
}
final PlayerInstance player = getOwner().getActingPlayer();
- int maxSetEnchant = 0;
- for (ItemInstance item : getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- final int enchantEffect = set.getLowestSetEnchant(player);
- if (enchantEffect > maxSetEnchant)
- {
- maxSetEnchant = enchantEffect;
- }
- }
- }
- return maxSetEnchant;
+ return _paperdollCache.getMaxSetEnchant(player);
}
public int getWeaponEnchant()
@@ -2512,6 +2507,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final Collection getPaperdollItems(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2532,6 +2532,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems().size();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2548,4 +2553,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
+
+ public PaperdollCache getPaperdollCache()
+ {
+ return _paperdollCache;
+ }
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/BaseStat.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
index 861b619297..dc0b1c6109 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
@@ -38,6 +38,8 @@ public enum BaseStat
CON(Stat.STAT_CON),
MEN(Stat.STAT_MEN);
+ private static final BaseStat[] VALUES = BaseStat.values();
+
public static final int MAX_STAT_VALUE = 201;
private final double[] _bonus = new double[MAX_STAT_VALUE];
@@ -90,7 +92,7 @@ public enum BaseStat
public static BaseStat valueOf(Stat stat)
{
- for (BaseStat baseStat : values())
+ for (BaseStat baseStat : VALUES)
{
if (baseStat.getStat() == stat)
{
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
index 3286b91bf0..9026f10ca6 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
@@ -92,10 +92,7 @@ public interface IStatFunction
final Inventory inv = creature.getInventory();
if (inv != null)
{
- for (ItemInstance item : inv.getPaperdollItems())
- {
- baseValue += item.getItem().getStats(stat, 0);
- }
+ baseValue += inv.getPaperdollCache().getStats(stat);
}
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
index 58369ad827..1355065c58 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
@@ -16,15 +16,10 @@
*/
package org.l2jmobius.gameserver.model.stats.finalizers;
-import java.util.HashSet;
import java.util.OptionalDouble;
-import java.util.Set;
-import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
-import org.l2jmobius.gameserver.model.ArmorSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
-import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.stats.BaseStat;
import org.l2jmobius.gameserver.model.stats.IStatFunction;
import org.l2jmobius.gameserver.model.stats.Stat;
@@ -46,19 +41,9 @@ public class BaseStatFinalizer implements IStatFunction
if (creature.isPlayer())
{
final PlayerInstance player = creature.getActingPlayer();
- final Set appliedSets = new HashSet<>(2);
// Armor sets calculation
- for (ItemInstance item : player.getInventory().getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
- {
- baseValue += set.getStatsBonus(BaseStat.valueOf(stat));
- }
- }
- }
+ baseValue += player.getInventory().getPaperdollCache().getBaseStatValue(player, BaseStat.valueOf(stat));
// Henna calculation
baseValue += player.getHennaValue(BaseStat.valueOf(stat));
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
index 0db62326a9..32a6f75639 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
@@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
+ player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/cache/PaperdollCache.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
new file mode 100644
index 0000000000..c908c4434d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
@@ -0,0 +1,127 @@
+/*
+ * 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.cache;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
+import org.l2jmobius.gameserver.model.ArmorSet;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.stats.BaseStat;
+import org.l2jmobius.gameserver.model.stats.Stat;
+
+/**
+ * @author Sahar
+ */
+public final class PaperdollCache
+{
+ private final Set _paperdollItems = ConcurrentHashMap.newKeySet();
+
+ private final Map _baseStatValues = new ConcurrentHashMap<>();
+ private final Map _statValues = new ConcurrentHashMap<>();
+ private int _maxSetEnchant = -1;
+
+ public Set getPaperdollItems()
+ {
+ return _paperdollItems;
+ }
+
+ public void clearCachedStats()
+ {
+ _baseStatValues.clear();
+ _statValues.clear();
+
+ clearMaxSetEnchant();
+ }
+
+ public void clearMaxSetEnchant()
+ {
+ _maxSetEnchant = -1;
+ }
+
+ public double getBaseStatValue(PlayerInstance player, final BaseStat stat)
+ {
+ final Double baseStatValue = _baseStatValues.get(stat);
+ if (baseStatValue != null)
+ {
+ return baseStatValue;
+ }
+
+ final Set appliedSets = new HashSet<>(2);
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
+ {
+ value += set.getStatsBonus(stat);
+ }
+ }
+ }
+
+ _baseStatValues.put(stat, value);
+ return value;
+ }
+
+ public int getMaxSetEnchant(PlayerInstance player)
+ {
+ int maxSetEnchant = _maxSetEnchant;
+ if (maxSetEnchant >= 0)
+ {
+ return maxSetEnchant;
+ }
+
+ maxSetEnchant = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ final int enchantEffect = set.getLowestSetEnchant(player);
+ if (enchantEffect > maxSetEnchant)
+ {
+ maxSetEnchant = enchantEffect;
+ }
+ }
+ }
+
+ _maxSetEnchant = maxSetEnchant;
+ return maxSetEnchant;
+ }
+
+ public double getStats(Stat stat)
+ {
+ final Double statValue = _statValues.get(stat);
+ if (statValue != null)
+ {
+ return statValue;
+ }
+
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ value += item.getItem().getStats(stat, 0);
+ }
+
+ _statValues.put(stat, value);
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index bb2d048efd..7ac140f2e4 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.cache.PaperdollCache;
import org.l2jmobius.gameserver.data.xml.impl.AppearanceItemData;
import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
import org.l2jmobius.gameserver.datatables.ItemTable;
@@ -151,6 +152,7 @@ public abstract class Inventory extends ItemContainer
private final ItemInstance[] _paperdoll;
private final List _paperdollListeners;
+ private final PaperdollCache _paperdollCache = new PaperdollCache();
// protected to be accessed from child classes only
protected int _totalWeight;
@@ -1314,6 +1316,8 @@ public abstract class Inventory extends ItemContainer
if (old != null)
{
_paperdoll[slot] = null;
+ _paperdollCache.getPaperdollItems().remove(old);
+
// Put old item from paperdoll slot to base location
old.setItemLocation(getBaseLocation());
old.setLastChange(ItemInstance.MODIFIED);
@@ -1344,6 +1348,8 @@ public abstract class Inventory extends ItemContainer
if (item != null)
{
_paperdoll[slot] = item;
+ _paperdollCache.getPaperdollItems().add(item);
+
item.setItemLocation(getEquipLocation(), slot);
item.setLastChange(ItemInstance.MODIFIED);
_wearedMask |= item.getItem().getItemMask();
@@ -1359,6 +1365,7 @@ public abstract class Inventory extends ItemContainer
item.updateDatabase();
}
+ _paperdollCache.clearCachedStats();
getOwner().getStat().recalculateStats(!getOwner().isPlayer());
if (getOwner().isPlayer())
@@ -2436,19 +2443,7 @@ public abstract class Inventory extends ItemContainer
}
final PlayerInstance player = getOwner().getActingPlayer();
- int maxSetEnchant = 0;
- for (ItemInstance item : getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- final int enchantEffect = set.getLowestSetEnchant(player);
- if (enchantEffect > maxSetEnchant)
- {
- maxSetEnchant = enchantEffect;
- }
- }
- }
- return maxSetEnchant;
+ return _paperdollCache.getMaxSetEnchant(player);
}
public int getWeaponEnchant()
@@ -2512,6 +2507,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final Collection getPaperdollItems(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2532,6 +2532,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems().size();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2548,4 +2553,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
+
+ public PaperdollCache getPaperdollCache()
+ {
+ return _paperdollCache;
+ }
}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/BaseStat.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
index 861b619297..dc0b1c6109 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
@@ -38,6 +38,8 @@ public enum BaseStat
CON(Stat.STAT_CON),
MEN(Stat.STAT_MEN);
+ private static final BaseStat[] VALUES = BaseStat.values();
+
public static final int MAX_STAT_VALUE = 201;
private final double[] _bonus = new double[MAX_STAT_VALUE];
@@ -90,7 +92,7 @@ public enum BaseStat
public static BaseStat valueOf(Stat stat)
{
- for (BaseStat baseStat : values())
+ for (BaseStat baseStat : VALUES)
{
if (baseStat.getStat() == stat)
{
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
index 3286b91bf0..9026f10ca6 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
@@ -92,10 +92,7 @@ public interface IStatFunction
final Inventory inv = creature.getInventory();
if (inv != null)
{
- for (ItemInstance item : inv.getPaperdollItems())
- {
- baseValue += item.getItem().getStats(stat, 0);
- }
+ baseValue += inv.getPaperdollCache().getStats(stat);
}
}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
index 58369ad827..1355065c58 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
@@ -16,15 +16,10 @@
*/
package org.l2jmobius.gameserver.model.stats.finalizers;
-import java.util.HashSet;
import java.util.OptionalDouble;
-import java.util.Set;
-import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
-import org.l2jmobius.gameserver.model.ArmorSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
-import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.stats.BaseStat;
import org.l2jmobius.gameserver.model.stats.IStatFunction;
import org.l2jmobius.gameserver.model.stats.Stat;
@@ -46,19 +41,9 @@ public class BaseStatFinalizer implements IStatFunction
if (creature.isPlayer())
{
final PlayerInstance player = creature.getActingPlayer();
- final Set appliedSets = new HashSet<>(2);
// Armor sets calculation
- for (ItemInstance item : player.getInventory().getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
- {
- baseValue += set.getStatsBonus(BaseStat.valueOf(stat));
- }
- }
- }
+ baseValue += player.getInventory().getPaperdollCache().getBaseStatValue(player, BaseStat.valueOf(stat));
// Henna calculation
baseValue += player.getHennaValue(BaseStat.valueOf(stat));
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
index a6385c03f1..52db3e4fb8 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
@@ -257,6 +257,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
+ player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/cache/PaperdollCache.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
new file mode 100644
index 0000000000..c908c4434d
--- /dev/null
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
@@ -0,0 +1,127 @@
+/*
+ * 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.cache;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
+import org.l2jmobius.gameserver.model.ArmorSet;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.stats.BaseStat;
+import org.l2jmobius.gameserver.model.stats.Stat;
+
+/**
+ * @author Sahar
+ */
+public final class PaperdollCache
+{
+ private final Set _paperdollItems = ConcurrentHashMap.newKeySet();
+
+ private final Map _baseStatValues = new ConcurrentHashMap<>();
+ private final Map _statValues = new ConcurrentHashMap<>();
+ private int _maxSetEnchant = -1;
+
+ public Set getPaperdollItems()
+ {
+ return _paperdollItems;
+ }
+
+ public void clearCachedStats()
+ {
+ _baseStatValues.clear();
+ _statValues.clear();
+
+ clearMaxSetEnchant();
+ }
+
+ public void clearMaxSetEnchant()
+ {
+ _maxSetEnchant = -1;
+ }
+
+ public double getBaseStatValue(PlayerInstance player, final BaseStat stat)
+ {
+ final Double baseStatValue = _baseStatValues.get(stat);
+ if (baseStatValue != null)
+ {
+ return baseStatValue;
+ }
+
+ final Set appliedSets = new HashSet<>(2);
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
+ {
+ value += set.getStatsBonus(stat);
+ }
+ }
+ }
+
+ _baseStatValues.put(stat, value);
+ return value;
+ }
+
+ public int getMaxSetEnchant(PlayerInstance player)
+ {
+ int maxSetEnchant = _maxSetEnchant;
+ if (maxSetEnchant >= 0)
+ {
+ return maxSetEnchant;
+ }
+
+ maxSetEnchant = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ final int enchantEffect = set.getLowestSetEnchant(player);
+ if (enchantEffect > maxSetEnchant)
+ {
+ maxSetEnchant = enchantEffect;
+ }
+ }
+ }
+
+ _maxSetEnchant = maxSetEnchant;
+ return maxSetEnchant;
+ }
+
+ public double getStats(Stat stat)
+ {
+ final Double statValue = _statValues.get(stat);
+ if (statValue != null)
+ {
+ return statValue;
+ }
+
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ value += item.getItem().getStats(stat, 0);
+ }
+
+ _statValues.put(stat, value);
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index b17a536c83..6ef4c07734 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.cache.PaperdollCache;
import org.l2jmobius.gameserver.data.xml.impl.AppearanceItemData;
import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
import org.l2jmobius.gameserver.datatables.ItemTable;
@@ -151,6 +152,7 @@ public abstract class Inventory extends ItemContainer
private final ItemInstance[] _paperdoll;
private final List _paperdollListeners;
+ private final PaperdollCache _paperdollCache = new PaperdollCache();
// protected to be accessed from child classes only
protected int _totalWeight;
@@ -1307,6 +1309,8 @@ public abstract class Inventory extends ItemContainer
if (old != null)
{
_paperdoll[slot] = null;
+ _paperdollCache.getPaperdollItems().remove(old);
+
// Put old item from paperdoll slot to base location
old.setItemLocation(getBaseLocation());
old.setLastChange(ItemInstance.MODIFIED);
@@ -1337,6 +1341,8 @@ public abstract class Inventory extends ItemContainer
if (item != null)
{
_paperdoll[slot] = item;
+ _paperdollCache.getPaperdollItems().add(item);
+
item.setItemLocation(getEquipLocation(), slot);
item.setLastChange(ItemInstance.MODIFIED);
_wearedMask |= item.getItem().getItemMask();
@@ -1352,6 +1358,7 @@ public abstract class Inventory extends ItemContainer
item.updateDatabase();
}
+ _paperdollCache.clearCachedStats();
getOwner().getStat().recalculateStats(!getOwner().isPlayer());
if (getOwner().isPlayer())
@@ -2420,19 +2427,7 @@ public abstract class Inventory extends ItemContainer
}
final PlayerInstance player = getOwner().getActingPlayer();
- int maxSetEnchant = 0;
- for (ItemInstance item : getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- final int enchantEffect = set.getLowestSetEnchant(player);
- if (enchantEffect > maxSetEnchant)
- {
- maxSetEnchant = enchantEffect;
- }
- }
- }
- return maxSetEnchant;
+ return _paperdollCache.getMaxSetEnchant(player);
}
public int getWeaponEnchant()
@@ -2496,6 +2491,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final Collection getPaperdollItems(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2516,6 +2516,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems().size();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2532,4 +2537,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
+
+ public PaperdollCache getPaperdollCache()
+ {
+ return _paperdollCache;
+ }
}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/stats/BaseStat.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
index 861b619297..dc0b1c6109 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
@@ -38,6 +38,8 @@ public enum BaseStat
CON(Stat.STAT_CON),
MEN(Stat.STAT_MEN);
+ private static final BaseStat[] VALUES = BaseStat.values();
+
public static final int MAX_STAT_VALUE = 201;
private final double[] _bonus = new double[MAX_STAT_VALUE];
@@ -90,7 +92,7 @@ public enum BaseStat
public static BaseStat valueOf(Stat stat)
{
- for (BaseStat baseStat : values())
+ for (BaseStat baseStat : VALUES)
{
if (baseStat.getStat() == stat)
{
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
index 3286b91bf0..9026f10ca6 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
@@ -92,10 +92,7 @@ public interface IStatFunction
final Inventory inv = creature.getInventory();
if (inv != null)
{
- for (ItemInstance item : inv.getPaperdollItems())
- {
- baseValue += item.getItem().getStats(stat, 0);
- }
+ baseValue += inv.getPaperdollCache().getStats(stat);
}
}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
index 58369ad827..1355065c58 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
@@ -16,15 +16,10 @@
*/
package org.l2jmobius.gameserver.model.stats.finalizers;
-import java.util.HashSet;
import java.util.OptionalDouble;
-import java.util.Set;
-import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
-import org.l2jmobius.gameserver.model.ArmorSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
-import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.stats.BaseStat;
import org.l2jmobius.gameserver.model.stats.IStatFunction;
import org.l2jmobius.gameserver.model.stats.Stat;
@@ -46,19 +41,9 @@ public class BaseStatFinalizer implements IStatFunction
if (creature.isPlayer())
{
final PlayerInstance player = creature.getActingPlayer();
- final Set appliedSets = new HashSet<>(2);
// Armor sets calculation
- for (ItemInstance item : player.getInventory().getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
- {
- baseValue += set.getStatsBonus(BaseStat.valueOf(stat));
- }
- }
- }
+ baseValue += player.getInventory().getPaperdollCache().getBaseStatValue(player, BaseStat.valueOf(stat));
// Henna calculation
baseValue += player.getHennaValue(BaseStat.valueOf(stat));
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
index a6385c03f1..52db3e4fb8 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
@@ -257,6 +257,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
+ player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;
diff --git a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/cache/PaperdollCache.java b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
new file mode 100644
index 0000000000..c908c4434d
--- /dev/null
+++ b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/cache/PaperdollCache.java
@@ -0,0 +1,127 @@
+/*
+ * 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.cache;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
+import org.l2jmobius.gameserver.model.ArmorSet;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.stats.BaseStat;
+import org.l2jmobius.gameserver.model.stats.Stat;
+
+/**
+ * @author Sahar
+ */
+public final class PaperdollCache
+{
+ private final Set _paperdollItems = ConcurrentHashMap.newKeySet();
+
+ private final Map _baseStatValues = new ConcurrentHashMap<>();
+ private final Map _statValues = new ConcurrentHashMap<>();
+ private int _maxSetEnchant = -1;
+
+ public Set getPaperdollItems()
+ {
+ return _paperdollItems;
+ }
+
+ public void clearCachedStats()
+ {
+ _baseStatValues.clear();
+ _statValues.clear();
+
+ clearMaxSetEnchant();
+ }
+
+ public void clearMaxSetEnchant()
+ {
+ _maxSetEnchant = -1;
+ }
+
+ public double getBaseStatValue(PlayerInstance player, final BaseStat stat)
+ {
+ final Double baseStatValue = _baseStatValues.get(stat);
+ if (baseStatValue != null)
+ {
+ return baseStatValue;
+ }
+
+ final Set appliedSets = new HashSet<>(2);
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
+ {
+ value += set.getStatsBonus(stat);
+ }
+ }
+ }
+
+ _baseStatValues.put(stat, value);
+ return value;
+ }
+
+ public int getMaxSetEnchant(PlayerInstance player)
+ {
+ int maxSetEnchant = _maxSetEnchant;
+ if (maxSetEnchant >= 0)
+ {
+ return maxSetEnchant;
+ }
+
+ maxSetEnchant = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
+ {
+ final int enchantEffect = set.getLowestSetEnchant(player);
+ if (enchantEffect > maxSetEnchant)
+ {
+ maxSetEnchant = enchantEffect;
+ }
+ }
+ }
+
+ _maxSetEnchant = maxSetEnchant;
+ return maxSetEnchant;
+ }
+
+ public double getStats(Stat stat)
+ {
+ final Double statValue = _statValues.get(stat);
+ if (statValue != null)
+ {
+ return statValue;
+ }
+
+ double value = 0;
+ for (ItemInstance item : _paperdollItems)
+ {
+ value += item.getItem().getStats(stat, 0);
+ }
+
+ _statValues.put(stat, value);
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index 5228ad8a48..93e45bf372 100644
--- a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.cache.PaperdollCache;
import org.l2jmobius.gameserver.data.xml.impl.AppearanceItemData;
import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
import org.l2jmobius.gameserver.datatables.ItemTable;
@@ -123,6 +124,7 @@ public abstract class Inventory extends ItemContainer
private final ItemInstance[] _paperdoll;
private final List _paperdollListeners;
+ private final PaperdollCache _paperdollCache = new PaperdollCache();
// protected to be accessed from child classes only
protected int _totalWeight;
@@ -1209,6 +1211,8 @@ public abstract class Inventory extends ItemContainer
if (old != null)
{
_paperdoll[slot] = null;
+ _paperdollCache.getPaperdollItems().remove(old);
+
// Put old item from paperdoll slot to base location
old.setItemLocation(getBaseLocation());
old.setLastChange(ItemInstance.MODIFIED);
@@ -1239,6 +1243,8 @@ public abstract class Inventory extends ItemContainer
if (item != null)
{
_paperdoll[slot] = item;
+ _paperdollCache.getPaperdollItems().add(item);
+
item.setItemLocation(getEquipLocation(), slot);
item.setLastChange(ItemInstance.MODIFIED);
_wearedMask |= item.getItem().getItemMask();
@@ -1254,6 +1260,7 @@ public abstract class Inventory extends ItemContainer
item.updateDatabase();
}
+ _paperdollCache.clearCachedStats();
getOwner().getStat().recalculateStats(!getOwner().isPlayer());
if (getOwner().isPlayer())
@@ -2126,19 +2133,7 @@ public abstract class Inventory extends ItemContainer
}
final PlayerInstance player = getOwner().getActingPlayer();
- int maxSetEnchant = 0;
- for (ItemInstance item : getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- final int enchantEffect = set.getLowestSetEnchant(player);
- if (enchantEffect > maxSetEnchant)
- {
- maxSetEnchant = enchantEffect;
- }
- }
- }
- return maxSetEnchant;
+ return _paperdollCache.getMaxSetEnchant(player);
}
public int getWeaponEnchant()
@@ -2202,6 +2197,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final Collection getPaperdollItems(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2222,6 +2222,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate... filters)
{
+ if (filters.length == 0)
+ {
+ return _paperdollCache.getPaperdollItems().size();
+ }
+
Predicate filter = Objects::nonNull;
for (Predicate additionalFilter : filters)
{
@@ -2238,4 +2243,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
+
+ public PaperdollCache getPaperdollCache()
+ {
+ return _paperdollCache;
+ }
}
diff --git a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/stats/BaseStat.java b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
index ea1f76bbb6..3b2a441178 100644
--- a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
+++ b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/stats/BaseStat.java
@@ -40,6 +40,8 @@ public enum BaseStat
CHA(Stat.STAT_CHA),
LUC(Stat.STAT_LUC);
+ private static final BaseStat[] VALUES = BaseStat.values();
+
public static final int MAX_STAT_VALUE = 201;
private final double[] _bonus = new double[MAX_STAT_VALUE];
@@ -92,7 +94,7 @@ public enum BaseStat
public static BaseStat valueOf(Stat stat)
{
- for (BaseStat baseStat : values())
+ for (BaseStat baseStat : VALUES)
{
if (baseStat.getStat() == stat)
{
diff --git a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
index 9da29a9c79..00e2ff03fd 100644
--- a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
+++ b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/stats/IStatFunction.java
@@ -92,10 +92,7 @@ public interface IStatFunction
final Inventory inv = creature.getInventory();
if (inv != null)
{
- for (ItemInstance item : inv.getPaperdollItems())
- {
- baseValue += item.getItem().getStats(stat, 0);
- }
+ baseValue += inv.getPaperdollCache().getStats(stat);
}
}
diff --git a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
index 58369ad827..1355065c58 100644
--- a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
+++ b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/model/stats/finalizers/BaseStatFinalizer.java
@@ -16,15 +16,10 @@
*/
package org.l2jmobius.gameserver.model.stats.finalizers;
-import java.util.HashSet;
import java.util.OptionalDouble;
-import java.util.Set;
-import org.l2jmobius.gameserver.data.xml.impl.ArmorSetData;
-import org.l2jmobius.gameserver.model.ArmorSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
-import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.stats.BaseStat;
import org.l2jmobius.gameserver.model.stats.IStatFunction;
import org.l2jmobius.gameserver.model.stats.Stat;
@@ -46,19 +41,9 @@ public class BaseStatFinalizer implements IStatFunction
if (creature.isPlayer())
{
final PlayerInstance player = creature.getActingPlayer();
- final Set appliedSets = new HashSet<>(2);
// Armor sets calculation
- for (ItemInstance item : player.getInventory().getPaperdollItems())
- {
- for (ArmorSet set : ArmorSetData.getInstance().getSets(item.getId()))
- {
- if ((set.getPiecesCountById(player) >= set.getMinimumPieces()) && appliedSets.add(set))
- {
- baseValue += set.getStatsBonus(BaseStat.valueOf(stat));
- }
- }
- }
+ baseValue += player.getInventory().getPaperdollCache().getBaseStatValue(player, BaseStat.valueOf(stat));
// Henna calculation
baseValue += player.getHennaValue(BaseStat.valueOf(stat));
diff --git a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
index 1ab8980f37..a45f7b8b9b 100644
--- a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
+++ b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/gameserver/network/clientpackets/RequestEnchantItem.java
@@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
+ player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;