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
/*==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; |
|
} |