Addition of paperdoll cache.

Contributed by Sahar.
This commit is contained in:
MobiusDevelopment 2020-07-04 00:26:44 +00:00
parent 37d338c51d
commit 1a1241957f
90 changed files with 2340 additions and 510 deletions

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<ItemInstance> _paperdollItems = ConcurrentHashMap.newKeySet();
private final Map<BaseStat, Double> _baseStatValues = new ConcurrentHashMap<>();
private final Map<Stat, Double> _statValues = new ConcurrentHashMap<>();
private int _maxSetEnchant = -1;
public Set<ItemInstance> 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<ArmorSet> 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;
}
}

View File

@ -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<PaperdollListener> _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<ItemInstance> getPaperdollItems(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2216,6 +2216,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems().size();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2232,4 +2237,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
public PaperdollCache getPaperdollCache()
{
return _paperdollCache;
}
}

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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<ArmorSet> 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));

View File

@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<ItemInstance> _paperdollItems = ConcurrentHashMap.newKeySet();
private final Map<BaseStat, Double> _baseStatValues = new ConcurrentHashMap<>();
private final Map<Stat, Double> _statValues = new ConcurrentHashMap<>();
private int _maxSetEnchant = -1;
public Set<ItemInstance> 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<ArmorSet> 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;
}
}

View File

@ -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<PaperdollListener> _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<ItemInstance> getPaperdollItems(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2222,6 +2222,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems().size();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2238,4 +2243,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
public PaperdollCache getPaperdollCache()
{
return _paperdollCache;
}
}

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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<ArmorSet> 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));

View File

@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<ItemInstance> _paperdollItems = ConcurrentHashMap.newKeySet();
private final Map<BaseStat, Double> _baseStatValues = new ConcurrentHashMap<>();
private final Map<Stat, Double> _statValues = new ConcurrentHashMap<>();
private int _maxSetEnchant = -1;
public Set<ItemInstance> 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<ArmorSet> 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;
}
}

View File

@ -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<PaperdollListener> _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<ItemInstance> getPaperdollItems(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2222,6 +2222,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems().size();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2238,4 +2243,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
public PaperdollCache getPaperdollCache()
{
return _paperdollCache;
}
}

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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<ArmorSet> 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));

View File

@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<ItemInstance> _paperdollItems = ConcurrentHashMap.newKeySet();
private final Map<BaseStat, Double> _baseStatValues = new ConcurrentHashMap<>();
private final Map<Stat, Double> _statValues = new ConcurrentHashMap<>();
private int _maxSetEnchant = -1;
public Set<ItemInstance> 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<ArmorSet> 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;
}
}

View File

@ -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<PaperdollListener> _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<ItemInstance> getPaperdollItems(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2222,6 +2222,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems().size();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2238,4 +2243,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
public PaperdollCache getPaperdollCache()
{
return _paperdollCache;
}
}

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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<ArmorSet> 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));

View File

@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<ItemInstance> _paperdollItems = ConcurrentHashMap.newKeySet();
private final Map<BaseStat, Double> _baseStatValues = new ConcurrentHashMap<>();
private final Map<Stat, Double> _statValues = new ConcurrentHashMap<>();
private int _maxSetEnchant = -1;
public Set<ItemInstance> 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<ArmorSet> 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;
}
}

View File

@ -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<PaperdollListener> _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<ItemInstance> getPaperdollItems(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2235,6 +2235,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems().size();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2251,4 +2256,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
public PaperdollCache getPaperdollCache()
{
return _paperdollCache;
}
}

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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<ArmorSet> 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));

View File

@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<ItemInstance> _paperdollItems = ConcurrentHashMap.newKeySet();
private final Map<BaseStat, Double> _baseStatValues = new ConcurrentHashMap<>();
private final Map<Stat, Double> _statValues = new ConcurrentHashMap<>();
private int _maxSetEnchant = -1;
public Set<ItemInstance> 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<ArmorSet> 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;
}
}

View File

@ -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<PaperdollListener> _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<ItemInstance> getPaperdollItems(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2532,6 +2532,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems().size();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2548,4 +2553,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
public PaperdollCache getPaperdollCache()
{
return _paperdollCache;
}
}

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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<ArmorSet> 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));

View File

@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<ItemInstance> _paperdollItems = ConcurrentHashMap.newKeySet();
private final Map<BaseStat, Double> _baseStatValues = new ConcurrentHashMap<>();
private final Map<Stat, Double> _statValues = new ConcurrentHashMap<>();
private int _maxSetEnchant = -1;
public Set<ItemInstance> 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<ArmorSet> 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;
}
}

View File

@ -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<PaperdollListener> _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<ItemInstance> getPaperdollItems(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2532,6 +2532,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems().size();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2548,4 +2553,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
public PaperdollCache getPaperdollCache()
{
return _paperdollCache;
}
}

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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<ArmorSet> 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));

View File

@ -257,6 +257,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<ItemInstance> _paperdollItems = ConcurrentHashMap.newKeySet();
private final Map<BaseStat, Double> _baseStatValues = new ConcurrentHashMap<>();
private final Map<Stat, Double> _statValues = new ConcurrentHashMap<>();
private int _maxSetEnchant = -1;
public Set<ItemInstance> 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<ArmorSet> 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;
}
}

View File

@ -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<PaperdollListener> _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<ItemInstance> getPaperdollItems(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2516,6 +2516,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems().size();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2532,4 +2537,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
public PaperdollCache getPaperdollCache()
{
return _paperdollCache;
}
}

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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<ArmorSet> 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));

