diff --git a/scripts/commands/generic/transferItemMisc.py b/scripts/commands/generic/transferItemMisc.py index de1b8aaf5..1b13ef7eb 100644 --- a/scripts/commands/generic/transferItemMisc.py +++ b/scripts/commands/generic/transferItemMisc.py @@ -2,18 +2,21 @@ import sys def execute(galacticManager, player, target, args): actor = player.getCreatureObject() - argsSplit = args.split(" ") - objManager = galacticManager.getObjectManager(); - containerId = long(args[1]) - containerObject = objManager.getObjectById(containerId) # Ziggy: The target container + if actor is None or target is None: + return + inventory = actor.getSlottedObject("inventory") - - if target.getParent().equals(actor) or not containerObject.equals(inventory): # Ziggy: We're already wearing this item, transfer it to the container - containerObject.addChild(target) - elif containerObject.equals(inventory): # We're transfering this item to our inventory but we don't want to equip it - containerObject.addChild(target) - else: # Ziggy: This is an item in our inventory that we want to equip - actor.equipItem(target) - - return - \ No newline at end of file + + if inventory is None: + return + + if target.getParent() == actor: + actor.removeEquipment(target) + target.moveToContainer(actor, inventory) + return + else: + target.moveToContainer(actor, actor) + # actor.addEquipment(target) # This seems to crash the client, look to + return + + return \ No newline at end of file diff --git a/src/resources/objects/SWGObject.java b/src/resources/objects/SWGObject.java index d885200ce..e1bd9823a 100644 --- a/src/resources/objects/SWGObject.java +++ b/src/resources/objects/SWGObject.java @@ -30,14 +30,8 @@ package resources.objects; import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.LinkedList; +import java.util.*; import java.util.List; -import java.util.Map; -import java.util.Vector; import network.packets.Packet; import network.packets.swg.zone.SceneCreateObjectByCrc; @@ -54,21 +48,23 @@ 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 { private static final long serialVersionUID = 1L; - - private final List children; // TODO Move this into slot-type system as only containers can have multiple children in 1 slot + private final Location location; private final long objectId; - private final Map slots; // Can only be occupied one time, containers are slots who have children + private final HashMap slots; // HashMap used for null value support + private final Map containedObjects; private final Map attributes; private final Map templateAttributes; private transient List objectsAware; private List > arrangement; - + private List descriptor; // TODO Remove this as slots can be used? + private Player owner = null; private SWGObject parent = null; private Stf stf = new Stf("", ""); @@ -76,9 +72,12 @@ public class SWGObject implements Serializable, Comparable { private String template = ""; private int crc = 0; private String objectName = ""; - private int volume = 0; // applies to containers only + private int volume = 0; private float complexity = 1; - private int containmentType = 4; + private int containerType = 0; + + private int slotArrangement = -1; + private int transformCounter = 0; public SWGObject() { @@ -88,9 +87,9 @@ public class SWGObject implements Serializable, Comparable { public SWGObject(long objectId) { this.objectId = objectId; this.location = new Location(); - this.children = new Vector(); this.objectsAware = new Vector(); - this.slots = new HashMap(); // Concurrent maps wont allow for null keys/values, which is what the empty slots are set to :/ + this.slots = new HashMap<>(); + this.containedObjects = Collections.synchronizedMap(new HashMap()); this.attributes = new LinkedHashMap(); this.templateAttributes = new HashMap(); } @@ -99,115 +98,151 @@ public class SWGObject implements Serializable, Comparable { ois.defaultReadObject(); objectsAware = new LinkedList(); } - - // TODO: Use a "transfer" method for switching objects between parents, this will also check volume limits - public void addChild(SWGObject object) { - synchronized (children) { - if (!children.contains(object)) - children.add(object); - } - updateContainment(object); - } - - private void updateContainment(SWGObject child) { - if (child.parent != null) - child.parent.removeChild(child); // Is this necessary? - child.parent = this; - Integer containmentType = (Integer)child.getTemplateAttribute("containerType"); - if (containmentType == null) - child.containmentType = 4; - else - child.containmentType = containmentType; - // TODO: Set containmentType based on if object is in a slot (4) or a container (-1) - sendObserversAndSelf(new UpdateContainmentMessage(child.objectId, objectId, containmentType)); - } - - public void addAttribute(String attribute, String value) { - attributes.put(attribute, value); - } - - public void addObjectSlot(String name, SWGObject object) { - synchronized (slots) { - slots.put(name, object); - } - } - - public SWGObject getSlottedObject(String slot) { - if (!slots.containsKey(slot)) { - System.err.println(getTemplate() + " doesn't contain slot " + slot + "!"); - return null; - } - - return slots.get(slot); - } - - public boolean hasSlot(String slot) { - return slots.containsKey(slot); - } - // TODO Refactor slots to just be used in addChild and removeChild as the proper slots can be set by using arrangement descriptors - - public boolean setSlot(String slot, SWGObject obj) { - if (!slots.containsKey(slot)) { - System.err.println("Could not set " + obj.getTemplate() + " to " + getTemplate() + " as it doesn't contain slot " + slot + "!"); - return false; - } - - List occupiedAvailSlots = new ArrayList(); - List arrangement = obj.getArrangement().get(0); // We only care about the main list here, not the children lists - for (String occupies : arrangement) { - if (hasSlot(occupies)) - occupiedAvailSlots.add(slot); - else - break; - } - - if (occupiedAvailSlots.size() != arrangement.size()) { - System.err.println("Needed slots are not available for " + obj); - return false; - } - - for (String availSlot : occupiedAvailSlots) { - obj.setParent(this); - addObjectSlot(availSlot, obj); - sendObserversAndSelf(new UpdateContainmentMessage(obj.objectId, objectId, containmentType)); - } - - return true; - } - - private void clearSlot(String slot) { - if (!slots.containsKey(slot)) { - System.err.println("Could not clear " + slot + " as it doesn't contain that slot!"); + /** + * Adds the specified object to this object and places it in the appropriate slot if needed + * @param object + */ + public void 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; } - - synchronized(slots) { - slots.put(slot, null); - } - } - - // TODO: Use a "transfer" method for switching objects between parents, this will also check volume limits - public void removeChild(SWGObject object) { - synchronized (children) { - children.remove(object); + // Not a child object, so time to check the slots! + + // Check to make sure this object is able to go into a slot in the parent + 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; + + // Add object to the slot + for (String requiredSlot : requiredSlots) { + slots.put(requiredSlot, object); } - for (String slot : object.getArrangement().get(0)) { - clearSlot(slot); + object.parent = this; + object.slotArrangement = arrangementId; + } + + /** + * Removes the specified object from this current object. + * @param object Object to remove + */ + public void removeObject(SWGObject object) { + // This object is a container object, so remove it from the container + if (object.getSlotArrangement() == -1) { + containedObjects.remove(object.objectId); + object.parent = null; + return; + } + + for (String slot : (slotArrangement == -1 ? + object.getArrangement().get(0) : object.getArrangement().get(slotArrangement - 4))) { + slots.put(slot, null); } object.parent = null; + object.slotArrangement = -1; } - - public Map getSlots() { - return new HashMap(slots); + + /** + * 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 + */ + public void moveToContainer(SWGObject requester, SWGObject container) { + // Before doing anything, get a 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 + if (parent != null) { + parent.removeObject(this); + } + + 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()); + } + } + } - - public List getChildren() { - return new ArrayList(children); + + public void addAttribute(String attribute, String value) { + attributes.put(attribute, value); } - + + /** + * Gets the object that occupies the specified slot + * @param slotName + * @return The {@link SWGObject} occupying the slot. Returns null if there is nothing in the slot or it doesn't exist. + *

