ManagedWeakReference<SceneObject*> SceneObjectImplementation::getRootParent() {
	ManagedReference<SceneObject*> grandParent = getParent();
	ManagedReference<SceneObject*> tempParent = NULL;

	if (grandParent == NULL)
		return NULL;

#ifdef DEBUG_GETROOT_PARENT
	SortedVector<ManagedReference<SceneObject*> > parents;
	parents.setNoDuplicateInsertPlan();
#endif

	while ((tempParent = grandParent->getParent()) != NULL && grandParent != asSceneObject()) {
		grandParent = tempParent;

#ifdef DEBUG_GETROOT_PARENT
		if (parents.contains(grandParent))
			return NULL;
		else
			parents.put(grandParent);
#endif
	}

	if (grandParent == asSceneObject())
		return NULL;

	ManagedWeakReference<SceneObject*> weak = grandParent.get();

	return weak;
}
void SceneObjectImplementation::notifyLoadFromDatabase() {
	if (!containerObjects.hasDelayedLoadOperationMode()) {
		for (int i = 0; i < slottedObjects.size(); ++i) {
			ManagedReference<SceneObject* > obj = slottedObjects.get(i);

			if (obj->getParent().get() != asSceneObject()) {
				obj->setParent(asSceneObject());

				if (obj->isPlayerCreature())
					obj->setContainmentType(5);
				else
					obj->setContainmentType(4);
			}
		}

		for (int i = 0; i < containerObjects.size(); ++i) {
			ManagedReference<SceneObject* > obj = containerObjects.get(i);

			if (obj->getParent() != asSceneObject()) {
				obj->setParent(asSceneObject());
				obj->setContainmentType(-1);
			}
		}

	}

	if (zone != NULL) {
		zone->transferObject(asSceneObject(), -1, true);
	}
}
void SceneObjectImplementation::sendAttributeListTo(CreatureObject* object) {

	AttributeListMessage* alm = new AttributeListMessage(asSceneObject());

	try {

		attributeListComponent->fillAttributeList(alm, object, asSceneObject());

	} catch (Exception& e) {
		error(e.getMessage());
		e.printStackTrace();

		delete alm;
		alm = NULL;
	} catch (...) {
		delete alm;
		alm = NULL;

		throw;
	}

	if (alm != NULL)
		alm->insertInt(0xFFFFFFFF);
		object->sendMessage(alm);
}
void SceneObjectImplementation::notifyPositionUpdate(QuadTreeEntry* entry) {
	if (entry == NULL || asSceneObject() == entry)
		return;

	//#ifdef WITH_STM
	notifyObservers(ObserverEventType::OBJECTINRANGEMOVED, entry);
	//#else

	//Core::getTaskManager()->executeTask(new PositionUpdateTask(asSceneObject(), entry));
	//#endif

	zoneComponent->notifyPositionUpdate(asSceneObject(), entry);
}
void SceneObjectImplementation::updateDirection(float angleHeadingRadians) {
	setDirection(angleHeadingRadians);

	++movementCounter;

	if (parent.get() != NULL) {
		DataTransformWithParent* pack = new DataTransformWithParent(asSceneObject());
		broadcastMessage(pack, true, true);
	} else {
		DataTransform* pack = new DataTransform(asSceneObject());
		broadcastMessage(pack, true, true);
	}
}
void SceneObjectImplementation::sendTo(SceneObject* player, bool doClose) {
	if (isStaticObject() || !sendToClient || player->getClient() == NULL)
		return;

	/*StringBuffer msgInfo;
	if (parent != NULL)
		msgInfo << "with parent " << getParent()->getLoggingName() << " ";
	msgInfo << "sending 0x" << hex << getClientObjectCRC() << " to " << player->getLoggingName();
	info(msgInfo.toString(), true);*/

	BaseMessage* msg = new SceneObjectCreateMessage(asSceneObject());
	player->sendMessage(msg);

	if (parent.get() != NULL)
		link(player, containmentType);

	try {
		sendBaselinesTo(player);

		sendContainerObjectsTo(player);

		sendSlottedObjectsTo(player);
	} catch (Exception& e) {
		error(e.getMessage());
		e.printStackTrace();
	}

	if (doClose) {
		SceneObjectImplementation::close(player);
	}
}
void SceneObjectImplementation::initializeTransientMembers() {
	ManagedObjectImplementation::initializeTransientMembers();

	// FIXME: temp hack
	server = Core::lookupObject<ZoneProcessServer>("ZoneProcessServer").get();

	templateObject = TemplateManager::instance()->getTemplate(serverObjectCRC);

	if (templateObject != NULL) {
		containerComponent = cast<ContainerComponent*>(templateObject->getContainerComponent());

		String zoneComponentClassName = templateObject->getZoneComponent();
		zoneComponent = ComponentManager::instance()->getComponent<ZoneComponent*>(zoneComponentClassName);

		if (zoneComponent == NULL) {
			zoneComponent = ComponentManager::instance()->getComponent<ZoneComponent*>("ZoneComponent");
		}

		objectMenuComponent = cast<ObjectMenuComponent*>(templateObject->getObjectMenuComponent());
	}

	if(dataObjectComponent != NULL) {
		dataObjectComponent->setParent(asSceneObject());
		dataObjectComponent->initializeTransientMembers();
	}

	movementCounter = 0;

	setGlobalLogging(true);
	setLogging(false);

	setLoggingName("SceneObject");
}
void SceneObjectImplementation::playEffect(const String& file,
		const String& aux) {
	PlayClientEffectObjectMessage* effect = new PlayClientEffectObjectMessage(
			asSceneObject(), file, aux);

	broadcastMessage(effect, true);
}
int SceneObjectImplementation::inRangeObjects(unsigned int gameObjectType, float range) {
	if (getZone() == NULL)
		return 0;

	int numberOfObjects = 0;

	SortedVector<ManagedReference<QuadTreeEntry*> > closeSceneObjects;
	int maxInRangeObjectCount = 0;

	if (closeobjects == NULL) {
		info("Null closeobjects vector in SceneObjectImplementation::inRangeObjects", true);
		zone->getInRangeObjects(getPositionX(), getPositionY(), range, &closeSceneObjects, true);

		maxInRangeObjectCount = closeSceneObjects.size();
	} else
		maxInRangeObjectCount = closeobjects->size();

	for (int i = 0; i < maxInRangeObjectCount; ++i) {
		SceneObject* scno;

		if (closeobjects != NULL)
			scno = static_cast<SceneObject*>(closeobjects->get(i).get());
		else
			scno = static_cast<SceneObject*>(closeSceneObjects.get(i).get());

		if (scno->isInRange(asSceneObject(), range) && scno->getGameObjectType() == gameObjectType)
			++numberOfObjects;
	}

	return numberOfObjects;
}
Reference<SceneObject*> SceneObjectImplementation::getCraftedComponentsSatchel() {
    
	Reference<SceneObject*> sceno = asSceneObject();
	if (sceno == NULL)
		return NULL;

	Reference<ZoneServer*> zServer = getZoneServer();

	if(zServer == NULL)
		return NULL;
	
	ManagedReference<SceneObject*> craftingComponents = sceno->getSlottedObject("crafted_components");
	ManagedReference<SceneObject*> craftingComponentsSatchel = NULL;
	
    
	if(craftingComponents == NULL) {

		/// Add Components to crafted object
		String craftingComponentsPath = "object/tangible/crafting/crafting_components_container.iff";
		craftingComponents = zServer->createObject(craftingComponentsPath.hashCode(), 1);

		Locker componentsLocker(craftingComponents);
		
		craftingComponents->setSendToClient(false);
		sceno->transferObject(craftingComponents, 4, false);

		craftingComponents->setContainerDefaultDenyPermission(ContainerPermissions::OPEN + ContainerPermissions::MOVEIN + ContainerPermissions::MOVEOUT + ContainerPermissions::MOVECONTAINER);
		craftingComponents->setContainerDefaultAllowPermission(0);
		craftingComponents->setContainerDenyPermission("owner", ContainerPermissions::OPEN + ContainerPermissions::MOVEIN + ContainerPermissions::MOVEOUT + ContainerPermissions::MOVECONTAINER);
		craftingComponents->setContainerDenyPermission("admin", ContainerPermissions::OPEN + ContainerPermissions::MOVEIN + ContainerPermissions::MOVEOUT + ContainerPermissions::MOVECONTAINER);
		craftingComponents->setContainerAllowPermission("owner", 0);
		craftingComponents->setContainerAllowPermission("admin", 0);
		craftingComponents->setContainerInheritPermissionsFromParent(false);

		//String craftingComponentsSatchelPath = "object/tangible/container/base/base_container_volume.iff";
		String craftingComponentsSatchelPath = "object/tangible/hopper/crafting_station_hopper/crafting_station_ingredient_hopper_large.iff";
		craftingComponentsSatchel = zServer->createObject(craftingComponentsSatchelPath.hashCode(), 1);

		Locker satchelLocker(craftingComponentsSatchel, craftingComponents);
		
		craftingComponentsSatchel->setContainerInheritPermissionsFromParent(false);
		craftingComponentsSatchel->setContainerDefaultDenyPermission(ContainerPermissions::OPEN + ContainerPermissions::MOVEIN + ContainerPermissions::MOVEOUT + ContainerPermissions::MOVECONTAINER);
		craftingComponentsSatchel->setContainerDefaultAllowPermission(0);
		craftingComponentsSatchel->setContainerAllowPermission("admin", ContainerPermissions::OPEN);
		craftingComponentsSatchel->setContainerDenyPermission("admin", ContainerPermissions::MOVEIN + ContainerPermissions::MOVEOUT + ContainerPermissions::MOVECONTAINER);
		craftingComponentsSatchel->setContainerAllowPermission("owner", 0);
		craftingComponentsSatchel->setContainerDenyPermission("owner", ContainerPermissions::OPEN + ContainerPermissions::MOVEIN + ContainerPermissions::MOVEOUT + ContainerPermissions::MOVECONTAINER);

		craftingComponents->transferObject(craftingComponentsSatchel, -1, false);

	} else {
		craftingComponentsSatchel = craftingComponents->getContainerObject(0);
	}
	
	return craftingComponentsSatchel;
}
void SceneObjectImplementation::sendWithoutParentTo(SceneObject* player) {
	BaseMessage* msg = new SceneObjectCreateMessage(asSceneObject());
	player->sendMessage(msg);

	sendBaselinesTo(player);

	sendSlottedObjectsTo(player);
	sendContainerObjectsTo(player);

	SceneObjectImplementation::close(player);
}
void SceneObjectImplementation::sendDestroyTo(SceneObject* player) {
	if (staticObject)
		return;

	/*StringBuffer msg;
	msg << "sending destroy to " << player->getLoggingName();
	info(msg.toString(), true);*/

	BaseMessage* msg = new SceneObjectDestroyMessage(asSceneObject());
	player->sendMessage(msg);
}
ManagedWeakReference<SceneObject*> SceneObjectImplementation::getParent() {
	Locker locker(&parentLock);

	ManagedReference<QuadTreeEntry*> parent = this->parent.get();

	if (parent == NULL)
		return NULL;

	assert(parent != asSceneObject());

	return ManagedWeakReference<SceneObject*>(parent.castTo<SceneObject*>());
}
void SceneObjectImplementation::destroyObjectFromDatabase(bool destroyContainedObjects) {
	//info("deleting from database", true);

	if (isPlayerCreature()) {
		assert(0 && "attempting to delete a player creature from database");
	}

	if(dataObjectComponent != NULL) {
		dataObjectComponent->notifyObjectDestroyingFromDatabase();
	}

	ZoneServer* server = getZoneServer();

	server->destroyObjectFromDatabase(getObjectID());

	asSceneObject()->setPersistent(0);

	if (!destroyContainedObjects)
		return;

	SortedVector<ManagedReference<SceneObject*> > destroyedObjects;
	destroyedObjects.setNoDuplicateInsertPlan();

	for (int i = 0; i < getSlottedObjectsSize(); ++i) {
		ManagedReference<SceneObject*> object = getSlottedObject(i);

		if (destroyedObjects.put(object) != -1) {
			Locker locker(object);
			object->destroyObjectFromDatabase(true);
		}
	}

	for (int j = 0; j < getContainerObjectsSize(); ++j) {
		ManagedReference<SceneObject*> object = getContainerObject(j);

		if (destroyedObjects.put(object) != -1) {
			Locker locker(object);
			object->destroyObjectFromDatabase(true);
		}
	}

	//Remove all child objects from database
	for (int i = 0; i < childObjects.size(); ++i) {
		ManagedReference<SceneObject*> child = childObjects.get(i);

		if (child == NULL)
			continue;

		Locker locker(child);

		child->destroyObjectFromDatabase(true);
	}
}
ManagedWeakReference<SceneObject*> SceneObjectImplementation::getParentRecursively(uint32 gameObjectType) {
	ManagedReference<SceneObject*> temp = getParent();

	if (temp == NULL)
		return NULL;

	if (temp->getGameObjectType() == gameObjectType)
		return temp.get();

	while ((temp = temp->getParent()) != NULL && temp != asSceneObject()) {
		if (temp->getGameObjectType() == gameObjectType) {
			ManagedWeakReference<SceneObject*> weak = temp.get();

			return weak;
		}
	}

	if (temp == asSceneObject())
		return NULL;

	return NULL;
}
void SceneObjectImplementation::sendWithoutContainerObjectsTo(SceneObject* player) {
	if (isStaticObject() || !sendToClient)
		return;

	BaseMessage* msg = new SceneObjectCreateMessage(asSceneObject());
	player->sendMessage(msg);

	if (parent.get() != NULL)
		link(player, containmentType);

	sendBaselinesTo(player);

	SceneObjectImplementation::close(player);
}
void SceneObjectImplementation::destroyChildObjects() {
	int size = childObjects.size();

	for (int i = 0; i < size; i++) {
		ManagedReference<SceneObject*> child = childObjects.get(0);

		if (child == NULL)
			continue;

		Locker clocker(child, asSceneObject());

		childObjects.drop(child);
		child->destroyObjectFromDatabase(true);
		child->destroyObjectFromWorld(true);
	}
}
void SceneObjectImplementation::broadcastMessages(Vector<BasePacket*>* messages, bool sendSelf) {
	SceneObject* selfObject = sendSelf ? NULL : asSceneObject();

	broadcastMessagesPrivate(messages, selfObject);
}
void SceneObjectImplementation::close(SceneObject* client) {
	BaseMessage* msg = new SceneObjectCloseMessage(asSceneObject());

	client->sendMessage(msg);
}
void SceneObjectImplementation::broadcastDestroy(SceneObject* object, bool sendSelf) {
	SceneObject* selfObject = sendSelf ? NULL : asSceneObject();
	broadcastDestroyPrivate(object, selfObject);
}
void SceneObjectImplementation::broadcastMessage(BasePacket* message, bool sendSelf, bool lockZone) {
	SceneObject* selfObject = sendSelf ? NULL : asSceneObject();

	broadcastMessagePrivate(message, selfObject, lockZone);
}
void SceneObjectImplementation::notifyRemoveFromZone() {
	zoneComponent->notifyRemoveFromZone(asSceneObject());
}
void SceneObjectImplementation::switchZone(const String& newTerrainName, float newPostionX, float newPositionZ, float newPositionY, uint64 parentID, bool toggleInvisibility) {
	zoneComponent->switchZone(asSceneObject(), newTerrainName, newPostionX, newPositionZ, newPositionY, parentID, toggleInvisibility);
}
bool SceneObjectImplementation::transferObject(SceneObject* object, int containmentType, bool notifyClient, bool allowOverflow, bool notifyRoot) {
	return containerComponent->transferObject(asSceneObject(), object, containmentType, notifyClient, allowOverflow, notifyRoot);
}
int SceneObjectImplementation::canAddObject(SceneObject* object, int containmentType, String& errorDescription) {
	return containerComponent->canAddObject(asSceneObject(), object, containmentType, errorDescription);
}
bool SceneObjectImplementation::removeObject(SceneObject* object, SceneObject* destination, bool notifyClient) {
	return containerComponent->removeObject(asSceneObject(), object, destination, notifyClient);
}
void SceneObjectImplementation::openContainerTo(CreatureObject* player) {
	ClientOpenContainerMessage* cont = new ClientOpenContainerMessage(asSceneObject());
	player->sendMessage(cont);

	sendContainerObjectsTo(player);
}
void SceneObjectImplementation::closeContainerTo(CreatureObject* player, bool notify) {
	if (notify) {
		ClientOpenContainerMessage* cont = new ClientOpenContainerMessage(asSceneObject(), true);
		player->sendMessage(cont);
	}
}
uint64 SceneObjectImplementation::getObjectID() {
	return asSceneObject()->_getObjectID();
}
void SceneObjectImplementation::link(SceneObject* client, uint32 containmentType) {
	BaseMessage* msg = new UpdateContainmentMessage(asSceneObject(), getParent().get(), containmentType);
	client->sendMessage(msg);
}