Exemplo n.º 1
0
void ZoneComponent::destroyObjectFromWorld(SceneObject* sceneObject, bool sendSelfDestroy) {
	ManagedReference<SceneObject*> par = sceneObject->getParent();

	sceneObject->broadcastDestroy(sceneObject, sendSelfDestroy);

	ManagedReference<Zone*> rootZone = sceneObject->getZone();
	ManagedReference<Zone*> zone = sceneObject->getLocalZone();

	if (par != NULL) {
		uint64 parentID = sceneObject->getParentID();
		par->removeObject(sceneObject, NULL, false);

		if (par->isCellObject()) {
			ManagedReference<BuildingObject*> build = cast<BuildingObject*>(par->getParent().get().get());

			if (build != NULL) {
				CreatureObject* creature = cast<CreatureObject*>(sceneObject);

				if (creature != NULL)
					build->onExit(creature, parentID);
			}
		}

		sceneObject->notifyObservers(ObserverEventType::OBJECTREMOVEDFROMZONE, sceneObject, 0);
	} else if (zone != NULL) {
		zone->removeObject(sceneObject, NULL, false);
	}

	if (rootZone != NULL) {
		Locker locker(rootZone);

		if (!sceneObject->isActiveArea())
			rootZone->remove(sceneObject);
			
		rootZone->dropSceneObject(sceneObject);

		SharedBuildingObjectTemplate* objtemplate = dynamic_cast<SharedBuildingObjectTemplate*>(sceneObject->getObjectTemplate());

		if (objtemplate != NULL) {
			String modFile = objtemplate->getTerrainModificationFile();

			if (!modFile.isEmpty()) {
				rootZone->getPlanetManager()->getTerrainManager()->removeTerrainModification(sceneObject->getObjectID());
			}
		}
		
		locker.release();


		SortedVector<ManagedReference<QuadTreeEntry*> > closeSceneObjects;

		CloseObjectsVector* closeobjects = (CloseObjectsVector*) sceneObject->getCloseObjects();

		if (closeobjects != NULL) {
			try {
				closeobjects->safeCopyTo(closeSceneObjects);

				while (closeSceneObjects.size() > 0) {
					ManagedReference<QuadTreeEntry*> obj = closeSceneObjects.get(0);

					if (obj != NULL && obj != sceneObject && obj->getCloseObjects() != NULL)
						obj->removeInRangeObject(sceneObject);
					
					sceneObject->removeInRangeObject((int) 0);

					closeSceneObjects.remove((int) 0);
				}

				closeobjects->removeAll();

			} catch (...) {
			}
		} else {
			SortedVector<ManagedReference<QuadTreeEntry*> > closeSceneObjects;

			sceneObject->info("Null closeobjects vector in ZoneComponent::destroyObjectFromWorld", true);

			rootZone->getInRangeObjects(sceneObject->getPositionX(), sceneObject->getPositionY(), 512, &closeSceneObjects, false);

			for (int i = 0; i < closeSceneObjects.size(); ++i) {
				QuadTreeEntry* obj = closeSceneObjects.get(i);

				if (obj != sceneObject && obj->getCloseObjects() != NULL)
					obj->removeInRangeObject(sceneObject);
			}
		}

//		rootZone->dropSceneObject(sceneObject);

//		locker.release();

		Vector<ManagedReference<ActiveArea*> >* activeAreas =  sceneObject->getActiveAreas();

		while (activeAreas->size() > 0) {
			Locker _alocker(sceneObject->getContainerLock());
			ManagedReference<ActiveArea*> area = activeAreas->get(0);
			activeAreas->remove(0);
			
			_alocker.release();
			
			area->enqueueExitEvent(sceneObject);
		}
	}
}
bool ZoneContainerComponent::removeObject(SceneObject* sceneObject, SceneObject* object, SceneObject* destination, bool notifyClient) {
	Zone* zone = dynamic_cast<Zone*>(sceneObject);

	if (object->isActiveArea())
		return removeActiveArea(zone, dynamic_cast<ActiveArea*>(object));

	ManagedReference<SceneObject*> parent = object->getParent();
	//SortedVector<ManagedReference<SceneObject*> >* notifiedSentObjects = sceneObject->getNotifiedSentObjects();

	try {
		Locker locker(object);

		if (zone == NULL)
			return false;

		object->info("removing from zone");

		Locker zoneLocker(zone);

		if (parent != NULL) {
			parent->removeObject(object, NULL, false);
		} else
			zone->remove(object);
			
		Zone* oldZone = zone;
			
//		oldZone->dropSceneObject(object);
		
//		zoneLocker.release();

		SortedVector<ManagedReference<QuadTreeEntry*> >* closeObjects = object->getCloseObjects();

		if (closeObjects != NULL) {
			try {
				while (closeObjects->size() > 0) {
					ManagedReference<QuadTreeEntry*> obj = closeObjects->get(0);

					if (obj != NULL && obj != object && obj->getCloseObjects() != NULL)
						obj->removeInRangeObject(object);

					object->removeInRangeObject((int) 0);
				}
			} catch (...) {
			}
		} else {
			object->info("Null closeobjects vector in ZoneContainerComponent::removeObject", true);
			SortedVector<ManagedReference<QuadTreeEntry*> > closeSceneObjects;

			zone->getInRangeObjects(object->getPositionX(), object->getPositionY(), 512, &closeSceneObjects, false);

			for (int i = 0; i < closeSceneObjects.size(); ++i) {
				QuadTreeEntry* obj = closeSceneObjects.get(i);

				if (obj != NULL && obj != object && obj->getCloseObjects() != NULL)
					obj->removeInRangeObject(object);
			}
		}

//		Zone* oldZone = zone;
		zone = NULL;

		oldZone->dropSceneObject(object);

		SharedBuildingObjectTemplate* objtemplate = dynamic_cast<SharedBuildingObjectTemplate*>(object->getObjectTemplate());

		if (objtemplate != NULL) {
			String modFile = objtemplate->getTerrainModificationFile();

			if (!modFile.isEmpty()) {
				oldZone->getPlanetManager()->getTerrainManager()->removeTerrainModification(object->getObjectID());
			}
		}

		zoneLocker.release();

		if (object->isTangibleObject()) {
			TangibleObject* tano = cast<TangibleObject*>(object);
			Vector<ManagedReference<ActiveArea*> >* activeAreas = tano->getActiveAreas();

			while (activeAreas->size() > 0) {
				Locker _alocker(object->getContainerLock());

				ManagedReference<ActiveArea*> area = activeAreas->get(0);
				activeAreas->remove(0);

				_alocker.release();

				area->enqueueExitEvent(object);
			}
		}

		SortedVector<ManagedReference<SceneObject*> >* childObjects = object->getChildObjects();

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

			if (outdoorChild == NULL)
				continue;

			if (outdoorChild->isInQuadTree()) {
				Locker locker(outdoorChild);

				outdoorChild->destroyObjectFromWorld(true);
			}
		}

	} catch (Exception& e) {

	}

	object->notifyObservers(ObserverEventType::OBJECTREMOVEDFROMZONE, NULL, 0);

	VectorMap<uint32, ManagedReference<Facade*> >* objectActiveSessions = object->getObjectActiveSessions();

	while (objectActiveSessions->size()) {
		ManagedReference<Facade*> facade = objectActiveSessions->remove(0).getValue();

		if (facade == NULL)
			continue;

		facade->cancelSession();
	}

	//activeAreas.removeAll();

	object->info("removed from zone");

	object->notifyRemoveFromZone();

	object->setZone(NULL);

	return true;
}
void ZoneImplementation::updateActiveAreas(TangibleObject* tano) {
	//Locker locker(_this.getReferenceUnsafeStaticCast());

	Locker _alocker(tano->getContainerLock());

	SortedVector<ManagedReference<ActiveArea* > > areas = *dynamic_cast<SortedVector<ManagedReference<ActiveArea* > >* >(tano->getActiveAreas());

	_alocker.release();

	Vector3 worldPos = tano->getWorldPosition();

	SortedVector<ManagedReference<QuadTreeEntry*> > entryObjects;

	Zone* managedRef = _this.getReferenceUnsafeStaticCast();

	bool readlock = !managedRef->isLockedByCurrentThread();

	managedRef->rlock(readlock);

	try {
		regionTree->inRange(worldPos.getX(), worldPos.getY(), entryObjects);
	} catch (...) {
		error("unexpeted error caught in void ZoneImplementation::updateActiveAreas(SceneObject* object) {");
	}

	managedRef->runlock(readlock);

	//locker.release();


	managedRef->unlock(!readlock);

	try {

		// update old ones
		for (int i = 0; i < areas.size(); ++i) {
			ManagedReference<ActiveArea*> area = areas.get(i);
//			Locker lockerO(object);

//			Locker locker(area, object);

			if (!area->containsPoint(worldPos.getX(), worldPos.getY(), tano->getParentID())) {
				tano->dropActiveArea(area);
				area->enqueueExitEvent(tano);
//				area->notifyExit(object);
			} else {
				area->notifyPositionUpdate(tano);
			}
		}

		// we update the ones in quadtree.
		for (int i = 0; i < entryObjects.size(); ++i) {
			//update in new ones
			ActiveArea* activeArea = dynamic_cast<ActiveArea*>(entryObjects.get(i).get());

			if (!tano->hasActiveArea(activeArea) && activeArea->containsPoint(worldPos.getX(), worldPos.getY(), tano->getParentID())) {
				//Locker lockerO(object);

				//Locker locker(activeArea, object);

				tano->addActiveArea(activeArea);
				activeArea->enqueueEnterEvent(tano);
				//activeArea->notifyEnter(object);
			}
		}

		// update world areas
		if (creatureManager != NULL) {
			Vector<ManagedReference<SpawnArea*> >* worldAreas = creatureManager->getWorldSpawnAreas();

			if (worldAreas != NULL) {
				for (int i = 0; i < worldAreas->size(); ++i) {
					ActiveArea* activeArea = worldAreas->get(i);
					Locker lockerO(tano);

					//			Locker locker(activeArea, object);

					if (!tano->hasActiveArea(activeArea)) {
						tano->addActiveArea(activeArea);
						//activeArea->enqueueEnterEvent(object);
						activeArea->notifyEnter(tano);
					} else {
						activeArea->notifyPositionUpdate(tano);
					}
				}
			}
		}
	} catch (...) {
		error("unexpected exception caught in void ZoneImplementation::updateActiveAreas(SceneObject* object) {");
		managedRef->wlock(!readlock);
		throw;
	}

	managedRef->wlock(!readlock);
}