void ObjectController::destroyObject(uint64 objectId)
{
    PlayerObject*	playerObject	= dynamic_cast<PlayerObject*>(mObject);
    Datapad*		datapad			= dynamic_cast<Datapad*>(playerObject->getEquipManager()->getEquippedObject(CreatureEquipSlot_Datapad));
    Object*			object			= gWorldManager->getObjectById(objectId);

    //could be a schematic!
    ManufacturingSchematic* schem	= datapad->getManufacturingSchematicById(objectId);

    if(schem != NULL)
    {
        //delete schematic
        datapad->removeManufacturingSchematic(objectId);

        //delete schematic object
        gObjectFactory->deleteObjectFromDB(schem);
        gMessageLib->sendDestroyObject(objectId,playerObject);

        return;
    }

    // could be a waypoint
    if(object == NULL)
    {
        object = datapad->getWaypointById(objectId);
    }

    // or something else
    if(object == NULL)
    {
        gLogger->logMsgF("ObjController::destroyObject: could not find object %"PRIu64"",MSG_NORMAL,objectId);

        return;
    }

    // waypoint
    if(object->getType() == ObjType_Waypoint)
    {
        // update our datapad
        if(!(datapad->removeWaypoint(objectId)))
        {
            gLogger->logMsgF("ObjController::handleDestroyObject: Error removing Waypoint from datapad %"PRIu64"",MSG_NORMAL,objectId);
        }

        gMessageLib->sendUpdateWaypoint(dynamic_cast<WaypointObject*>(object),ObjectUpdateDelete,playerObject);

        // delete from db
        gObjectFactory->deleteObjectFromDB(object);

        delete(object);
    }

    //Inangible Objects
    if(object->getType() == ObjType_Intangible)
    {
        //update the datapad
        if(!(datapad->removeData(objectId)))
        {
            gLogger->logMsgF("ObjController::handleDestroyObject: Error removing Data from datapad %"PRIu64"",MSG_NORMAL,objectId);
        }

        if(Vehicle* vehicle = dynamic_cast<Vehicle*>(object))
        {
            vehicle->store();
        }

        gObjectFactory->deleteObjectFromDB(object);
        gMessageLib->sendDestroyObject(objectId,playerObject);

    }


    // tangible
    else if(object->getType() == ObjType_Tangible)
    {
        TangibleObject* tangibleObject = dynamic_cast<TangibleObject*>(object);

        // items
        if(Item* item = dynamic_cast<Item*>(tangibleObject))
        {
            // Does the item have a owner?
            /*
            if (item->getOwner() != 0)
            {
            	gLogger->logMsgF("ObjController::handleDestroyObject: OwnerId = %"PRIu64", playerId = %"PRIu64"", MSG_NORMAL, item->getOwner(), playerObject->getId());
            	// Yes, is it my item?
            	if (item->getOwner() != playerObject->getId())
            	{
            		// Not allowed to delete this item.
            		gMessageLib->sendSystemMessage(playerObject,L"","error_message","insufficient_permissions");
            		return;
            	}
            }
            */

            // handle any family specifics
            switch(item->getItemFamily())
            {
            case ItemFamily_CraftingTools:
                _handleDestroyCraftingTool(dynamic_cast<CraftingTool*>(item));
                break;
            case ItemFamily_Instrument:
                _handleDestroyInstrument(item);
                break;

            default:
                break;
            }

            // destroy it for the player
            gMessageLib->sendDestroyObject(objectId,playerObject);

            // Also update the world...if the object is not private.
            if ((item->getParentId() != playerObject->getId()) && (item->getParentId() != dynamic_cast<Inventory*>(playerObject->getEquipManager()->getEquippedObject(CreatureEquipSlot_Inventory))->getId()))
            {
                PlayerObjectSet* inRangePlayers	= playerObject->getKnownPlayers();
                PlayerObjectSet::iterator it = inRangePlayers->begin();
                while(it != inRangePlayers->end())
                {
                    PlayerObject* targetObject = (*it);
                    gMessageLib->sendDestroyObject(tangibleObject->getId(),targetObject);
                    targetObject->removeKnownObject(tangibleObject);
                    ++it;
                }
                tangibleObject->destroyKnownObjects();
            }

            // update the equiplist, if its an equipable item
            CreatureObject* creature = dynamic_cast<CreatureObject*>(gWorldManager->getObjectById(item->getParentId()));
            if(creature)
            {
                // remove from creatures slotmap
                playerObject->getEquipManager()->removeEquippedObject(object);

                // send out the new equiplist
                gMessageLib->sendEquippedListUpdate_InRange(playerObject);

                // destroy it for players in range
                PlayerObjectSet* objList		= playerObject->getKnownPlayers();
                PlayerObjectSet::iterator it	= objList->begin();

                while(it != objList->end())
                {
                    gMessageLib->sendDestroyObject(objectId,(*it));

                    ++it;
                }
            }
        }
        else if(ResourceContainer* container = dynamic_cast<ResourceContainer*>(object))
        {
            //gLogger->logMsg("destroy ressourcecontainer");
            gMessageLib->sendDestroyObject(container->getId(),playerObject);
        }

        // reset pending ui callbacks
        playerObject->resetUICallbacks(object);

        // delete from db CAVE :: mark if its an Object saved in the db!!!!
        // temporary placed instruments are not saved in the db
        gObjectFactory->deleteObjectFromDB(object);

        // remove from inventory
        if(object->getParentId() == dynamic_cast<Inventory*>(playerObject->getEquipManager()->getEquippedObject(CreatureEquipSlot_Inventory))->getId())
        {
            dynamic_cast<Inventory*>(playerObject->getEquipManager()->getEquippedObject(CreatureEquipSlot_Inventory))->deleteObject(object);
        }
        // remove from world
        else
        {
            gWorldManager->destroyObject(object);
        }
    }
}
bool ObjectController::_destroyOutOfRangeObjects(ObjectSet *inRangeObjects)
{
	//TODO: when a container gets out of range
	//we need to destroy the children, too!!!!!!!

	// iterate our knowns
	PlayerObject*				player			= dynamic_cast<PlayerObject*>(mObject);
	ObjectSet*					knownObjects	= player->getKnownObjects();
	ObjectSet::iterator			objIt			= knownObjects->begin();
	PlayerObjectSet*			knownPlayers	= player->getKnownPlayers();
	PlayerObjectSet::iterator	playerIt		= knownPlayers->begin();

	const uint32 objectDestroyLimit = 5000;

	// update players
	while(playerIt != knownPlayers->end())
	{
		PlayerObject* playerObject = (*playerIt);

		// if its not in the current inrange queries result, destroy it
		if(inRangeObjects->find(playerObject) == inRangeObjects->end())
		{
			// send a destroy to us
			gMessageLib->sendDestroyObject(playerObject->getId(),player);

			//If player is mounted destroy his mount too
			if(playerObject->checkIfMounted() && playerObject->getMount())
			{
				gMessageLib->sendDestroyObject(playerObject->getMount()->getId(),player);
				
				player->removeKnownObject(playerObject->getMount());
				playerObject->getMount()->removeKnownObject(player);
				
			}

			//send a destroy to him
			gMessageLib->sendDestroyObject(player->getId(),playerObject);

			//If we're mounted destroy our mount too
			if(player->checkIfMounted() && playerObject->getMount())
			{
				gMessageLib->sendDestroyObject(player->getMount()->getId(),playerObject);
				playerObject->removeKnownObject(player->getMount());
				player->getMount()->removeKnownObject(playerObject);
				
			}

			// we don't know each other anymore
			knownPlayers->erase(playerIt++);
			playerObject->removeKnownObject(player);


			continue;
		}
		++playerIt;
	}

	// We may want to limit the amount of messages sent in one session.
	uint32 messageCount = 0;

	// update objects
	while(objIt != knownObjects->end())
	{
		Object* object = (*objIt);

		// if its not in the current inrange queries result, destroy it
		if(inRangeObjects->find(object) == inRangeObjects->end())
		{

			if(object->getType() == ObjType_Structure)
			{
				if(FactoryObject* factory = dynamic_cast<FactoryObject*>(object))
				{
					//delete the hoppers contents
					TangibleObject* hopper = dynamic_cast<TangibleObject*>(gWorldManager->getObjectById(factory->getIngredientHopper()));
					if(hopper)
					{
							ObjectIDList*			ol = hopper->getObjects();
							ObjectIDList::iterator	it = ol->begin();

							while(it != ol->end())
							{
								TangibleObject* tO = dynamic_cast<TangibleObject*>(gWorldManager->getObjectById((*it)));
								if(!tO)
								{
									assert(false && "ObjectController::_destroyOutOfRangeObjects WorldManager unable to find TangibleObject instance");
								}

								tO->removeKnownObject(player);
								player->removeKnownObject(tO);
								gMessageLib->sendDestroyObject(tO->getId(),player);
								it++;
							}
					
							hopper->removeKnownObject(player);
							player->removeKnownObject(hopper);
							
							gMessageLib->sendDestroyObject(hopper->getId(),player);					
					}

					hopper = dynamic_cast<TangibleObject*>(gWorldManager->getObjectById(factory->getOutputHopper()));
					if(hopper)
					{
							ObjectIDList*			ol = hopper->getObjects();
							ObjectIDList::iterator	it = ol->begin();

							while(it != ol->end())
							{
								TangibleObject* tO = dynamic_cast<TangibleObject*>(gWorldManager->getObjectById((*it)));
								if(!tO)
								{
									assert(false && "ObjectController::_destroyOutOfRangeObjects WorldManager unable to find TangibleObject instance");
								}

								//PlayerObject* player = dynamic_cast<PlayerObject*>(gWorldManager->getObjectById(targetObject->getId()));
								tO->removeKnownObject(player);
								player->removeKnownObject(tO);
								gMessageLib->sendDestroyObject(tO->getId(),player);
								
								it++;
							}
					
							hopper->removeKnownObject(player);
							player->removeKnownObject(hopper);
							gMessageLib->sendDestroyObject(hopper->getId(),player);					
					}

				}
			}
			// send a destroy to us
			gMessageLib->sendDestroyObject(object->getId(),player);

			// we don't know each other anymore
			knownObjects->erase(objIt++);
			object->removeKnownObject(player);

			if (++messageCount >= objectDestroyLimit)
			{
				// gLogger->logMsg("Pausing sendDestroyObject()-calls.");
				break;
			}
			continue;
		}

		++objIt;
	}
	// For test
	bool allDestroyed = false;
	if (objIt == knownObjects->end())
	{
		// gLogger->logMsg("Finished sendDestroyObject()-calls.");
		allDestroyed = true;
	}
	return allDestroyed;
}
bool ArtisanManager::handleRequestSurvey(Object* playerObject,Object* target,Message* message,ObjectControllerCmdProperties* cmdProperties)
{
    PlayerObject*		player = dynamic_cast<PlayerObject*>(playerObject);
    std::shared_ptr<SimpleEvent> start_survey_event = nullptr;

    if(cmdProperties)
        mSurveyMindCost = cmdProperties->mMindCost;

    // don't allow survey in buildings
    if(player->getParentId())
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_in_structure"), player);
        return false;
    }
    if(player->getPerformingState() != PlayerPerformance_None)
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "wrong_state"), player);
        return false;
    }
    if(player->getSurveyState())
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_cant"), player);
        return false;
    }
    if(player->getSamplingState())
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_sample"), player);
        return false;
    }

    SurveyTool*			tool			= dynamic_cast<SurveyTool*>(target);
    CurrentResource*	resource		= NULL;
    BString				resourceName;

    message->getStringUnicode16(resourceName);
    resourceName.convert(BSTRType_ANSI);

    resource = reinterpret_cast<CurrentResource*>(gResourceManager->getResourceByNameCRC(resourceName.getCrc()));

    if(tool && resource)
    {
        player->setSurveyState(true);

        // play effect
        std::string effect = gWorldManager->getClientEffect(tool->getInternalAttribute<uint32>("survey_effect"));
        gMessageLib->sendPlayClientEffectLocMessage(effect,player->mPosition,player);

        PlayerObjectSet*			playerList	= player->getKnownPlayers();
        PlayerObjectSet::iterator	it			= playerList->begin();

        while(it != playerList->end())
        {
            gMessageLib->sendPlayClientEffectLocMessage(effect,player->mPosition,(*it));

            ++it;
        }
        uint32 mindCost = mSurveyMindCost;
        Ham* hamz = player->getHam();
        //are we able to sample in the first place ??
        if(!hamz->checkMainPools(0,0,mindCost))
        {
            
            int32 myMind = hamz->mAction.getCurrentHitPoints();		
            
            //return message for sampling cancel based on HAM
            if(myMind < (int32)mindCost)
            {
                gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "sample_mind"), player);
            }

            //message for stop sampling
            gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "sample_cancel"), player);

            player->getSampleData()->mPendingSurvey = false;

            hamz->updateRegenRates();
            player->updateMovementProperties();
            return false;
        }

        hamz->performSpecialAction(0,0,(float)mindCost,HamProperty_CurrentHitpoints);
        // send system message
        resourceName.convert(BSTRType_Unicode16);
        gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "start_survey", L"", L"", resourceName.getUnicode16()), player);

        // schedule execution
        start_survey_event = std::make_shared<SimpleEvent>(EventType("start_survey"),0, 5000, 
            std::bind(&ArtisanManager::surveyEvent, this, player, resource, tool));
        
    }
    else
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("ui","survey_nothingfound"));
        return false;
    }
    // notify any listeners
    if (start_survey_event)
        gEventDispatcher.Notify(start_survey_event);
    return true;
}
bool ObjectController::_destroyOutOfRangeObjects(ObjectSet *inRangeObjects)
{
    //TODO: when a container gets out of range
    //we need to destroy the children, too!!!!!!!

    // iterate our knowns
    PlayerObject*				player			= dynamic_cast<PlayerObject*>(mObject);
    ObjectSet*					knownObjects	= player->getKnownObjects();
    ObjectSet::iterator			objIt			= knownObjects->begin();
    PlayerObjectSet*			knownPlayers	= player->getKnownPlayers();
    PlayerObjectSet::iterator	playerIt		= knownPlayers->begin();

    const uint32 objectDestroyLimit = 5000;

    // update players
    while(playerIt != knownPlayers->end())
    {
        PlayerObject* playerObject = (*playerIt);

        // if its not in the current inrange queries result, destroy it
        if(inRangeObjects->find(playerObject) == inRangeObjects->end())
        {
            // send a destroy to us
            gMessageLib->sendDestroyObject(playerObject->getId(),player);

            //If player is mounted destroy his mount too
            if(playerObject->checkIfMounted() && playerObject->getMount())
            {
                gMessageLib->sendDestroyObject(playerObject->getMount()->getId(),player);

                player->removeKnownObject(playerObject->getMount());
                playerObject->getMount()->removeKnownObject(player);

            }

            //send a destroy to him
            gMessageLib->sendDestroyObject(player->getId(),playerObject);

            //If we're mounted destroy our mount too
            if(player->checkIfMounted() && playerObject->getMount())
            {
                gMessageLib->sendDestroyObject(player->getMount()->getId(),playerObject);
                playerObject->removeKnownObject(player->getMount());
                player->getMount()->removeKnownObject(playerObject);

            }

            // we don't know each other anymore
            knownPlayers->erase(playerIt++);
            playerObject->removeKnownObject(player);


            continue;
        }
        ++playerIt;
    }

    // We may want to limit the amount of messages sent in one session.
    uint32 messageCount = 0;

    // update objects
    //for(ObjectSet::const_iterator	objIt	= knownObjects->begin(); objIt != knownObjects->end(); objIt++)

    //we access the list above so it needs to be reset to the beginning
    objIt		= knownObjects->begin();
    while(objIt != knownObjects->end())
    {
        Object* object = (*objIt);

        // if its not in the current inrange queries result, destroy it
        if(inRangeObjects->find(object) == inRangeObjects->end())
        {

            if(object->getType() == ObjType_Structure)//ObjType_Tangible
            {

            }
            // send a destroy to us
            gMessageLib->sendDestroyObject(object->getId(),player);

            // we don't know each other anymore
            knownObjects->erase(objIt++);
            object->removeKnownObject(player);

            if (++messageCount >= objectDestroyLimit)
            {
                break;
            }
            continue;
        }

        ++objIt;
    }
    // For test
    bool allDestroyed = false;
    if (objIt == knownObjects->end())
    {
        allDestroyed = true;
    }
    return allDestroyed;
}