// NeL - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
#include "std3d.h"
#include "nel/3d/zone_manager.h"
#include "nel/misc/path.h"
#include "nel/misc/file.h"
using namespace std;
using namespace NLMISC;
namespace NL3D
{
// ------------------------------------------------------------------------------------------------
// CZoneManager
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
CZoneManager::CZoneManager()
{
_RemovingZone= false;
_ZoneTileColorMono = true;
_ZoneTileColorFactor = 1.0f;
_LastArea= 0;
_LastX= _LastY= std::numeric_limits::max();
}
// ------------------------------------------------------------------------------------------------
CZoneManager::~CZoneManager()
{
}
// ------------------------------------------------------------------------------------------------
uint CZoneManager::getNumZoneLeftToLoad ()
{
// Make a set of the loaded zone
set zoneLoaded;
uint32 i;
for (i = 0; i < _LoadedZones.size(); ++i)
{
zoneLoaded.insert (_LoadedZones[i]);
}
// Check for each zone in the list if they are loaded or not
uint zoneCount = 0;
for (i = 0; i < _ZoneList.size(); ++i)
{
if (zoneLoaded.find (_ZoneList[i]) == zoneLoaded.end ())
zoneCount++;
}
return zoneCount;
}
// ------------------------------------------------------------------------------------------------
void CZoneManager::checkZonesAround (uint x, uint y, uint area, const std::vector *validZoneIds)
{
if (_RemovingZone) return;
// Obtain the new set of zones around
if ( (x != _LastX) || (y != _LastY) || (area != _LastArea) )
getListZoneId (x, y, area, _ZoneList, validZoneIds);
_LastX = x;
_LastY = y;
_LastArea = area;
// **** Look if we have zone loaded that is not needed anymore
uint32 i, j;
for (i = 0; i < _LoadedZones.size(); ++i)
{
// If the loadedzone i do not appear in the zone list so we have to remove it
bool bFound = false;
uint16 nLoadedZone = _LoadedZones[i];
for (j = 0; j < _ZoneList.size(); ++j)
{
if (_ZoneList[j] == nLoadedZone)
{
bFound = true;
break;
}
}
if (!bFound)
{
// Remove the zone nLoadedZone
_IdZoneToRemove = nLoadedZone;
_RemovingZone = true;
return;
}
}
// **** Look if we have zone not already loaded
for (i = 0; i < _ZoneList.size(); ++i)
{
// If the zone requested appear in the zone loaded, we don't have to load it
bool bFound = false;
uint16 nZone = _ZoneList[i];
for (j = 0; j < _LoadedZones.size(); ++j)
{
if (_LoadedZones[j] == nZone)
{
bFound = true;
break;
}
}
// if the zone is not already loaded
if (!bFound)
{
// Already loading ?
std::list::iterator ite = _LoadingZones.begin ();
while (ite != _LoadingZones.end())
{
if (ite->ZoneToAddId == nZone)
break;
// Next loading zone
ite++;
}
// Not loading ?
if (ite == _LoadingZones.end())
{
// Add a new zone to load
_LoadingZones.push_back(CLoadingZone ());
CLoadingZone &newZone = _LoadingZones.back();
newZone.ZoneToAddName = getZoneNameFromId(nZone);
newZone.ZoneToAddId = nZone;
newZone.Zone = NULL;
// We have to load this zone. add a load task
CAsyncFileManager &rAFM = CAsyncFileManager::getInstance();
// Make a position
uint x, y;
getZonePos (newZone.ZoneToAddId, x, y);
CVector v = CVector ((float)x, -(float)y, 0);
rAFM.addTask (new CZoneLoadingTask(newZone.ZoneToAddName, &newZone.Zone, v, _ZoneTileColorMono, _ZoneTileColorFactor));
}
}
}
}
// ------------------------------------------------------------------------------------------------
bool CZoneManager::isWorkComplete (CZoneManager::SZoneManagerWork &rWork)
{
// Check if there is someting to add
std::list::iterator ite = _LoadingZones.begin ();
while (ite != _LoadingZones.end())
{
// Loaded ?
if (ite->Zone)
{
rWork.ZoneAdded = true;
rWork.NameZoneAdded = ite->ZoneToAddName;
rWork.ZoneRemoved = false;
rWork.IdZoneToRemove = 0;
rWork.NameZoneRemoved = "";
rWork.Zone = const_cast(ite->Zone);
_LoadedZones.push_back (ite->ZoneToAddId);
// Remove from loading zone
_LoadingZones.erase(ite);
return true;
}
// Next zone
ite++;
}
if (_RemovingZone)
{
_RemovingZone = false;
rWork.ZoneAdded = false;
rWork.NameZoneAdded = "";
rWork.ZoneRemoved = true;
rWork.IdZoneToRemove = _IdZoneToRemove;
rWork.NameZoneRemoved = getZoneNameFromId(_IdZoneToRemove);
uint32 i, j;
for (i = 0 ; i < _LoadedZones.size(); ++i)
if (_LoadedZones[i] == _IdZoneToRemove)
break;
if (i < _LoadedZones.size())
{
for (j = i; j < _LoadedZones.size()-1; ++j)
_LoadedZones[j] = _LoadedZones[j+1];
_LoadedZones.resize(_LoadedZones.size()-1);
}
rWork.Zone = NULL;
return true;
}
return false;
}
// ------------------------------------------------------------------------------------------------
void CZoneManager::clear()
{
nlassert(_LoadingZones.size() == 0);
_LoadedZones.clear();
_RemovingZone = false;
}
// ------------------------------------------------------------------------------------------------
// CZoneLoadingTask
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
CZoneLoadingTask::CZoneLoadingTask(const std::string &sZoneName, TVolatileZonePtr *ppZone, CVector &pos, bool monochrome, float factor)
{
*ppZone = NULL;
_Zone = ppZone;
_ZoneName = sZoneName;
Position = pos;
_Monochrome = monochrome;
_TileColorFactor = max(0.0f, factor);
}
// ------------------------------------------------------------------------------------------------
void CZoneLoadingTask::run(void)
{
// Lookup the zone
string zonePathLookup = CPath::lookup (_ZoneName, false, false, true);
if (zonePathLookup.empty())
zonePathLookup = _ZoneName;
CZone *ZoneTmp = new CZone;
CIFile file;
file.setAsyncLoading(true);
file.setCacheFileOnOpen(true);
if(file.open(zonePathLookup))
{
ZoneTmp->serial(file);
file.close();
ZoneTmp->setTileColor(_Monochrome, _TileColorFactor);
*_Zone = ZoneTmp;
}
else
{
//nldebug("CZoneLoadingTask::run(): File not found: %s", zonePathLookup.c_str ());
delete ZoneTmp;
*_Zone = (CZone*)-1; // Return error
}
delete this;
}
// ***************************************************************************
void CZoneLoadingTask::getName (std::string &result) const
{
result = "LoadZone(" + _ZoneName + ")";
}
// ***************************************************************************
CZoneLoadingTask::~CZoneLoadingTask()
{
}
} // NL3D