You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
255 lines
5.9 KiB
255 lines
5.9 KiB
14 years ago
|
/*==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/>.
|
||
|
|
||
|
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 = TRACKED_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
|
||
|
|
||
|
hsBool 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 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
|
||
|
}
|
||
|
|
||
|
|
||
|
hsBool 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 plRelevanceMgr::GetIndex(char *regionName)
|
||
|
{
|
||
|
int i;
|
||
|
for (i = 0; i < fRegions.GetCount(); i++)
|
||
|
{
|
||
|
if (fRegions[i] && !stricmp(regionName, fRegions[i]->GetKeyName()))
|
||
|
return i + 1;
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
void plRelevanceMgr::MarkRegion(UInt32 localIdx, UInt32 remoteIdx, hsBool doICare)
|
||
|
{
|
||
|
if (localIdx == (UInt32)-1 || remoteIdx == (UInt32)-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;
|
||
|
hsBool 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 = TRACKED_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];
|
||
|
}
|
||
|
|
||
|
std::string plRelevanceMgr::GetRegionNames(hsBitVector regions)
|
||
|
{
|
||
|
std::string retVal = "";
|
||
|
if (regions.IsBitSet(0))
|
||
|
retVal = "-Nowhere (0)-";
|
||
|
|
||
|
for (int i = 0; i < fRegions.GetCount(); ++i)
|
||
|
{
|
||
|
if (regions.IsBitSet(i + 1))
|
||
|
{
|
||
|
if (retVal.length() != 0)
|
||
|
retVal += ", ";
|
||
|
if (fRegions[i])
|
||
|
retVal += fRegions[i]->GetKeyName();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (retVal.length() == 0)
|
||
|
retVal = "<NONE>";
|
||
|
return retVal;
|
||
|
}
|