mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 02:27:40 -04:00
Merge branch 'master' into ticket/11
This commit is contained in:
@ -424,6 +424,14 @@ bool plAnimStage::IMoveBackward(double time, float delta, float &overrun, plArma
|
||||
bool infiniteLoop = fLoops == -1;
|
||||
bool loopsRemain = fCurLoop > 0 || infiniteLoop;
|
||||
|
||||
// If we don't have this animation, just pretend to have worked.
|
||||
// Otherwise, we crash the client.
|
||||
if (!fAnimInstance)
|
||||
{
|
||||
hsAssert(false, "AnimInstance nil");
|
||||
return true;
|
||||
}
|
||||
|
||||
// This must be here before we set the local time.
|
||||
if (fAnimInstance->GetTimeConvert())
|
||||
fAnimInstance->GetTimeConvert()->Backwards();
|
||||
@ -476,6 +484,14 @@ bool plAnimStage::IMoveForward(double time, float delta, float &overrun, plArmat
|
||||
// first get the target time in local time, ignoring overruns
|
||||
float target = fLocalTime + delta;
|
||||
|
||||
// If we don't have this animation, just pretend to have worked.
|
||||
// Otherwise, we crash the client.
|
||||
if (!fAnimInstance)
|
||||
{
|
||||
hsAssert(false, "AnimInstance nil");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (fAnimInstance->GetTimeConvert())
|
||||
fAnimInstance->GetTimeConvert()->Forewards();
|
||||
|
||||
|
@ -1978,7 +1978,7 @@ hsBool plArmatureMod::IsLocalAvatar()
|
||||
return plAvatarMgr::GetInstance()->GetLocalAvatar() == this;
|
||||
}
|
||||
|
||||
hsBool plArmatureMod::IsLocalAI()
|
||||
hsBool plArmatureMod::IsLocalAI() const
|
||||
{
|
||||
plAvBrainCritter* ai = plAvBrainCritter::ConvertNoRef(FindBrainByClass(plAvBrainCritter::Index()));
|
||||
if (ai)
|
||||
|
@ -220,7 +220,7 @@ public:
|
||||
void GetPositionAndRotationSim(hsPoint3* position, hsQuat* rotation);
|
||||
|
||||
hsBool IsLocalAvatar();
|
||||
hsBool IsLocalAI();
|
||||
hsBool IsLocalAI() const;
|
||||
virtual const plSceneObject *FindBone(const char * name) const;
|
||||
virtual const plSceneObject *FindBone(UInt32 id) const; // use an id from an appropriate taxonomy, such as plAvBrainHuman::BoneID
|
||||
virtual void AddBoneMapping(UInt32 id, const plSceneObject *bone);
|
||||
|
@ -404,7 +404,7 @@ void hsInterp::GetBoundaryKeyFrames(hsScalar time, UInt32 numKeys, void *keys, U
|
||||
{
|
||||
hsAssert(numKeys>1, "Must have more than 1 keyframe");
|
||||
int k1, k2;
|
||||
UInt16 frame = (UInt16)(time * MAX_FRAMES_PER_SEC);
|
||||
float frame = (time * MAX_FRAMES_PER_SEC);
|
||||
|
||||
// boundary case, past end
|
||||
if (frame > GetKey(numKeys-1, keys, size)->fFrame)
|
||||
|
@ -557,8 +557,13 @@ hsScalar plAnimTimeConvert::WorldToAnimTime(double wSecs)
|
||||
{
|
||||
if (secs > fLoopEnd)
|
||||
{
|
||||
secs = fmodf(secs - fLoopBegin, fLoopEnd - fLoopBegin) + fLoopBegin;
|
||||
wrapped = true;
|
||||
float result = fmodf(secs - fLoopBegin, fLoopEnd - fLoopBegin) + fLoopBegin;
|
||||
// if fLoopBegin == fLoopEnd == 0, result will not be a number
|
||||
if (!_isnan(result))
|
||||
{
|
||||
secs = result;
|
||||
wrapped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -576,8 +581,13 @@ hsScalar plAnimTimeConvert::WorldToAnimTime(double wSecs)
|
||||
{
|
||||
if (secs < fLoopBegin)
|
||||
{
|
||||
secs = fLoopEnd - fmodf(fLoopEnd - secs, fLoopEnd - fLoopBegin);
|
||||
wrapped = true;
|
||||
float result = fLoopEnd - fmodf(fLoopEnd - secs, fLoopEnd - fLoopBegin);
|
||||
// if fLoopBegin == fLoopEnd == 0, result will not be a number
|
||||
if (!_isnan(result))
|
||||
{
|
||||
secs = result;
|
||||
wrapped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +61,9 @@ public:
|
||||
kUnRegisteredOwnedAge = plNetCommon::VaultTasks::kUnRegisterOwnedAge,
|
||||
kUnRegisteredVisitAge = plNetCommon::VaultTasks::kUnRegisterVisitAge,
|
||||
kPublicAgeCreated,
|
||||
kPublicAgeRemoved
|
||||
kPublicAgeRemoved,
|
||||
kRegisteredSubAgeLink,
|
||||
kRegisteredChildAgeLink,
|
||||
};
|
||||
|
||||
plVaultNotifyMsg();
|
||||
|
@ -279,3 +279,12 @@ void plLogicModifier::VolumeIgnoreExtraEnters(bool ignore /* = true */)
|
||||
condition->IgnoreExtraEnters(ignore);
|
||||
}
|
||||
}
|
||||
|
||||
void plLogicModifier::VolumeNoArbitration(bool noArbitration)
|
||||
{
|
||||
for (size_t i = 0; i < fConditionList.Count(); ++i) {
|
||||
plVolumeSensorConditionalObject* condition = plVolumeSensorConditionalObject::ConvertNoRef(fConditionList[i]);
|
||||
if (condition)
|
||||
condition->NoServerArbitration(noArbitration);
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ public:
|
||||
virtual void Reset(bool bCounterReset);
|
||||
|
||||
void VolumeIgnoreExtraEnters(bool ignore = true); // hack for garrison
|
||||
void VolumeNoArbitration(bool noArbitration = true);
|
||||
|
||||
int fMyCursor;
|
||||
};
|
||||
|
@ -84,6 +84,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
#include "../plMessage/plNetVoiceListMsg.h"
|
||||
#include "../plMessage/plNetCommMsgs.h"
|
||||
#include "../plMessage/plNetClientMgrMsg.h"
|
||||
#include "../plMessage/plVaultNotifyMsg.h"
|
||||
#include "../plResMgr/plKeyFinder.h"
|
||||
#include "../plResMgr/plPageInfo.h"
|
||||
#include "../plNetTransport/plNetTransportMember.h"
|
||||
@ -352,6 +353,9 @@ int plNetClientMgr::Init()
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plNetCommActivePlayerMsg::Index(), GetKey());
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plNetCommLinkToAgeMsg::Index(), GetKey());
|
||||
|
||||
// We need plVaultNotifyMsgs for the NetLinkingMgr
|
||||
plgDispatch::Dispatch()->RegisterForType(plVaultNotifyMsg::Index(), GetKey());
|
||||
|
||||
IInitNetClientComm();
|
||||
|
||||
return ret;
|
||||
|
@ -62,7 +62,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
#include "../plAvatar/plArmatureMod.h"
|
||||
#include "../plFile/hsFiles.h"
|
||||
#include "../plMessage/plNCAgeJoinerMsg.h"
|
||||
#include "../plVault/plVault.h"
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
@ -330,6 +329,13 @@ hsBool plNetLinkingMgr::MsgReceive( plMessage *msg )
|
||||
return true;
|
||||
}
|
||||
|
||||
// If a link was deferred in order to register an owned age, we will
|
||||
// get a VaultNotify about the registration
|
||||
if (plVaultNotifyMsg* vaultMsg = plVaultNotifyMsg::ConvertNoRef(msg)) {
|
||||
IProcessVaultNotifyMsg(vaultMsg);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -363,37 +369,19 @@ bool plNetLinkingMgr::IProcessLinkToAgeMsg( plLinkToAgeMsg * msg )
|
||||
GetPrevAgeLink()->CopyFrom( GetAgeLink() );
|
||||
GetAgeLink()->CopyFrom( msg->GetAgeLink() );
|
||||
|
||||
if ( IPreProcessLink() )
|
||||
// Actually do stuff...
|
||||
UInt8 pre = IPreProcessLink();
|
||||
if (pre == kLinkImmediately)
|
||||
{
|
||||
GetAgeLink()->SetSpawnPoint(msg->GetAgeLink()->SpawnPoint());
|
||||
|
||||
if (fLinkedIn) {
|
||||
// Set the link out animation we should use
|
||||
if (plSceneObject *localSO = plSceneObject::ConvertNoRef(nc->GetLocalPlayer())) {
|
||||
plArmatureMod *avMod = const_cast<plArmatureMod*>(plArmatureMod::ConvertNoRef(localSO->GetModifierByType(plArmatureMod::Index())));
|
||||
avMod->SetLinkInAnim(msg->GetLinkInAnimName());
|
||||
}
|
||||
// Queue leave op
|
||||
NlmLeaveAgeOp * leaveAgeOp = NEWZERO(NlmLeaveAgeOp);
|
||||
QueueOp(leaveAgeOp);
|
||||
}
|
||||
|
||||
// Queue join op
|
||||
NlmJoinAgeOp * joinAgeOp = NEWZERO(NlmJoinAgeOp);
|
||||
joinAgeOp->age.ageInstId = (Uuid) *GetAgeLink()->GetAgeInfo()->GetAgeInstanceGuid();
|
||||
StrCopy(
|
||||
joinAgeOp->age.ageDatasetName,
|
||||
GetAgeLink()->GetAgeInfo()->GetAgeFilename(),
|
||||
arrsize(joinAgeOp->age.ageDatasetName)
|
||||
);
|
||||
StrCopy(
|
||||
joinAgeOp->age.spawnPtName,
|
||||
GetAgeLink()->SpawnPoint().GetName(),
|
||||
arrsize(joinAgeOp->age.spawnPtName)
|
||||
);
|
||||
QueueOp(joinAgeOp);
|
||||
msg->Ref();
|
||||
IDoLink(msg);
|
||||
}
|
||||
else
|
||||
else if (pre == kLinkDeferred)
|
||||
{
|
||||
msg->Ref();
|
||||
fDeferredLink = msg;
|
||||
}
|
||||
else if (pre == kLinkFailed)
|
||||
{
|
||||
hsLogEntry( nc->ErrorMsg( "IPreProcessLink failed. Not linking." ) );
|
||||
// Restore previous age info state.
|
||||
@ -407,6 +395,43 @@ bool plNetLinkingMgr::IProcessLinkToAgeMsg( plLinkToAgeMsg * msg )
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
void plNetLinkingMgr::IDoLink(plLinkToAgeMsg* msg)
|
||||
{
|
||||
plNetClientMgr* nc = plNetClientMgr::GetInstance();
|
||||
GetAgeLink()->SetSpawnPoint(msg->GetAgeLink()->SpawnPoint());
|
||||
|
||||
if (fLinkedIn) {
|
||||
// Set the link out animation we should use
|
||||
if (plSceneObject *localSO = plSceneObject::ConvertNoRef(nc->GetLocalPlayer())) {
|
||||
plArmatureMod *avMod = const_cast<plArmatureMod*>(plArmatureMod::ConvertNoRef(localSO->GetModifierByType(plArmatureMod::Index())));
|
||||
avMod->SetLinkInAnim(msg->GetLinkInAnimName());
|
||||
}
|
||||
// Queue leave op
|
||||
NlmLeaveAgeOp * leaveAgeOp = NEWZERO(NlmLeaveAgeOp);
|
||||
QueueOp(leaveAgeOp);
|
||||
}
|
||||
|
||||
// Queue join op
|
||||
NlmJoinAgeOp * joinAgeOp = NEWZERO(NlmJoinAgeOp);
|
||||
joinAgeOp->age.ageInstId = (Uuid) *GetAgeLink()->GetAgeInfo()->GetAgeInstanceGuid();
|
||||
StrCopy(
|
||||
joinAgeOp->age.ageDatasetName,
|
||||
GetAgeLink()->GetAgeInfo()->GetAgeFilename(),
|
||||
arrsize(joinAgeOp->age.ageDatasetName)
|
||||
);
|
||||
StrCopy(
|
||||
joinAgeOp->age.spawnPtName,
|
||||
GetAgeLink()->SpawnPoint().GetName(),
|
||||
arrsize(joinAgeOp->age.spawnPtName)
|
||||
);
|
||||
QueueOp(joinAgeOp);
|
||||
|
||||
// UnRef
|
||||
msg->UnRef();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool plNetLinkingMgr::IProcessLinkingMgrMsg( plLinkingMgrMsg * msg )
|
||||
{
|
||||
plNetClientMgr * nc = plNetClientMgr::GetInstance();
|
||||
@ -458,6 +483,49 @@ bool plNetLinkingMgr::IProcessLinkingMgrMsg( plLinkingMgrMsg * msg )
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool plNetLinkingMgr::IProcessVaultNotifyMsg(plVaultNotifyMsg* msg)
|
||||
{
|
||||
// No deferred link? Bye bye.
|
||||
if (fDeferredLink == nil)
|
||||
return false;
|
||||
|
||||
plAgeLinkStruct* cur = GetAgeLink();
|
||||
RelVaultNode* cVaultLink = nil;
|
||||
switch (msg->GetType())
|
||||
{
|
||||
case plVaultNotifyMsg::kRegisteredChildAgeLink:
|
||||
case plVaultNotifyMsg::kRegisteredOwnedAge:
|
||||
case plVaultNotifyMsg::kRegisteredSubAgeLink:
|
||||
cVaultLink = VaultGetNodeIncRef(msg->GetArgs()->GetInt(plNetCommon::VaultTaskArgs::kAgeLinkNode));
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cVaultLink != nil)
|
||||
{
|
||||
// This is something that Cyan does... >.<
|
||||
// It's very useful though...
|
||||
VaultAgeLinkNode accLink(cVaultLink);
|
||||
accLink.CopyTo(cur);
|
||||
if (RelVaultNode* rvnInfo = cVaultLink->GetChildNodeIncRef(plVault::kNodeType_AgeInfo, 1))
|
||||
{
|
||||
VaultAgeInfoNode accInfo(rvnInfo);
|
||||
accInfo.CopyTo(cur->GetAgeInfo());
|
||||
rvnInfo->DecRef();
|
||||
}
|
||||
|
||||
IDoLink(fDeferredLink);
|
||||
fDeferredLink = nil;
|
||||
return true;
|
||||
|
||||
cVaultLink->DecRef();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -681,23 +749,27 @@ void plNetLinkingMgr::OfferLinkToPlayer( const plAgeInfoStruct * inInfo, UInt32
|
||||
|
||||
void plNetLinkingMgr::IPostProcessLink( void )
|
||||
{
|
||||
bool city = (0 == stricmp( GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kCityAgeFilename ));
|
||||
bool hood = (0 == stricmp( GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kNeighborhoodAgeFilename ));
|
||||
bool psnl = (0 == stricmp( GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kPersonalAgeFilename ));
|
||||
// Grab some useful things...
|
||||
plAgeLinkStruct* link = GetAgeLink();
|
||||
plAgeInfoStruct* info = link->GetAgeInfo();
|
||||
|
||||
bool city = (stricmp(info->GetAgeFilename(), kCityAgeFilename) == 0);
|
||||
bool hood = (stricmp(info->GetAgeFilename(), kNeighborhoodAgeFilename) == 0);
|
||||
bool psnl = (stricmp(info->GetAgeFilename(), kPersonalAgeFilename) == 0);
|
||||
|
||||
// Update our online status
|
||||
if (RelVaultNode * rvnInfo = VaultGetPlayerInfoNodeIncRef()) {
|
||||
VaultPlayerInfoNode accInfo(rvnInfo);
|
||||
wchar ageInstName[MAX_PATH];
|
||||
Uuid ageInstGuid = *GetAgeLink()->GetAgeInfo()->GetAgeInstanceGuid();
|
||||
StrToUnicode(ageInstName, GetAgeLink()->GetAgeInfo()->GetAgeInstanceName(), arrsize(ageInstName));
|
||||
Uuid ageInstGuid = *info->GetAgeInstanceGuid();
|
||||
StrToUnicode(ageInstName, info->GetAgeInstanceName(), arrsize(ageInstName));
|
||||
accInfo.SetAgeInstName(ageInstName);
|
||||
accInfo.SetAgeInstUuid(ageInstGuid);
|
||||
accInfo.SetOnline(true);
|
||||
rvnInfo->DecRef();
|
||||
}
|
||||
|
||||
switch (GetAgeLink()->GetLinkingRules()) {
|
||||
switch (link->GetLinkingRules()) {
|
||||
|
||||
case plNetCommon::LinkingRules::kOwnedBook: {
|
||||
// SPECIAL CASE: City: Every player ever created would be in the list; avoid that.
|
||||
@ -710,10 +782,12 @@ void plNetLinkingMgr::IPostProcessLink( void )
|
||||
|
||||
if (fldr && info)
|
||||
if (!fldr->IsParentOf(info->nodeId, 1))
|
||||
VaultAddChildNodeAndWait(
|
||||
VaultAddChildNode(
|
||||
fldr->nodeId,
|
||||
info->nodeId,
|
||||
NetCommGetPlayer()->playerInt
|
||||
NetCommGetPlayer()->playerInt,
|
||||
nil,
|
||||
nil
|
||||
);
|
||||
|
||||
if (fldr)
|
||||
@ -735,10 +809,12 @@ void plNetLinkingMgr::IPostProcessLink( void )
|
||||
|
||||
if (fldr && info)
|
||||
if (!fldr->IsParentOf(info->nodeId, 1))
|
||||
VaultAddChildNodeAndWait(
|
||||
VaultAddChildNode(
|
||||
fldr->nodeId,
|
||||
info->nodeId,
|
||||
NetCommGetPlayer()->playerInt
|
||||
NetCommGetPlayer()->playerInt,
|
||||
nil,
|
||||
nil
|
||||
);
|
||||
|
||||
if (fldr)
|
||||
@ -752,7 +828,7 @@ void plNetLinkingMgr::IPostProcessLink( void )
|
||||
case plNetCommon::LinkingRules::kSubAgeBook: {
|
||||
// Register the previous age as a sub age of the current one so that we can link back to that instance
|
||||
plAgeLinkStruct subAgeLink;
|
||||
VaultAgeFindOrCreateSubAgeLinkAndWait(GetPrevAgeLink()->GetAgeInfo(), &subAgeLink, NetCommGetAge()->ageInstId);
|
||||
VaultAgeFindOrCreateSubAgeLink(GetPrevAgeLink()->GetAgeInfo(), &subAgeLink, NetCommGetAge()->ageInstId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -760,16 +836,19 @@ void plNetLinkingMgr::IPostProcessLink( void )
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool plNetLinkingMgr::IPreProcessLink( void )
|
||||
UInt8 plNetLinkingMgr::IPreProcessLink( void )
|
||||
{
|
||||
plNetClientMgr * nc = plNetClientMgr::GetInstance();
|
||||
// Grab some stuff we're gonna use extensively
|
||||
plNetClientMgr* nc = plNetClientMgr::GetInstance();
|
||||
plAgeLinkStruct* link = GetAgeLink();
|
||||
plAgeInfoStruct* info = link->GetAgeInfo();
|
||||
|
||||
bool success = true;
|
||||
PreProcessResult success = kLinkImmediately;
|
||||
|
||||
if ( nc->GetFlagsBit( plNetClientMgr::kNullSend ) )
|
||||
{
|
||||
hsLogEntry( nc->DebugMsg( "NetClientMgr nullsend. Not linking." ) );
|
||||
return false;
|
||||
return kLinkFailed;
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -787,7 +866,7 @@ bool plNetLinkingMgr::IPreProcessLink( void )
|
||||
VaultPlayerInfoNode accInfo(rvnInfo);
|
||||
wchar ageInstName[MAX_PATH];
|
||||
Uuid ageInstGuid = *GetAgeLink()->GetAgeInfo()->GetAgeInstanceGuid();
|
||||
StrToUnicode(ageInstName, GetAgeLink()->GetAgeInfo()->GetAgeInstanceName(), arrsize(ageInstName));
|
||||
StrToUnicode(ageInstName, info->GetAgeInstanceName(), arrsize(ageInstName));
|
||||
accInfo.SetAgeInstName(ageInstName);
|
||||
accInfo.SetAgeInstUuid(ageInstGuid);
|
||||
accInfo.SetOnline(true);
|
||||
@ -797,50 +876,50 @@ bool plNetLinkingMgr::IPreProcessLink( void )
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Fixup empty fields
|
||||
if ( GetAgeLink()->GetAgeInfo()->HasAgeFilename() )
|
||||
if (info->HasAgeFilename())
|
||||
{
|
||||
GetAgeLink()->GetAgeInfo()->SetAgeFilename( plNetLinkingMgr::GetProperAgeName( GetAgeLink()->GetAgeInfo()->GetAgeFilename() ).c_str() );
|
||||
|
||||
if ( !GetAgeLink()->GetAgeInfo()->HasAgeInstanceName() )
|
||||
if (!info->HasAgeInstanceName())
|
||||
{
|
||||
GetAgeLink()->GetAgeInfo()->SetAgeInstanceName( GetAgeLink()->GetAgeInfo()->GetAgeFilename() );
|
||||
info->SetAgeInstanceName(info->GetAgeFilename());
|
||||
}
|
||||
}
|
||||
|
||||
hsLogEntry( nc->DebugMsg( "plNetLinkingMgr: Pre-Process: Linking with %s rules...",
|
||||
plNetCommon::LinkingRules::LinkingRuleStr( GetAgeLink()->GetLinkingRules() ) ) );
|
||||
plNetCommon::LinkingRules::LinkingRuleStr( link->GetLinkingRules() ) ) );
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// SPECIAL CASE: StartUp: force basic link
|
||||
if ( stricmp( GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kStartUpAgeFilename )==0 )
|
||||
if (stricmp(info->GetAgeFilename(), kStartUpAgeFilename) == 0)
|
||||
{
|
||||
GetAgeLink()->SetLinkingRules( plNetCommon::LinkingRules::kBasicLink );
|
||||
link->SetLinkingRules( plNetCommon::LinkingRules::kBasicLink );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// SPECIAL CASE: Nexus: force original link
|
||||
if ( stricmp( GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kNexusAgeFilename )==0 )
|
||||
if (stricmp(info->GetAgeFilename(), kNexusAgeFilename) == 0)
|
||||
{
|
||||
GetAgeLink()->SetLinkingRules( plNetCommon::LinkingRules::kOriginalBook );
|
||||
link->SetLinkingRules(plNetCommon::LinkingRules::kOriginalBook);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// SPECIAL CASE: ACA: force original link
|
||||
if ( stricmp( GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kAvCustomizationFilename )==0 )
|
||||
if (stricmp(info->GetAgeFilename(), kAvCustomizationFilename ) == 0)
|
||||
{
|
||||
GetAgeLink()->SetLinkingRules( plNetCommon::LinkingRules::kOriginalBook );
|
||||
link->SetLinkingRules(plNetCommon::LinkingRules::kOriginalBook);
|
||||
}
|
||||
|
||||
hsLogEntry( nc->DebugMsg( "plNetLinkingMgr: Process: Linking with %s rules...",
|
||||
plNetCommon::LinkingRules::LinkingRuleStr( GetAgeLink()->GetLinkingRules() ) ) );
|
||||
plNetCommon::LinkingRules::LinkingRuleStr( link->GetLinkingRules() ) ) );
|
||||
|
||||
switch ( GetAgeLink()->GetLinkingRules() )
|
||||
switch ( link->GetLinkingRules() )
|
||||
{
|
||||
//--------------------------------------------------------------------
|
||||
// BASIC LINK. Link to a unique instance of the age, if no instance specified.
|
||||
case plNetCommon::LinkingRules::kBasicLink:
|
||||
if (!GetAgeLink()->GetAgeInfo()->HasAgeInstanceGuid())
|
||||
GetAgeLink()->GetAgeInfo()->SetAgeInstanceGuid(&plUUID(GuidGenerate()));
|
||||
if (!info->HasAgeInstanceGuid())
|
||||
info->SetAgeInstanceGuid(&plUUID(GuidGenerate()));
|
||||
break;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
@ -851,12 +930,12 @@ bool plNetLinkingMgr::IPreProcessLink( void )
|
||||
// we just want to find out if we own *any* link to the age, not the specific
|
||||
// link that we're linking through
|
||||
plAgeInfoStruct ageInfo;
|
||||
ageInfo.SetAgeFilename(GetAgeLink()->GetAgeInfo()->GetAgeFilename());
|
||||
ageInfo.SetAgeFilename(info->GetAgeFilename());
|
||||
|
||||
plAgeLinkStruct ownedLink;
|
||||
if (!VaultGetOwnedAgeLink(&ageInfo, &ownedLink)) {
|
||||
// Fill in fields for new age create.
|
||||
if ( !GetAgeLink()->GetAgeInfo()->HasAgeUserDefinedName() )
|
||||
if (!info->HasAgeUserDefinedName())
|
||||
{
|
||||
// set user-defined name
|
||||
std::string title;
|
||||
@ -865,25 +944,28 @@ bool plNetLinkingMgr::IPreProcessLink( void )
|
||||
xtl::format( title, "%s'", nc->GetPlayerName() );
|
||||
else
|
||||
xtl::format( title, "%s's", nc->GetPlayerName() );
|
||||
GetAgeLink()->GetAgeInfo()->SetAgeUserDefinedName( title.c_str() );
|
||||
info->SetAgeUserDefinedName(title.c_str());
|
||||
}
|
||||
if ( !GetAgeLink()->GetAgeInfo()->HasAgeDescription() )
|
||||
if (!info->HasAgeDescription())
|
||||
{
|
||||
// set description
|
||||
std::string desc;
|
||||
unsigned nameLen = StrLen(nc->GetPlayerName());
|
||||
if (nc->GetPlayerName()[nameLen - 1] == 's' || nc->GetPlayerName()[nameLen - 1] == 'S')
|
||||
xtl::format( desc, "%s' %s", nc->GetPlayerName(), GetAgeLink()->GetAgeInfo()->GetAgeInstanceName() );
|
||||
xtl::format( desc, "%s' %s", nc->GetPlayerName(), info->GetAgeInstanceName() );
|
||||
else
|
||||
xtl::format( desc, "%s's %s", nc->GetPlayerName(), GetAgeLink()->GetAgeInfo()->GetAgeInstanceName() );
|
||||
GetAgeLink()->GetAgeInfo()->SetAgeDescription( desc.c_str() );
|
||||
xtl::format( desc, "%s's %s", nc->GetPlayerName(), info->GetAgeInstanceName() );
|
||||
info->SetAgeDescription( desc.c_str() );
|
||||
}
|
||||
if (!GetAgeLink()->GetAgeInfo()->HasAgeInstanceGuid()) {
|
||||
GetAgeLink()->GetAgeInfo()->SetAgeInstanceGuid(&plUUID(GuidGenerate()));
|
||||
if (!info->HasAgeInstanceGuid()) {
|
||||
info->SetAgeInstanceGuid(&plUUID(GuidGenerate()));
|
||||
}
|
||||
|
||||
// register this as an owned age now before we link to it.
|
||||
VaultRegisterOwnedAgeAndWait(GetAgeLink());
|
||||
// Note: We MUST break or the OwnedBook code will fail!
|
||||
VaultRegisterOwnedAge(link);
|
||||
success = kLinkDeferred;
|
||||
break;
|
||||
}
|
||||
else if (RelVaultNode * linkNode = VaultGetOwnedAgeLinkIncRef(&ageInfo)) {
|
||||
// We have the age in our AgesIOwnFolder. If its volatile, dump it for the new one.
|
||||
@ -891,7 +973,7 @@ bool plNetLinkingMgr::IPreProcessLink( void )
|
||||
if (linkAcc.volat) {
|
||||
if (VaultUnregisterOwnedAgeAndWait(&ageInfo)) {
|
||||
// Fill in fields for new age create.
|
||||
if ( !GetAgeLink()->GetAgeInfo()->HasAgeUserDefinedName() )
|
||||
if ( !info->HasAgeUserDefinedName() )
|
||||
{
|
||||
// set user-defined name
|
||||
std::string title;
|
||||
@ -900,32 +982,36 @@ bool plNetLinkingMgr::IPreProcessLink( void )
|
||||
xtl::format( title, "%s'", nc->GetPlayerName() );
|
||||
else
|
||||
xtl::format( title, "%s's", nc->GetPlayerName() );
|
||||
GetAgeLink()->GetAgeInfo()->SetAgeUserDefinedName( title.c_str() );
|
||||
info->SetAgeUserDefinedName( title.c_str() );
|
||||
}
|
||||
if ( !GetAgeLink()->GetAgeInfo()->HasAgeDescription() )
|
||||
if ( !info->HasAgeDescription() )
|
||||
{
|
||||
// set description
|
||||
std::string desc;
|
||||
unsigned nameLen = StrLen(nc->GetPlayerName());
|
||||
if (nc->GetPlayerName()[nameLen - 1] == 's' || nc->GetPlayerName()[nameLen - 1] == 'S')
|
||||
xtl::format( desc, "%s' %s", nc->GetPlayerName(), GetAgeLink()->GetAgeInfo()->GetAgeInstanceName() );
|
||||
xtl::format( desc, "%s' %s", nc->GetPlayerName(), info->GetAgeInstanceName() );
|
||||
else
|
||||
xtl::format( desc, "%s's %s", nc->GetPlayerName(), GetAgeLink()->GetAgeInfo()->GetAgeInstanceName() );
|
||||
GetAgeLink()->GetAgeInfo()->SetAgeDescription( desc.c_str() );
|
||||
xtl::format( desc, "%s's %s", nc->GetPlayerName(), info->GetAgeInstanceName() );
|
||||
info->SetAgeDescription( desc.c_str() );
|
||||
}
|
||||
if (!GetAgeLink()->GetAgeInfo()->HasAgeInstanceGuid()) {
|
||||
GetAgeLink()->GetAgeInfo()->SetAgeInstanceGuid(&plUUID(GuidGenerate()));
|
||||
if (!info->HasAgeInstanceGuid()) {
|
||||
info->SetAgeInstanceGuid(&plUUID(GuidGenerate()));
|
||||
}
|
||||
|
||||
VaultRegisterOwnedAgeAndWait(GetAgeLink());
|
||||
VaultRegisterOwnedAge(link);
|
||||
|
||||
// Note: We MUST break or the OwnedBook code will fail!
|
||||
success = kLinkDeferred;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (stricmp(GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kNeighborhoodAgeFilename) == 0) {
|
||||
// if we get here then its because we're linking to a neighborhood that we don't belong to
|
||||
if (stricmp(info->GetAgeFilename(), kNeighborhoodAgeFilename) == 0) {
|
||||
// if we get here then it's because we're linking to a neighborhood that we don't belong to
|
||||
// and our own neighborhood book is not volatile, so really we want to basic link
|
||||
GetAgeLink()->SetLinkingRules(plNetCommon::LinkingRules::kBasicLink);
|
||||
success = true;
|
||||
link->SetLinkingRules(plNetCommon::LinkingRules::kBasicLink);
|
||||
success = kLinkImmediately;
|
||||
|
||||
break;
|
||||
}
|
||||
@ -933,7 +1019,7 @@ bool plNetLinkingMgr::IPreProcessLink( void )
|
||||
linkNode->DecRef();
|
||||
}
|
||||
}
|
||||
GetAgeLink()->SetLinkingRules( plNetCommon::LinkingRules::kOwnedBook );
|
||||
link->SetLinkingRules( plNetCommon::LinkingRules::kOwnedBook );
|
||||
// falls thru to OWNED BOOK case...
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
@ -941,14 +1027,14 @@ bool plNetLinkingMgr::IPreProcessLink( void )
|
||||
case plNetCommon::LinkingRules::kOwnedBook:
|
||||
{
|
||||
plAgeLinkStruct ownedLink;
|
||||
if (VaultGetOwnedAgeLink(GetAgeLink()->GetAgeInfo(), &ownedLink)) {
|
||||
GetAgeLink()->GetAgeInfo()->CopyFrom(ownedLink.GetAgeInfo());
|
||||
if (VaultGetOwnedAgeLink(info, &ownedLink)) {
|
||||
info->CopyFrom(ownedLink.GetAgeInfo());
|
||||
// Remember spawn point (treasure book support)
|
||||
plSpawnPointInfo theSpawnPt = GetAgeLink()->SpawnPoint();
|
||||
VaultAddOwnedAgeSpawnPoint(*GetAgeLink()->GetAgeInfo()->GetAgeInstanceGuid(), theSpawnPt);
|
||||
plSpawnPointInfo theSpawnPt = link->SpawnPoint();
|
||||
VaultAddOwnedAgeSpawnPoint(*info->GetAgeInstanceGuid(), theSpawnPt);
|
||||
}
|
||||
else {
|
||||
success = false;
|
||||
success = kLinkFailed;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -958,10 +1044,10 @@ bool plNetLinkingMgr::IPreProcessLink( void )
|
||||
case plNetCommon::LinkingRules::kVisitBook:
|
||||
{
|
||||
plAgeLinkStruct visitLink;
|
||||
if (VaultGetVisitAgeLink(GetAgeLink()->GetAgeInfo(), &visitLink))
|
||||
GetAgeLink()->GetAgeInfo()->CopyFrom(visitLink.GetAgeInfo());
|
||||
if (VaultGetVisitAgeLink(info, &visitLink))
|
||||
info->CopyFrom(visitLink.GetAgeInfo());
|
||||
else
|
||||
success = false;
|
||||
success = kLinkFailed;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -971,10 +1057,10 @@ bool plNetLinkingMgr::IPreProcessLink( void )
|
||||
case plNetCommon::LinkingRules::kSubAgeBook:
|
||||
{
|
||||
plAgeLinkStruct subAgeLink;
|
||||
if (VaultAgeFindOrCreateSubAgeLinkAndWait(GetAgeLink()->GetAgeInfo(), &subAgeLink, NetCommGetAge()->ageInstId))
|
||||
GetAgeLink()->GetAgeInfo()->CopyFrom(subAgeLink.GetAgeInfo());
|
||||
if (VaultAgeFindOrCreateSubAgeLink(info, &subAgeLink, NetCommGetAge()->ageInstId))
|
||||
info->CopyFrom(subAgeLink.GetAgeInfo());
|
||||
else
|
||||
success = false;
|
||||
success = kLinkDeferred;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -985,28 +1071,38 @@ bool plNetLinkingMgr::IPreProcessLink( void )
|
||||
{
|
||||
plAgeLinkStruct childLink;
|
||||
wchar parentAgeName[MAX_PATH];
|
||||
if (GetAgeLink()->HasParentAgeFilename()) {
|
||||
StrToUnicode(parentAgeName, GetAgeLink()->GetParentAgeFilename(), arrsize(parentAgeName));
|
||||
success = VaultAgeFindOrCreateChildAgeLinkAndWait(parentAgeName, GetAgeLink()->GetAgeInfo(), &childLink);
|
||||
}
|
||||
else {
|
||||
success = VaultAgeFindOrCreateChildAgeLinkAndWait(nil, GetAgeLink()->GetAgeInfo(), &childLink);
|
||||
if (link->HasParentAgeFilename())
|
||||
StrToUnicode(parentAgeName, link->GetParentAgeFilename(), arrsize(parentAgeName));
|
||||
|
||||
switch(VaultAgeFindOrCreateChildAgeLink(
|
||||
(link->HasParentAgeFilename() ? parentAgeName : nil),
|
||||
info,
|
||||
&childLink))
|
||||
{
|
||||
case hsFail:
|
||||
success = kLinkFailed;
|
||||
break;
|
||||
case FALSE:
|
||||
success = kLinkDeferred;
|
||||
break;
|
||||
case TRUE:
|
||||
success = kLinkImmediately;
|
||||
}
|
||||
|
||||
if (success)
|
||||
GetAgeLink()->GetAgeInfo()->CopyFrom(childLink.GetAgeInfo());
|
||||
if (success == kLinkImmediately)
|
||||
info->CopyFrom(childLink.GetAgeInfo());
|
||||
}
|
||||
break;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// ???
|
||||
DEFAULT_FATAL(GetAgeLink()->GetLinkingRules());
|
||||
DEFAULT_FATAL(link->GetLinkingRules());
|
||||
}
|
||||
|
||||
hsLogEntry( nc->DebugMsg( "plNetLinkingMgr: Post-Process: Linking with %s rules...",
|
||||
plNetCommon::LinkingRules::LinkingRuleStr( GetAgeLink()->GetLinkingRules() ) ) );
|
||||
plNetCommon::LinkingRules::LinkingRuleStr( link->GetLinkingRules() ) ) );
|
||||
|
||||
hsAssert( GetAgeLink()->GetAgeInfo()->HasAgeFilename(), "AgeLink has no AgeFilename. Link will fail." );
|
||||
hsAssert( info->HasAgeFilename(), "AgeLink has no AgeFilename. Link will fail." );
|
||||
|
||||
return success;
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
#include "../plMessage/plLinkToAgeMsg.h"
|
||||
|
||||
class plMessage;
|
||||
class plVaultNotifyMsg;
|
||||
struct plNCAgeJoiner;
|
||||
struct plNCAgeLeaver;
|
||||
|
||||
@ -91,10 +92,23 @@ class plNetLinkingMgr
|
||||
kLinkPlayerToPrevAge
|
||||
};
|
||||
|
||||
bool IPreProcessLink( void );
|
||||
plLinkToAgeMsg* fDeferredLink;
|
||||
|
||||
enum PreProcessResult {
|
||||
// Old style IPreProcessLink style "false" result
|
||||
kLinkFailed,
|
||||
// Old style IPreProcessLink style "true" result
|
||||
kLinkImmediately,
|
||||
// Defer the link until later, don't trash the structs
|
||||
kLinkDeferred,
|
||||
};
|
||||
|
||||
UInt8 IPreProcessLink( void );
|
||||
void IPostProcessLink( void );
|
||||
bool IProcessLinkingMgrMsg( plLinkingMgrMsg * msg );
|
||||
bool IProcessLinkToAgeMsg( plLinkToAgeMsg * msg );
|
||||
void IDoLink(plLinkToAgeMsg* link);
|
||||
bool IProcessVaultNotifyMsg(plVaultNotifyMsg* msg);
|
||||
|
||||
bool IDispatchMsg( plMessage * msg, UInt32 playerID );
|
||||
|
||||
|
@ -127,6 +127,7 @@ plNetMsgScreener::Answer plNetMsgScreener::IAllowMessageType(Int16 classIndex, c
|
||||
case CLASS_INDEX_SCOPED(plClothingMsg):
|
||||
case CLASS_INDEX_SCOPED(plEnableMsg):
|
||||
case CLASS_INDEX_SCOPED(plLinkToAgeMsg):
|
||||
case CLASS_INDEX_SCOPED(plSubWorldMsg):
|
||||
return kYes;
|
||||
|
||||
// definitely yes or no (based on whether sender is a CCR)
|
||||
|
@ -61,6 +61,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
#include "../pnKeyedObject/plKey.h"
|
||||
#include "../pnMessage/plCorrectionMsg.h"
|
||||
#include "../pnMessage/plNodeRefMsg.h"
|
||||
#include "../pnMessage/plObjRefMsg.h"
|
||||
#include "../pnMessage/plSDLModifierMsg.h"
|
||||
#include "../plMessage/plSimStateMsg.h"
|
||||
#include "../plMessage/plSimInfluenceMsg.h"
|
||||
@ -72,6 +73,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
#include "../plStatusLog/plStatusLog.h"
|
||||
#include "plPXConvert.h"
|
||||
#include "plPXPhysicalControllerCore.h"
|
||||
#include "plPXSubWorld.h"
|
||||
|
||||
#include "../plModifier/plDetectorLog.h"
|
||||
|
||||
@ -84,25 +86,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
|
||||
#define LogActivate(func) if (fActor->isSleeping()) SimLog("%s activated by %s", GetKeyName(), func);
|
||||
|
||||
PhysRecipe::PhysRecipe()
|
||||
: mass(0.f)
|
||||
, friction(0.f)
|
||||
, restitution(0.f)
|
||||
, bounds(plSimDefs::kBoundsMax)
|
||||
, group(plSimDefs::kGroupMax)
|
||||
, reportsOn(0)
|
||||
, objectKey(nil)
|
||||
, sceneNode(nil)
|
||||
, worldKey(nil)
|
||||
, convexMesh(nil)
|
||||
, triMesh(nil)
|
||||
, radius(0.f)
|
||||
, offset(0.f, 0.f, 0.f)
|
||||
, meshStream(nil)
|
||||
{
|
||||
l2s.Reset();
|
||||
}
|
||||
|
||||
plProfile_Extern(MaySendLocation);
|
||||
plProfile_Extern(LocationsSent);
|
||||
plProfile_Extern(PhysicsUpdates);
|
||||
@ -128,19 +111,15 @@ int plPXPhysical::fNumberAnimatedActivators = 0;
|
||||
plPXPhysical::plPXPhysical()
|
||||
: fSDLMod(nil)
|
||||
, fActor(nil)
|
||||
, fBoundsType(plSimDefs::kBoundsMax)
|
||||
, fLOSDBs(plSimDefs::kLOSDBNone)
|
||||
, fGroup(plSimDefs::kGroupMax)
|
||||
, fReportsOn(0)
|
||||
, fLastSyncTime(0.0f)
|
||||
, fProxyGen(nil)
|
||||
, fSceneNode(nil)
|
||||
, fWorldKey(nil)
|
||||
, fSndGroup(nil)
|
||||
, fWorldHull(nil)
|
||||
, fSaveTriangles(nil)
|
||||
, fHullNumberPlanes(0)
|
||||
, fMass(0.f)
|
||||
, fWeWereHit(false)
|
||||
, fHitForce(0,0,0)
|
||||
, fHitPos(0,0,0)
|
||||
@ -354,15 +333,14 @@ hsBool plPXPhysical::Should_I_Trigger(hsBool enter, hsPoint3& pos)
|
||||
}
|
||||
|
||||
|
||||
hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
hsBool plPXPhysical::Init()
|
||||
{
|
||||
hsBool startAsleep = false;
|
||||
fBoundsType = recipe.bounds;
|
||||
fGroup = recipe.group;
|
||||
fReportsOn = recipe.reportsOn;
|
||||
fObjectKey = recipe.objectKey;
|
||||
fSceneNode = recipe.sceneNode;
|
||||
fWorldKey = recipe.worldKey;
|
||||
|
||||
fGroup = fRecipe.group;
|
||||
fReportsOn = fRecipe.reportsOn;
|
||||
fObjectKey = fRecipe.objectKey;
|
||||
fSceneNode = fRecipe.sceneNode;
|
||||
|
||||
NxActorDesc actorDesc;
|
||||
NxSphereShapeDesc sphereDesc;
|
||||
@ -370,19 +348,19 @@ hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
NxTriangleMeshShapeDesc trimeshShapeDesc;
|
||||
NxBoxShapeDesc boxDesc;
|
||||
|
||||
plPXConvert::Matrix(recipe.l2s, actorDesc.globalPose);
|
||||
plPXConvert::Matrix(fRecipe.l2s, actorDesc.globalPose);
|
||||
|
||||
switch (fBoundsType)
|
||||
switch (fRecipe.bounds)
|
||||
{
|
||||
case plSimDefs::kSphereBounds:
|
||||
{
|
||||
hsMatrix44 sphereL2W;
|
||||
sphereL2W.Reset();
|
||||
sphereL2W.SetTranslate(&recipe.offset);
|
||||
sphereL2W.SetTranslate(&fRecipe.offset);
|
||||
|
||||
sphereDesc.radius = recipe.radius;
|
||||
sphereDesc.radius = fRecipe.radius;
|
||||
plPXConvert::Matrix(sphereL2W, sphereDesc.localPose);
|
||||
sphereDesc.group = fGroup;
|
||||
sphereDesc.group = fRecipe.group;
|
||||
actorDesc.shapes.pushBack(&sphereDesc);
|
||||
}
|
||||
break;
|
||||
@ -391,54 +369,54 @@ hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
// If this is read time (ie, meshStream is nil), turn the convex hull
|
||||
// into a box. That way the data won't have to change when convex hulls
|
||||
// actually work right.
|
||||
if (fGroup == plSimDefs::kGroupDetector && recipe.meshStream == nil)
|
||||
if (fRecipe.group == plSimDefs::kGroupDetector && fRecipe.meshStream == nil)
|
||||
{
|
||||
#ifdef USE_BOXES_FOR_DETECTOR_HULLS
|
||||
MakeBoxFromHull(recipe.convexMesh, boxDesc);
|
||||
plSimulationMgr::GetInstance()->GetSDK()->releaseConvexMesh(*recipe.convexMesh);
|
||||
boxDesc.group = fGroup;
|
||||
MakeBoxFromHull(fRecipe.convexMesh, boxDesc);
|
||||
plSimulationMgr::GetInstance()->GetSDK()->releaseConvexMesh(*fRecipe.convexMesh);
|
||||
boxDesc.group = fRecipe.group;
|
||||
actorDesc.shapes.push_back(&boxDesc);
|
||||
#else
|
||||
#ifdef USE_PHYSX_CONVEXHULL_WORKAROUND
|
||||
// make a hull of planes for testing IsInside
|
||||
IMakeHull(recipe.convexMesh,recipe.l2s);
|
||||
IMakeHull(fRecipe.convexMesh,fRecipe.l2s);
|
||||
#endif // USE_PHYSX_CONVEXHULL_WORKAROUND
|
||||
convexShapeDesc.meshData = recipe.convexMesh;
|
||||
convexShapeDesc.userData = recipe.meshStream;
|
||||
convexShapeDesc.group = fGroup;
|
||||
convexShapeDesc.meshData = fRecipe.convexMesh;
|
||||
convexShapeDesc.userData = fRecipe.meshStream;
|
||||
convexShapeDesc.group = fRecipe.group;
|
||||
actorDesc.shapes.pushBack(&convexShapeDesc);
|
||||
#endif // USE_BOXES_FOR_DETECTOR_HULLS
|
||||
}
|
||||
else
|
||||
{
|
||||
convexShapeDesc.meshData = recipe.convexMesh;
|
||||
convexShapeDesc.userData = recipe.meshStream;
|
||||
convexShapeDesc.group = fGroup;
|
||||
convexShapeDesc.meshData = fRecipe.convexMesh;
|
||||
convexShapeDesc.userData = fRecipe.meshStream;
|
||||
convexShapeDesc.group = fRecipe.group;
|
||||
actorDesc.shapes.pushBack(&convexShapeDesc);
|
||||
}
|
||||
break;
|
||||
case plSimDefs::kBoxBounds:
|
||||
{
|
||||
boxDesc.dimensions = plPXConvert::Point(recipe.bDimensions);
|
||||
boxDesc.dimensions = plPXConvert::Point(fRecipe.bDimensions);
|
||||
|
||||
hsMatrix44 boxL2W;
|
||||
boxL2W.Reset();
|
||||
boxL2W.SetTranslate(&recipe.bOffset);
|
||||
boxL2W.SetTranslate(&fRecipe.bOffset);
|
||||
plPXConvert::Matrix(boxL2W, boxDesc.localPose);
|
||||
|
||||
boxDesc.group = fGroup;
|
||||
boxDesc.group = fRecipe.group;
|
||||
actorDesc.shapes.push_back(&boxDesc);
|
||||
}
|
||||
break;
|
||||
case plSimDefs::kExplicitBounds:
|
||||
case plSimDefs::kProxyBounds:
|
||||
if (fGroup == plSimDefs::kGroupDetector)
|
||||
if (fRecipe.group == plSimDefs::kGroupDetector)
|
||||
{
|
||||
SimLog("Someone using an Exact on a detector region: %s", GetKeyName());
|
||||
}
|
||||
trimeshShapeDesc.meshData = recipe.triMesh;
|
||||
trimeshShapeDesc.userData = recipe.meshStream;
|
||||
trimeshShapeDesc.group = fGroup;
|
||||
trimeshShapeDesc.meshData = fRecipe.triMesh;
|
||||
trimeshShapeDesc.userData = fRecipe.meshStream;
|
||||
trimeshShapeDesc.group = fRecipe.group;
|
||||
actorDesc.shapes.pushBack(&trimeshShapeDesc);
|
||||
break;
|
||||
default:
|
||||
@ -449,10 +427,9 @@ hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
|
||||
// Now fill out the body, or dynamic part of the physical
|
||||
NxBodyDesc bodyDesc;
|
||||
fMass = recipe.mass;
|
||||
if (recipe.mass != 0)
|
||||
if (fRecipe.mass != 0)
|
||||
{
|
||||
bodyDesc.mass = recipe.mass;
|
||||
bodyDesc.mass = fRecipe.mass;
|
||||
actorDesc.body = &bodyDesc;
|
||||
|
||||
if (GetProperty(plSimulationInterface::kPinned))
|
||||
@ -461,13 +438,13 @@ hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
startAsleep = true; // put it to sleep if they are going to be frozen
|
||||
}
|
||||
|
||||
if (fGroup != plSimDefs::kGroupDynamic || GetProperty(plSimulationInterface::kPhysAnim))
|
||||
if (fRecipe.group != plSimDefs::kGroupDynamic || GetProperty(plSimulationInterface::kPhysAnim))
|
||||
{
|
||||
SetProperty(plSimulationInterface::kPassive, true);
|
||||
|
||||
// Even though the code for animated physicals and animated activators are the same
|
||||
// keep these code snippets separated for fine tuning. Thanks.
|
||||
if (fGroup == plSimDefs::kGroupDynamic)
|
||||
if (fRecipe.group == plSimDefs::kGroupDynamic)
|
||||
{
|
||||
// handle the animated physicals.... make kinematic for now.
|
||||
fNumberAnimatedPhysicals++;
|
||||
@ -495,7 +472,7 @@ hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
|
||||
// Put the dynamics into actor group 1. The actor groups are only used for
|
||||
// deciding who we get contact reports for.
|
||||
if (fGroup == plSimDefs::kGroupDynamic)
|
||||
if (fRecipe.group == plSimDefs::kGroupDynamic)
|
||||
actorDesc.group = 1;
|
||||
|
||||
NxScene* scene = plSimulationMgr::GetInstance()->GetScene(fWorldKey);
|
||||
@ -512,7 +489,7 @@ hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
return false;
|
||||
|
||||
NxShape* shape = fActor->getShapes()[0];
|
||||
shape->setMaterial(plSimulationMgr::GetInstance()->GetMaterialIdx(scene, recipe.friction, recipe.restitution));
|
||||
shape->setMaterial(plSimulationMgr::GetInstance()->GetMaterialIdx(scene, fRecipe.friction, fRecipe.restitution));
|
||||
|
||||
// Turn on the trigger flags for any detectors.
|
||||
//
|
||||
@ -523,7 +500,7 @@ hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
// problems trying to calculate an intertial tensor. By letting it be
|
||||
// created as a normal dynamic first, then setting the flags, we work around
|
||||
// that problem.
|
||||
if (fGroup == plSimDefs::kGroupDetector)
|
||||
if (fRecipe.group == plSimDefs::kGroupDetector)
|
||||
{
|
||||
shape->setFlag(NX_TRIGGER_ON_ENTER, true);
|
||||
shape->setFlag(NX_TRIGGER_ON_LEAVE, true);
|
||||
@ -547,14 +524,8 @@ hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
plNodeRefMsg* refMsg = TRACKED_NEW plNodeRefMsg(fSceneNode, plRefMsg::kOnCreate, -1, plNodeRefMsg::kPhysical);
|
||||
hsgResMgr::ResMgr()->AddViaNotify(GetKey(), refMsg, plRefFlags::kActiveRef);
|
||||
|
||||
if (fWorldKey)
|
||||
{
|
||||
plGenRefMsg* ref = TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kPhysRefWorld);
|
||||
hsgResMgr::ResMgr()->AddViaNotify(fWorldKey, ref, plRefFlags::kActiveRef);
|
||||
}
|
||||
|
||||
// only dynamic physicals without noSync need SDLs
|
||||
if ( fGroup == plSimDefs::kGroupDynamic && !fProps.IsBitSet(plSimulationInterface::kNoSynchronize) )
|
||||
if ( fRecipe.group == plSimDefs::kGroupDynamic && !fProps.IsBitSet(plSimulationInterface::kNoSynchronize) )
|
||||
{
|
||||
// add SDL modifier
|
||||
plSceneObject* sceneObj = plSceneObject::ConvertNoRef(fObjectKey->ObjectIsLoaded());
|
||||
@ -611,29 +582,65 @@ hsBool plPXPhysical::MsgReceive( plMessage* msg )
|
||||
hsBool plPXPhysical::HandleRefMsg(plGenRefMsg* refMsg)
|
||||
{
|
||||
UInt8 refCtxt = refMsg->GetContext();
|
||||
plKey refKey = refMsg->GetRef()->GetKey();
|
||||
plKey ourKey = GetKey();
|
||||
PhysRefType refType = PhysRefType(refMsg->fType);
|
||||
|
||||
const char* refKeyName = refKey ? refKey->GetName() : "MISSING";
|
||||
switch (refMsg->fType) {
|
||||
case kPhysRefWorld: {
|
||||
switch (refCtxt) {
|
||||
case plRefMsg::kOnCreate:
|
||||
case plRefMsg::kOnRequest:
|
||||
// PotS files specify a plHKSubWorld as the subworld key. For everything else,
|
||||
// the subworlds are a plSceneObject key. For sanity purposes, we will allow
|
||||
// references to the plPXSubWorld here. HOWEVER, we will need to grab the target
|
||||
// and replace our reference...
|
||||
if (plPXSubWorld* subWorldIface = plPXSubWorld::ConvertNoRef(refMsg->GetRef())) {
|
||||
hsAssert(subWorldIface->GetOwnerKey(), "subworld owner is NULL?! Uh oh...");
|
||||
plGenRefMsg* replaceRefMsg = new plGenRefMsg(GetKey(), plRefMsg::kOnReplace, 0, kPhysRefWorld);
|
||||
hsgResMgr::ResMgr()->AddViaNotify(subWorldIface->GetOwnerKey(), replaceRefMsg, plRefFlags::kActiveRef);
|
||||
}
|
||||
// fall-thru is intentional :)
|
||||
case plRefMsg::kOnReplace:
|
||||
// loading into a subworld
|
||||
if (plSceneObject* subSO = plSceneObject::ConvertNoRef(refMsg->GetRef())) {
|
||||
fWorldKey = subSO->GetKey();
|
||||
|
||||
if (refType == kPhysRefWorld)
|
||||
{
|
||||
if (refCtxt == plRefMsg::kOnCreate || refCtxt == plRefMsg::kOnRequest)
|
||||
{
|
||||
// Cache the initial transform, since we assume the sceneobject already knows
|
||||
// that and doesn't need to be told again
|
||||
IGetTransformGlobal(fCachedLocal2World);
|
||||
// Cyan produced files will never have plPXSubWorld as this is a H'uru-ism.
|
||||
// Let us make a default one such that we can play with default subworlds at runtime.
|
||||
// HAAAAAAAAAX!!!
|
||||
plPXSubWorld* subWorldIface = plPXSubWorld::ConvertNoRef(subSO->GetGenericInterface(plPXSubWorld::Index()));
|
||||
if (!subWorldIface) {
|
||||
subWorldIface = new plPXSubWorld();
|
||||
|
||||
// This can be simplified if/when incorporating zrax' String Theory library
|
||||
std::string strKeyName = std::string(subSO->GetKeyName()) + "_DefSubWorld";
|
||||
const char *cKeyName = strKeyName.c_str();
|
||||
|
||||
hsgResMgr::ResMgr()->NewKey(cKeyName,
|
||||
subWorldIface, GetKey()->GetUoid().GetLocation());
|
||||
|
||||
plObjRefMsg* subIfaceRef = new plObjRefMsg(subSO->GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kInterface);
|
||||
// this will send the reference immediately
|
||||
hsgResMgr::ResMgr()->SendRef(subWorldIface, subIfaceRef, plRefFlags::kActiveRef);
|
||||
}
|
||||
|
||||
// Now, we can initialize the physical...
|
||||
Init();
|
||||
IGetTransformGlobal(fCachedLocal2World);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (refCtxt == plRefMsg::kOnDestroy)
|
||||
{
|
||||
break;
|
||||
case plRefMsg::kOnDestroy: {
|
||||
// our world was deleted out from under us: move to the main world
|
||||
// NOTE: this was not implemented even before the PXSubWorld rewrite.
|
||||
// not going to bother!
|
||||
// hsAssert(0, "Lost world");
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (refType == kPhysRefSndGroup)
|
||||
{
|
||||
switch (refCtxt)
|
||||
break;
|
||||
|
||||
case kPhysRefSndGroup: {
|
||||
switch (refCtxt)
|
||||
{
|
||||
case plRefMsg::kOnCreate:
|
||||
case plRefMsg::kOnRequest:
|
||||
@ -645,9 +652,11 @@ hsBool plPXPhysical::HandleRefMsg(plGenRefMsg* refMsg)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
|
||||
default:
|
||||
hsAssert(0, "Unknown ref type, who sent us this?");
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -878,7 +887,6 @@ void plPXPhysical::IGetTransformGlobal(hsMatrix44& l2w) const
|
||||
{
|
||||
plSceneObject* so = plSceneObject::ConvertNoRef(fWorldKey->ObjectIsLoaded());
|
||||
hsAssert(so, "Scene object not loaded while accessing subworld.");
|
||||
// We'll hit this at export time, when the ci isn't ready yet, so do a check
|
||||
if (so->GetCoordinateInterface())
|
||||
{
|
||||
const hsMatrix44& s2w = so->GetCoordinateInterface()->GetLocalToWorld();
|
||||
@ -1026,23 +1034,22 @@ void plPXPhysical::Read(hsStream* stream, hsResMgr* mgr)
|
||||
plPhysical::Read(stream, mgr);
|
||||
ClearMatrix(fCachedLocal2World);
|
||||
|
||||
PhysRecipe recipe;
|
||||
recipe.mass = stream->ReadSwapScalar();
|
||||
recipe.friction = stream->ReadSwapScalar();
|
||||
recipe.restitution = stream->ReadSwapScalar();
|
||||
recipe.bounds = (plSimDefs::Bounds)stream->ReadByte();
|
||||
recipe.group = (plSimDefs::Group)stream->ReadByte();
|
||||
recipe.reportsOn = stream->ReadSwap32();
|
||||
fRecipe.mass = stream->ReadSwapScalar();
|
||||
fRecipe.friction = stream->ReadSwapScalar();
|
||||
fRecipe.restitution = stream->ReadSwapScalar();
|
||||
fRecipe.bounds = (plSimDefs::Bounds)stream->ReadByte();
|
||||
fRecipe.group = (plSimDefs::Group)stream->ReadByte();
|
||||
fRecipe.reportsOn = stream->ReadSwap32();
|
||||
fLOSDBs = stream->ReadSwap16();
|
||||
//hack for swim regions currently they are labeled as static av blockers
|
||||
if(fLOSDBs==plSimDefs::kLOSDBSwimRegion)
|
||||
{
|
||||
recipe.group=plSimDefs::kGroupMax;
|
||||
fRecipe.group=plSimDefs::kGroupMax;
|
||||
}
|
||||
//
|
||||
recipe.objectKey = mgr->ReadKey(stream);
|
||||
recipe.sceneNode = mgr->ReadKey(stream);
|
||||
recipe.worldKey = mgr->ReadKey(stream);
|
||||
fRecipe.objectKey = mgr->ReadKey(stream);
|
||||
fRecipe.sceneNode = mgr->ReadKey(stream);
|
||||
fRecipe.worldKey = mgr->ReadKeyNotifyMe(stream, new plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kPhysRefWorld), plRefFlags::kActiveRef);
|
||||
|
||||
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kPhysRefSndGroup), plRefFlags::kActiveRef);
|
||||
|
||||
@ -1050,30 +1057,33 @@ void plPXPhysical::Read(hsStream* stream, hsResMgr* mgr)
|
||||
hsQuat rot;
|
||||
pos.Read(stream);
|
||||
rot.Read(stream);
|
||||
rot.MakeMatrix(&recipe.l2s);
|
||||
recipe.l2s.SetTranslate(&pos);
|
||||
rot.MakeMatrix(&fRecipe.l2s);
|
||||
fRecipe.l2s.SetTranslate(&pos);
|
||||
|
||||
fProps.Read(stream);
|
||||
|
||||
if (recipe.bounds == plSimDefs::kSphereBounds)
|
||||
if (fRecipe.bounds == plSimDefs::kSphereBounds)
|
||||
{
|
||||
recipe.radius = stream->ReadSwapScalar();
|
||||
recipe.offset.Read(stream);
|
||||
fRecipe.radius = stream->ReadSwapScalar();
|
||||
fRecipe.offset.Read(stream);
|
||||
}
|
||||
else if (recipe.bounds == plSimDefs::kBoxBounds)
|
||||
else if (fRecipe.bounds == plSimDefs::kBoxBounds)
|
||||
{
|
||||
recipe.bDimensions.Read(stream);
|
||||
recipe.bOffset.Read(stream);
|
||||
fRecipe.bDimensions.Read(stream);
|
||||
fRecipe.bOffset.Read(stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (recipe.bounds == plSimDefs::kHullBounds)
|
||||
recipe.convexMesh = IReadHull(stream);
|
||||
if (fRecipe.bounds == plSimDefs::kHullBounds)
|
||||
fRecipe.convexMesh = IReadHull(stream);
|
||||
else
|
||||
recipe.triMesh = IReadTriMesh(stream);
|
||||
fRecipe.triMesh = IReadTriMesh(stream);
|
||||
}
|
||||
|
||||
Init(recipe);
|
||||
// If we do not have a world, specified, we go ahead and init into the main world...
|
||||
// This will been done in MsgReceive otherwise
|
||||
if (!fRecipe.worldKey)
|
||||
Init();
|
||||
|
||||
hsAssert(!fProxyGen, "Already have proxy gen, double read?");
|
||||
|
||||
@ -1115,7 +1125,7 @@ void plPXPhysical::Read(hsStream* stream, hsResMgr* mgr)
|
||||
// Statics are yellow
|
||||
physColor.Set(1.f,0.8f,0.2f,1.f);
|
||||
// if in a subworld... slightly transparent
|
||||
if(fWorldKey)
|
||||
if(fRecipe.worldKey)
|
||||
opac = 0.6f;
|
||||
}
|
||||
else
|
||||
@ -1241,7 +1251,7 @@ void plPXPhysical::Write(hsStream* stream, hsResMgr* mgr)
|
||||
stream->WriteSwapScalar(fActor->getMass());
|
||||
stream->WriteSwapScalar(friction);
|
||||
stream->WriteSwapScalar(restitution);
|
||||
stream->WriteByte(fBoundsType);
|
||||
stream->WriteByte(fRecipe.bounds);
|
||||
stream->WriteByte(fGroup);
|
||||
stream->WriteSwap32(fReportsOn);
|
||||
stream->WriteSwap16(fLOSDBs);
|
||||
@ -1259,14 +1269,14 @@ void plPXPhysical::Write(hsStream* stream, hsResMgr* mgr)
|
||||
|
||||
fProps.Write(stream);
|
||||
|
||||
if (fBoundsType == plSimDefs::kSphereBounds)
|
||||
if (fRecipe.bounds == plSimDefs::kSphereBounds)
|
||||
{
|
||||
const NxSphereShape* sphereShape = shape->isSphere();
|
||||
stream->WriteSwapScalar(sphereShape->getRadius());
|
||||
hsPoint3 localPos = plPXConvert::Point(sphereShape->getLocalPosition());
|
||||
localPos.Write(stream);
|
||||
}
|
||||
else if (fBoundsType == plSimDefs::kBoxBounds)
|
||||
else if (fRecipe.bounds == plSimDefs::kBoxBounds)
|
||||
{
|
||||
const NxBoxShape* boxShape = shape->isBox();
|
||||
hsPoint3 dim = plPXConvert::Point(boxShape->getDimensions());
|
||||
@ -1276,7 +1286,7 @@ void plPXPhysical::Write(hsStream* stream, hsResMgr* mgr)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fBoundsType == plSimDefs::kHullBounds)
|
||||
if (fRecipe.bounds == plSimDefs::kHullBounds)
|
||||
hsAssert(shape->isConvexMesh(), "Hull shape isn't a convex mesh");
|
||||
else
|
||||
hsAssert(shape->isTriangleMesh(), "Exact shape isn't a trimesh");
|
||||
|
@ -47,6 +47,9 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
#include "../plPhysical/plSimDefs.h"
|
||||
#include "hsBitVector.h"
|
||||
#include "hsUtils.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
class NxActor;
|
||||
class NxConvexMesh;
|
||||
@ -72,8 +75,6 @@ class NxCapsule;
|
||||
class PhysRecipe
|
||||
{
|
||||
public:
|
||||
PhysRecipe();
|
||||
|
||||
hsScalar mass;
|
||||
hsScalar friction;
|
||||
hsScalar restitution;
|
||||
@ -100,6 +101,12 @@ public:
|
||||
|
||||
// For export time only. The original data used to create the mesh
|
||||
hsVectorStream* meshStream;
|
||||
|
||||
PhysRecipe()
|
||||
: mass(0.f), friction(0.f), restitution(0.f), bounds(plSimDefs::kBoundsMax),
|
||||
group(plSimDefs::kGroupMax), reportsOn(0), convexMesh(nullptr), triMesh(nullptr),
|
||||
radius(0.f), offset(0.f, 0.f, 0.f), meshStream(nullptr)
|
||||
{ }
|
||||
};
|
||||
|
||||
class plPXPhysical : public plPhysical
|
||||
@ -120,7 +127,7 @@ public:
|
||||
GETINTERFACE_ANY(plPXPhysical, plPhysical);
|
||||
|
||||
// Export time and internal use only
|
||||
hsBool Init(PhysRecipe& recipe);
|
||||
hsBool Init();
|
||||
|
||||
virtual void Read(hsStream* s, hsResMgr* mgr);
|
||||
virtual void Write(hsStream* s, hsResMgr* mgr);
|
||||
@ -191,7 +198,11 @@ public:
|
||||
//this partially for exclude regions vs avatar capsule
|
||||
virtual hsBool OverlapWithCapsule(NxCapsule& cap);
|
||||
|
||||
virtual hsScalar GetMass() {return fMass;}
|
||||
virtual hsScalar GetMass() {return fRecipe.mass;}
|
||||
|
||||
PhysRecipe& GetRecipe() { return fRecipe; }
|
||||
const PhysRecipe& GetRecipe() const { return fRecipe; }
|
||||
|
||||
protected:
|
||||
class NxConvexMesh* IReadHull(hsStream* s);
|
||||
class NxTriangleMesh* IReadTriMesh(hsStream* s);
|
||||
@ -244,12 +255,11 @@ protected:
|
||||
NxActor* fActor;
|
||||
plKey fWorldKey; // either a subworld or nil
|
||||
|
||||
plSimDefs::Bounds fBoundsType;
|
||||
PhysRecipe fRecipe;
|
||||
plSimDefs::Group fGroup;
|
||||
UInt32 fReportsOn; // bit vector for groups we report interactions with
|
||||
UInt16 fLOSDBs; // Which LOS databases we get put into
|
||||
hsBitVector fProps; // plSimulationInterface::plSimulationProperties kept here
|
||||
float fMass;
|
||||
|
||||
plKey fObjectKey; // the key to our scene object
|
||||
plKey fSceneNode; // the room we're in
|
||||
|
52
Sources/Plasma/PubUtilLib/plPhysX/plPXSubWorld.cpp
Normal file
52
Sources/Plasma/PubUtilLib/plPhysX/plPXSubWorld.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
/*==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 "plPXSubWorld.h"
|
||||
|
||||
void plPXSubWorld::Read(hsStream* s, hsResMgr* mgr)
|
||||
{
|
||||
plObjInterface::Read(s, mgr);
|
||||
fGravity.Read(s);
|
||||
}
|
||||
|
||||
void plPXSubWorld::Write(hsStream* s, hsResMgr* mgr)
|
||||
{
|
||||
plObjInterface::Write(s, mgr);
|
||||
fGravity.Write(s);
|
||||
}
|
||||
|
||||
void plPXSubWorld::SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l)
|
||||
{
|
||||
// All this magick is handled elsewhere... Not asserting due to call spam.
|
||||
}
|
67
Sources/Plasma/PubUtilLib/plPhysX/plPXSubWorld.h
Normal file
67
Sources/Plasma/PubUtilLib/plPhysX/plPXSubWorld.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*==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==*/
|
||||
|
||||
#ifndef plPXSubWorld_h_inc
|
||||
#define plPXSubWorld_h_inc
|
||||
|
||||
#include "../../NucleusLib/pnSceneObject/plObjInterface.h"
|
||||
#include "hsGeometry3.h"
|
||||
|
||||
#define X_GRAVITY 0.f
|
||||
#define Y_GRAVITY 0.f
|
||||
#define Z_GRAVITY -32.174049f
|
||||
|
||||
class plPXSubWorld : public plObjInterface
|
||||
{
|
||||
hsVector3 fGravity;
|
||||
|
||||
public:
|
||||
plPXSubWorld() : fGravity(X_GRAVITY, Y_GRAVITY, Z_GRAVITY) { }
|
||||
plPXSubWorld(const hsVector3& gravity) : fGravity(gravity) { }
|
||||
|
||||
CLASSNAME_REGISTER(plPXSubWorld);
|
||||
GETINTERFACE_ANY(plPXSubWorld, plObjInterface);
|
||||
|
||||
void Read(hsStream* s, hsResMgr* mgr) HS_OVERRIDE;
|
||||
void Write(hsStream* s, hsResMgr* mgr) HS_OVERRIDE;
|
||||
|
||||
Int32 GetNumProperties() const HS_OVERRIDE { return 0; }
|
||||
void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l) HS_OVERRIDE;
|
||||
|
||||
const hsVector3& GetGravity() const { return fGravity; }
|
||||
hsVector3& GetGravity() { return fGravity; }
|
||||
void SetGravity(const hsVector3& gravity) { fGravity = gravity; }
|
||||
};
|
||||
|
||||
#endif // plPXSubWorld_h_inc
|
@ -48,6 +48,9 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
|
||||
REGISTER_CREATABLE(plPXPhysical);
|
||||
|
||||
#include "plPXSubWorld.h"
|
||||
REGISTER_CREATABLE(plPXSubWorld);
|
||||
|
||||
//#include "plHKSimulationSynchMsg.h"
|
||||
//REGISTER_CREATABLE(plHKSimulationSynchMsg);
|
||||
|
||||
|
@ -49,6 +49,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
#include "plPXPhysical.h"
|
||||
#include "plPXPhysicalControllerCore.h"
|
||||
#include "plPXConvert.h"
|
||||
#include "plPXSubWorld.h"
|
||||
#include "plLOSDispatch.h"
|
||||
#include "../plPhysical/plPhysicsSoundMgr.h"
|
||||
#include "../plStatusLog/plStatusLog.h"
|
||||
@ -424,8 +425,18 @@ NxScene* plSimulationMgr::GetScene(plKey world)
|
||||
{
|
||||
UInt32 maxSteps = (UInt32)hsCeil(fMaxDelta / fStepSize);
|
||||
|
||||
// The world key is assumed to be loaded (or null for main world) if we are here.
|
||||
// As such, let us grab the plSceneObject's PXSubWorld definition to figure out
|
||||
// what gravity should look like. Who knows, we might be in MC Escher land...
|
||||
NxVec3 gravity(X_GRAVITY, Y_GRAVITY, Z_GRAVITY);
|
||||
if (plSceneObject* so = plSceneObject::ConvertNoRef(world->VerifyLoaded())) {
|
||||
if (plPXSubWorld* subworld = plPXSubWorld::ConvertNoRef(so->GetGenericInterface(plPXSubWorld::Index()))) {
|
||||
gravity = plPXConvert::Vector(subworld->GetGravity());
|
||||
}
|
||||
}
|
||||
|
||||
NxSceneDesc sceneDesc;
|
||||
sceneDesc.gravity.set(0, 0, -32.174049f);
|
||||
sceneDesc.gravity = gravity;
|
||||
sceneDesc.userTriggerReport = &gSensorReport;
|
||||
sceneDesc.userContactReport = &gContactReport;
|
||||
sceneDesc.maxTimestep = fStepSize;
|
||||
@ -615,15 +626,15 @@ void plSimulationMgr::Advance(float delSecs)
|
||||
{
|
||||
if (fExtraProfile)
|
||||
Log("Step clamped from %f to limit of %f", fAccumulator, fMaxDelta);
|
||||
fAccumulator = fMaxDelta;
|
||||
fAccumulator = kDefaultMaxDelta;
|
||||
}
|
||||
|
||||
++fStepCount;
|
||||
|
||||
// Perform as many whole substeps as possible saving the remainder in our accumulator.
|
||||
int numSubSteps = (int)(fAccumulator / fStepSize + 0.000001f);
|
||||
float delta = numSubSteps * fStepSize;
|
||||
fAccumulator -= delta;
|
||||
// Perform as many whole substeps as possible saving the remainder in our accumulator.
|
||||
int numSubSteps = (int)(fAccumulator / fStepSize + 0.000001f);
|
||||
float delta = numSubSteps * fStepSize;
|
||||
fAccumulator -= delta;
|
||||
|
||||
plProfile_IncCount(StepLen, (int)(delta*1000));
|
||||
plProfile_BeginTiming(Step);
|
||||
@ -772,25 +783,21 @@ void plSimulationMgr::ISendUpdates()
|
||||
// RESOLUTION & TIMEOUT PARAMETERS
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void plSimulationMgr::SetMaxDelta(float maxDelta)
|
||||
{
|
||||
fMaxDelta = maxDelta;
|
||||
}
|
||||
|
||||
float plSimulationMgr::GetMaxDelta() const
|
||||
{
|
||||
return fMaxDelta;
|
||||
}
|
||||
|
||||
void plSimulationMgr::SetStepsPerSecond(int stepsPerSecond)
|
||||
{
|
||||
fStepSize = 1.0f / (float)stepsPerSecond;
|
||||
}
|
||||
|
||||
int plSimulationMgr::GetStepsPerSecond()
|
||||
{
|
||||
return (int)((1.0 / fStepSize) + 0.5f); // round to nearest int
|
||||
return (int)((1.0 / fStepSize) + 0.5f); // round to nearest int
|
||||
}
|
||||
|
||||
int plSimulationMgr::GetMaterialIdx(NxScene* scene, hsScalar friction, hsScalar restitution)
|
||||
|
@ -122,7 +122,7 @@ protected:
|
||||
// physicals and the avatar may move at a faster rate than usual.
|
||||
void SetMaxDelta(float maxDelta);
|
||||
float GetMaxDelta() const;
|
||||
|
||||
|
||||
// Set the number of steps per second that physics will advance.
|
||||
// The more steps per second, the less fallthough and more accurate
|
||||
// simulation response.
|
||||
@ -159,6 +159,7 @@ protected:
|
||||
|
||||
float fMaxDelta;
|
||||
float fStepSize;
|
||||
|
||||
float fAccumulator;
|
||||
|
||||
UInt32 fStepCount;
|
||||
|
@ -2550,6 +2550,113 @@ bool VaultGetVisitAgeLink (const plAgeInfoStruct * info, class plAgeLinkStruct *
|
||||
return true;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
namespace _VaultRegisterVisitAge {
|
||||
struct _Params {
|
||||
|
||||
plSpawnPointInfo* fSpawn;
|
||||
void* fAgeInfoId;
|
||||
|
||||
~_Params() {
|
||||
DEL(fSpawn);
|
||||
}
|
||||
};
|
||||
|
||||
void _CreateAgeLinkNode(ENetError result, void* state, void* param, RelVaultNode* node) {
|
||||
if (IS_NET_ERROR(result)) {
|
||||
LogMsg(kLogError, "RegisterVisitAge: Failed to create AgeLink (async)");
|
||||
DEL(param);
|
||||
return;
|
||||
}
|
||||
|
||||
_Params* p = (_Params*)param;
|
||||
RelVaultNode* ageInfo = VaultGetNodeIncRef((UInt32)p->fAgeInfoId);
|
||||
|
||||
// Add ourselves to the Can Visit folder of the age
|
||||
if (RelVaultNode * playerInfo = VaultGetPlayerInfoNodeIncRef()) {
|
||||
if (RelVaultNode* canVisit = ageInfo->GetChildPlayerInfoListNodeIncRef(plVault::kCanVisitFolder, 1)) {
|
||||
VaultAddChildNode(canVisit->nodeId, playerInfo->nodeId, 0, nil, nil);
|
||||
canVisit->DecRef();
|
||||
}
|
||||
|
||||
playerInfo->DecRef();
|
||||
}
|
||||
|
||||
// Get our AgesICanVisit folder
|
||||
if (RelVaultNode* iCanVisit = VaultGetAgesICanVisitFolderIncRef()) {
|
||||
VaultAddChildNode(node->nodeId, ageInfo->nodeId, 0, nil, nil);
|
||||
VaultAddChildNode(iCanVisit->nodeId, node->nodeId, 0, nil, nil);
|
||||
}
|
||||
|
||||
// Update the AgeLink with a spawn point
|
||||
VaultAgeLinkNode access(node);
|
||||
access.AddSpawnPoint(*p->fSpawn);
|
||||
|
||||
// Send out the VaultNotify msg
|
||||
plVaultNotifyMsg * msg = NEWZERO(plVaultNotifyMsg);
|
||||
msg->SetType(plVaultNotifyMsg::kRegisteredVisitAge);
|
||||
msg->SetResultCode(true);
|
||||
msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, node->nodeId);
|
||||
msg->Send();
|
||||
|
||||
//Don't leak memory
|
||||
DEL(param);
|
||||
}
|
||||
|
||||
void _DownloadCallback(ENetError result, void* param) {
|
||||
if (IS_NET_ERROR(result)) {
|
||||
LogMsg(kLogError, "RegisterVisitAge: Failed to download age vault (async)");
|
||||
DEL(param);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the AgeLink node
|
||||
VaultCreateNode(plVault::kNodeType_AgeLink, (FVaultCreateNodeCallback)_CreateAgeLinkNode, nil, param);
|
||||
}
|
||||
|
||||
void _InitAgeCallback(ENetError result, void* state, void* param, UInt32 ageVaultId, UInt32 ageInfoId) {
|
||||
if (IS_NET_ERROR(result)) {
|
||||
LogMsg(kLogError, "RegisterVisitAge: Failed to init age vault (async)");
|
||||
DEL(param);
|
||||
return;
|
||||
}
|
||||
|
||||
// Save the AgeInfo nodeID, then download the age vault
|
||||
_Params* p = (_Params*)param;
|
||||
p->fAgeInfoId = (void*)ageInfoId;
|
||||
|
||||
VaultDownload(L"RegisterVisitAge",
|
||||
ageInfoId,
|
||||
(FVaultDownloadCallback)_DownloadCallback,
|
||||
param,
|
||||
nil,
|
||||
nil
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
void VaultRegisterVisitAge(const plAgeLinkStruct* link) {
|
||||
using namespace _VaultRegisterVisitAge;
|
||||
|
||||
// Test to see if we already have this visit age...
|
||||
plAgeLinkStruct existing;
|
||||
if (VaultGetVisitAgeLink(link->GetAgeInfo(), &existing))
|
||||
return;
|
||||
|
||||
// Still here? We need to actually do some work, then.
|
||||
_Params* p = TRACKED_NEW _Params;
|
||||
p->fSpawn = TRACKED_NEW plSpawnPointInfo(link->SpawnPoint());
|
||||
|
||||
// This doesn't actually *create* a new age but rather fetches the
|
||||
// already existing age vault. Weird? Yes...
|
||||
VaultInitAge(link->GetAgeInfo(),
|
||||
kNilGuid,
|
||||
(FVaultInitAgeCallback)_InitAgeCallback,
|
||||
nil,
|
||||
p
|
||||
);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
namespace _VaultRegisterOwnedAgeAndWait {
|
||||
|
||||
@ -2807,6 +2914,123 @@ bool VaultRegisterOwnedAgeAndWait (const plAgeLinkStruct * link) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
namespace _VaultRegisterOwnedAge {
|
||||
struct _Params {
|
||||
plSpawnPointInfo* fSpawn;
|
||||
void* fAgeInfoId;
|
||||
|
||||
~_Params() {
|
||||
DEL(fSpawn);
|
||||
}
|
||||
};
|
||||
|
||||
void _AddAgeInfoNode(ENetError result, void* param) {
|
||||
if (IS_NET_ERROR(result))
|
||||
LogMsg(kLogError, "VaultRegisterOwnedAge: Failed to add info to link (async)");
|
||||
}
|
||||
|
||||
void _AddAgeLinkNode(ENetError result, void* param) {
|
||||
if (IS_NET_ERROR(result))
|
||||
LogMsg(kLogError, "VaultRegisterOwnedAge: Failed to add age to bookshelf (async)");
|
||||
}
|
||||
|
||||
void _AddPlayerInfoNode(ENetError result, void* param) {
|
||||
if (IS_NET_ERROR(result))
|
||||
LogMsg(kLogError, "VaultRegisterOwnedAge: Failed to add playerInfo to ageOwners (async)");
|
||||
}
|
||||
|
||||
void _CreateAgeLinkNode(ENetError result, void* state, void* param, RelVaultNode* node) {
|
||||
if (IS_NET_ERROR(result)) {
|
||||
LogMsg(kLogError, "VaultRegisterOwnedAge: Failed to create AgeLink (async)");
|
||||
DEL(param);
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab our params
|
||||
_Params* p = (_Params*)param;
|
||||
|
||||
// Set swpoint
|
||||
VaultAgeLinkNode aln(node);
|
||||
aln.AddSpawnPoint(*(p->fSpawn));
|
||||
|
||||
// Make some refs
|
||||
RelVaultNode* agesIOwn = VaultGetAgesIOwnFolderIncRef();
|
||||
RelVaultNode* plyrInfo = VaultGetPlayerInfoNodeIncRef();
|
||||
VaultAddChildNode(agesIOwn->nodeId, node->nodeId, 0, (FVaultAddChildNodeCallback)_AddAgeLinkNode, nil);
|
||||
VaultAddChildNode(node->nodeId, (UInt32)p->fAgeInfoId, 0, (FVaultAddChildNodeCallback)_AddAgeInfoNode, nil);
|
||||
|
||||
// Add our PlayerInfo to important places
|
||||
if (RelVaultNode* rvnAgeInfo = VaultGetNodeIncRef((UInt32)p->fAgeInfoId)) {
|
||||
if (RelVaultNode* rvnAgeOwners = rvnAgeInfo->GetChildPlayerInfoListNodeIncRef(plVault::kAgeOwnersFolder, 1)) {
|
||||
VaultAddChildNode(rvnAgeOwners->nodeId, plyrInfo->nodeId, 0, (FVaultAddChildNodeCallback)_AddPlayerInfoNode, nil);
|
||||
rvnAgeOwners->DecRef();
|
||||
}
|
||||
|
||||
rvnAgeInfo->DecRef();
|
||||
}
|
||||
|
||||
// Fire off vault callbacks
|
||||
plVaultNotifyMsg* msg = NEWZERO(plVaultNotifyMsg);
|
||||
msg->SetType(plVaultNotifyMsg::kRegisteredOwnedAge);
|
||||
msg->SetResultCode(result);
|
||||
msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, node->nodeId);
|
||||
msg->Send();
|
||||
|
||||
// Don't leak memory
|
||||
agesIOwn->DecRef();
|
||||
plyrInfo->DecRef();
|
||||
DEL(p);
|
||||
}
|
||||
|
||||
void _DownloadCallback(ENetError result, void* param) {
|
||||
if (IS_NET_ERROR(result)) {
|
||||
LogMsg(kLogError, "VaultRegisterOwnedAge: Failed to download age vault (async)");
|
||||
DEL(param);
|
||||
} else
|
||||
VaultCreateNode(plVault::kNodeType_AgeLink, (FVaultCreateNodeCallback)_CreateAgeLinkNode, nil, param);
|
||||
}
|
||||
|
||||
void _InitAgeCallback(ENetError result, void* state, void* param, UInt32 ageVaultId, UInt32 ageInfoVaultId) {
|
||||
if (IS_NET_SUCCESS(result)) {
|
||||
_Params* p = TRACKED_NEW _Params();
|
||||
p->fAgeInfoId = (void*)ageInfoVaultId;
|
||||
p->fSpawn = (plSpawnPointInfo*)param;
|
||||
|
||||
VaultDownload(
|
||||
L"RegisterOwnedAge",
|
||||
ageInfoVaultId,
|
||||
(FVaultDownloadCallback)_DownloadCallback,
|
||||
p,
|
||||
nil,
|
||||
nil);
|
||||
} else
|
||||
LogMsg(kLogError, "VaultRegisterOwnedAge: Failed to init age (async)");
|
||||
}
|
||||
}; // namespace _VaultRegisterOwnedAge
|
||||
|
||||
void VaultRegisterOwnedAge(const plAgeLinkStruct* link) {
|
||||
using namespace _VaultRegisterOwnedAge;
|
||||
|
||||
RelVaultNode* agesIOwn = VaultGetAgesIOwnFolderIncRef();
|
||||
if (agesIOwn == nil) {
|
||||
LogMsg(kLogError, "VaultRegisterOwnedAge: Couldn't find the stupid AgesIOwnfolder!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we don't already have the age
|
||||
plAgeLinkStruct existing;
|
||||
if (VaultGetOwnedAgeLink(link->GetAgeInfo(), &existing))
|
||||
return;
|
||||
|
||||
// Let's go async, my friend :)
|
||||
VaultInitAge(link->GetAgeInfo(),
|
||||
kNilGuid,
|
||||
(FVaultInitAgeCallback)_InitAgeCallback,
|
||||
nil,
|
||||
TRACKED_NEW plSpawnPointInfo(link->SpawnPoint()));
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
namespace _VaultRegisterVisitAgeAndWait {
|
||||
|
||||
@ -3220,6 +3444,38 @@ bool VaultHasChronicleEntry (const wchar entryName[], int entryType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
void VaultAddChronicleEntry (const wchar entryName[], int entryType, const wchar entryValue[]) {
|
||||
// Sometimes we try to create chrons in StartUp.
|
||||
// This is bad...
|
||||
if (GetPlayerNode() == nil)
|
||||
return;
|
||||
|
||||
if (RelVaultNode* rvnChrn = VaultFindChronicleEntryIncRef(entryName, entryType)) {
|
||||
VaultChronicleNode chrnNode(rvnChrn);
|
||||
chrnNode.SetEntryValue(entryValue);
|
||||
rvnChrn->DecRef();
|
||||
} else {
|
||||
NetVaultNode* templateNode = NEWZERO(NetVaultNode);
|
||||
templateNode->IncRef();
|
||||
templateNode->SetNodeType(plVault::kNodeType_Chronicle);
|
||||
VaultChronicleNode chrnNode(templateNode);
|
||||
chrnNode.SetEntryName(entryName);
|
||||
chrnNode.SetEntryType(entryType);
|
||||
chrnNode.SetEntryValue(entryValue);
|
||||
VaultCreateNode(templateNode, (FVaultCreateNodeCallback)(_VaultAddChronicleEntryCB), nil, nil);
|
||||
templateNode->DecRef();
|
||||
}
|
||||
}
|
||||
|
||||
void _VaultAddChronicleEntryCB(ENetError result, void* state, void * param, RelVaultNode* node) {
|
||||
if (result == ENetError::kNetSuccess) {
|
||||
RelVaultNode* rvnFldr = GetChildFolderNode(GetPlayerNode(), plVault::kChronicleFolder, 1);
|
||||
if (rvnFldr != nil)
|
||||
VaultAddChildNode(rvnFldr->nodeId, node->nodeId, 0, nil, nil);
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
void VaultAddChronicleEntryAndWait (
|
||||
const wchar entryName[],
|
||||
@ -3457,7 +3713,7 @@ void VaultProcessVisitNote(RelVaultNode * rvnVisit) {
|
||||
plAgeLinkStruct link;
|
||||
if (visitAcc.GetVisitInfo(link.GetAgeInfo())) {
|
||||
// Add it to our "ages i can visit" folder
|
||||
VaultRegisterVisitAgeAndWait(&link);
|
||||
VaultRegisterVisitAge(&link);
|
||||
}
|
||||
// remove it from the inbox
|
||||
VaultRemoveChildNode(rvnInbox->nodeId, rvnVisit->nodeId, nil, nil);
|
||||
@ -3504,7 +3760,7 @@ void VaultProcessPlayerInbox () {
|
||||
plAgeLinkStruct link;
|
||||
if (visitAcc.GetVisitInfo(link.GetAgeInfo())) {
|
||||
// Add it to our "ages i can visit" folder
|
||||
VaultRegisterVisitAgeAndWait(&link);
|
||||
VaultRegisterVisitAge(&link);
|
||||
}
|
||||
// remove it from the inbox
|
||||
VaultRemoveChildNode(rvnInbox->nodeId, rvnVisit->nodeId, nil, nil);
|
||||
@ -4196,6 +4452,89 @@ bool VaultAgeFindOrCreateSubAgeLinkAndWait (
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
namespace _VaultCreateSubAge {
|
||||
void _CreateNodeCallback(ENetError result, void* state, void* param, RelVaultNode* node) {
|
||||
if (IS_NET_ERROR(result)) {
|
||||
LogMsg(kLogError, "CreateSubAge: Failed to create AgeLink (async)");
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the children to the right places
|
||||
VaultAddChildNode(node->nodeId, (UInt32)param, 0, nil, nil);
|
||||
if (RelVaultNode* saFldr = VaultGetAgeSubAgesFolderIncRef()) {
|
||||
VaultAddChildNode(saFldr->nodeId, node->nodeId, 0, nil, nil);
|
||||
saFldr->DecRef();
|
||||
} else
|
||||
LogMsg(kLogError, "CreateSubAge: Couldn't find SubAges folder (async)");
|
||||
|
||||
// Send the VaultNotify that the plNetLinkingMgr wants...
|
||||
plVaultNotifyMsg * msg = NEWZERO(plVaultNotifyMsg);
|
||||
msg->SetType(plVaultNotifyMsg::kRegisteredSubAgeLink);
|
||||
msg->SetResultCode(result);
|
||||
msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, node->nodeId);
|
||||
msg->Send();
|
||||
}
|
||||
|
||||
void _DownloadCallback(ENetError result, void* param) {
|
||||
if (IS_NET_ERROR(result)) {
|
||||
LogMsg(kLogError, "CreateSubAge: Failed to download age vault (async)");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the AgeLink node
|
||||
VaultCreateNode(plVault::kNodeType_AgeLink,
|
||||
(FVaultCreateNodeCallback)_CreateNodeCallback,
|
||||
nil,
|
||||
param
|
||||
);
|
||||
}
|
||||
|
||||
void _InitAgeCallback(ENetError result, void* state, void* param, UInt32 ageVaultId, UInt32 ageInfoId) {
|
||||
if (IS_NET_ERROR(result)) {
|
||||
LogMsg(kLogError, "CreateSubAge: Failed to init age (async)");
|
||||
return;
|
||||
}
|
||||
|
||||
// Download age vault
|
||||
VaultDownload(L"CreateSubAge",
|
||||
ageInfoId,
|
||||
(FVaultDownloadCallback)_DownloadCallback,
|
||||
(void*)ageInfoId,
|
||||
nil,
|
||||
nil
|
||||
);
|
||||
}
|
||||
}; // namespace _VaultCreateSubAge
|
||||
|
||||
bool VaultAgeFindOrCreateSubAgeLink(const plAgeInfoStruct* info, plAgeLinkStruct* link, const Uuid& parentUuid) {
|
||||
using namespace _VaultCreateSubAge;
|
||||
|
||||
// First, try to find an already existing subage
|
||||
if (RelVaultNode* rvnLink = VaultGetSubAgeLinkIncRef(info)) {
|
||||
VaultAgeLinkNode accLink(rvnLink);
|
||||
accLink.CopyTo(link);
|
||||
|
||||
if (RelVaultNode* rvnInfo = rvnLink->GetChildNodeIncRef(plVault::kNodeType_AgeInfo, 1)) {
|
||||
VaultAgeInfoNode accInfo(rvnInfo);
|
||||
accInfo.CopyTo(link->GetAgeInfo());
|
||||
rvnInfo->DecRef();
|
||||
}
|
||||
|
||||
rvnLink->DecRef();
|
||||
return true;
|
||||
}
|
||||
|
||||
VaultInitAge(info,
|
||||
parentUuid,
|
||||
(FVaultInitAgeCallback)_InitAgeCallback,
|
||||
nil,
|
||||
nil
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
namespace _VaultCreateChildAgeAndWait {
|
||||
|
||||
@ -4472,6 +4811,144 @@ bool VaultAgeFindOrCreateChildAgeLinkAndWait (
|
||||
return true;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
namespace _VaultCreateChildAge {
|
||||
struct _Params {
|
||||
void* fChildAgesFldr;
|
||||
void* fAgeInfoId;
|
||||
};
|
||||
|
||||
void _CreateNodeCallback(ENetError result, void* state, void* param, RelVaultNode* node) {
|
||||
if (IS_NET_ERROR(result)) {
|
||||
LogMsg(kLogError, "CreateChildAge: Failed to create AgeLink (async)");
|
||||
DEL(param);
|
||||
return;
|
||||
}
|
||||
|
||||
_Params* p = (_Params*)param;
|
||||
|
||||
// Add the children to the right places
|
||||
VaultAddChildNode(node->nodeId, (UInt32)p->fAgeInfoId, 0, nil, nil);
|
||||
VaultAddChildNode((UInt32)p->fChildAgesFldr, node->nodeId, 0, nil, nil);
|
||||
|
||||
// Send the VaultNotify that the plNetLinkingMgr wants...
|
||||
plVaultNotifyMsg * msg = NEWZERO(plVaultNotifyMsg);
|
||||
msg->SetType(plVaultNotifyMsg::kRegisteredChildAgeLink);
|
||||
msg->SetResultCode(result);
|
||||
msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, node->nodeId);
|
||||
msg->Send();
|
||||
|
||||
DEL(param);
|
||||
}
|
||||
|
||||
void _DownloadCallback(ENetError result, void* param) {
|
||||
if (IS_NET_ERROR(result)) {
|
||||
LogMsg(kLogError, "CreateChildAge: Failed to download age vault (async)");
|
||||
DEL(param);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the AgeLink node
|
||||
VaultCreateNode(plVault::kNodeType_AgeLink,
|
||||
(FVaultCreateNodeCallback)_CreateNodeCallback,
|
||||
nil,
|
||||
param
|
||||
);
|
||||
}
|
||||
|
||||
void _InitAgeCallback(ENetError result, void* state, void* param, UInt32 ageVaultId, UInt32 ageInfoId) {
|
||||
if (IS_NET_ERROR(result)) {
|
||||
LogMsg(kLogError, "CreateChildAge: Failed to init age (async)");
|
||||
DEL(param);
|
||||
return;
|
||||
}
|
||||
|
||||
_Params* p = (_Params*)param;
|
||||
p->fAgeInfoId = (void*)ageInfoId;
|
||||
|
||||
// Download age vault
|
||||
VaultDownload(L"CreateChildAge",
|
||||
ageInfoId,
|
||||
(FVaultDownloadCallback)_DownloadCallback,
|
||||
param,
|
||||
nil,
|
||||
nil
|
||||
);
|
||||
}
|
||||
}; // namespace _VaultCreateAge
|
||||
|
||||
UInt8 VaultAgeFindOrCreateChildAgeLink(
|
||||
const wchar parentAgeName[],
|
||||
const plAgeInfoStruct* info,
|
||||
plAgeLinkStruct* link)
|
||||
{
|
||||
using namespace _VaultCreateChildAge;
|
||||
|
||||
// First, try to find an already existing ChildAge
|
||||
char name[MAX_PATH];
|
||||
StrToAnsi(name, parentAgeName, arrsize(parentAgeName));
|
||||
plAgeInfoStruct search;
|
||||
search.SetAgeFilename(name);
|
||||
|
||||
RelVaultNode* rvnParentInfo = nil;
|
||||
if (RelVaultNode* rvnParentLink = VaultGetOwnedAgeLinkIncRef(&search)) {
|
||||
rvnParentInfo = rvnParentLink->GetChildNodeIncRef(plVault::kNodeType_AgeInfo, 1);
|
||||
rvnParentLink->DecRef();
|
||||
} else // Fallback to current age
|
||||
rvnParentInfo = VaultGetAgeInfoNodeIncRef();
|
||||
|
||||
// Test to make sure nothing went horribly wrong...
|
||||
if (rvnParentInfo == nil) {
|
||||
LogMsg(kLogError, "CreateChildAge: Couldn't find the parent ageinfo (async)");
|
||||
return hsFail;
|
||||
}
|
||||
|
||||
// Still here? Try to find the Child Ages folder
|
||||
UInt8 retval = hsFail;
|
||||
if (RelVaultNode* rvnChildAges = rvnParentInfo->GetChildAgeInfoListNodeIncRef(plVault::kChildAgesFolder, 1)) {
|
||||
const char* ageName = info->GetAgeFilename();
|
||||
wchar hack[MAX_PATH];
|
||||
StrToUnicode(hack, ageName, arrsize(ageName));
|
||||
|
||||
// Search for our age
|
||||
NetVaultNode* temp = NEWZERO(NetVaultNode);
|
||||
temp->SetNodeType(plVault::kNodeType_AgeInfo);
|
||||
VaultAgeInfoNode theAge(temp);
|
||||
theAge.SetAgeFilename(hack);
|
||||
|
||||
if (RelVaultNode* rvnAgeInfo = rvnChildAges->GetChildNodeIncRef(temp, 2)) {
|
||||
RelVaultNode* rvnAgeLink = rvnAgeInfo->GetParentAgeLinkIncRef();
|
||||
|
||||
VaultAgeLinkNode accAgeLink(rvnAgeLink);
|
||||
accAgeLink.CopyTo(link);
|
||||
VaultAgeInfoNode accAgeInfo(rvnAgeInfo);
|
||||
accAgeInfo.CopyTo(link->GetAgeInfo());
|
||||
|
||||
rvnAgeLink->DecRef();
|
||||
rvnAgeInfo->DecRef();
|
||||
|
||||
retval = TRUE;
|
||||
} else {
|
||||
_Params* p = TRACKED_NEW _Params;
|
||||
p->fChildAgesFldr = (void*)rvnChildAges->nodeId;
|
||||
|
||||
VaultAgeInfoNode accParentInfo(rvnParentInfo);
|
||||
VaultInitAge(info,
|
||||
accParentInfo.ageInstUuid,
|
||||
(FVaultInitAgeCallback)_InitAgeCallback,
|
||||
nil,
|
||||
p
|
||||
);
|
||||
}
|
||||
|
||||
temp->DecRef();
|
||||
rvnChildAges->DecRef();
|
||||
retval = FALSE;
|
||||
}
|
||||
|
||||
rvnParentInfo->DecRef();
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
|
@ -349,12 +349,16 @@ bool VaultSetAgePublicAndWait (NetVaultNode * ageInfoNode, bool publicOrNot);
|
||||
RelVaultNode * VaultGetVisitAgeLinkIncRef (const plAgeInfoStruct * info);
|
||||
bool VaultGetVisitAgeLink (const plAgeInfoStruct * info, class plAgeLinkStruct * link);
|
||||
bool VaultRegisterOwnedAgeAndWait (const plAgeLinkStruct * link);
|
||||
void VaultRegisterOwnedAge(const plAgeLinkStruct* link);
|
||||
bool VaultRegisterVisitAgeAndWait (const plAgeLinkStruct * link);
|
||||
void VaultRegisterVisitAge (const plAgeLinkStruct* link);
|
||||
bool VaultUnregisterOwnedAgeAndWait (const plAgeInfoStruct * info);
|
||||
bool VaultUnregisterVisitAgeAndWait (const plAgeInfoStruct * info);
|
||||
RelVaultNode * VaultFindChronicleEntryIncRef (const wchar entryName[], int entryType = -1);
|
||||
bool VaultHasChronicleEntry (const wchar entryName[], int entryType = -1);
|
||||
// if entry of same name and type already exists, value is updated
|
||||
void VaultAddChronicleEntry (const wchar entryName[], int entryType, const wchar entryValue[]);
|
||||
void _VaultAddChronicleEntryCB(ENetError result, void* state, void * param, RelVaultNode* node);
|
||||
void VaultAddChronicleEntryAndWait (
|
||||
const wchar entryName[],
|
||||
int entryType,
|
||||
@ -421,6 +425,7 @@ void VaultAgeUpdateAgeSDL (const class plStateDataRecord * rec);
|
||||
|
||||
unsigned VaultAgeGetAgeTime ();
|
||||
|
||||
RelVaultNode * VaultGetSubAgeLinkIncRef (const plAgeInfoStruct * info);
|
||||
bool VaultAgeGetSubAgeLink (
|
||||
const plAgeInfoStruct * info,
|
||||
plAgeLinkStruct * link
|
||||
@ -430,12 +435,13 @@ bool VaultAgeFindOrCreateSubAgeLinkAndWait (
|
||||
plAgeLinkStruct * link,
|
||||
const Uuid & parentAgeInstId
|
||||
);
|
||||
bool VaultAgeFindOrCreateSubAgeLink(const plAgeInfoStruct* info, plAgeLinkStruct* link, const Uuid& parentUuid);
|
||||
bool VaultAgeFindOrCreateChildAgeLinkAndWait (
|
||||
const wchar parentAgeName[], // nil --> current age, non-nil --> owned age by given name
|
||||
const plAgeInfoStruct * info,
|
||||
plAgeLinkStruct * link
|
||||
);
|
||||
|
||||
UInt8 VaultAgeFindOrCreateChildAgeLink(const wchar parentAgeName[], const plAgeInfoStruct* info, plAgeLinkStruct* link);
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
Reference in New Issue
Block a user