From 352735c8c98aedf0e0e70d2fecf9fbff9bfaa182 Mon Sep 17 00:00:00 2001 From: Rogiel Date: Thu, 15 Dec 2011 12:31:47 -0200 Subject: [PATCH] Implements item pick up --- .../database/AbstractJDBCDatabaseService.java | 42 ++-- .../l2jserver/game/net/Lineage2Client.java | 54 +++++ .../net/packet/client/CM_CHAR_ACTION.java | 73 +++++- .../net/packet/server/SM_CHAR_INVENTORY.java | 6 +- .../server/SM_CHAR_INVENTORY_UPDATE.java | 226 ++++++++++++++++++ .../java/com/l2jserver/model/world/Item.java | 16 +- .../world/actor/effect/TemporalEffect.java | 2 +- .../world/character/CharacterInventory.java | 48 +++- .../model/world/character/CharacterStats.java | 40 +++- .../model/world/item/ItemPickUpEvent.java | 84 +++++++ .../service/database/jdbc/JDBCItemDAO.java | 62 ++++- .../game/effect/SimpleEffectService.java | 6 +- .../ItemAlreadyOnGroundServiceException.java | 59 +++++ .../item/ItemNotOnGroundServiceException.java | 59 +++++ .../service/game/item/ItemService.java | 65 +++++ .../game/item/ItemServiceException.java | 68 ++++++ .../service/game/item/ItemServiceImpl.java | 77 +++++- .../game/world/filter/impl/RangeFilter.java | 2 + .../broadcast/BroadcastServiceImpl.java | 5 +- .../util/calculator/ComplexCalculator.java | 8 + 20 files changed, 948 insertions(+), 54 deletions(-) create mode 100644 l2jserver2-gameserver/src/main/java/com/l2jserver/game/net/packet/server/SM_CHAR_INVENTORY_UPDATE.java create mode 100644 l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/item/ItemPickUpEvent.java create mode 100644 l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemAlreadyOnGroundServiceException.java create mode 100644 l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemNotOnGroundServiceException.java create mode 100644 l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemServiceException.java diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/AbstractJDBCDatabaseService.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/AbstractJDBCDatabaseService.java index 1627f09ef..ed5d03a76 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/AbstractJDBCDatabaseService.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/AbstractJDBCDatabaseService.java @@ -302,19 +302,25 @@ public abstract class AbstractJDBCDatabaseService extends AbstractService new Runnable() { @Override public void run() { - log.debug("Auto save task started"); - int objects = 0; - for (final Model object : objectCache) { - @SuppressWarnings("unchecked") - final DataAccessObject, ?> dao = (DataAccessObject, ?>) daoResolver - .getDAO(object.getClass()); - if (dao.save(object)) { - objects++; + try { + log.debug("Auto save task started"); + int objects = 0; + for (final Model object : objectCache) { + @SuppressWarnings("unchecked") + final DataAccessObject, ?> dao = (DataAccessObject, ?>) daoResolver + .getDAO(object.getClass()); + if (dao == null) + continue; + if (dao.save(object)) { + objects++; + } } + log.info( + "{} objects have been saved by the auto save task", + objects); + } catch (Exception e) { + log.error("Error occured in save thread", e); } - log.info( - "{} objects have been saved by the auto save task", - objects); } }); } @@ -609,8 +615,11 @@ public abstract class AbstractJDBCDatabaseService extends AbstractService log.debug("Mapper {} returned a null row", mapper); continue; } - if (obj instanceof Model) - ((Model) obj).setObjectDesire(ObjectDesire.NONE); + if (obj instanceof Model) { + if (((Model) obj).getObjectDesire() == ObjectDesire.INSERT) { + ((Model) obj).setObjectDesire(ObjectDesire.NONE); + } + } log.debug("Mapper {} returned {}", mapper, obj); list.add(obj); } @@ -685,8 +694,11 @@ public abstract class AbstractJDBCDatabaseService extends AbstractService while (rs.next()) { log.debug("Mapping row {} with {}", rs, mapper); final T object = mapper.map(rs); - if (object instanceof Model) - ((Model) object).setObjectDesire(ObjectDesire.NONE); + if (object instanceof Model) { + if (((Model) object).getObjectDesire() == ObjectDesire.INSERT) { + ((Model) object).setObjectDesire(ObjectDesire.NONE); + } + } log.debug("Mapper {} returned {}", mapper, object); return object; } diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/game/net/Lineage2Client.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/game/net/Lineage2Client.java index c6ecb10c2..c3cfbff78 100644 --- a/l2jserver2-gameserver/src/main/java/com/l2jserver/game/net/Lineage2Client.java +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/game/net/Lineage2Client.java @@ -27,6 +27,9 @@ import com.l2jserver.game.net.codec.Lineage2PacketReader; import com.l2jserver.game.net.codec.Lineage2PacketWriter; import com.l2jserver.game.net.packet.ServerPacket; import com.l2jserver.game.net.packet.server.SM_ACTION_FAILED; +import com.l2jserver.game.net.packet.server.SM_CHAR_INVENTORY; +import com.l2jserver.game.net.packet.server.SM_CHAR_INVENTORY_UPDATE; +import com.l2jserver.game.net.packet.server.SM_CHAR_INVENTORY_UPDATE.InventoryUpdateType; import com.l2jserver.game.net.packet.server.SM_COMMUNITY_HTML; import com.l2jserver.game.net.packet.server.SM_HTML; import com.l2jserver.game.net.packet.server.SM_SYSTEM_MESSAGE; @@ -321,6 +324,57 @@ public class Lineage2Client { return write(new SM_COMMUNITY_HTML(template)); } + /** + * Sends the whole user inventory to the client. This is a very bandwidth + * consuming process and should be avoided. + * + * @return the {@link ChannelFuture} that will be notified once the packet + * has been written. + */ + public ChannelFuture sendInventoryUpdate() { + return write(new SM_CHAR_INVENTORY(characterID.getObject() + .getInventory())); + } + + /** + * Removes items from the game client UI. + * + * @param items + * the list of items to be removed + * @return the {@link ChannelFuture} that will be notified once the packet + * has been written. + */ + public ChannelFuture removeInventoryItems(Item... items) { + return write(new SM_CHAR_INVENTORY_UPDATE(InventoryUpdateType.REMOVE, + items)); + } + + /** + * Updates items in the game client UI. + * + * @param items + * the list of items to be updated + * @return the {@link ChannelFuture} that will be notified once the packet + * has been written. + */ + public ChannelFuture updateInventoryItems(Item... items) { + return write(new SM_CHAR_INVENTORY_UPDATE(InventoryUpdateType.UPDATE, + items)); + } + + /** + * Adds items in the game client UI. + * + * @param items + * the list of items to be added + * @return the {@link ChannelFuture} that will be notified once the packet + * has been written. + */ + public ChannelFuture addInventoryItems(Item... items) { + return write(new SM_CHAR_INVENTORY_UPDATE(InventoryUpdateType.ADD, + items)); + } + /** * Broadcast a packet to all characters in this character knownlist. *

diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/game/net/packet/client/CM_CHAR_ACTION.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/game/net/packet/client/CM_CHAR_ACTION.java index 46055a499..143b9c56f 100644 --- a/l2jserver2-gameserver/src/main/java/com/l2jserver/game/net/packet/client/CM_CHAR_ACTION.java +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/game/net/packet/client/CM_CHAR_ACTION.java @@ -20,14 +20,20 @@ import org.jboss.netty.buffer.ChannelBuffer; import com.google.inject.Inject; import com.l2jserver.game.net.Lineage2Client; +import com.l2jserver.game.net.SystemMessage; import com.l2jserver.game.net.packet.AbstractClientPacket; import com.l2jserver.model.id.ObjectID; +import com.l2jserver.model.id.object.ItemID; import com.l2jserver.model.id.object.NPCID; import com.l2jserver.model.id.object.provider.ObjectIDResolver; +import com.l2jserver.model.world.Item; import com.l2jserver.model.world.NPC; import com.l2jserver.service.game.character.CannotSetTargetServiceException; +import com.l2jserver.service.game.item.ItemNotOnGroundServiceException; +import com.l2jserver.service.game.item.ItemService; import com.l2jserver.service.game.npc.ActionServiceException; import com.l2jserver.service.game.npc.NPCService; +import com.l2jserver.service.game.spawn.NotSpawnedServiceException; import com.l2jserver.util.geometry.Coordinate; /** @@ -41,18 +47,37 @@ public class CM_CHAR_ACTION extends AbstractClientPacket { */ public static final int OPCODE = 0x1f; + /** + * The {@link ObjectID} resolver + */ private final ObjectIDResolver idResolver; + /** + * The {@link NPC} Service + */ private final NPCService npcService; + /** + * The {@link Item} Service + */ + private final ItemService itemService; + /** + * The object id + */ private int objectId; @SuppressWarnings("unused") private Coordinate origin; + /** + * The character action type (aka mouse button) + */ private CharacterAction action; public enum CharacterAction { + /** + * If the player has clicked with the left mouse button. + */ CLICK(0), /** - * This is the right click action. + * If the player has clicked with the right mouse button. */ RIGHT_CLICK(1); @@ -71,9 +96,11 @@ public class CM_CHAR_ACTION extends AbstractClientPacket { } @Inject - public CM_CHAR_ACTION(ObjectIDResolver idResolver, NPCService npcService) { + public CM_CHAR_ACTION(ObjectIDResolver idResolver, NPCService npcService, + ItemService itemService) { this.idResolver = idResolver; this.npcService = npcService; + this.itemService = itemService; } @Override @@ -86,19 +113,39 @@ public class CM_CHAR_ACTION extends AbstractClientPacket { @Override public void process(final Lineage2Client conn) { - // since this is an erasure type, this is safe. - final ObjectID id = idResolver.resolve(objectId); - if (!(id instanceof NPCID)) { + final ObjectID id = idResolver.resolve(objectId); + if (id instanceof NPCID) { + final NPC npc = ((NPCID) id).getObject(); + try { + npcService.action(npc, conn.getCharacter(), action); + } catch (ActionServiceException e) { + conn.sendActionFailed(); + } catch (CannotSetTargetServiceException e) { + conn.sendActionFailed(); + } + } else if (id instanceof ItemID) { + final Item item = ((ItemID) id).getObject(); + try { + final Item stackItem = itemService.action(item, + conn.getCharacter(), action); + if (stackItem.equals(item)) { // adds + conn.addInventoryItems(stackItem); + } else { // update only + conn.updateInventoryItems(stackItem); + } + conn.sendSystemMessage(SystemMessage.YOU_PICKED_UP_S1_S2, Long + .toString(item.getCount()), item.getTemplate() + .getName()); + conn.sendActionFailed(); + } catch (ItemNotOnGroundServiceException + | NotSpawnedServiceException e) { + conn.sendSystemMessage(SystemMessage.FAILED_TO_PICKUP_S1, item + .getTemplate().getName()); + conn.sendActionFailed(); + } + } else { conn.sendActionFailed(); return; } - final NPC npc = id.getObject(); - try { - npcService.action(npc, conn.getCharacter(), action); - } catch (ActionServiceException e) { - conn.sendActionFailed(); - } catch (CannotSetTargetServiceException e) { - conn.sendActionFailed(); - } } } diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/game/net/packet/server/SM_CHAR_INVENTORY.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/game/net/packet/server/SM_CHAR_INVENTORY.java index d6c095ff9..e8b7efeda 100644 --- a/l2jserver2-gameserver/src/main/java/com/l2jserver/game/net/packet/server/SM_CHAR_INVENTORY.java +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/game/net/packet/server/SM_CHAR_INVENTORY.java @@ -22,7 +22,7 @@ import com.l2jserver.game.net.Lineage2Client; import com.l2jserver.game.net.packet.AbstractServerPacket; import com.l2jserver.model.world.Item; import com.l2jserver.model.world.character.CharacterInventory; -import com.l2jserver.model.world.character.CharacterInventory.InventoryLocation; +import com.l2jserver.model.world.character.CharacterInventory.ItemLocation; /** * This packet send the inventory to the client @@ -58,7 +58,7 @@ public class SM_CHAR_INVENTORY extends AbstractServerPacket { // TODO implement real item slot int slot = 0; for (Item item : inventory) { - if (item.getLocation() == InventoryLocation.WAREHOUSE + if (item.getLocation() == ItemLocation.WAREHOUSE || item.getLocation() == null) { continue; } @@ -69,7 +69,7 @@ public class SM_CHAR_INVENTORY extends AbstractServerPacket { buffer.writeLong(item.getCount()); // count buffer.writeShort(0x00); // item type2 buffer.writeShort(0x00); // item type3 - buffer.writeShort((item.getLocation() == InventoryLocation.PAPERDOLL ? 0x01 + buffer.writeShort((item.getLocation() == ItemLocation.PAPERDOLL ? 0x01 : 0x00)); // equiped? buffer.writeInt((item.getPaperdoll() != null ? item.getPaperdoll().id : 0)); // body part diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/game/net/packet/server/SM_CHAR_INVENTORY_UPDATE.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/game/net/packet/server/SM_CHAR_INVENTORY_UPDATE.java new file mode 100644 index 000000000..1d6618d85 --- /dev/null +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/game/net/packet/server/SM_CHAR_INVENTORY_UPDATE.java @@ -0,0 +1,226 @@ +/* + * This file is part of l2jserver2 . + * + * l2jserver2 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. + * + * l2jserver2 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 l2jserver2. If not, see . + */ +package com.l2jserver.game.net.packet.server; + +import java.util.Map; +import java.util.Map.Entry; + +import org.jboss.netty.buffer.ChannelBuffer; + +import com.l2jserver.game.net.Lineage2Client; +import com.l2jserver.game.net.packet.AbstractServerPacket; +import com.l2jserver.model.world.Item; +import com.l2jserver.model.world.character.CharacterInventory.ItemLocation; +import com.l2jserver.util.factory.CollectionFactory; + +/** + * This packet send the inventory to the client + * + * @author Rogiel + */ +public class SM_CHAR_INVENTORY_UPDATE extends AbstractServerPacket { + /** + * The packet OPCODE + */ + public static final int OPCODE = 0x21; + + /** + * List of items to be updated in the client + */ + private final Map items = CollectionFactory + .newMap(); + + /** + * The type of operation to be performed. + * + * @author Rogiel + */ + public enum InventoryUpdateType { + /** + * Flags the item to be added to the inventory list + */ + ADD(1), + /** + * Flags the item to be updated in the inventory list + */ + UPDATE(2), + /** + * Flags the item to be removed in the inventory list + */ + REMOVE(3); + + /** + * The operation ID + */ + public final int id; + + /** + * @param id + * the operation ID + */ + private InventoryUpdateType(int id) { + this.id = id; + } + } + + /** + * Creates an empty instance. Items can be added, removed or update using + * {@link #add(Item)}, {@link #remove(Item)} and {@link #update(Item)}. + */ + public SM_CHAR_INVENTORY_UPDATE() { + super(OPCODE); + } + + /** + * Creates a new instance with several items performing + * {@link InventoryUpdateType} type operation. + * + * @param type + * the operation type + * @param items + * the items + */ + public SM_CHAR_INVENTORY_UPDATE(InventoryUpdateType type, Item... items) { + super(OPCODE); + switch (type) { + case ADD: + add(items); + break; + case REMOVE: + remove(items); + break; + case UPDATE: + update(items); + break; + } + } + + @Override + public void write(Lineage2Client conn, ChannelBuffer buffer) { + buffer.writeShort(items.size()); // item count + + for (Entry e : items.entrySet()) { + final Item item = e.getKey(); + final InventoryUpdateType type = e.getValue(); + + buffer.writeShort(type.id); // change type + buffer.writeInt(item.getID().getID()); // obj id + buffer.writeInt(item.getTemplateID().getID()); // item id + buffer.writeInt(0x00); // loc slot + buffer.writeLong(item.getCount()); // count + buffer.writeShort(0x00); // item type2 + buffer.writeShort(0x00); // item type3 + buffer.writeShort((item.getLocation() == ItemLocation.PAPERDOLL ? 0x01 + : 0x00)); // equiped? + buffer.writeInt((item.getPaperdoll() != null ? item.getPaperdoll().id + : 0)); // body part + buffer.writeShort(127); // enchant level + // race tickets + buffer.writeShort(0x00); // item type4 (custom type 2) + buffer.writeInt(0x00); // augument + buffer.writeInt(0x00); // mana + buffer.writeInt(-9999); // time + buffer.writeShort(0x00); // attack element type + buffer.writeShort(0x00); // attack element power + for (byte i = 0; i < 6; i++) { + buffer.writeShort(0x00); // element def attrib + } + // Enchant Effects + buffer.writeShort(0x00); + buffer.writeShort(0x00); + buffer.writeShort(0x00); + } + } + + /** + * Removes a single item + * + * @param item + * the item to be removed + * @return this instance + */ + public SM_CHAR_INVENTORY_UPDATE remove(Item item) { + items.put(item, InventoryUpdateType.REMOVE); + return this; + } + + /** + * Removes several items + * + * @param items + * the items to be removed + * @return this instance + */ + public SM_CHAR_INVENTORY_UPDATE remove(Item... items) { + for (final Item item : items) { + remove(item); + } + return this; + } + + /** + * Adds a single item + * + * @param item + * the item to be added + * @return this instance + */ + public SM_CHAR_INVENTORY_UPDATE add(Item item) { + items.put(item, InventoryUpdateType.ADD); + return this; + } + + /** + * Adds several items + * + * @param items + * the item to be added + * @return this instance + */ + public SM_CHAR_INVENTORY_UPDATE add(Item... items) { + for (final Item item : items) { + add(item); + } + return this; + } + + /** + * Updates a single item + * + * @param item + * the item to be updated + * @return this instance + */ + public SM_CHAR_INVENTORY_UPDATE update(Item item) { + items.put(item, InventoryUpdateType.UPDATE); + return this; + } + + /** + * Updates several items + * + * @param items + * the item to be updated + * @return this instance + */ + public SM_CHAR_INVENTORY_UPDATE update(Item... items) { + for (final Item item : items) { + update(item); + } + return this; + } +} diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/Item.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/Item.java index d0ade6f0a..a1ee76749 100644 --- a/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/Item.java +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/Item.java @@ -19,7 +19,7 @@ package com.l2jserver.model.world; import com.l2jserver.model.id.object.CharacterID; import com.l2jserver.model.id.template.ItemTemplateID; import com.l2jserver.model.template.item.ItemTemplate; -import com.l2jserver.model.world.character.CharacterInventory.InventoryLocation; +import com.l2jserver.model.world.character.CharacterInventory.ItemLocation; import com.l2jserver.model.world.character.CharacterInventory.InventoryPaperdoll; /** @@ -27,13 +27,13 @@ import com.l2jserver.model.world.character.CharacterInventory.InventoryPaperdoll * be: *

    *
  • In the {@link L2Character character} inventory: location - * is {@link InventoryLocation#INVENTORY}, coordinate and + * is {@link ItemLocation#INVENTORY}, coordinate and * paperdoll are null.
  • *
  • In the {@link L2Character character} warehouse: location - * is {@link InventoryLocation#WAREHOUSE}, coordinate and + * is {@link ItemLocation#WAREHOUSE}, coordinate and * paperdoll are null.
  • *
  • Equipped by the {@link L2Character character}: location - * is {@link InventoryLocation#PAPERDOLL}, paperdoll is not null and + * is {@link ItemLocation#PAPERDOLL}, paperdoll is not null and * coordinate is null.
  • *
  • Dropped on the ground: location
  • and * paperdoll are null, coordinate is not null and represents @@ -58,7 +58,7 @@ public class Item extends PositionableObject { /** * Inventory location of this item */ - private InventoryLocation location; + private ItemLocation location; /** * Paperdoll slot for this item */ @@ -96,7 +96,7 @@ public class Item extends PositionableObject { /** * @return the location */ - public InventoryLocation getLocation() { + public ItemLocation getLocation() { return location; } @@ -104,10 +104,10 @@ public class Item extends PositionableObject { * @param location * the location to set */ - public void setLocation(InventoryLocation location) { + public void setLocation(ItemLocation location) { desireUpdate(); this.location = location; - if (location != InventoryLocation.PAPERDOLL) + if (location != ItemLocation.PAPERDOLL) this.paperdoll = null; } diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/actor/effect/TemporalEffect.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/actor/effect/TemporalEffect.java index b66c59f22..74fef57dc 100644 --- a/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/actor/effect/TemporalEffect.java +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/actor/effect/TemporalEffect.java @@ -36,7 +36,7 @@ public interface TemporalEffect extends Effect { * @author Rogiel */ public enum TemporalEffectAction { - CANCEL; + CANCEL, CONTINUE; } /** diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/character/CharacterInventory.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/character/CharacterInventory.java index b7dd8fd21..49c8081c1 100644 --- a/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/character/CharacterInventory.java +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/character/CharacterInventory.java @@ -16,10 +16,12 @@ */ package com.l2jserver.model.world.character; +import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.Set; +import com.l2jserver.model.id.object.ItemID; import com.l2jserver.model.world.Item; import com.l2jserver.model.world.L2Character; import com.l2jserver.util.factory.CollectionFactory; @@ -50,6 +52,48 @@ public class CharacterInventory implements Iterable { this.character = character; } + /** + * Adds an item to the player inventory. + * + * @param item + * the item + */ + public void add(Item item) { + items.add(item); + } + + /** + * Removes the item from the players inventory. + * + * @param item + * the item to be removed + * @return the item if it was successfully removed or null if + * the item was not removed. + */ + public Item remove(Item item) { + if (items.remove(item)) + return item; + return null; + } + + /** + * Removes all items from the given {@link ItemID} + * + * @param itemID + * the {@link ItemID} + * @return an array of all items removed. Can never be null. + */ + public Item[] remove(ItemID itemID) { + final ArrayList removedItems = new ArrayList(); + for (final Item item : items) { + if (item.getID().equals(itemID)) { + items.remove(item); + removedItems.add(item); + } + } + return removedItems.toArray(new Item[removedItems.size()]); + } + /** * Get the item in the given paperdoll slot * @@ -105,7 +149,7 @@ public class CharacterInventory implements Iterable { * * @author Rogiel */ - public enum InventoryLocation { + public enum ItemLocation { /** * The item is dropped on the ground */ @@ -125,7 +169,7 @@ public class CharacterInventory implements Iterable { } /** - * {@link InventoryLocation#PAPERDOLL Paperdoll} slots for items + * {@link ItemLocation#PAPERDOLL Paperdoll} slots for items * * @author Rogiel */ diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/character/CharacterStats.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/character/CharacterStats.java index 40dbb428d..b89d15dfd 100644 --- a/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/character/CharacterStats.java +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/character/CharacterStats.java @@ -19,6 +19,7 @@ package com.l2jserver.model.world.character; import com.l2jserver.model.template.item.ItemTemplate; import com.l2jserver.model.world.L2Character; import com.l2jserver.model.world.actor.calculator.ActorCalculator; +import com.l2jserver.model.world.actor.calculator.ActorCalculatorContext; import com.l2jserver.model.world.actor.stat.ActorStats; import com.l2jserver.model.world.actor.stat.StatType; import com.l2jserver.model.world.character.CharacterInventory.InventoryPaperdoll; @@ -50,6 +51,7 @@ import com.l2jserver.model.world.character.calculator.base.CharacterBaseRunSpeed import com.l2jserver.model.world.character.calculator.base.CharacterBaseStrengthCalculator; import com.l2jserver.model.world.character.calculator.base.CharacterBaseWalkSpeedCalculator; import com.l2jserver.model.world.character.calculator.base.CharacterBaseWitnessCalculator; +import com.l2jserver.util.calculator.Calculator; /** * This class is responsible for calculating the real character stats. The real @@ -263,7 +265,7 @@ public class CharacterStats extends ActorStats { /** * The character calculator */ - private static final CharacterCalculator calculator = new CharacterCalculator(); + private final CharacterCalculator calculator = new CharacterCalculator(); /** * Creates a new {@link CharacterStats} and adds default calculators @@ -289,12 +291,48 @@ public class CharacterStats extends ActorStats { return (int) calc(StatType.MAX_CP); } + /** + * Adds an formula to the character calculator + * + * @param formula + * the formula + */ + public void addMaxCP(Calculator formula) { + calculator.add(formula); + } + + /** + * Reset the calculator to its default state + */ + public void resetMaxCP() { + calculator.remove(BASE_CP_FORMULA); + calculator.add(BASE_CP_FORMULA); + } + /** * @return the calculated maximum load */ public int getMaximumLoad() { return (int) calc(StatType.MAX_LOAD); } + + /** + * Adds an formula to the character calculator + * + * @param formula + * the formula + */ + public void addMaximumLoad(Calculator formula) { + calculator.add(formula); + } + + /** + * Reset the calculator to its default state + */ + public void resetMaximumLoad() { + calculator.remove(BASE_CP_FORMULA); + calculator.add(BASE_CP_FORMULA); + } /** * Setups the default formulas diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/item/ItemPickUpEvent.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/item/ItemPickUpEvent.java new file mode 100644 index 000000000..1623b224a --- /dev/null +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/model/world/item/ItemPickUpEvent.java @@ -0,0 +1,84 @@ +/* + * This file is part of l2jserver2 . + * + * l2jserver2 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. + * + * l2jserver2 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 l2jserver2. If not, see . + */ +package com.l2jserver.model.world.item; + +import com.l2jserver.model.id.ObjectID; +import com.l2jserver.model.world.Actor; +import com.l2jserver.model.world.Item; +import com.l2jserver.model.world.L2Character; +import com.l2jserver.model.world.Player; +import com.l2jserver.model.world.WorldObject; +import com.l2jserver.model.world.character.event.CharacterEvent; + +/** + * Event dispatched once an {@link Item} has been picked up on the ground. + * + * @author Rogiel + */ +public class ItemPickUpEvent implements ItemEvent, CharacterEvent { + /** + * The pickupping character + */ + private final L2Character character; + /** + * The item picked up + */ + private final Item item; + + /** + * Creates a new instance of this event + * + * @param character + * the picking up character + * @param item + * the picked up item + */ + public ItemPickUpEvent(L2Character character, Item item) { + this.character = character; + this.item = item; + } + + @Override + public WorldObject getObject() { + return item; + } + + @Override + public L2Character getCharacter() { + return character; + } + + @Override + public Player getPlayer() { + return character; + } + + @Override + public Item getItem() { + return item; + } + + @Override + public Actor getActor() { + return character; + } + + @Override + public ObjectID[] getDispatchableObjects() { + return new ObjectID[] { item.getID() }; + } +} diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/jdbc/JDBCItemDAO.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/jdbc/JDBCItemDAO.java index c0b1c8173..beaabef7b 100644 --- a/l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/jdbc/JDBCItemDAO.java +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/jdbc/JDBCItemDAO.java @@ -19,6 +19,7 @@ package com.l2jserver.service.database.jdbc; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Types; import java.util.List; import org.slf4j.Logger; @@ -36,8 +37,8 @@ import com.l2jserver.model.template.item.ItemTemplate; import com.l2jserver.model.world.Item; import com.l2jserver.model.world.L2Character; import com.l2jserver.model.world.character.CharacterInventory; -import com.l2jserver.model.world.character.CharacterInventory.InventoryLocation; import com.l2jserver.model.world.character.CharacterInventory.InventoryPaperdoll; +import com.l2jserver.model.world.character.CharacterInventory.ItemLocation; import com.l2jserver.service.database.AbstractJDBCDatabaseService.CachedMapper; import com.l2jserver.service.database.AbstractJDBCDatabaseService.InsertUpdateQuery; import com.l2jserver.service.database.AbstractJDBCDatabaseService.Mapper; @@ -129,7 +130,8 @@ public abstract class JDBCItemDAO extends AbstractJDBCDAO .getInt(TEMPLATE_ID)); final ItemTemplate template = templateId.getTemplate(); if (template == null) { - log.warn("No template found for {} while loading {}", templateId, id); + log.warn("No template found for {} while loading {}", + templateId, id); return null; } final Item item = template.create(); @@ -138,8 +140,7 @@ public abstract class JDBCItemDAO extends AbstractJDBCDAO if (rs.getObject(CHAR_ID) != null) item.setOwnerID(charIdFactory.resolveID(rs.getInt(CHAR_ID))); if (rs.getObject(LOCATION) != null) - item.setLocation(InventoryLocation.valueOf(rs - .getString(LOCATION))); + item.setLocation(ItemLocation.valueOf(rs.getString(LOCATION))); if (rs.getObject(PAPERDOLL) != null) item.setPaperdoll(InventoryPaperdoll.valueOf(rs .getString(PAPERDOLL))); @@ -211,7 +212,7 @@ public abstract class JDBCItemDAO extends AbstractJDBCDAO @Override protected void parametize(PreparedStatement st) throws SQLException { - st.setString(1, InventoryLocation.GROUND.name()); + st.setString(1, ItemLocation.GROUND.name()); } @Override @@ -244,7 +245,56 @@ public abstract class JDBCItemDAO extends AbstractJDBCDAO @Override public boolean update(Item item) { - return false; + // public static final String ITEM_ID = "item_id"; + // public static final String TEMPLATE_ID = "template_id"; + // public static final String CHAR_ID = JDBCCharacterDAO.CHAR_ID; + // + // public static final String LOCATION = "location"; + // public static final String PAPERDOLL = "paperdoll"; + // public static final String COUNT = "count"; + // public static final String COORD_X = "coord_x"; + // public static final String COORD_Y = "coord_y"; + // public static final String COORD_Z = "coord_z"; + + return database.query(new InsertUpdateQuery(item) { + @Override + protected String query() { + return "UPDATE `" + TABLE + "` SET `" + CHAR_ID + "` = ?,`" + + LOCATION + "` = ?,`" + PAPERDOLL + "` = ?,`" + COUNT + + "` = ?,`" + COORD_X + "` = ?,`" + COORD_Y + "` = ?,`" + + COORD_Z + "` = ? WHERE `" + ITEM_ID + "` = ?"; + } + + @Override + protected void parametize(PreparedStatement st, Item item) + throws SQLException { + int i = 1; + + // SET + if (item.getOwnerID() != null) { + st.setInt(i++, item.getOwnerID().getID()); + } else { + st.setNull(i++, Types.INTEGER); + } + st.setString(i++, item.getLocation().name()); + st.setString(i++, (item.getPaperdoll() != null ? item + .getPaperdoll().name() : null)); + st.setLong(i++, item.getCount()); + if (item.getPoint() != null) { + st.setInt(i++, item.getPoint().getX()); + st.setInt(i++, item.getPoint().getY()); + st.setInt(i++, item.getPoint().getZ()); + } else { + st.setInt(i++, 0); + st.setInt(i++, 0); + st.setInt(i++, 0); + } + + // WHERE + st.setInt(i++, item.getID().getID()); + } + }) > 0; + } @Override diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/effect/SimpleEffectService.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/effect/SimpleEffectService.java index 16106c9b6..fbb72dd8e 100644 --- a/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/effect/SimpleEffectService.java +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/effect/SimpleEffectService.java @@ -63,8 +63,10 @@ public class SimpleEffectService extends AbstractService implements @Override protected void doStart() throws ServiceStartException { - pool = threadService.createThreadPool("EffectService", 20); - for (int i = 0; i < 20; i++) { + final int threads = Runtime.getRuntime().availableProcessors(); + + pool = threadService.createThreadPool("EffectService", threads); + for (int i = 0; i < threads; i++) { pool.async(10, TimeUnit.MILLISECONDS, 10, new Runnable() { @Override public void run() { diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemAlreadyOnGroundServiceException.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemAlreadyOnGroundServiceException.java new file mode 100644 index 000000000..db6d50d79 --- /dev/null +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemAlreadyOnGroundServiceException.java @@ -0,0 +1,59 @@ +/* + * This file is part of l2jserver2 . + * + * l2jserver2 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. + * + * l2jserver2 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 l2jserver2. If not, see . + */ +package com.l2jserver.service.game.item; + +/** + * @author Rogiel + */ +public class ItemAlreadyOnGroundServiceException extends ItemServiceException { + /** + * Java Serialization API ID + */ + private static final long serialVersionUID = 1L; + + /** + * Creates a new instance + */ + public ItemAlreadyOnGroundServiceException() { + } + + /** + * @param message + * the message + * @param cause + * the cause + */ + public ItemAlreadyOnGroundServiceException(String message, Throwable cause) { + super(message, cause); + } + + /** + * @param message + * the message + */ + public ItemAlreadyOnGroundServiceException(String message) { + super(message); + } + + /** + * @param cause + * the cause + */ + public ItemAlreadyOnGroundServiceException(Throwable cause) { + super(cause); + } +} diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemNotOnGroundServiceException.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemNotOnGroundServiceException.java new file mode 100644 index 000000000..71d8b9f58 --- /dev/null +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemNotOnGroundServiceException.java @@ -0,0 +1,59 @@ +/* + * This file is part of l2jserver2 . + * + * l2jserver2 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. + * + * l2jserver2 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 l2jserver2. If not, see . + */ +package com.l2jserver.service.game.item; + +/** + * @author Rogiel + */ +public class ItemNotOnGroundServiceException extends ItemServiceException { + /** + * Java Serialization API ID + */ + private static final long serialVersionUID = 1L; + + /** + * Creates a new instance + */ + public ItemNotOnGroundServiceException() { + } + + /** + * @param message + * the message + * @param cause + * the cause + */ + public ItemNotOnGroundServiceException(String message, Throwable cause) { + super(message, cause); + } + + /** + * @param message + * the message + */ + public ItemNotOnGroundServiceException(String message) { + super(message); + } + + /** + * @param cause + * the cause + */ + public ItemNotOnGroundServiceException(Throwable cause) { + super(cause); + } +} diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemService.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemService.java index e5eada574..5e1782eee 100644 --- a/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemService.java +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemService.java @@ -16,7 +16,17 @@ */ package com.l2jserver.service.game.item; +import com.l2jserver.game.net.packet.client.CM_CHAR_ACTION.CharacterAction; +import com.l2jserver.model.world.Actor; +import com.l2jserver.model.world.Item; +import com.l2jserver.model.world.L2Character; import com.l2jserver.service.Service; +import com.l2jserver.service.game.spawn.AlreadySpawnedServiceException; +import com.l2jserver.service.game.spawn.NotSpawnedServiceException; +import com.l2jserver.service.game.spawn.SpawnPointNotFoundServiceException; +import com.l2jserver.service.game.spawn.SpawnService; +import com.l2jserver.service.game.world.WorldService; +import com.l2jserver.util.geometry.Point3D; /** * This service handles item management. Drop and pick up, create and destroy. @@ -24,5 +34,60 @@ import com.l2jserver.service.Service; * @author Rogiel */ public interface ItemService extends Service { + /** + * Executes an action for an Item. + * + * @param item + * the item + * @param character + * the character issuing the action + * @param action + * the action type + * @return item or another instance if the item was stacked. + * @throws ItemNotOnGroundServiceException + * if the item is not on ground at the moment + * @throws NotSpawnedServiceException + * if the item is not registered with {@link SpawnService} + */ + Item action(Item item, L2Character character, CharacterAction action) + throws ItemNotOnGroundServiceException, NotSpawnedServiceException; + /** + * Picks up an dropped item and places it into another players inventory + * + * @param item + * the item + * @param character + * the character + * @return item or another instance if the item was stacked. + * @throws ItemNotOnGroundServiceException + * if the item is not on ground at the moment + * @throws NotSpawnedServiceException + * if the item is not registered with {@link SpawnService} + */ + Item pickUp(Item item, L2Character character) + throws ItemNotOnGroundServiceException, NotSpawnedServiceException; + + /** + * Drops an item on the ground. If actor is not + * null he is flagged as the dropper actor. + * + * @param item + * the item + * @param point + * the drop point. Can be null if + * {@link Item#getPoint()} is set. + * @param actor + * the dropping actor. Can be null. + * @throws ItemAlreadyOnGroundServiceException + * if the item is already dropped + * @throws AlreadySpawnedServiceException + * if the item is already spawned in the {@link WorldService} + * @throws SpawnPointNotFoundServiceException + * if point was null and + * {@link Item#getPoint()} was not set. + */ + void drop(Item item, Point3D point, Actor actor) + throws ItemAlreadyOnGroundServiceException, + AlreadySpawnedServiceException, SpawnPointNotFoundServiceException; } diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemServiceException.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemServiceException.java new file mode 100644 index 000000000..bf8ddbc1e --- /dev/null +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemServiceException.java @@ -0,0 +1,68 @@ +/* + * This file is part of l2jserver2 . + * + * l2jserver2 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. + * + * l2jserver2 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 l2jserver2. If not, see . + */ +package com.l2jserver.service.game.item; + +import com.l2jserver.service.ServiceException; + +/** + * @author Rogiel + */ +public class ItemServiceException extends ServiceException { + /** + * The Java Serialization API serial + */ + private static final long serialVersionUID = 1L; + + /** + * Creates a new instance of this exception + */ + public ItemServiceException() { + super(); + } + + /** + * Creates a new instance of this exception + * + * @param message + * the message + * @param cause + * the root cause + */ + public ItemServiceException(String message, Throwable cause) { + super(message, cause); + } + + /** + * Creates a new instance of this exception + * + * @param message + * the message + */ + public ItemServiceException(String message) { + super(message); + } + + /** + * Creates a new instance of this exception + * + * @param cause + * the root cause + */ + public ItemServiceException(Throwable cause) { + super(cause); + } +} diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemServiceImpl.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemServiceImpl.java index 49a30855d..b0de05953 100644 --- a/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemServiceImpl.java +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/item/ItemServiceImpl.java @@ -19,16 +19,25 @@ package com.l2jserver.service.game.item; import java.util.List; import com.google.inject.Inject; +import com.l2jserver.game.net.packet.client.CM_CHAR_ACTION.CharacterAction; import com.l2jserver.model.dao.ItemDAO; +import com.l2jserver.model.world.Actor; import com.l2jserver.model.world.Item; +import com.l2jserver.model.world.L2Character; +import com.l2jserver.model.world.character.CharacterInventory.ItemLocation; +import com.l2jserver.model.world.item.ItemPickUpEvent; import com.l2jserver.service.AbstractService; import com.l2jserver.service.AbstractService.Depends; import com.l2jserver.service.ServiceStartException; import com.l2jserver.service.ServiceStopException; import com.l2jserver.service.database.DatabaseService; import com.l2jserver.service.game.spawn.AlreadySpawnedServiceException; +import com.l2jserver.service.game.spawn.NotSpawnedServiceException; import com.l2jserver.service.game.spawn.SpawnPointNotFoundServiceException; import com.l2jserver.service.game.spawn.SpawnService; +import com.l2jserver.service.game.world.WorldService; +import com.l2jserver.service.game.world.event.WorldEventDispatcher; +import com.l2jserver.util.geometry.Point3D; /** * @author Rogiel @@ -43,6 +52,10 @@ public class ItemServiceImpl extends AbstractService implements ItemService { * The Spawn Service */ private final SpawnService spawnService; + /** + * The {@link WorldService} event dispatcher + */ + private final WorldEventDispatcher eventDispatcher; /** * All items on the ground persisted to the database @@ -54,11 +67,15 @@ public class ItemServiceImpl extends AbstractService implements ItemService { * the item DAO * @param spawnService * the spawn service + * @param eventDispatcher + * the world service event dispatcher */ @Inject - private ItemServiceImpl(ItemDAO itemDao, SpawnService spawnService) { + private ItemServiceImpl(ItemDAO itemDao, SpawnService spawnService, + WorldEventDispatcher eventDispatcher) { this.itemDao = itemDao; this.spawnService = spawnService; + this.eventDispatcher = eventDispatcher; } @Override @@ -75,8 +92,64 @@ public class ItemServiceImpl extends AbstractService implements ItemService { } } + @Override + public Item action(Item item, L2Character character, CharacterAction action) + throws ItemNotOnGroundServiceException, NotSpawnedServiceException { + switch (action) { + case CLICK: + return pickUp(item, character); + case RIGHT_CLICK: + return item; + } + return item; + } + + @Override + public Item pickUp(Item item, L2Character character) + throws ItemNotOnGroundServiceException, NotSpawnedServiceException { + synchronized (item) { + if (item.getLocation() != ItemLocation.GROUND) + throw new ItemNotOnGroundServiceException(); + + item.setLocation(ItemLocation.INVENTORY); + item.setPaperdoll(null); + item.setOwnerID(character.getID()); + character.getInventory().add(item); + + items.remove(item); + + spawnService.unspawn(item); + eventDispatcher.dispatch(new ItemPickUpEvent(character, item)); + + return item; + } + } + + @Override + public void drop(Item item, Point3D point, Actor actor) + throws SpawnPointNotFoundServiceException, + ItemAlreadyOnGroundServiceException, AlreadySpawnedServiceException { + synchronized (item) { + if (item.getLocation() == ItemLocation.GROUND) + throw new AlreadySpawnedServiceException(); + + item.setLocation(ItemLocation.GROUND); + item.setPaperdoll(null); + // point will be set here + spawnService.spawn(item, point); + + items.add(item); + } + } + @Override protected void doStop() throws ServiceStopException { - super.doStop(); + try { + for (final Item item : items) { + spawnService.unspawn(item); + } + } catch (NotSpawnedServiceException e) { + throw new ServiceStopException("Item is not spawned anymore", e); + } } } diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/world/filter/impl/RangeFilter.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/world/filter/impl/RangeFilter.java index 061c346b9..a656ddbeb 100644 --- a/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/world/filter/impl/RangeFilter.java +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/game/world/filter/impl/RangeFilter.java @@ -56,6 +56,8 @@ public class RangeFilter implements WorldObjectFilter { public boolean accept(PositionableObject other) { if (other == null) return false; + if(other.getPoint() == null) + return false; final double dx = FastMath.abs(object.getPoint().getX() - other.getPoint().getX()); diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/service/network/broadcast/BroadcastServiceImpl.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/network/broadcast/BroadcastServiceImpl.java index 70a320be3..b7caa4170 100644 --- a/l2jserver2-gameserver/src/main/java/com/l2jserver/service/network/broadcast/BroadcastServiceImpl.java +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/service/network/broadcast/BroadcastServiceImpl.java @@ -46,6 +46,7 @@ import com.l2jserver.model.world.character.event.CharacterLeaveWorldEvent; import com.l2jserver.model.world.character.event.CharacterMoveEvent; import com.l2jserver.model.world.character.event.CharacterRunningEvent; import com.l2jserver.model.world.character.event.CharacterWalkingEvent; +import com.l2jserver.model.world.item.ItemPickUpEvent; import com.l2jserver.model.world.npc.event.NPCSpawnEvent; import com.l2jserver.model.world.player.event.PlayerTeleportedEvent; import com.l2jserver.service.AbstractService; @@ -125,8 +126,10 @@ public class BroadcastServiceImpl extends AbstractService implements broadcast(conn, e.getObject()); } else if (e instanceof ActorTeleportingEvent || e instanceof CharacterLeaveWorldEvent - || e instanceof ActorUnspawnEvent) { + || e instanceof ActorUnspawnEvent + || e instanceof ItemPickUpEvent) { // object is now out of sight + //FIXME pick up animation is not happening conn.write(new SM_OBJECT_REMOVE(object)); } else if (e instanceof CharacterWalkingEvent) { conn.write(new SM_MOVE_TYPE(((CharacterWalkingEvent) e) diff --git a/l2jserver2-gameserver/src/main/java/com/l2jserver/util/calculator/ComplexCalculator.java b/l2jserver2-gameserver/src/main/java/com/l2jserver/util/calculator/ComplexCalculator.java index 9a87e2abc..c7c190c19 100644 --- a/l2jserver2-gameserver/src/main/java/com/l2jserver/util/calculator/ComplexCalculator.java +++ b/l2jserver2-gameserver/src/main/java/com/l2jserver/util/calculator/ComplexCalculator.java @@ -168,6 +168,14 @@ public class ComplexCalculator> public void remove(Function function) { getList(function.type()).remove(function); } + + /** + * Removes all functions from type + * @param type the type + */ + public void remove(V type) { + getList(type).clear(); + } /** * Imports all functions from the given calculator. This is useful