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;