oldObservers = getObjectsAware();
// Remove this object from the old parent if one exists
if (parent != null) {
parent.removeObject(this);
}
container.addObject(this);
// Observer notification
sendUpdatedContainment(oldObservers, new ArrayList<>(container.getObjectsAware()));
return ContainerResult.SUCCESS;
}
public boolean hasOwnerPermissions(SWGObject object) {
return (object.getObjectId() == containerPermissions.getOwner());
}
public boolean hasPermission(SWGObject object, ContainerPermissions.Permission... permissions) {
if (object == this || hasOwnerPermissions(object))
return true;
if (!containerPermissions.hasPermissions(String.valueOf(object.getObjectId()), permissions)) {
// Doesn't have any owner permissions or specific permissions, check to see if this object has an
// acceptable permission group with the specified permissions available.
for (String permissionGroup : object.containerPermissions.getPermissionGroups()) {
if (containerPermissions.hasPermissions(permissionGroup, permissions)) {
//System.out.println(object + " can view " + this);
return true;
}
}
return false;
}
else return true;
}
public void addPermissions(String group, ContainerPermissions.Permission... permissions) {
containerPermissions.addPermissions(group, permissions);
}
public void removePermissions(String group, ContainerPermissions.Permission... permissions) {
containerPermissions.removePermissions(group, permissions);
}
public void addPermissions(SWGObject permissionRequester, ContainerPermissions.Permission... permissions) {
addPermissions(String.valueOf(permissionRequester.getObjectId()), permissions);
}
public void removePermissions(SWGObject permissionRequester, ContainerPermissions.Permission... permissions) {
removePermissions(String.valueOf(permissionRequester.getObjectId()), permissions);
}
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 Map getSlots() {
return slots;
}
public void setOwner(Player player) {
this.owner = player;
}
public void setParent(SWGObject parent) {
this.parent = parent;
}
public void setLocation(Location l) {
if (l == null)
return;
location.mergeWith(l);
}
public void setLocation(double x, double y, double z) {
location.mergeLocation(x, y, z);
}
public void setStf(String stfFile, String stfKey) {
this.stf = new Stf(stfFile, stfKey);
}
public void setStf(String stf) {
this.stf = new Stf(stf);
}
public void setDetailStf(String stfFile, String stfKey) {
this.detailStf = new Stf(stfFile, stfKey);
}
public void setDetailStf(String stf) {
this.detailStf = new Stf(stf);
}
public void setTemplate(String template) {
this.template = template;
this.crc = CRC.getCrc(template);
}
public void setName(String name) {
this.objectName = name;
}
public void setVolume(int volume) {
this.volume = volume;
}
public void setComplexity(float complexity) {
this.complexity = complexity;
}
public Player getOwner() {
if (owner != null)
return owner;
if (getParent() != null)
return getParent().getOwner(); // Ziggy: Player owner is found recursively
return null;
}
public SWGObject getParent() {
return parent;
}
public Stf getStf() {
return stf;
}
public Stf getDetailStf() {
return detailStf;
}
public String getTemplate() {
return template;
}
public int getCrc() {
return crc;
}
public long getObjectId() {
return objectId;
}
public Location getLocation() {
return location;
}
public String getName() {
return objectName;
}
public int getVolume() {
return volume;
}
public float getComplexity() {
return complexity;
}
public Object getTemplateAttribute(String key) {
return templateAttributes.get(key);
}
public void setTemplateAttribute(String key, Object value) {
templateAttributes.put(key, value);
}
public List> getArrangement() {
return arrangement;
}
public void setArrangement(List> arrangement) {
this.arrangement = arrangement;
}
public String getAttribute(String attribute) {
return attributes.get(attribute);
}
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());
}
public ContainerPermissions getContainerPermissions() { return containerPermissions; }
/**
* 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);
if (parent != null)
target.sendPacket(new UpdateContainmentMessage(objectId, parent.getObjectId(), slotArrangement));
}
protected final void sendSceneDestroyObject(Player target) {
SceneDestroyObject destroy = new SceneDestroyObject();
destroy.setObjectId(objectId);
target.sendPacket(destroy);
}
protected void createObject(Player target) {
sendSceneCreateObject(target);
createChildrenObjects(target);
target.sendPacket(new SceneEndBaselines(getObjectId()));
}
public void clearAware() {
SWGObject [] objects;
synchronized (objectsAware) {
objects = objectsAware.toArray(new SWGObject[objectsAware.size()]);
}
for (SWGObject o : objects) {
o.awarenessOutOfRange(this);
awarenessOutOfRange(o);
}
}
public List getObjectsAware() {
synchronized (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());
return awareness;
}
public void sendObserversAndSelf(Packet ... packets) {
sendSelf(packets);
sendObservers(packets);
}
public void sendObservers(Packet ... packets) {
synchronized (objectsAware) {
for (SWGObject obj : objectsAware) {
Player p = obj.getOwner();
if (p == null || p.getPlayerState() != PlayerState.ZONED_IN)
continue;
p.sendPacket(packets);
}
List childrenAwareness = getChildrenAwareness();
childrenAwareness.removeAll(objectsAware);
childrenAwareness.remove(this); // Remove self since only observers being notified
for (SWGObject childObserver : childrenAwareness) {
if (childObserver == null)
continue;
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);
}
}
public void sendSelf(Packet ... packets) {
Player owner = getOwner();
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);
outOfRange.removeAll(withinRange);
for (SWGObject o : outOfRange)
awarenessOutOfRange(o);
for (SWGObject o : withinRange)
awarenessInRange(o);
}
}
private void awarenessOutOfRange(SWGObject o) {
synchronized (objectsAware) {
if (objectsAware.remove(o)) {
if (o.getOwner() != null) {
sendSceneDestroyObject(o.getOwner());
}
if (getOwner() != null)
o.awarenessOutOfRange(this);
}
}
}
private void awarenessInRange(SWGObject o) {
synchronized (objectsAware) {
if (!objectsAware.contains(o)) {
objectsAware.add(o);
if (o.getOwner() != null) {
createObject(o.getOwner());
}
if (getOwner() != null)
o.awarenessInRange(this);
}
}
}
public void sendDataTransforms(DataTransform dTransform) {
Location loc = dTransform.getLocation();
float speed = dTransform.getSpeed();
sendDataTransforms(loc, (byte) dTransform.getMovementAngle(), speed);
}
public void sendDataTransforms(Location loc, int direction, float speed) {
UpdateTransformsMessage transform = new UpdateTransformsMessage();
transform.setObjectId(getObjectId()); // (short) (xPosition * 4 + 0.5)
transform.setX((short) (loc.getX() * 4 + 0.5));
transform.setY((short) (loc.getY() * 4 + 0.5));
transform.setZ((short) (loc.getZ() * 4 + 0.5));
transform.setUpdateCounter(transformCounter++);
transform.setDirection((byte) direction);
transform.setSpeed(speed);
sendObserversAndSelf(transform);
}
protected void createChildrenObjects(Player target) {
if (!hasPermission(target.getCreatureObject(), ContainerPermissions.Permission.OPEN)) {
// System.out.println(target.getCreatureObject() + " doesn't have permission to view " + this + " -- skipping packet sending");
return;
}
// First create the objects in the slots
for (SWGObject slotObject : slots.values()) {
if (slotObject != null) {
// System.out.println("Sending slotObj " + slotObject + " to " + target);
slotObject.createObject(target);
}
}
// Now create the contained objects
for (SWGObject containedObject : containedObjects.values()) {
if (containedObject != null) {
// System.out.println("Sending containedObj " + containedObject + " to " + target);
containedObject.createObject(target);
}
}
}
@Override
public String toString() {
return "SWGObject[ID=" + objectId + " NAME=" + objectName + " TEMPLATE=" + template + "]";
}
@Override
public int compareTo(SWGObject obj) {
if (getObjectId() < obj.getObjectId())
return -1;
if (getObjectId() == obj.getObjectId())
return 0;
return 1;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof SWGObject))
return false;
return getObjectId() == ((SWGObject)o).getObjectId();
}
@Override
public int hashCode() {
return Long.valueOf(getObjectId()).hashCode();
}
public void createBaseline1(Player target, BaselineBuilder bb) {
}
public void createBaseline3(Player target, BaselineBuilder bb) {
bb.addFloat(complexity); // 0
bb.addObject(stf); // 1
bb.addUnicode(objectName); // custom name -- 2
bb.addInt(volume); // 3
bb.incrementOperandCount(4);
}
public void createBaseline4(Player target, BaselineBuilder bb) {
}
public void createBaseline6(Player target, BaselineBuilder bb) {
bb.addInt(target.galaxyId); // 0
bb.addObject(detailStf); // 1
bb.incrementOperandCount(2);
}
public void createBaseline7(Player target, BaselineBuilder bb) {
}
public void createBaseline8(Player target, BaselineBuilder bb) {
}
public void createBaseline9(Player target, BaselineBuilder bb) {
}
public void sendDelta(int type, int update, Object value) {
}
public final void sendDelta(BaselineType baseline, int type, int update, Object value) {
if (owner == null || (owner.getPlayerState() != PlayerState.ZONED_IN))
return;
DeltaBuilder builder = new DeltaBuilder(this, baseline, type, update, value);
builder.send();
}
public final void sendDelta(BaselineType baseline, int type, int update, Object value, StringType strType) {
if (owner == null || (owner.getPlayerState() != PlayerState.ZONED_IN))
return;
DeltaBuilder builder = new DeltaBuilder(this, baseline, type, update, value, strType);
builder.send();
}
/* Baseline send permissions based on packet observations:
*
* Baseline1 sent if you have full permissions to the object.
* Baseline4 sent if you have full permissions to the object.
*
* Baseline8 sent if you have some permissions to the object.
* Baseline9 sent if you have some permissions to the object.
*
* Baseline3 always sent.
* Baseline6 always sent.
*
* Baseline7 sent on using the object.
*
* Only sent if they are defined (can still be empty if defined).
*/
}