View File

@ -257,6 +257,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<ItemInstance> _paperdollItems = ConcurrentHashMap.newKeySet();
private final Map<BaseStat, Double> _baseStatValues = new ConcurrentHashMap<>();
private final Map<Stat, Double> _statValues = new ConcurrentHashMap<>();
private int _maxSetEnchant = -1;
public Set<ItemInstance> 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<ArmorSet> 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;
}
}

View File

@ -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<PaperdollListener> _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<ItemInstance> getPaperdollItems(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2222,6 +2222,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems().size();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2238,4 +2243,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
public PaperdollCache getPaperdollCache()
{
return _paperdollCache;
}
}

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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<ArmorSet> 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));

View File

@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<ItemInstance> _paperdollItems = ConcurrentHashMap.newKeySet();
private final Map<BaseStat, Double> _baseStatValues = new ConcurrentHashMap<>();
private final Map<Stat, Double> _statValues = new ConcurrentHashMap<>();
private int _maxSetEnchant = -1;
public Set<ItemInstance> 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<ArmorSet> 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;
}
}

View File

@ -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<PaperdollListener> _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<ItemInstance> getPaperdollItems(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2222,6 +2222,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems().size();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2238,4 +2243,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
public PaperdollCache getPaperdollCache()
{
return _paperdollCache;
}
}

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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<ArmorSet> 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));

View File

@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<ItemInstance> _paperdollItems = ConcurrentHashMap.newKeySet();
private final Map<BaseStat, Double> _baseStatValues = new ConcurrentHashMap<>();
private final Map<Stat, Double> _statValues = new ConcurrentHashMap<>();
private int _maxSetEnchant = -1;
public Set<ItemInstance> 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<ArmorSet> 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;
}
}

View File

@ -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<PaperdollListener> _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<ItemInstance> getPaperdollItems(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2241,6 +2241,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems().size();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2257,4 +2262,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
public PaperdollCache getPaperdollCache()
{
return _paperdollCache;
}
}

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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<ArmorSet> 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));

View File

@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<ItemInstance> _paperdollItems = ConcurrentHashMap.newKeySet();
private final Map<BaseStat, Double> _baseStatValues = new ConcurrentHashMap<>();
private final Map<Stat, Double> _statValues = new ConcurrentHashMap<>();
private int _maxSetEnchant = -1;
public Set<ItemInstance> 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<ArmorSet> 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;
}
}

View File

@ -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<PaperdollListener> _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<ItemInstance> getPaperdollItems(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2532,6 +2532,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems().size();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2548,4 +2553,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
public PaperdollCache getPaperdollCache()
{
return _paperdollCache;
}
}

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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<ArmorSet> 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));

View File

@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<ItemInstance> _paperdollItems = ConcurrentHashMap.newKeySet();
private final Map<BaseStat, Double> _baseStatValues = new ConcurrentHashMap<>();
private final Map<Stat, Double> _statValues = new ConcurrentHashMap<>();
private int _maxSetEnchant = -1;
public Set<ItemInstance> 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<ArmorSet> 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;
}
}

View File

@ -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<PaperdollListener> _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<ItemInstance> getPaperdollItems(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2532,6 +2532,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems().size();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2548,4 +2553,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
public PaperdollCache getPaperdollCache()
{
return _paperdollCache;
}
}

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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<ArmorSet> 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));

View File

@ -257,6 +257,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<ItemInstance> _paperdollItems = ConcurrentHashMap.newKeySet();
private final Map<BaseStat, Double> _baseStatValues = new ConcurrentHashMap<>();
private final Map<Stat, Double> _statValues = new ConcurrentHashMap<>();
private int _maxSetEnchant = -1;
public Set<ItemInstance> 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<ArmorSet> 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;
}
}

View File

@ -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<PaperdollListener> _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<ItemInstance> getPaperdollItems(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2516,6 +2516,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems().size();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2532,4 +2537,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
public PaperdollCache getPaperdollCache()
{
return _paperdollCache;
}
}

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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<ArmorSet> 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));

View File

@ -257,6 +257,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<ItemInstance> _paperdollItems = ConcurrentHashMap.newKeySet();
private final Map<BaseStat, Double> _baseStatValues = new ConcurrentHashMap<>();
private final Map<Stat, Double> _statValues = new ConcurrentHashMap<>();
private int _maxSetEnchant = -1;
public Set<ItemInstance> 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<ArmorSet> 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;
}
}

View File

@ -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<PaperdollListener> _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<ItemInstance> getPaperdollItems(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2222,6 +2222,11 @@ public abstract class Inventory extends ItemContainer
@SafeVarargs
public final int getPaperdollItemCount(Predicate<ItemInstance>... filters)
{
if (filters.length == 0)
{
return _paperdollCache.getPaperdollItems().size();
}
Predicate<ItemInstance> filter = Objects::nonNull;
for (Predicate<ItemInstance> additionalFilter : filters)
{
@ -2238,4 +2243,9 @@ public abstract class Inventory extends ItemContainer
}
return count;
}
public PaperdollCache getPaperdollCache()
{
return _paperdollCache;
}
}

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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<ArmorSet> 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));

View File

@ -255,6 +255,7 @@ public class RequestEnchantItem implements IClientIncomingPacket
}
});
}
player.getInventory().getPaperdollCache().clearMaxSetEnchant();
player.broadcastUserInfo(); // update user info
}
break;