If the slot doesn't exist, then an error is printed as well.

+ */ + public SWGObject getSlottedObject(String slotName) { + if (hasSlot(slotName)) + return slots.get(slotName); + else { + System.err.println(this + " does not contain " + slotName); + return null; + } + } + + /** + * Gets the object in the container with the specified objectId + * @param objectId of the {@link SWGObject} to retrieve + * @return {@link SWGObject} with the specified objectId + */ + public SWGObject getContainedObject(long objectId) { + return containedObjects.get(objectId); + } + + /** + * Gets a list of all the objects in the current container. This should only be used for viewing the objects + * in the current container. + * @return An unmodifiable {@link Collection} of {@link SWGObject}'s in the container + */ + public Collection getContainedObjects() { + return Collections.unmodifiableCollection(containedObjects.values()); + } + + public boolean hasSlot(String slotName) { + return slots.containsKey(slotName); + } + + public List getAvailableSlots() { + return Collections.unmodifiableList(descriptor); + } + + public Map getSlots() { + return slots; + } + public void setOwner(Player player) { this.owner = player; } @@ -262,7 +297,8 @@ public class SWGObject implements Serializable, Comparable { public Player getOwner() { 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 @@ -312,7 +348,7 @@ public class SWGObject implements Serializable, Comparable { public Object getTemplateAttribute(String key) { return templateAttributes.get(key); } - + public void setTemplateAttribute(String key, Object value) { templateAttributes.put(key, value); } @@ -332,15 +368,70 @@ public class SWGObject implements Serializable, Comparable { public Map getAttributes() { return attributes; } - + + public int getContainerType() { + return containerType; + } + + public void setContainerType(int containerType) { + this.containerType = containerType; + } + + public int getSlotArrangement() { + return slotArrangement; + } + + public void setSlotArrangement(int slotArrangement) { + this.slotArrangement = slotArrangement; + } + + public int getMaxContainerSize() { + return Integer.valueOf(templateAttributes.get("containerVolumeLimit").toString()); + } + + /** + * Gets the arrangementId for the {@link SWGObject} for the current instance + * @param object + * @return Arrangement ID for the object + */ + public int getArrangementId(SWGObject object) { + if (object.getArrangement() == null) + return -1; + + int arrangementId = 4; + int filledId = -1; + + for (List arrangementList : object.getArrangement()) { + boolean passesCompletely = true; + boolean isValid = true; + for (String slot : arrangementList) { + if (!hasSlot(slot)) { + isValid = false; + break; + } + if (slots.get(slot) != null) { + passesCompletely = false; + } + } + if (isValid && passesCompletely) + return arrangementId; + else if (isValid) + filledId = arrangementId; + + arrangementId++; + } + return (filledId != -1) ? arrangementId : 4; + } + protected final void sendSceneCreateObject(Player target) { SceneCreateObjectByCrc create = new SceneCreateObjectByCrc(); create.setObjectId(objectId); create.setLocation(location); create.setObjectCrc(crc); target.sendPacket(create); + // TODO: Move this to createChildrenObjects? if (parent != null) - target.sendPacket(new UpdateContainmentMessage(objectId, parent.getObjectId(), containmentType)); + target.sendPacket(new UpdateContainmentMessage(objectId, parent.getObjectId(), slotArrangement)); } @@ -352,8 +443,7 @@ public class SWGObject implements Serializable, Comparable { protected void createObject(Player target) { sendSceneCreateObject(target); - //if (target.getCreatureObject().getOwner() == getOwner()) //TODO: Update for view permissions - createChildrenObjects(target); + createChildrenObjects(target); target.sendPacket(new SceneEndBaselines(getObjectId())); } @@ -370,15 +460,30 @@ public class SWGObject implements Serializable, Comparable { public List getObjectsAware() { synchronized (objectsAware) { - return Collections.unmodifiableList(objectsAware); + return Collections.unmodifiableList(getChildrenAwareness()); } } - + + private List getChildrenAwareness() { + List awareness = new ArrayList<>(objectsAware); + + if (getParent() != null && !(awareness.contains(getParent()))) + awareness.addAll(getParent().getObjectsAware()); + + if (getOwner() != null && getOwner().getCreatureObject() != null + && !(awareness.contains(getOwner().getCreatureObject()))) + awareness.add(getOwner().getCreatureObject()); + + // TODO Permission checking + + return awareness; + } + public void sendObserversAndSelf(Packet ... packets) { sendSelf(packets); sendObservers(packets); } - + public void sendObservers(Packet ... packets) { synchronized (objectsAware) { for (SWGObject obj : objectsAware) { @@ -387,12 +492,22 @@ public class SWGObject implements Serializable, Comparable { continue; p.sendPacket(packets); } - + + List childrenAwareness = getChildrenAwareness(); + childrenAwareness.removeAll(objectsAware); + childrenAwareness.remove(this); // Remove self since only observers being notified + + for (SWGObject childObserver : childrenAwareness) { + Player p = childObserver.getOwner(); + if (p == null || p.getPlayerState() != PlayerState.ZONED_IN) + continue; + p.sendPacket(packets); + } + SWGObject parent = getParent(); if(parent != null) parent.sendObservers(packets); - } } @@ -457,15 +572,18 @@ public class SWGObject implements Serializable, Comparable { } protected void createChildrenObjects(Player target) { - for (SWGObject child : children) { - child.createObject(target); + // TODO Permission check for the target + + // First create the objects in the slots + for (SWGObject slotObject : slots.values()) { + if (slotObject != null) + slotObject.createObject(target); } - // TODO: We will need permission checks here in the future which will create the object based on another players permissions to view that slot. - for (SWGObject slotEntry : slots.values()) { - if (slotEntry == null) - continue; - - slotEntry.createObject(target); + + // Now create the contained objects + for (SWGObject containedObject : containedObjects.values()) { + if (containedObject != null) + containedObject.createObject(target); } } diff --git a/src/resources/objects/buildouts/TerrainBuildoutLoader.java b/src/resources/objects/buildouts/TerrainBuildoutLoader.java index 358d44047..4bd383af1 100644 --- a/src/resources/objects/buildouts/TerrainBuildoutLoader.java +++ b/src/resources/objects/buildouts/TerrainBuildoutLoader.java @@ -95,13 +95,14 @@ class TerrainBuildoutLoader { } private void finalizeCells() { + // TODO This will need to be re-looked at since the slot update for (Entry > entry : buildingCells.entrySet()) { SWGObject building = objectTable.get(entry.getKey()); if (building == null) continue; List cells = entry.getValue(); for (CellObject cell : cells) { - building.addChild(cell); + building.addObject(cell); } cells.clear(); } @@ -178,6 +179,7 @@ class TerrainBuildoutLoader { } private void matchParent(SWGObject obj, long containerId) { + // TODO This will need to be relooked at since the slot update if (containerId == 0) { obj.setLocation(obj.getLocation().translate(areaLocation)); objects.add(obj); @@ -187,18 +189,19 @@ class TerrainBuildoutLoader { if (container == null) { parentless.add(new Orphan(obj, containerId)); } else { - container.addChild(obj); + container.addObject(obj); objects.add(obj); } } private void updateParentless() { + // TODO This will need to be relooked at since the slot update Iterator orphanIt = parentless.iterator(); while (orphanIt.hasNext()) { Orphan orphan = orphanIt.next(); SWGObject container = objectTable.get(orphan.getContainer()); if (container != null) { - container.addChild(orphan.getObject()); + container.addObject(orphan.getObject()); orphanIt.remove(); } } diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index f2a3c61f6..dd7167ef9 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -112,41 +112,6 @@ public class CreatureObject extends TangibleObject { initCurrentAttributes(); initBaseAttributes(); } - - /** - * It is only recommended that this method be used when you have - * an item and you won't know which slots it will occupy until you've - * looped through the arrangement list that resides within SWGObject. - * - * If you know the slot which your object is supposed to occupy, it's - * recommended that you instead use setSlot(), effectively skipping - * the process of looping. - * - * @param item to equip - */ - public void equipItem(TangibleObject item) { - equipItemToContainer(item, this); - } - - public void equipAppearanceItem(TangibleObject item) { - equipItemToContainer(item, super.getSlottedObject("appearance_inventory")); - } - - public void unequipAppearanceItem(TangibleObject item) { - unequipItemFromContainer(item, super.getSlottedObject("appearance_inventory")); - } - - private void equipItemToContainer(TangibleObject item, SWGObject container) { - for(List slotNameList : item.getArrangement()) - for(String slotName : slotNameList) - container.setSlot(slotName, item); - } - - private void unequipItemFromContainer(TangibleObject item, SWGObject container) { - for(List slotNameList : item.getArrangement()) - for(String slotName : slotNameList) - container.setSlot(slotName, null); - } public void removeEquipment(SWGObject obj) { synchronized (equipmentList) { @@ -171,7 +136,14 @@ public class CreatureObject extends TangibleObject { appearanceList.sendDeltaMessage(this); } } - + + public void removeAppearanceItem(SWGObject obj) { + synchronized (appearanceList) { + if (appearanceList.remove(obj)) + appearanceList.sendDeltaMessage(this); + } + } + public SWGList getEquipmentList() { return equipmentList; } diff --git a/src/services/objects/ObjectCreator.java b/src/services/objects/ObjectCreator.java index bbc130a2a..274cd117b 100644 --- a/src/services/objects/ObjectCreator.java +++ b/src/services/objects/ObjectCreator.java @@ -48,6 +48,7 @@ import resources.objects.staticobject.StaticObject; import resources.objects.tangible.TangibleObject; import resources.objects.waypoint.WaypointObject; import resources.objects.weapon.WeaponObject; +import resources.server_info.Log; public final class ObjectCreator { @@ -61,8 +62,9 @@ public final class ObjectCreator { SWGObject obj = createObjectFromType(objectId, getFirstTemplatePart(template.substring(7, template.length()-7-4))); if (obj == null) return null; - addObjectAttributes(obj, template); obj.setTemplate(template); + + handlePostCreation(obj); return obj; } @@ -85,10 +87,15 @@ public final class ObjectCreator { } return null; } - + + private static void handlePostCreation(SWGObject object) { + addObjectAttributes(object, object.getTemplate()); + createObjectSlots(object); + } + private static void addObjectAttributes(SWGObject obj, String template) { ObjectData attributes = (ObjectData) clientFac.getInfoFromFile(ClientFactory.formatToSharedFile(template)); - + String stf = (String) attributes.getAttribute(ObjectData.OBJ_STF); String detailStf = (String) attributes.getAttribute(ObjectData.DETAIL_STF); Integer volumeLimit = (Integer) attributes.getAttribute(ObjectData.VOLUME_LIMIT); @@ -100,28 +107,39 @@ public final class ObjectCreator { obj.setVolume(volumeLimit); for (Entry e : attributes.getAttributes().entrySet()) { obj.setTemplateAttribute(e.getKey(), e.getValue()); + + setObjectAttribute(e.getKey(), e.getValue().toString(), obj); } - - addSlotsToObject(obj, attributes); } - - private static void addSlotsToObject(SWGObject obj, ObjectData attributes) { - if (attributes.getAttribute(ObjectData.SLOT_DESCRIPTOR) != null) { + + private static void setObjectAttribute(String key, String value, SWGObject object) { + switch(key) { + case "volume": object.setVolume(Integer.valueOf(value)); break; + case "containerType": object.setContainerType(Integer.valueOf(value)); break; + default: break; + } + } + + private static void createObjectSlots(SWGObject object) { + if (object.getTemplateAttribute(ObjectData.SLOT_DESCRIPTOR) != null) { // These are the slots that the object *HAS* - SlotDescriptorData descriptor = (SlotDescriptorData) clientFac.getInfoFromFile((String) attributes.getAttribute(ObjectData.SLOT_DESCRIPTOR)); - + SlotDescriptorData descriptor = (SlotDescriptorData) clientFac.getInfoFromFile((String) object.getTemplateAttribute(ObjectData.SLOT_DESCRIPTOR)); + for (String slotName : descriptor.getSlots()) { - obj.addObjectSlot(slotName, null); + object.getSlots().put(slotName, null); } } - if (attributes.getAttribute(ObjectData.ARRANGEMENT_FILE) != null) { - // This is what slots the object *USES* - SlotArrangementData arrangementData = (SlotArrangementData) clientFac.getInfoFromFile((String) attributes.getAttribute(ObjectData.ARRANGEMENT_FILE)); - obj.setArrangement(arrangementData.getArrangement()); + if (object.getTemplateAttribute(ObjectData.ARRANGEMENT_FILE) != null) { + // This is what slots the created object is able to go into/use + SlotArrangementData arrangementData = (SlotArrangementData) clientFac.getInfoFromFile((String) object.getTemplateAttribute(ObjectData.ARRANGEMENT_FILE)); + object.setArrangement(arrangementData.getArrangement()); } } - + + /* + Misc helper methods + */ private static String getFirstTemplatePart(String template) { int ind = template.indexOf('/'); if (ind == -1) diff --git a/src/services/objects/ObjectManager.java b/src/services/objects/ObjectManager.java index 8b6f0fa05..6f9c35a2e 100644 --- a/src/services/objects/ObjectManager.java +++ b/src/services/objects/ObjectManager.java @@ -32,10 +32,7 @@ import intents.PlayerEventIntent; import intents.ZoneInIntent; import intents.network.GalacticPacketIntent; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import main.ProjectSWG; import network.packets.Packet; @@ -225,12 +222,18 @@ public class ObjectManager extends Manager { if (obj == null) return null; objectAwareness.remove(obj); - for (SWGObject child : obj.getChildren()) - if (child != null) - deleteObject(child.getObjectId()); - for (SWGObject slot : obj.getSlots().values()) - if (slot != null) - deleteObject(slot.getObjectId()); + +/* 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; } @@ -246,12 +249,20 @@ public class ObjectManager extends Manager { long objId = object.getObjectId(); - List children = object.getChildren(); - synchronized (children) { - for (SWGObject child : children) { - destroyObject(child.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()); + } } - } + }*/ // Remove object from the parent SWGObject parent = object.getParent(); @@ -259,7 +270,7 @@ public class ObjectManager extends Manager { if (parent instanceof CreatureObject) { ((CreatureObject) parent).removeEquipment(object); } - parent.removeChild(object); + //parent.removeChild(object); } object.sendObservers(new SceneDestroyObject(objId)); diff --git a/src/services/player/ZoneService.java b/src/services/player/ZoneService.java index a49be8601..ebfb3da9f 100644 --- a/src/services/player/ZoneService.java +++ b/src/services/player/ZoneService.java @@ -404,7 +404,7 @@ public class ZoneService extends Service { creatureObj.setVolume(0x000F4240); creatureObj.setOwner(player); - creatureObj.setSlot("ghost", playerObj); + creatureObj.addObject(playerObj); // ghost slot playerObj.setAdminTag(player.getAccessLevel()); playerObj.setOwner(player); player.setCreatureObject(creatureObj); @@ -438,7 +438,7 @@ public class ZoneService extends Service { TangibleObject hairObj = createTangible(objManager, ClientFactory.formatToSharedFile(hair)); hairObj.setAppearanceData(customization); - creatureObj.setSlot("hair", hairObj); + creatureObj.addObject(hairObj); // slot = hair creatureObj.addEquipment(hairObj); } @@ -453,9 +453,10 @@ public class ZoneService extends Service { creatureObj.setName(create.getName()); creatureObj.setPvpType(20); creatureObj.getSkills().add("species_" + creatureObj.getRace().getSpecies()); - creatureObj.setSlot("inventory", inventory); - creatureObj.setSlot("datapad", datapad); - creatureObj.setSlot("appearance_inventory", apprncInventory); + + creatureObj.addObject(inventory); // slot = inventory + creatureObj.addObject(datapad); // slot = datapad + creatureObj.addObject(apprncInventory); // slot = appearance_inventory creatureObj.addEquipment(inventory); creatureObj.addEquipment(datapad); @@ -475,9 +476,13 @@ public class ZoneService extends Service { private void createStarterClothing(ObjectManager objManager, CreatureObject player, String race, String profession) { if (player.getSlottedObject("inventory") == null) return; - - for (String template : profTemplates.get(profession).getItems(ClientFactory.formatToSharedFile(race))) - player.equipItem(createTangible(objManager, template)); + + for (String template : profTemplates.get(profession).getItems(ClientFactory.formatToSharedFile(race))) { + TangibleObject item = createTangible(objManager, template); + // Move the new item to the player's clothing slots and add to equipment list + item.moveToContainer(player, player); + player.addEquipment(item); + } }