Ver código fonte

BETA: Fixing possible client crash due unbound buy of items (weight and inventory slots not validated).
* Thanks Starter for report and first implementation.
* This generic version implements exchangeItemsById(..) for information refers to its JavaDocs.
* Try to use it instead of destroyItem/addItem methods.
* Cleanup related to this changes.

Zoey76 13 anos atrás
pai
commit
9f13bbb458

+ 2 - 10
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2CastleMagicianInstance.java

@@ -32,11 +32,10 @@ import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.AcquireSkillList;
 import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
 import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
-import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
 import com.l2jserver.util.Rnd;
 
 /**
- * @author Kerberos | ZaKaX
+ * @author Kerberos, ZaKaX
  */
 public class L2CastleMagicianInstance extends L2NpcInstance implements L2SquadTrainer
 {
@@ -321,15 +320,8 @@ public class L2CastleMagicianInstance extends L2NpcInstance implements L2SquadTr
 				}
 			}
 			
-			if (player.destroyItemByItemId("ExchangeKE", 9912, 10, this, false))
+			if (player.exchangeItemsById("ExchangeKE", this, 9912, 10, item, 1, true))
 			{
-				final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.S2_S1_DISAPPEARED);
-				msg.addItemName(9912);
-				msg.addNumber(10);
-				player.sendPacket(msg);
-				
-				player.addItem("ExchangeKE", item, 1, player, true);
-				
 				filename = "data/html/castlemagician/magician-KE-Exchange.htm";
 			}
 			else

+ 2 - 11
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2FortSupportCaptainInstance.java

@@ -26,7 +26,6 @@ import com.l2jserver.gameserver.model.base.AcquireSkillType;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.AcquireSkillList;
 import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
-import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
 import com.l2jserver.util.Rnd;
 
 /**
@@ -77,17 +76,9 @@ public class L2FortSupportCaptainInstance extends L2MerchantInstance implements
 		}
 		else if (actualCommand.equalsIgnoreCase("ExchangeKE"))
 		{
-			int item = TalismanIds[Rnd.get(TalismanIds.length)];
-			
-			if (player.destroyItemByItemId("FortSupportUnit", 9912, 10, this, false))
+			final int itemId = TalismanIds[Rnd.get(TalismanIds.length)];
+			if (player.exchangeItemsById("FortSupportUnitExchangeKE", this, 9912, 10, itemId, 1, true))
 			{
-				final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.S2_S1_DISAPPEARED);
-				msg.addItemName(9912);
-				msg.addNumber(10);
-				player.sendPacket(msg);
-				
-				player.addItem("FortSupportUnit", item, 1, player, true);
-				
 				showChatWindow(player, "data/html/fortress/supportunit-talisman.htm");
 			}
 			else

+ 40 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java

@@ -4032,6 +4032,46 @@ public final class L2PcInstance extends L2Playable
 		return newItem;
 	}
 	
+	/**
+	 * Use instead of calling {@link #addItem(String, L2ItemInstance, L2Object, boolean)} and {@link #destroyItemByItemId(String, int, long, L2Object, boolean)}<br>
+	 * This method validates slots and weight limit, for stackable and non-stackable items.
+	 * @param process a generic string representing the process that is exchanging this items
+	 * @param reference the (probably NPC) reference, could be null
+	 * @param coinId the item Id of the item given on the exchange
+	 * @param cost the amount of items given on the exchange
+	 * @param rewardId the item received on the exchange
+	 * @param count the amount of items received on the exchange
+	 * @param sendMessage if {@code true} it will send messages to the acting player
+	 * @return {@code true} if the player successfully exchanged the items, {@code false} otherwise
+	 */
+	public boolean exchangeItemsById(String process, L2Object reference, int coinId, long cost, int rewardId, long count, boolean sendMessage)
+	{
+		final PcInventory inv = getInventory();
+		if (!inv.validateCapacityByItemId(rewardId, count))
+		{
+			if (sendMessage)
+			{
+				sendPacket(SystemMessageId.SLOTS_FULL);
+			}
+			return false;
+		}
+		
+		if (!inv.validateWeightByItemId(rewardId, count))
+		{
+			if (sendMessage)
+			{
+				sendPacket(SystemMessageId.WEIGHT_LIMIT_EXCEEDED);
+			}
+			return false;
+		}
+		
+		if (destroyItemByItemId(process, coinId, cost, reference, sendMessage))
+		{
+			addItem(process, rewardId, count, reference, sendMessage);
+			return true;
+		}
+		return false;
+	}
 	/**
 	 * Drop item from inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance.
 	 * @param process String Identifier of process triggering this action

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/model/itemcontainer/ClanWarehouse.java

@@ -76,7 +76,7 @@ public final class ClanWarehouse extends Warehouse
 	}
 	
 	@Override
-	public boolean validateCapacity(int slots)
+	public boolean validateCapacity(long slots)
 	{
 		return ((_items.size() + slots) <= Config.WAREHOUSE_SLOTS_CLAN);
 	}

+ 24 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/model/itemcontainer/ItemContainer.java

@@ -614,14 +614,36 @@ public abstract class ItemContainer
 		}
 	}
 	
-	public boolean validateCapacity(int slots)
+	public boolean validateCapacity(long slots)
 	{
 		return true;
 	}
 	
-	public boolean validateWeight(int weight)
+	public boolean validateWeight(long weight)
 	{
 		return true;
 	}
 	
+	/**
+	 * If the item is stackable validates 1 slot, if the item isn't stackable validates the item count.
+	 * @param itemId the item Id to verify
+	 * @param count amount of item's weight to validate
+	 * @return {@code true} if the item doesn't exists or it validates its slot count
+	 */
+	public boolean validateCapacityByItemId(int itemId, long count)
+	{
+		final L2Item template = ItemTable.getInstance().getTemplate(itemId);
+		return (template == null) || (template.isStackable() ? validateCapacity(1) : validateCapacity(count));
+	}
+	
+	/**
+	 * @param itemId the item Id to verify
+	 * @param count amount of item's weight to validate
+	 * @return {@code true} if the item doesn't exists or it validates its weight
+	 */
+	public boolean validateWeightByItemId(int itemId, long count)
+	{
+		final L2Item template = ItemTable.getInstance().getTemplate(itemId);
+		return (template == null) || validateWeight(template.getWeight() * count);
+	}
 }

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/model/itemcontainer/PcFreight.java

