|
|
|
/*==LICENSE==*
|
|
|
|
|
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools
|
|
|
|
Copyright (C) 2011 Cyan Worlds, Inc.
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU 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 General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
Additional permissions under GNU GPL version 3 section 7
|
|
|
|
|
|
|
|
If you modify this Program, or any covered work, by linking or
|
|
|
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
|
|
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
|
|
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
|
|
|
(or a modified version of those libraries),
|
|
|
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
|
|
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
|
|
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
|
|
|
licensors of this Program grant you additional
|
|
|
|
permission to convey the resulting work. Corresponding Source for a
|
|
|
|
non-source form of such a combination shall include the source code for
|
|
|
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
|
|
|
work.
|
|
|
|
|
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|
|
|
or by snail mail at:
|
|
|
|
Cyan Worlds, Inc.
|
|
|
|
14617 N Newport Hwy
|
|
|
|
Mead, WA 99021
|
|
|
|
|
|
|
|
*==LICENSE==*/
|
|
|
|
#include "plRelevanceMgr.h"
|
|
|
|
#include "plRelevanceRegion.h"
|
|
|
|
#include "plIntersect/plRegionBase.h"
|
|
|
|
#include "hsStream.h"
|
|
|
|
#include "hsStringTokenizer.h"
|
|
|
|
|
|
|
|
plRelevanceMgr* plRelevanceMgr::fInstance = nil;
|
|
|
|
|
|
|
|
plRelevanceMgr::plRelevanceMgr() : fEnabled(true)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRelevanceMgr::Init()
|
|
|
|
{
|
|
|
|
fInstance = new plRelevanceMgr;
|
|
|
|
fInstance->RegisterAs(kRelevanceMgr_KEY);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRelevanceMgr::DeInit()
|
|
|
|
{
|
|
|
|
if (fInstance)
|
|
|
|
{
|
|
|
|
fInstance->UnRegisterAs(kRelevanceMgr_KEY);
|
|
|
|
fInstance = nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRelevanceMgr::IAddRegion(plRelevanceRegion *region)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int dstIdx = fRegions.GetCount();
|
|
|
|
for (i = 0; i < fRegions.GetCount(); i++)
|
|
|
|
{
|
|
|
|
if (fRegions[i] == nil)
|
|
|
|
{
|
|
|
|
dstIdx = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dstIdx == fRegions.GetCount())
|
|
|
|
fRegions.Append(region);
|
|
|
|
else
|
|
|
|
fRegions[i] = region;
|
|
|
|
|
|
|
|
region->SetMgrIndex(dstIdx + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRelevanceMgr::IRemoveRegion(plRelevanceRegion *region)
|
|
|
|
{
|
|
|
|
fRegions[region->fMgrIdx - 1] = nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRelevanceMgr::SetRegionVectors(const hsPoint3 &pos, hsBitVector ®ionsImIn, hsBitVector ®ionsICareAbout)
|
|
|
|
{
|
|
|
|
regionsImIn.Clear();
|
|
|
|
regionsICareAbout.Clear();
|
|
|
|
regionsICareAbout.SetBit(0, true); // Always care about region zero, the special "No region" node
|
|
|
|
|
|
|
|
bool inAnyRegion = false;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < fRegions.GetCount(); i++)
|
|
|
|
{
|
|
|
|
if (fRegions[i] && fRegions[i]->fRegion->IsInside(pos))
|
|
|
|
{
|
|
|
|
regionsImIn.SetBit(i + 1, true);
|
|
|
|
regionsICareAbout |= fRegions[i]->fRegionsICareAbout;
|
|
|
|
inAnyRegion = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If I'm not in any region, that means I'm in the special zero region and care about everything.
|
|
|
|
if (!inAnyRegion)
|
|
|
|
{
|
|
|
|
regionsImIn.SetBit(0, true);
|
|
|
|
regionsICareAbout.Set(fRegions.GetCount());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t plRelevanceMgr::GetNumRegions() const
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = fRegions.GetCount(); i > 0 && fRegions[i - 1] == nil; i--);
|
|
|
|
|
|
|
|
return i + 1; // Add 1 for the special zero-region
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool plRelevanceMgr::MsgReceive(plMessage* msg)
|
|
|
|
{
|
|
|
|
plGenRefMsg *genMsg = plGenRefMsg::ConvertNoRef(msg);
|
|
|
|
if (genMsg)
|
|
|
|
{
|
|
|
|
plRelevanceRegion *region = plRelevanceRegion::ConvertNoRef(genMsg->GetRef());
|
|
|
|
if( genMsg->GetContext() & (plRefMsg::kOnCreate) )
|
|
|
|
{
|
|
|
|
IAddRegion(region);
|
|
|
|
}
|
|
|
|
else if( genMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
|
|
|
|
{
|
|
|
|
IRemoveRegion(region);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hsKeyedObject::MsgReceive(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t plRelevanceMgr::GetIndex(const plString ®ionName)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < fRegions.GetCount(); i++)
|
|
|
|
{
|
|
|
|
if (fRegions[i] && !regionName.Compare(fRegions[i]->GetKeyName(), plString::kCaseInsensitive))
|
|
|
|
return i + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRelevanceMgr::MarkRegion(uint32_t localIdx, uint32_t remoteIdx, bool doICare)
|
|
|
|
{
|
|
|
|
if (localIdx == (uint32_t)-1 || remoteIdx == (uint32_t)-1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (localIdx - 1 >= fRegions.GetCount() || remoteIdx - 1 >= fRegions.GetCount() || fRegions[localIdx - 1] == nil)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fRegions[localIdx - 1]->fRegionsICareAbout.SetBit(remoteIdx, doICare);
|
|
|
|
}
|
|
|
|
|
|
|
|
// tiny class for the function below
|
|
|
|
class plRegionInfo
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
char *fName;
|
|
|
|
int fIndex;
|
|
|
|
|
|
|
|
plRegionInfo() : fName(nil), fIndex(-1) {}
|
|
|
|
~plRegionInfo() { delete [] fName; }
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function expects a CSV file representing the matrix
|
|
|
|
*
|
|
|
|
* name1 name2 name3
|
|
|
|
* name1 value value value
|
|
|
|
* name2 value value value
|
|
|
|
* name3 value value value
|
|
|
|
*
|
|
|
|
* where the value determines how much the that row's region cares about the region in the current column.
|
|
|
|
* (Currently, the possible values are:
|
|
|
|
* 0: Doesn't care
|
|
|
|
* 1 or greater: row cares about column
|
|
|
|
*/
|
|
|
|
void plRelevanceMgr::ParseCsvInput(hsStream *s)
|
|
|
|
{
|
|
|
|
const int kBufSize = 512;
|
|
|
|
char buff[kBufSize];
|
|
|
|
hsTArray<plRegionInfo*> regions;
|
|
|
|
hsStringTokenizer toke;
|
|
|
|
bool firstLine = true;
|
|
|
|
|
|
|
|
while (!s->AtEnd())
|
|
|
|
{
|
|
|
|
if (!s->ReadLn(buff, kBufSize))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (firstLine)
|
|
|
|
{
|
|
|
|
firstLine = false;
|
|
|
|
toke.Reset(buff, ",");
|
|
|
|
|
|
|
|
while (toke.Next(buff, kBufSize))
|
|
|
|
{
|
|
|
|
if (strcmp(buff, "") == 0)
|
|
|
|
continue; // ignore the initial blank one
|
|
|
|
|
|
|
|
plRegionInfo *info = new plRegionInfo;
|
|
|
|
regions.Append(info);
|
|
|
|
info->fName = hsStrcpy(buff);
|
|
|
|
info->fIndex = GetIndex(buff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else // parsing actual settings.
|
|
|
|
{
|
|
|
|
toke.Reset(buff, ",");
|
|
|
|
if (!toke.Next(buff, kBufSize))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
int rowIndex = GetIndex(buff);
|
|
|
|
int column = 0;
|
|
|
|
while (toke.Next(buff, kBufSize) && column < regions.GetCount())
|
|
|
|
{
|
|
|
|
int value = atoi(buff);
|
|
|
|
MarkRegion(rowIndex, regions[column]->fIndex, value != 0);
|
|
|
|
|
|
|
|
column++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for (i = regions.GetCount() - 1; i >= 0; i--)
|
|
|
|
delete regions[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
plString plRelevanceMgr::GetRegionNames(hsBitVector regions)
|
|
|
|
{
|
|
|
|
plString retVal;
|
|
|
|
if (regions.IsBitSet(0))
|
|
|
|
retVal = "-Nowhere (0)-";
|
|
|
|
|
|
|
|
for (int i = 0; i < fRegions.GetCount(); ++i)
|
|
|
|
{
|
|
|
|
if (regions.IsBitSet(i + 1))
|
|
|
|
{
|
|
|
|
if (!retVal.IsEmpty())
|
|
|
|
retVal += ", ";
|
|
|
|
if (fRegions[i])
|
|
|
|
retVal += fRegions[i]->GetKeyName();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retVal.IsEmpty())
|
|
|
|
retVal = "<NONE>";
|
|
|
|
return retVal;
|
|
|
|
}
|