mirror of
https://github.com/Rogiel/l2jserver2
synced 2025-12-06 07:32:46 +00:00
Implements item dropping and pickup stacking
This commit is contained in:
@@ -16,6 +16,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.l2jserver.model;
|
package com.l2jserver.model;
|
||||||
|
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.l2jserver.model.id.ID;
|
import com.l2jserver.model.id.ID;
|
||||||
|
|
||||||
@@ -28,6 +32,8 @@ import com.l2jserver.model.id.ID;
|
|||||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractModel<T extends ID<?>> implements Model<T> {
|
public abstract class AbstractModel<T extends ID<?>> implements Model<T> {
|
||||||
|
private final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The object id
|
* The object id
|
||||||
*/
|
*/
|
||||||
@@ -58,6 +64,7 @@ public abstract class AbstractModel<T extends ID<?>> implements Model<T> {
|
|||||||
public void setObjectDesire(ObjectDesire desire) {
|
public void setObjectDesire(ObjectDesire desire) {
|
||||||
if (desire == null)
|
if (desire == null)
|
||||||
desire = ObjectDesire.NONE;
|
desire = ObjectDesire.NONE;
|
||||||
|
log.debug("{} set desire to {}", this, desire);
|
||||||
this.desire = desire;
|
this.desire = desire;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,9 +76,11 @@ public abstract class AbstractModel<T extends ID<?>> implements Model<T> {
|
|||||||
@SuppressWarnings("javadoc")
|
@SuppressWarnings("javadoc")
|
||||||
protected void desireUpdate() {
|
protected void desireUpdate() {
|
||||||
if (this.desire != ObjectDesire.INSERT
|
if (this.desire != ObjectDesire.INSERT
|
||||||
&& this.desire != ObjectDesire.DELETE)
|
&& this.desire != ObjectDesire.DELETE) {
|
||||||
|
log.debug("{} desires an update", this);
|
||||||
this.desire = ObjectDesire.UPDATE;
|
this.desire = ObjectDesire.UPDATE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set this object desire to {@link ObjectDesire#INSERT}. If the desire is
|
* Set this object desire to {@link ObjectDesire#INSERT}. If the desire is
|
||||||
@@ -79,9 +88,11 @@ public abstract class AbstractModel<T extends ID<?>> implements Model<T> {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("javadoc")
|
@SuppressWarnings("javadoc")
|
||||||
protected void desireInsert() {
|
protected void desireInsert() {
|
||||||
if (this.desire != ObjectDesire.DELETE)
|
if (this.desire != ObjectDesire.DELETE) {
|
||||||
|
log.debug("{} desires an insert", this);
|
||||||
this.desire = ObjectDesire.INSERT;
|
this.desire = ObjectDesire.INSERT;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
|
|||||||
@@ -515,7 +515,7 @@ public abstract class AbstractJDBCDatabaseService extends AbstractService
|
|||||||
this.parametize(st, object);
|
this.parametize(st, object);
|
||||||
|
|
||||||
log.debug("Sending query to database for {}", object);
|
log.debug("Sending query to database for {}", object);
|
||||||
rows += st.executeUpdate();
|
rows = st.executeUpdate();
|
||||||
log.debug("Query inserted or updated {} rows for {}", rows,
|
log.debug("Query inserted or updated {} rows for {}", rows,
|
||||||
object);
|
object);
|
||||||
|
|
||||||
@@ -616,10 +616,8 @@ public abstract class AbstractJDBCDatabaseService extends AbstractService
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (obj instanceof Model) {
|
if (obj instanceof Model) {
|
||||||
if (((Model<?>) obj).getObjectDesire() == ObjectDesire.INSERT) {
|
|
||||||
((Model<?>) obj).setObjectDesire(ObjectDesire.NONE);
|
((Model<?>) obj).setObjectDesire(ObjectDesire.NONE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
log.debug("Mapper {} returned {}", mapper, obj);
|
log.debug("Mapper {} returned {}", mapper, obj);
|
||||||
list.add(obj);
|
list.add(obj);
|
||||||
}
|
}
|
||||||
@@ -695,10 +693,8 @@ public abstract class AbstractJDBCDatabaseService extends AbstractService
|
|||||||
log.debug("Mapping row {} with {}", rs, mapper);
|
log.debug("Mapping row {} with {}", rs, mapper);
|
||||||
final T object = mapper.map(rs);
|
final T object = mapper.map(rs);
|
||||||
if (object instanceof Model) {
|
if (object instanceof Model) {
|
||||||
if (((Model<?>) object).getObjectDesire() == ObjectDesire.INSERT) {
|
|
||||||
((Model<?>) object).setObjectDesire(ObjectDesire.NONE);
|
((Model<?>) object).setObjectDesire(ObjectDesire.NONE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
log.debug("Mapper {} returned {}", mapper, object);
|
log.debug("Mapper {} returned {}", mapper, object);
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,6 +120,17 @@ public class Point3D extends Point {
|
|||||||
return coordinate;
|
return coordinate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Point3D [" + coordinate.getX() + "," + coordinate.getY() + ","
|
||||||
|
+ coordinate.getZ() + "," + angle + "]";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance from the 3 points and an angle
|
* Creates a new instance from the 3 points and an angle
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ public enum SystemMessage {
|
|||||||
* ID: 29<br>
|
* ID: 29<br>
|
||||||
* Message: You have obtained $s2 $s1.
|
* Message: You have obtained $s2 $s1.
|
||||||
*/
|
*/
|
||||||
YOU_PICKED_UP_S1_S2(29),
|
YOU_PICKED_UP_S2_S1(29),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID: 30<br>
|
* ID: 30<br>
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import com.l2jserver.game.net.packet.client.CM_CHAR_POSITION;
|
|||||||
import com.l2jserver.game.net.packet.client.CM_CHAR_REQ_INVENTORY;
|
import com.l2jserver.game.net.packet.client.CM_CHAR_REQ_INVENTORY;
|
||||||
import com.l2jserver.game.net.packet.client.CM_CHAR_SELECT;
|
import com.l2jserver.game.net.packet.client.CM_CHAR_SELECT;
|
||||||
import com.l2jserver.game.net.packet.client.CM_CHAT;
|
import com.l2jserver.game.net.packet.client.CM_CHAT;
|
||||||
|
import com.l2jserver.game.net.packet.client.CM_DROP_ITEM;
|
||||||
import com.l2jserver.game.net.packet.client.CM_ENTER_WORLD;
|
import com.l2jserver.game.net.packet.client.CM_ENTER_WORLD;
|
||||||
import com.l2jserver.game.net.packet.client.CM_EXT_REQ_ALL_FORTRESS_INFO;
|
import com.l2jserver.game.net.packet.client.CM_EXT_REQ_ALL_FORTRESS_INFO;
|
||||||
import com.l2jserver.game.net.packet.client.CM_EXT_REQ_KEY_MAPPING;
|
import com.l2jserver.game.net.packet.client.CM_EXT_REQ_KEY_MAPPING;
|
||||||
@@ -187,6 +188,8 @@ public class Lineage2PacketReader extends OneToOneDecoder {
|
|||||||
return CM_CHAR_OPEN_MAP.class;
|
return CM_CHAR_OPEN_MAP.class;
|
||||||
case CM_ATTACK.OPCODE:
|
case CM_ATTACK.OPCODE:
|
||||||
return CM_ATTACK.class;
|
return CM_ATTACK.class;
|
||||||
|
case CM_DROP_ITEM.OPCODE:
|
||||||
|
return CM_DROP_ITEM.class;
|
||||||
default:
|
default:
|
||||||
logger.warn("Unknown packet for 0x{}", Integer.toHexString(opcode));
|
logger.warn("Unknown packet for 0x{}", Integer.toHexString(opcode));
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -118,9 +118,7 @@ public class CM_CHAR_ACTION extends AbstractClientPacket {
|
|||||||
final NPC npc = ((NPCID) id).getObject();
|
final NPC npc = ((NPCID) id).getObject();
|
||||||
try {
|
try {
|
||||||
npcService.action(npc, conn.getCharacter(), action);
|
npcService.action(npc, conn.getCharacter(), action);
|
||||||
} catch (ActionServiceException e) {
|
} catch (ActionServiceException | CannotSetTargetServiceException e) {
|
||||||
conn.sendActionFailed();
|
|
||||||
} catch (CannotSetTargetServiceException e) {
|
|
||||||
conn.sendActionFailed();
|
conn.sendActionFailed();
|
||||||
}
|
}
|
||||||
} else if (id instanceof ItemID) {
|
} else if (id instanceof ItemID) {
|
||||||
@@ -133,7 +131,7 @@ public class CM_CHAR_ACTION extends AbstractClientPacket {
|
|||||||
} else { // update only
|
} else { // update only
|
||||||
conn.updateInventoryItems(stackItem);
|
conn.updateInventoryItems(stackItem);
|
||||||
}
|
}
|
||||||
conn.sendSystemMessage(SystemMessage.YOU_PICKED_UP_S1_S2, Long
|
conn.sendSystemMessage(SystemMessage.YOU_PICKED_UP_S2_S1, Long
|
||||||
.toString(item.getCount()), item.getTemplate()
|
.toString(item.getCount()), item.getTemplate()
|
||||||
.getName());
|
.getName());
|
||||||
conn.sendActionFailed();
|
conn.sendActionFailed();
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of l2jserver2 <l2jserver2.com>.
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.l2jserver.game.net.packet.client;
|
||||||
|
|
||||||
|
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.object.ItemID;
|
||||||
|
import com.l2jserver.model.id.object.provider.ItemIDProvider;
|
||||||
|
import com.l2jserver.model.world.Item;
|
||||||
|
import com.l2jserver.service.game.item.ItemAlreadyOnGroundServiceException;
|
||||||
|
import com.l2jserver.service.game.item.ItemService;
|
||||||
|
import com.l2jserver.service.game.item.NotEnoughItemsServiceException;
|
||||||
|
import com.l2jserver.service.game.spawn.AlreadySpawnedServiceException;
|
||||||
|
import com.l2jserver.service.game.spawn.SpawnPointNotFoundServiceException;
|
||||||
|
import com.l2jserver.util.geometry.Point3D;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This packet drops items on the ground.
|
||||||
|
*
|
||||||
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
|
*/
|
||||||
|
public class CM_DROP_ITEM extends AbstractClientPacket {
|
||||||
|
/**
|
||||||
|
* The packet OPCODE
|
||||||
|
*/
|
||||||
|
public static final int OPCODE = 0x17;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link ItemService}
|
||||||
|
*/
|
||||||
|
private final ItemService itemService;
|
||||||
|
private final ItemIDProvider itemIdProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The item ID
|
||||||
|
*/
|
||||||
|
private int objectId;
|
||||||
|
/**
|
||||||
|
* The number of items to be dropped
|
||||||
|
*/
|
||||||
|
private long count;
|
||||||
|
/**
|
||||||
|
* The location to be dropped
|
||||||
|
*/
|
||||||
|
private Point3D point;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param itemService
|
||||||
|
* the item service
|
||||||
|
* @param itemIdProvider
|
||||||
|
* the item id provider
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
public CM_DROP_ITEM(ItemService itemService, ItemIDProvider itemIdProvider) {
|
||||||
|
this.itemService = itemService;
|
||||||
|
this.itemIdProvider = itemIdProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(Lineage2Client conn, ChannelBuffer buffer) {
|
||||||
|
objectId = buffer.readInt();
|
||||||
|
count = buffer.readLong();
|
||||||
|
point = Point3D.fromXYZ(buffer.readInt(), buffer.readInt(),
|
||||||
|
buffer.readInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(final Lineage2Client conn) {
|
||||||
|
final ItemID id = itemIdProvider.resolveID(objectId);
|
||||||
|
final Item item = id.getObject();
|
||||||
|
|
||||||
|
if (item == null) {
|
||||||
|
conn.sendActionFailed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!conn.getCharacterID().equals(item.getOwnerID())) {
|
||||||
|
conn.sendActionFailed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final Item dropped = itemService.drop(item, count, point,
|
||||||
|
conn.getCharacter());
|
||||||
|
if (dropped.equals(item)) {
|
||||||
|
conn.removeInventoryItems(dropped);
|
||||||
|
} else {
|
||||||
|
conn.updateInventoryItems(item);
|
||||||
|
}
|
||||||
|
if (dropped.getCount() == 1) {
|
||||||
|
conn.sendSystemMessage(SystemMessage.YOU_DROPPED_S1, item
|
||||||
|
.getTemplate().getName());
|
||||||
|
} else {
|
||||||
|
conn.sendSystemMessage(SystemMessage.DROPPED_S1_S2, item
|
||||||
|
.getTemplate().getName(), Long.toString(dropped
|
||||||
|
.getCount()));
|
||||||
|
}
|
||||||
|
} catch (ItemAlreadyOnGroundServiceException
|
||||||
|
| AlreadySpawnedServiceException
|
||||||
|
| SpawnPointNotFoundServiceException
|
||||||
|
| NotEnoughItemsServiceException e) {
|
||||||
|
conn.sendActionFailed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,6 +59,7 @@ public class SM_CHAR_INVENTORY extends AbstractServerPacket {
|
|||||||
int slot = 0;
|
int slot = 0;
|
||||||
for (Item item : inventory) {
|
for (Item item : inventory) {
|
||||||
if (item.getLocation() == ItemLocation.WAREHOUSE
|
if (item.getLocation() == ItemLocation.WAREHOUSE
|
||||||
|
|| item.getLocation() == ItemLocation.GROUND
|
||||||
|| item.getLocation() == null) {
|
|| item.getLocation() == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,21 +17,22 @@
|
|||||||
package com.l2jserver.model.world;
|
package com.l2jserver.model.world;
|
||||||
|
|
||||||
import com.l2jserver.model.id.object.CharacterID;
|
import com.l2jserver.model.id.object.CharacterID;
|
||||||
|
import com.l2jserver.model.id.object.ItemID;
|
||||||
import com.l2jserver.model.id.template.ItemTemplateID;
|
import com.l2jserver.model.id.template.ItemTemplateID;
|
||||||
import com.l2jserver.model.template.item.ItemTemplate;
|
import com.l2jserver.model.template.item.ItemTemplate;
|
||||||
import com.l2jserver.model.world.character.CharacterInventory.ItemLocation;
|
|
||||||
import com.l2jserver.model.world.character.CharacterInventory.InventoryPaperdoll;
|
import com.l2jserver.model.world.character.CharacterInventory.InventoryPaperdoll;
|
||||||
|
import com.l2jserver.model.world.character.CharacterInventory.ItemLocation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents an {@link Item} in the Lineage II World. The item can
|
* This class represents an {@link Item} in the Lineage II World. The item can
|
||||||
* be:
|
* be:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li><b>In the {@link L2Character character} inventory</b>: <tt>location</tt>
|
* <li><b>In the {@link L2Character character} inventory</b>: <tt>location</tt>
|
||||||
* is {@link ItemLocation#INVENTORY}, <tt>coordinate</tt> and
|
* is {@link ItemLocation#INVENTORY}, <tt>coordinate</tt> and <tt>paperdoll</tt>
|
||||||
* <tt>paperdoll</tt> are null.</li>
|
* are null.</li>
|
||||||
* <li><b>In the {@link L2Character character} warehouse</b>: <tt>location</tt>
|
* <li><b>In the {@link L2Character character} warehouse</b>: <tt>location</tt>
|
||||||
* is {@link ItemLocation#WAREHOUSE}, <tt>coordinate</tt> and
|
* is {@link ItemLocation#WAREHOUSE}, <tt>coordinate</tt> and <tt>paperdoll</tt>
|
||||||
* <tt>paperdoll</tt> are null.</li>
|
* are null.</li>
|
||||||
* <li><b>Equipped by the {@link L2Character character}</b>: <tt>location</tt>
|
* <li><b>Equipped by the {@link L2Character character}</b>: <tt>location</tt>
|
||||||
* is {@link ItemLocation#PAPERDOLL}, <tt>paperdoll</tt> is not null and
|
* is {@link ItemLocation#PAPERDOLL}, <tt>paperdoll</tt> is not null and
|
||||||
* <tt>coordinate</tt> is null.</li>
|
* <tt>coordinate</tt> is null.</li>
|
||||||
@@ -58,7 +59,7 @@ public class Item extends PositionableObject {
|
|||||||
/**
|
/**
|
||||||
* Inventory location of this item
|
* Inventory location of this item
|
||||||
*/
|
*/
|
||||||
private ItemLocation location;
|
private ItemLocation location = ItemLocation.INVENTORY;
|
||||||
/**
|
/**
|
||||||
* Paperdoll slot for this item
|
* Paperdoll slot for this item
|
||||||
*/
|
*/
|
||||||
@@ -156,4 +157,9 @@ public class Item extends PositionableObject {
|
|||||||
desireUpdate();
|
desireUpdate();
|
||||||
this.ownerID = ownerID;
|
this.ownerID = ownerID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemID getID() {
|
||||||
|
return (ItemID) super.getID();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,13 @@
|
|||||||
*/
|
*/
|
||||||
package com.l2jserver.model.world.character;
|
package com.l2jserver.model.world.character;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import com.l2jserver.model.id.object.ItemID;
|
import com.l2jserver.model.id.object.ItemID;
|
||||||
|
import com.l2jserver.model.id.template.ItemTemplateID;
|
||||||
import com.l2jserver.model.world.Item;
|
import com.l2jserver.model.world.Item;
|
||||||
import com.l2jserver.model.world.L2Character;
|
import com.l2jserver.model.world.L2Character;
|
||||||
import com.l2jserver.util.factory.CollectionFactory;
|
import com.l2jserver.util.factory.CollectionFactory;
|
||||||
@@ -76,6 +77,23 @@ public class CharacterInventory implements Iterable<Item> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes several items from the players inventory.
|
||||||
|
*
|
||||||
|
* @param items
|
||||||
|
* the items to be removed
|
||||||
|
* @return the items that were effectivelly removed
|
||||||
|
*/
|
||||||
|
public Item[] remove(Item... items) {
|
||||||
|
final List<Item> removedItems = CollectionFactory.newList();
|
||||||
|
for (final Item item : items) {
|
||||||
|
if (this.items.remove(item)) {
|
||||||
|
removedItems.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return removedItems.toArray(new Item[removedItems.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all items from the given {@link ItemID}
|
* Removes all items from the given {@link ItemID}
|
||||||
*
|
*
|
||||||
@@ -84,7 +102,7 @@ public class CharacterInventory implements Iterable<Item> {
|
|||||||
* @return an array of all items removed. Can never be <code>null</code>.
|
* @return an array of all items removed. Can never be <code>null</code>.
|
||||||
*/
|
*/
|
||||||
public Item[] remove(ItemID itemID) {
|
public Item[] remove(ItemID itemID) {
|
||||||
final ArrayList<Item> removedItems = new ArrayList<Item>();
|
final List<Item> removedItems = CollectionFactory.newList();
|
||||||
for (final Item item : items) {
|
for (final Item item : items) {
|
||||||
if (item.getID().equals(itemID)) {
|
if (item.getID().equals(itemID)) {
|
||||||
items.remove(item);
|
items.remove(item);
|
||||||
@@ -94,6 +112,23 @@ public class CharacterInventory implements Iterable<Item> {
|
|||||||
return removedItems.toArray(new Item[removedItems.size()]);
|
return removedItems.toArray(new Item[removedItems.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all items from the given {@link ItemTemplateID}
|
||||||
|
*
|
||||||
|
* @param itemTemplateID
|
||||||
|
* the {@link ItemTemplateID}
|
||||||
|
* @return an array of all items with the given ID
|
||||||
|
*/
|
||||||
|
public Item[] getItems(ItemTemplateID itemTemplateID) {
|
||||||
|
final List<Item> allItems = CollectionFactory.newList();
|
||||||
|
for (final Item item : items) {
|
||||||
|
if (item.getTemplateID().equals(itemTemplateID)) {
|
||||||
|
allItems.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allItems.toArray(new Item[allItems.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the item in the given <tt>paperdoll</tt> slot
|
* Get the item in the given <tt>paperdoll</tt> slot
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -19,20 +19,19 @@ package com.l2jserver.model.world.item;
|
|||||||
import com.l2jserver.model.id.ObjectID;
|
import com.l2jserver.model.id.ObjectID;
|
||||||
import com.l2jserver.model.world.Actor;
|
import com.l2jserver.model.world.Actor;
|
||||||
import com.l2jserver.model.world.Item;
|
import com.l2jserver.model.world.Item;
|
||||||
import com.l2jserver.model.world.Player;
|
|
||||||
import com.l2jserver.model.world.WorldObject;
|
import com.l2jserver.model.world.WorldObject;
|
||||||
import com.l2jserver.model.world.player.event.PlayerEvent;
|
import com.l2jserver.model.world.actor.event.ActorEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event dispatched once an {@link Item} has been dropped on the ground.
|
* Event dispatched once an {@link Item} has been dropped on the ground.
|
||||||
*
|
*
|
||||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
*/
|
*/
|
||||||
public class ItemDropEvent implements ItemEvent, PlayerEvent {
|
public class ItemDropEvent implements ItemEvent, ActorEvent {
|
||||||
/**
|
/**
|
||||||
* The dropping player
|
* The dropping actor
|
||||||
*/
|
*/
|
||||||
private final Player player;
|
private final Actor actor;
|
||||||
/**
|
/**
|
||||||
* The item dropped
|
* The item dropped
|
||||||
*/
|
*/
|
||||||
@@ -41,13 +40,13 @@ public class ItemDropEvent implements ItemEvent, PlayerEvent {
|
|||||||
/**
|
/**
|
||||||
* Creates a new instance of this event
|
* Creates a new instance of this event
|
||||||
*
|
*
|
||||||
* @param player
|
* @param actor
|
||||||
* the dropping player
|
* the dropping actor
|
||||||
* @param item
|
* @param item
|
||||||
* the dropped item
|
* the dropped item
|
||||||
*/
|
*/
|
||||||
public ItemDropEvent(Player player, Item item) {
|
public ItemDropEvent(Actor actor, Item item) {
|
||||||
this.player = player;
|
this.actor = actor;
|
||||||
this.item = item;
|
this.item = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,11 +55,6 @@ public class ItemDropEvent implements ItemEvent, PlayerEvent {
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Player getPlayer() {
|
|
||||||
return player;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Item getItem() {
|
public Item getItem() {
|
||||||
return item;
|
return item;
|
||||||
@@ -68,7 +62,7 @@ public class ItemDropEvent implements ItemEvent, PlayerEvent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Actor getActor() {
|
public Actor getActor() {
|
||||||
return player;
|
return actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ public class ItemPickUpEvent implements ItemEvent, CharacterEvent {
|
|||||||
* The item picked up
|
* The item picked up
|
||||||
*/
|
*/
|
||||||
private final Item item;
|
private final Item item;
|
||||||
|
/**
|
||||||
|
* The new item
|
||||||
|
*/
|
||||||
|
private final Item newItem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of this event
|
* Creates a new instance of this event
|
||||||
@@ -46,10 +50,19 @@ public class ItemPickUpEvent implements ItemEvent, CharacterEvent {
|
|||||||
* the picking up character
|
* the picking up character
|
||||||
* @param item
|
* @param item
|
||||||
* the picked up item
|
* the picked up item
|
||||||
|
* @param newItem the new {@link Item}
|
||||||
*/
|
*/
|
||||||
public ItemPickUpEvent(L2Character character, Item item) {
|
public ItemPickUpEvent(L2Character character, Item item, Item newItem) {
|
||||||
this.character = character;
|
this.character = character;
|
||||||
this.item = item;
|
this.item = item;
|
||||||
|
this.newItem = newItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the new {@link Item}
|
||||||
|
*/
|
||||||
|
public Item getNewItem() {
|
||||||
|
return newItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -184,12 +184,13 @@ public abstract class JDBCItemDAO extends AbstractJDBCDAO<Item, ItemID>
|
|||||||
@Override
|
@Override
|
||||||
protected String query() {
|
protected String query() {
|
||||||
return "SELECT * FROM `" + TABLE + "` WHERE `" + CHAR_ID
|
return "SELECT * FROM `" + TABLE + "` WHERE `" + CHAR_ID
|
||||||
+ "` = ?";
|
+ "` = ? AND `location` = ?";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void parametize(PreparedStatement st) throws SQLException {
|
protected void parametize(PreparedStatement st) throws SQLException {
|
||||||
st.setInt(1, character.getID().getID());
|
st.setInt(1, character.getID().getID());
|
||||||
|
st.setString(2, ItemLocation.INVENTORY.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -239,23 +240,47 @@ public abstract class JDBCItemDAO extends AbstractJDBCDAO<Item, ItemID>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean insert(Item item) {
|
public boolean insert(Item item) {
|
||||||
throw new UnsupportedOperationException(
|
return database.query(new InsertUpdateQuery<Item>(item) {
|
||||||
"Saving items is not yet implemented!");
|
@Override
|
||||||
|
protected String query() {
|
||||||
|
return "INSERT INTO `" + TABLE + "` (`" + ITEM_ID + "`,`"
|
||||||
|
+ TEMPLATE_ID + "`,`" + CHAR_ID + "`,`" + LOCATION
|
||||||
|
+ "`,`" + PAPERDOLL + "`,`" + COUNT + "`,`" + COORD_X
|
||||||
|
+ "`,`" + COORD_Y + "`,`" + COORD_Z
|
||||||
|
+ "`) VALUES(?,?,?,?,?,?,?,?,?)";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void parametize(PreparedStatement st, Item item)
|
||||||
|
throws SQLException {
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
|
st.setInt(i++, item.getID().getID());
|
||||||
|
st.setInt(i++, item.getTemplateID().getID());
|
||||||
|
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.setNull(i++, Types.INTEGER);
|
||||||
|
st.setNull(i++, Types.INTEGER);
|
||||||
|
st.setNull(i++, Types.INTEGER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean update(Item item) {
|
public boolean update(Item item) {
|
||||||
// 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>(item) {
|
return database.query(new InsertUpdateQuery<Item>(item) {
|
||||||
@Override
|
@Override
|
||||||
protected String query() {
|
protected String query() {
|
||||||
@@ -285,16 +310,15 @@ public abstract class JDBCItemDAO extends AbstractJDBCDAO<Item, ItemID>
|
|||||||
st.setInt(i++, item.getPoint().getY());
|
st.setInt(i++, item.getPoint().getY());
|
||||||
st.setInt(i++, item.getPoint().getZ());
|
st.setInt(i++, item.getPoint().getZ());
|
||||||
} else {
|
} else {
|
||||||
st.setInt(i++, 0);
|
st.setNull(i++, Types.INTEGER);
|
||||||
st.setInt(i++, 0);
|
st.setNull(i++, Types.INTEGER);
|
||||||
st.setInt(i++, 0);
|
st.setNull(i++, Types.INTEGER);
|
||||||
}
|
}
|
||||||
|
|
||||||
// WHERE
|
// WHERE
|
||||||
st.setInt(i++, item.getID().getID());
|
st.setInt(i++, item.getID().getID());
|
||||||
}
|
}
|
||||||
}) > 0;
|
}) > 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -52,6 +52,33 @@ public interface ItemService extends Service {
|
|||||||
Item action(Item item, L2Character character, CharacterAction action)
|
Item action(Item item, L2Character character, CharacterAction action)
|
||||||
throws ItemNotOnGroundServiceException, NotSpawnedServiceException;
|
throws ItemNotOnGroundServiceException, NotSpawnedServiceException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits this item in two pieces
|
||||||
|
*
|
||||||
|
* @param item
|
||||||
|
* the item to be splitted
|
||||||
|
* @param count
|
||||||
|
* the amount of items that will be decreased from the argument
|
||||||
|
* {@link Item} and added to the result one.
|
||||||
|
* @return the splitted item
|
||||||
|
* @throws NotEnoughItemsServiceException
|
||||||
|
* if <code>count</code> is bigger than {@link Item#getCount()}.
|
||||||
|
*/
|
||||||
|
Item split(Item item, long count) throws NotEnoughItemsServiceException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stacks several items into a single one. Items must be provided by the
|
||||||
|
* same template!
|
||||||
|
*
|
||||||
|
* @param items
|
||||||
|
* the items to be stacked
|
||||||
|
* @return the stacked item (it may be a totally new item or it might reuse
|
||||||
|
* another one)
|
||||||
|
* @throws NonStackableItemsServiceException
|
||||||
|
* if the item templates says they are not stackable
|
||||||
|
*/
|
||||||
|
Item stack(Item... items) throws NonStackableItemsServiceException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Picks up an dropped item and places it into another players inventory
|
* Picks up an dropped item and places it into another players inventory
|
||||||
*
|
*
|
||||||
@@ -68,6 +95,35 @@ public interface ItemService extends Service {
|
|||||||
Item pickUp(Item item, L2Character character)
|
Item pickUp(Item item, L2Character character)
|
||||||
throws ItemNotOnGroundServiceException, NotSpawnedServiceException;
|
throws ItemNotOnGroundServiceException, NotSpawnedServiceException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drops an item on the ground. If <code>actor</code> is not
|
||||||
|
* <code>null</code> he is flagged as the dropper actor.
|
||||||
|
*
|
||||||
|
* @param item
|
||||||
|
* the item
|
||||||
|
* @param count
|
||||||
|
* the number of items to be dropped. Will cause an split.
|
||||||
|
* @param point
|
||||||
|
* the drop point. Can be <code>null</code> if
|
||||||
|
* {@link Item#getPoint()} is set.
|
||||||
|
* @param actor
|
||||||
|
* the dropping actor. Can be <code>null</code>.
|
||||||
|
* @return <code>item</code> or another instance if the item was splitted.
|
||||||
|
* @throws ItemAlreadyOnGroundServiceException
|
||||||
|
* if the item is already dropped
|
||||||
|
* @throws AlreadySpawnedServiceException
|
||||||
|
* if the item is already spawned in the {@link WorldService}
|
||||||
|
* @throws SpawnPointNotFoundServiceException
|
||||||
|
* if <code>point</code> was <code>null</code> and
|
||||||
|
* {@link Item#getPoint()} was not set.
|
||||||
|
* @throws NotEnoughItemsServiceException
|
||||||
|
* if <code>count</code> is bigger than {@link Item#getCount()}.
|
||||||
|
*/
|
||||||
|
Item drop(Item item, long count, Point3D point, Actor actor)
|
||||||
|
throws ItemAlreadyOnGroundServiceException,
|
||||||
|
AlreadySpawnedServiceException, SpawnPointNotFoundServiceException,
|
||||||
|
NotEnoughItemsServiceException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Drops an item on the ground. If <code>actor</code> is not
|
* Drops an item on the ground. If <code>actor</code> is not
|
||||||
* <code>null</code> he is flagged as the dropper actor.
|
* <code>null</code> he is flagged as the dropper actor.
|
||||||
@@ -86,8 +142,11 @@ public interface ItemService extends Service {
|
|||||||
* @throws SpawnPointNotFoundServiceException
|
* @throws SpawnPointNotFoundServiceException
|
||||||
* if <code>point</code> was <code>null</code> and
|
* if <code>point</code> was <code>null</code> and
|
||||||
* {@link Item#getPoint()} was not set.
|
* {@link Item#getPoint()} was not set.
|
||||||
|
* @throws NotEnoughItemsServiceException
|
||||||
|
* if <code>count</code> is bigger than {@link Item#getCount()}.
|
||||||
*/
|
*/
|
||||||
void drop(Item item, Point3D point, Actor actor)
|
void drop(Item item, Point3D point, Actor actor)
|
||||||
throws ItemAlreadyOnGroundServiceException,
|
throws ItemAlreadyOnGroundServiceException,
|
||||||
AlreadySpawnedServiceException, SpawnPointNotFoundServiceException;
|
AlreadySpawnedServiceException, SpawnPointNotFoundServiceException,
|
||||||
|
NotEnoughItemsServiceException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,15 +16,22 @@
|
|||||||
*/
|
*/
|
||||||
package com.l2jserver.service.game.item;
|
package com.l2jserver.service.game.item;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.l2jserver.game.net.packet.client.CM_CHAR_ACTION.CharacterAction;
|
import com.l2jserver.game.net.packet.client.CM_CHAR_ACTION.CharacterAction;
|
||||||
|
import com.l2jserver.model.Model.ObjectDesire;
|
||||||
import com.l2jserver.model.dao.ItemDAO;
|
import com.l2jserver.model.dao.ItemDAO;
|
||||||
|
import com.l2jserver.model.id.object.ItemID;
|
||||||
|
import com.l2jserver.model.id.object.provider.ItemIDProvider;
|
||||||
|
import com.l2jserver.model.id.template.ItemTemplateID;
|
||||||
import com.l2jserver.model.world.Actor;
|
import com.l2jserver.model.world.Actor;
|
||||||
import com.l2jserver.model.world.Item;
|
import com.l2jserver.model.world.Item;
|
||||||
import com.l2jserver.model.world.L2Character;
|
import com.l2jserver.model.world.L2Character;
|
||||||
import com.l2jserver.model.world.character.CharacterInventory.ItemLocation;
|
import com.l2jserver.model.world.character.CharacterInventory.ItemLocation;
|
||||||
|
import com.l2jserver.model.world.item.ItemDropEvent;
|
||||||
import com.l2jserver.model.world.item.ItemPickUpEvent;
|
import com.l2jserver.model.world.item.ItemPickUpEvent;
|
||||||
import com.l2jserver.service.AbstractService;
|
import com.l2jserver.service.AbstractService;
|
||||||
import com.l2jserver.service.AbstractService.Depends;
|
import com.l2jserver.service.AbstractService.Depends;
|
||||||
@@ -56,6 +63,10 @@ public class ItemServiceImpl extends AbstractService implements ItemService {
|
|||||||
* The {@link WorldService} event dispatcher
|
* The {@link WorldService} event dispatcher
|
||||||
*/
|
*/
|
||||||
private final WorldEventDispatcher eventDispatcher;
|
private final WorldEventDispatcher eventDispatcher;
|
||||||
|
/**
|
||||||
|
* The {@link ItemID} provider
|
||||||
|
*/
|
||||||
|
private final ItemIDProvider itemIdProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All items on the ground persisted to the database
|
* All items on the ground persisted to the database
|
||||||
@@ -69,13 +80,16 @@ public class ItemServiceImpl extends AbstractService implements ItemService {
|
|||||||
* the spawn service
|
* the spawn service
|
||||||
* @param eventDispatcher
|
* @param eventDispatcher
|
||||||
* the world service event dispatcher
|
* the world service event dispatcher
|
||||||
|
* @param itemIdProvider
|
||||||
|
* the {@link ItemID} provider
|
||||||
*/
|
*/
|
||||||
@Inject
|
@Inject
|
||||||
private ItemServiceImpl(ItemDAO itemDao, SpawnService spawnService,
|
private ItemServiceImpl(ItemDAO itemDao, SpawnService spawnService,
|
||||||
WorldEventDispatcher eventDispatcher) {
|
WorldEventDispatcher eventDispatcher, ItemIDProvider itemIdProvider) {
|
||||||
this.itemDao = itemDao;
|
this.itemDao = itemDao;
|
||||||
this.spawnService = spawnService;
|
this.spawnService = spawnService;
|
||||||
this.eventDispatcher = eventDispatcher;
|
this.eventDispatcher = eventDispatcher;
|
||||||
|
this.itemIdProvider = itemIdProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -104,6 +118,44 @@ public class ItemServiceImpl extends AbstractService implements ItemService {
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Item split(Item item, long count)
|
||||||
|
throws NotEnoughItemsServiceException {
|
||||||
|
if (item.getCount() < count)
|
||||||
|
throw new NotEnoughItemsServiceException();
|
||||||
|
if (item.getCount() == count)
|
||||||
|
return item;
|
||||||
|
|
||||||
|
final Item splitItem = item.getTemplate().create();
|
||||||
|
splitItem.setID(itemIdProvider.createID());
|
||||||
|
splitItem.setCount(count);
|
||||||
|
item.setCount(item.getCount() - count);
|
||||||
|
|
||||||
|
splitItem.setObjectDesire(ObjectDesire.INSERT);
|
||||||
|
|
||||||
|
return splitItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Item stack(Item... items) throws NonStackableItemsServiceException {
|
||||||
|
Preconditions.checkState(items.length >= 2,
|
||||||
|
"items length must be 2 or greater");
|
||||||
|
// TODO implement real item stacking
|
||||||
|
|
||||||
|
final ItemTemplateID templateID = items[0].getTemplateID();
|
||||||
|
for (final Item item : items) {
|
||||||
|
if (!item.getTemplateID().equals(templateID))
|
||||||
|
throw new NonStackableItemsServiceException();
|
||||||
|
}
|
||||||
|
|
||||||
|
final Item item = items[0];
|
||||||
|
for (int i = 1; i < items.length; i++) {
|
||||||
|
item.setCount(item.getCount() + items[i].getCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Item pickUp(Item item, L2Character character)
|
public Item pickUp(Item item, L2Character character)
|
||||||
throws ItemNotOnGroundServiceException, NotSpawnedServiceException {
|
throws ItemNotOnGroundServiceException, NotSpawnedServiceException {
|
||||||
@@ -111,15 +163,75 @@ public class ItemServiceImpl extends AbstractService implements ItemService {
|
|||||||
if (item.getLocation() != ItemLocation.GROUND)
|
if (item.getLocation() != ItemLocation.GROUND)
|
||||||
throw new ItemNotOnGroundServiceException();
|
throw new ItemNotOnGroundServiceException();
|
||||||
|
|
||||||
|
final Item originalItem = item;
|
||||||
|
|
||||||
item.setLocation(ItemLocation.INVENTORY);
|
item.setLocation(ItemLocation.INVENTORY);
|
||||||
item.setPaperdoll(null);
|
item.setPaperdoll(null);
|
||||||
item.setOwnerID(character.getID());
|
item.setOwnerID(character.getID());
|
||||||
|
final Item[] items = character.getInventory().getItems(
|
||||||
|
item.getTemplateID());
|
||||||
|
if (items.length != 0) {
|
||||||
|
Item[] stackItems = Arrays.copyOf(items, items.length + 1);
|
||||||
|
stackItems[items.length] = item;
|
||||||
|
try {
|
||||||
|
item = stack(stackItems);
|
||||||
|
Item[] removedItems = character.getInventory().remove(
|
||||||
|
stackItems);
|
||||||
|
for (final Item removeItem : removedItems) {
|
||||||
|
if (!removeItem.equals(item)) {
|
||||||
|
itemDao.delete(removeItem);
|
||||||
|
itemIdProvider.destroy(removeItem.getID());
|
||||||
|
}
|
||||||
|
}
|
||||||
character.getInventory().add(item);
|
character.getInventory().add(item);
|
||||||
|
} catch (NonStackableItemsServiceException e) {
|
||||||
|
character.getInventory().add(item);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
character.getInventory().add(item);
|
||||||
|
}
|
||||||
|
|
||||||
items.remove(item);
|
character.getInventory().add(item);
|
||||||
|
this.items.remove(item);
|
||||||
|
|
||||||
spawnService.unspawn(item);
|
itemDao.save(item);
|
||||||
eventDispatcher.dispatch(new ItemPickUpEvent(character, item));
|
spawnService.unspawn(originalItem);
|
||||||
|
eventDispatcher.dispatch(new ItemPickUpEvent(character,
|
||||||
|
originalItem, item));
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Item drop(Item item, long count, Point3D point, Actor actor)
|
||||||
|
throws SpawnPointNotFoundServiceException,
|
||||||
|
ItemAlreadyOnGroundServiceException,
|
||||||
|
AlreadySpawnedServiceException, NotEnoughItemsServiceException {
|
||||||
|
synchronized (item) {
|
||||||
|
if (item.getLocation() == ItemLocation.GROUND)
|
||||||
|
throw new AlreadySpawnedServiceException();
|
||||||
|
|
||||||
|
final Item sourceItem = item;
|
||||||
|
item = split(sourceItem, count);
|
||||||
|
|
||||||
|
item.setLocation(ItemLocation.GROUND);
|
||||||
|
item.setPaperdoll(null);
|
||||||
|
|
||||||
|
spawnService.spawn(item, point);
|
||||||
|
eventDispatcher.dispatch(new ItemDropEvent(actor, item));
|
||||||
|
|
||||||
|
if (actor instanceof L2Character) {
|
||||||
|
if (sourceItem.equals(item)) {
|
||||||
|
((L2Character) actor).getInventory().remove(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
itemDao.save(item);
|
||||||
|
if (!item.equals(sourceItem)) {
|
||||||
|
itemDao.save(sourceItem);
|
||||||
|
}
|
||||||
|
items.add(item);
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
@@ -128,18 +240,9 @@ public class ItemServiceImpl extends AbstractService implements ItemService {
|
|||||||
@Override
|
@Override
|
||||||
public void drop(Item item, Point3D point, Actor actor)
|
public void drop(Item item, Point3D point, Actor actor)
|
||||||
throws SpawnPointNotFoundServiceException,
|
throws SpawnPointNotFoundServiceException,
|
||||||
ItemAlreadyOnGroundServiceException, AlreadySpawnedServiceException {
|
ItemAlreadyOnGroundServiceException,
|
||||||
synchronized (item) {
|
AlreadySpawnedServiceException, NotEnoughItemsServiceException {
|
||||||
if (item.getLocation() == ItemLocation.GROUND)
|
drop(item, item.getCount(), point, actor);
|
||||||
throw new AlreadySpawnedServiceException();
|
|
||||||
|
|
||||||
item.setLocation(ItemLocation.GROUND);
|
|
||||||
item.setPaperdoll(null);
|
|
||||||
// point will be set here
|
|
||||||
spawnService.spawn(item, point);
|
|
||||||
|
|
||||||
items.add(item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of l2jserver2 <l2jserver2.com>.
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.l2jserver.service.game.item;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
|
*/
|
||||||
|
public class NonStackableItemsServiceException extends ItemServiceException {
|
||||||
|
/**
|
||||||
|
* Java Serialization API ID
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*/
|
||||||
|
public NonStackableItemsServiceException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message
|
||||||
|
* the message
|
||||||
|
* @param cause
|
||||||
|
* the cause
|
||||||
|
*/
|
||||||
|
public NonStackableItemsServiceException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message
|
||||||
|
* the message
|
||||||
|
*/
|
||||||
|
public NonStackableItemsServiceException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param cause
|
||||||
|
* the cause
|
||||||
|
*/
|
||||||
|
public NonStackableItemsServiceException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of l2jserver2 <l2jserver2.com>.
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.l2jserver.service.game.item;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
|
*/
|
||||||
|
public class NotEnoughItemsServiceException extends ItemServiceException {
|
||||||
|
/**
|
||||||
|
* Java Serialization API ID
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*/
|
||||||
|
public NotEnoughItemsServiceException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message
|
||||||
|
* the message
|
||||||
|
* @param cause
|
||||||
|
* the cause
|
||||||
|
*/
|
||||||
|
public NotEnoughItemsServiceException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message
|
||||||
|
* the message
|
||||||
|
*/
|
||||||
|
public NotEnoughItemsServiceException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param cause
|
||||||
|
* the cause
|
||||||
|
*/
|
||||||
|
public NotEnoughItemsServiceException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,7 +30,10 @@ import com.l2jserver.model.world.player.event.PlayerTeleportedEvent;
|
|||||||
import com.l2jserver.service.Service;
|
import com.l2jserver.service.Service;
|
||||||
import com.l2jserver.service.core.threading.AsyncFuture;
|
import com.l2jserver.service.core.threading.AsyncFuture;
|
||||||
import com.l2jserver.service.core.threading.ThreadService;
|
import com.l2jserver.service.core.threading.ThreadService;
|
||||||
|
import com.l2jserver.service.game.character.CharacterService;
|
||||||
|
import com.l2jserver.service.game.item.ItemService;
|
||||||
import com.l2jserver.service.game.npc.NPCService;
|
import com.l2jserver.service.game.npc.NPCService;
|
||||||
|
import com.l2jserver.service.game.world.WorldService;
|
||||||
import com.l2jserver.util.geometry.Coordinate;
|
import com.l2jserver.util.geometry.Coordinate;
|
||||||
import com.l2jserver.util.geometry.Point3D;
|
import com.l2jserver.util.geometry.Point3D;
|
||||||
|
|
||||||
@@ -52,6 +55,12 @@ import com.l2jserver.util.geometry.Point3D;
|
|||||||
* do, the {@link NPC} will not be respawned. The only possible way to respawn
|
* do, the {@link NPC} will not be respawned. The only possible way to respawn
|
||||||
* it is through an forced spawn (manual) or server restart. See
|
* it is through an forced spawn (manual) or server restart. See
|
||||||
* {@link NPCService} if you wish to correctly unspawn an {@link NPC}.
|
* {@link NPCService} if you wish to correctly unspawn an {@link NPC}.
|
||||||
|
* <p>
|
||||||
|
* Also note that this service is a low level implementation. In most cases, it
|
||||||
|
* might be more suitable the usage of high-level services, like
|
||||||
|
* {@link ItemService}, {@link NPCService} or {@link CharacterService}, since
|
||||||
|
* they can provide more security and dispatch more events to the
|
||||||
|
* {@link WorldService}.
|
||||||
*
|
*
|
||||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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.CharacterMoveEvent;
|
||||||
import com.l2jserver.model.world.character.event.CharacterRunningEvent;
|
import com.l2jserver.model.world.character.event.CharacterRunningEvent;
|
||||||
import com.l2jserver.model.world.character.event.CharacterWalkingEvent;
|
import com.l2jserver.model.world.character.event.CharacterWalkingEvent;
|
||||||
|
import com.l2jserver.model.world.item.ItemDropEvent;
|
||||||
import com.l2jserver.model.world.item.ItemPickUpEvent;
|
import com.l2jserver.model.world.item.ItemPickUpEvent;
|
||||||
import com.l2jserver.model.world.npc.event.NPCSpawnEvent;
|
import com.l2jserver.model.world.npc.event.NPCSpawnEvent;
|
||||||
import com.l2jserver.model.world.player.event.PlayerTeleportedEvent;
|
import com.l2jserver.model.world.player.event.PlayerTeleportedEvent;
|
||||||
@@ -115,7 +116,7 @@ public class BroadcastServiceImpl extends AbstractService implements
|
|||||||
@Override
|
@Override
|
||||||
protected boolean dispatch(WorldEvent e, PositionableObject object) {
|
protected boolean dispatch(WorldEvent e, PositionableObject object) {
|
||||||
log.debug("Broadcast event received: {}", e);
|
log.debug("Broadcast event received: {}", e);
|
||||||
if (e instanceof NPCSpawnEvent) {
|
if (e instanceof NPCSpawnEvent || e instanceof ItemDropEvent) {
|
||||||
broadcast(conn, e.getObject());
|
broadcast(conn, e.getObject());
|
||||||
} else if (e instanceof CharacterMoveEvent) {
|
} else if (e instanceof CharacterMoveEvent) {
|
||||||
final CharacterMoveEvent evt = (CharacterMoveEvent) e;
|
final CharacterMoveEvent evt = (CharacterMoveEvent) e;
|
||||||
|
|||||||
Reference in New Issue
Block a user