@@ -109,7 +109,7 @@ public class PcFreight extends ItemContainer
 	}
 	
 	@Override
-	public boolean validateCapacity(int slots)
+	public boolean validateCapacity(long slots)
 	{
 		int curSlots = _owner == null ? Config.ALT_FREIGHT_SLOTS : Config.ALT_FREIGHT_SLOTS + (int)_owner.getStat().calcStat(Stats.FREIGHT_LIM, 0, null, null);
 		return (getSize() + slots <= curSlots);

+ 3 - 3
L2J_Server_BETA/java/com/l2jserver/gameserver/model/itemcontainer/PcInventory.java

@@ -828,12 +828,12 @@ public class PcInventory extends Inventory
 	}
 	
 	@Override
-	public boolean validateCapacity(int slots)
+	public boolean validateCapacity(long slots)
 	{
 		return validateCapacity(slots, false);
 	}
 	
-	public boolean validateCapacity(int slots, boolean questItem)
+	public boolean validateCapacity(long slots, boolean questItem)
 	{
 		if (!questItem)
 			return (_items.size() - _questSlots + slots <= _owner.getInventoryLimit());
@@ -841,7 +841,7 @@ public class PcInventory extends Inventory
 	}
 	
 	@Override
-	public boolean validateWeight(int weight)
+	public boolean validateWeight(long weight)
 	{
 		// Disable weight check for GMs.
 		if (_owner.isGM() && _owner.getDietMode() && _owner.getAccessLevel().allowTransaction())

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/model/itemcontainer/PcWarehouse.java

@@ -47,7 +47,7 @@ public class PcWarehouse extends Warehouse
 	}
 	
 	@Override
-	public boolean validateCapacity(int slots)
+	public boolean validateCapacity(long slots)
 	{
 		return (_items.size() + slots <= _owner.getWareHouseLimit());
 	}

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/model/itemcontainer/PetInventory.java

@@ -73,7 +73,7 @@ public class PetInventory extends Inventory
 	}
 	
 	@Override
-	public boolean validateCapacity(int slots)
+	public boolean validateCapacity(long slots)
 	{
 		return (_items.size() + slots <= _owner.getInventoryLimit());
 	}
@@ -88,7 +88,7 @@ public class PetInventory extends Inventory
 	}
 	
 	@Override
-	public boolean validateWeight(int weight)
+	public boolean validateWeight(long weight)
 	{
 		return (_totalWeight + weight <= _owner.getMaxLoad());
 	}