diff --git a/src/resources/containers/ContainerResult.java b/src/resources/containers/ContainerResult.java new file mode 100644 index 000000000..48ec3ec0c --- /dev/null +++ b/src/resources/containers/ContainerResult.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2015 /// Project SWG /// www.projectswg.com + * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. + * Our goal is to create an emulator which will provide a server for players to + * continue playing a game similar to the one they used to play. We are basing + * it on the final publish of the game prior to end-game events. + * + * This file is part of Holocore. + * + * -------------------------------------------------------------------------------- + * + * Holocore is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Holocore 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Holocore. If not, see + ******************************************************************************/ + +package resources.containers; + +public enum ContainerResult { + SLOT_OCCUPIED, + SLOT_NO_EXIST, + CONTAINER_FULL, + NO_PERMISSION, + SUCCESS +} diff --git a/src/resources/objects/SWGObject.java b/src/resources/objects/SWGObject.java index e1bd9823a..e810365a8 100644 --- a/src/resources/objects/SWGObject.java +++ b/src/resources/objects/SWGObject.java @@ -43,12 +43,12 @@ import network.packets.swg.zone.baselines.Baseline.BaselineType; import network.packets.swg.zone.object_controller.DataTransform; import resources.Location; import resources.common.CRC; +import resources.containers.ContainerResult; import resources.encodables.Stf; import resources.network.BaselineBuilder; import resources.network.DeltaBuilder; import resources.player.Player; import resources.player.PlayerState; -import resources.server_info.Log; import utilities.Encoder.StringType; public class SWGObject implements Serializable, Comparable { @@ -103,13 +103,13 @@ public class SWGObject implements Serializable, Comparable { * Adds the specified object to this object and places it in the appropriate slot if needed * @param object */ - public void addObject(SWGObject object) { + public boolean addObject(SWGObject object) { // If the arrangement is -1, then this object will be a contained object int arrangementId = getArrangementId(object); if (arrangementId == -1) { containedObjects.put(object.getObjectId(), object); object.parent = this; - return; + return true; } // Not a child object, so time to check the slots! @@ -117,7 +117,7 @@ public class SWGObject implements Serializable, Comparable { List requiredSlots = object.getArrangement().get(arrangementId - 4); // Note that some objects don't have a descriptor, meaning it has no slots if (descriptor != null && !descriptor.containsAll(requiredSlots)) - return; + return false; // Add object to the slot for (String requiredSlot : requiredSlots) { @@ -126,6 +126,7 @@ public class SWGObject implements Serializable, Comparable { object.parent = this; object.slotArrangement = arrangementId; + return true; } /** @@ -153,9 +154,38 @@ public class SWGObject implements Serializable, Comparable { * Moves the current object to the target object * @param requester Object that is requesting to move the object, used for permission checking * @param container Where this object should be moved to + * @return {@link ContainerResult} */ - public void moveToContainer(SWGObject requester, SWGObject container) { - // Before doing anything, get a list of the observers so we can send create/destroy/update messages + public ContainerResult moveToContainer(SWGObject requester, SWGObject container) { + // TODO ContainerPermission check + + // Check if object can fit into container or slots + int arrangementId = container.getArrangementId(this); + if (arrangementId == -1) { + // Item is going to go into the container, so check to see if it'll fit + if (container.getMaxContainerSize() >= container.getContainedObjects().size()) + return ContainerResult.CONTAINER_FULL; + } else { + List requiredSlots = getArrangement().get(arrangementId - 4); + if (!container.getAvailableSlots().containsAll(requiredSlots)) + return ContainerResult.SLOT_NO_EXIST; + else { + // Check to see if any of the required slots are occupied + int emptySlots = 0; + for (Map.Entry entry : container.getSlots().entrySet()) { + if (emptySlots == requiredSlots.size()) + break; + + if (requiredSlots.contains(entry.getKey()) && entry.getValue() == null) + emptySlots++; + } + + if (emptySlots != requiredSlots.size()) + return ContainerResult.SLOT_OCCUPIED; + } + } + + // Get a pre-parent-removal list of the observers so we can send create/destroy/update messages List oldObservers = getObjectsAware(); // Remove this object from the old parent if one exists @@ -165,33 +195,10 @@ public class SWGObject implements Serializable, Comparable { container.addObject(this); - List newObservers = new ArrayList<>(container.getObjectsAware()); - - List same = new ArrayList<>(oldObservers); - same.retainAll(newObservers); - - List added = new ArrayList<>(newObservers); - added.removeAll(oldObservers); - - List removed = new ArrayList<>(oldObservers); - removed.removeAll(newObservers); - - for (SWGObject swgObject : same) { - swgObject.sendSelf(new UpdateContainmentMessage(objectId, parent.getObjectId(), slotArrangement)); - } - - for (SWGObject swgObject : added) { - if (swgObject.getOwner() != null) { - createObject(swgObject.getOwner()); - } - } - - for (SWGObject swgObject : removed) { - if (swgObject.getOwner() != null) { - sendSceneDestroyObject(swgObject.getOwner()); - } - } + // Observer notification + sendUpdatedContainment(oldObservers, new ArrayList<>(container.getObjectsAware())); + return ContainerResult.SUCCESS; } public void addAttribute(String attribute, String value) { @@ -298,7 +305,6 @@ public class SWGObject implements Serializable, Comparable { if (owner != null) return owner; - // TODO getOwner() should also search for the "master" container that has a PlayerObject if (getParent() != null) return getParent().getOwner(); // Ziggy: Player owner is found recursively @@ -429,7 +435,6 @@ public class SWGObject implements Serializable, Comparable { create.setLocation(location); create.setObjectCrc(crc); target.sendPacket(create); - // TODO: Move this to createChildrenObjects? if (parent != null) target.sendPacket(new UpdateContainmentMessage(objectId, parent.getObjectId(), slotArrangement)); @@ -516,7 +521,34 @@ public class SWGObject implements Serializable, Comparable { if (owner != null) owner.sendPacket(packets); } - + + private void sendUpdatedContainment(List oldObservers, List newObservers) { + List same = new ArrayList<>(oldObservers); + same.retainAll(newObservers); + + List added = new ArrayList<>(newObservers); + added.removeAll(oldObservers); + + List removed = new ArrayList<>(oldObservers); + removed.removeAll(newObservers); + + for (SWGObject swgObject : same) { + swgObject.sendSelf(new UpdateContainmentMessage(objectId, parent.getObjectId(), slotArrangement)); + } + + for (SWGObject swgObject : added) { + if (swgObject.getOwner() != null) { + createObject(swgObject.getOwner()); + } + } + + for (SWGObject swgObject : removed) { + if (swgObject.getOwner() != null) { + sendSceneDestroyObject(swgObject.getOwner()); + } + } + } + public void updateObjectAwareness(List withinRange) { synchronized (objectsAware) { List outOfRange = new ArrayList(objectsAware); diff --git a/src/services/objects/ObjectManager.java b/src/services/objects/ObjectManager.java index 6f9c35a2e..1f1398ee0 100644 --- a/src/services/objects/ObjectManager.java +++ b/src/services/objects/ObjectManager.java @@ -222,18 +222,6 @@ public class ObjectManager extends Manager { if (obj == null) return null; objectAwareness.remove(obj); - -/* for (Slot slot : obj.getSlots()) { - if (slot != null) { - if (slot instanceof Container) { - for (SWGObject child : ((Container) slot).getContainedObjects()) { - deleteObject(child.getObjectId()); - } - } - if (slot.getObject() != null) - deleteObject(slot.getObject().getObjectId()); - } - }*/ Log.i("ObjectManager", "Deleted object %d [%s]", obj.getObjectId(), obj.getTemplate()); return obj; } @@ -249,20 +237,15 @@ public class ObjectManager extends Manager { long objId = object.getObjectId(); -/* Collection slots = object.getSlots(); - synchronized (slots) { - for (Slot slot : slots) { - if (slot != null) { - if (slot instanceof Container) { - for (SWGObject child : ((Container) slot).getContainedObjects()) { - deleteObject(child.getObjectId()); - } - } - if (slot.getObject() != null) - deleteObject(slot.getObject().getObjectId()); - } - } - }*/ + for (SWGObject slottedObj : object.getSlots().values()) { + if (slottedObj != null) + destroyObject(slottedObj); + } + + for (SWGObject containedObj : object.getContainedObjects()) { + if (containedObj != null) + destroyObject(containedObj); + } // Remove object from the parent SWGObject parent = object.getParent(); @@ -270,7 +253,7 @@ public class ObjectManager extends Manager { if (parent instanceof CreatureObject) { ((CreatureObject) parent).removeEquipment(object); } - //parent.removeChild(object); + parent.removeObject(object); } object.sendObservers(new SceneDestroyObject(objId));