void plNetServerSessionInfo::Clear()
{
    fFlags = 0;
    fServerName = "";
    fServerType = plNetServerConstants::kInvalidLo;
    fServerAddr = "";
    fServerPort = 0;
    fServerGuid = plUUID();
}
////////////////////////////////////////////////////////
// plNetMsgMemberUpdate
////////////////////////////////////////////////////////
int plNetMsgMemberUpdate::IPokeBuffer(hsStream* stream, uint32_t peekOptions)
{
    int bytes=plNetMsgServerToClient::IPokeBuffer(stream, peekOptions);
    if (bytes)
    {
        // FIX ME to something nice
        fMemberInfo.GetClientGuid()->SetClientKey(_TEMP_CONVERT_FROM_LITERAL(""));
        fMemberInfo.GetClientGuid()->SetAccountUUID(plUUID());
        fMemberInfo.Poke(stream, peekOptions);
        stream->WriteByte(fAddMember);
        
        bytes=stream->GetPosition();
    }
    return bytes;
}
hsBool  plSceneInputInterface::MsgReceive( plMessage *msg )
{
    plLOSHitMsg *pLOSMsg = plLOSHitMsg::ConvertNoRef( msg );
    if( pLOSMsg )
    {
        if( pLOSMsg->fRequestID == ID_FIND_CLICKABLE )
        {
            hsBool clearCursor = false;
            if (!fClickability)
                return true;
            if( pLOSMsg->fObj )
            {
                // is this object clickable?
                plSceneObject *pObj = plSceneObject::ConvertNoRef( pLOSMsg->fObj->ObjectIsLoaded() );
                if( pObj )
                {
                    if (fShowLOS)
                    {
                        if (pLOSMsg->fNoHit)
                            DetectorLogSpecial("%s: LOS miss", pObj->GetKeyName().c_str());
                        else
                            DetectorLogSpecial("%s: LOS hit", pObj->GetKeyName().c_str());
                    }
                    int i;
                    const plInterfaceInfoModifier* pMod = 0;
                    for( i = 0; i < pObj->GetNumModifiers(); i++ )
                    {
                        if (fBookMode == kNotOffering) // when sharing a book we don't care about other clickables
                        {
                            pMod = plInterfaceInfoModifier::ConvertNoRef( pObj->GetModifier(i) );
                            if (pMod) // we found our list, stop here
                            {
                                plLogicModBase* pLogicMod = (plLogicModBase*)pObj->GetModifierByType(plLogicModBase::Index());
                                if (!pLogicMod)
                                    return true;

                                if (fCurrentClickable != pObj->GetKey())
                                {   // is it the current clickable already?
                                    ClearClickableMap();
                                    fCurrentCursor = SetCurrentCursorID(kNullCursor);
                                    fCurrentClickable = pObj->GetKey();
                                    fCurrentClickableLogicMod = pLogicMod->GetKey();
                                    fCurrentClickPoint = pLOSMsg->fHitPoint;
                                    for (int x = 0; x < pMod->GetNumReferencedKeys(); x++)
                                        fClickableMap.Append( new clickableTest(pMod->GetReferencedKey(x)));
                                }
                                else
                                {
                                    // even if this is still the same clickable object, the cursor could be
                                    // ...at a different spot on the clickable, so save that
                                    fCurrentClickPoint = pLOSMsg->fHitPoint;
                                }
                                fCurrClickIsAvatar = false;
                                return true;
                            }
                        }
                        
                        // see if it is an avatar 
                        plArmatureMod* armMod = (plArmatureMod*)plArmatureMod::ConvertNoRef( pObj->GetModifier(i));
                        if (armMod)
                        {
                            if (armMod->IsMidLink())
                                return true;

                            // okay, are we a CCR?
                            hsBool amCCR = plNetClientMgr::GetInstance()->GetCCRLevel();
                            
                            // is this person a NPC or CCR?
                            int mbrIdx=plNetClientMgr::GetInstance()->TransportMgr().FindMember(pObj->GetKey());
                            plNetTransportMember* pMbr = plNetClientMgr::GetInstance()->TransportMgr().GetMember(mbrIdx);
                            if (!pMbr) // whoops - it's a freakin' NPC !
                                return true;
                            
                            if (pMbr->IsCCR())
                            {
                                if (amCCR)
                                {
                                    // we can click on them 
                                    plMouseDevice::AddCCRToCursor();
                                }
                                else
                                {
                                    // nope
                                    return true;
                                }
                                
                            }
                            // now, if I am a CCR, let me click on anyone at any time
                            if (amCCR)
                            {
                                ClearClickableMap();
                                fCurrentClickable = pObj->GetKey();
                                fCurrentClickableLogicMod = nil;
                                fCurrClickIsAvatar = true;
                                fCurrentCursor = SetCurrentCursorID(kCursorPoised);
                                // not sure why we need to point on the avatar...
                                // ...but maybe something in the future will need this
                                fCurrentClickPoint = pLOSMsg->fHitPoint;
                                plMouseDevice::AddNameToCursor(plNetClientMgr::GetInstance()->GetPlayerName(fCurrentClickable));
                                // also add their player ID to the cursor
                                plMouseDevice::AddIDNumToCursor(pMbr->GetPlayerID());
                                return true;
                            }
                            // otherwise, cull people as necessary
                            // also make sure that they are not in our ignore list
                            else if (VaultAmIgnoringPlayer( pMbr->GetPlayerID()))
                                return true;
                            // further, if we are offering a book, only allow clicks on the person
                            // whom we've already offered it to (to cancel it)
                            else if (fBookMode == kBookOffered && pObj->GetKey() != fOffereeKey)
                                return true;
                            // within distance
                            // also... make sure they aren't off climbing a ladder or looking at their KI
                            else if (fBookMode == kOfferBook)
                            {
                                plArmatureBrain* curBrain = armMod->GetCurrentBrain();
                                if (curBrain)
                                {
                                    if (curBrain->IsRunningTask())
                                    {
                                        fCurrentCursor = SetCurrentCursorID(kCursorClickDisabled);
                                        plMouseDevice::AddNameToCursor(plNetClientMgr::GetInstance()->GetPlayerName(pObj->GetKey()));
                                        return true;
                                    }
                                }
                                plAvatarMgr* aMgr = plAvatarMgr::GetInstance();
                                if (aMgr)
                                {
                                    if (aMgr->IsACoopRunning())
                                    {
                                        fCurrentCursor = SetCurrentCursorID(kCursorClickDisabled);
                                        plMouseDevice::AddNameToCursor(plNetClientMgr::GetInstance()->GetPlayerName(pObj->GetKey()));
                                        return true;
                                    }
                                }
                                plSceneObject* locPlayer = (plSceneObject*)plNetClientMgr::GetInstance()->GetLocalPlayer();
                                // make sure that they are facing each other
                                if ( locPlayer )
                                {
                                    hsVector3 ourView = locPlayer->GetCoordinateInterface()->GetLocalToWorld().GetAxis(hsMatrix44::kView);
                                    hsVector3 theirView = pObj->GetCoordinateInterface()->GetLocalToWorld().GetAxis(hsMatrix44::kView);
                                    float viewdot = ourView * theirView;
                                    hsVector3 towards(locPlayer->GetCoordinateInterface()->GetLocalToWorld().GetTranslate() - pObj->GetCoordinateInterface()->GetLocalToWorld().GetTranslate());
                                    towards.Normalize();
                                    float towardsdot = ourView * towards;
                                    if (viewdot > SHARE_FACING_TOLERANCE || towardsdot > SHARE_FACING_TOLERANCE )
                                    {
                                        ResetClickableState();
                                        return true;    // not facing enough... reject
                                    }
                                }
                                //otherwise make sure that they are close enough to click on
                                if (locPlayer)
                                {
                                    hsPoint3 avPt = locPlayer->GetCoordinateInterface()->GetLocalToWorld().GetTranslate();
                                    hsPoint3 objPt = pObj->GetCoordinateInterface()->GetLocalToWorld().GetTranslate();
                                    hsVector3 dist(avPt - objPt);
                                    if ( dist.MagnitudeSquared() >= 16.0f ) // you are too far away
                                    {
                                        ResetClickableState();
                                        return true;
                                    }
                                    
                                    if (hsABS(avPt.fZ - objPt.fZ) > 1.0f) // you need to also be in the same plane (some books are on top of rocks you need to jump onto)
                                    {
                                        ResetClickableState();
                                        return true;
                                    }
                                }
                            }
                            // finally - make sure this guy is not in our ignore lists.
                            int x;
                            for (x = 0; x < fIgnoredAvatars.Count(); x++)
                            {
                                if (fIgnoredAvatars[x] == pObj->GetKey())
                                {   
                                    fCurrentCursor = SetCurrentCursorID(kCursorClickDisabled);
                                    plMouseDevice::AddNameToCursor(plNetClientMgr::GetInstance()->GetPlayerName(pObj->GetKey()));
                                    return true;
                                }
                            }
                            for (x = 0; x < fGUIIgnoredAvatars.Count(); x++)
                            {
                                if (fGUIIgnoredAvatars[x] == pObj->GetKey())
                                {   
                                    fCurrentCursor = SetCurrentCursorID(kCursorClickDisabled);
                                    plMouseDevice::AddNameToCursor(plNetClientMgr::GetInstance()->GetPlayerName(pObj->GetKey()));
                                    return true;
                                }
                            }
                            
                            ClearClickableMap();
                            fCurrentClickable = pObj->GetKey();
                            fCurrentClickableLogicMod = nil;
                            fCurrClickIsAvatar = true;
                            fCurrentCursor = SetCurrentCursorID(kCursorPoised);
                            // not sure why we need to point on the avatar...
                            // ...but maybe something in the future will need this
                            fCurrentClickPoint = pLOSMsg->fHitPoint;
                            plMouseDevice::AddNameToCursor(plNetClientMgr::GetInstance()->GetPlayerName(fCurrentClickable));
                            return true;
                        }
                    }
                    // here! it's an object which is not clickable
                    // no object, or not clickable or avatar
                    
                    fCurrentClickPoint = pLOSMsg->fHitPoint;
                    ResetClickableState();
                    return false;
                }
            }
            // no object, or not clickable or avatar
            ResetClickableState();
        }
        else
        if( pLOSMsg->fRequestID == ID_FIND_LOCALPLAYER )
        {
            bool result = false;
            if( pLOSMsg->fObj )
            {
                // is this object clickable?
                plSceneObject *pObj = plSceneObject::ConvertNoRef( pLOSMsg->fObj->ObjectIsLoaded() );
                if( pObj )
                {   
                    if (pObj == plNetClientMgr::GetInstance()->GetLocalPlayer())
                        result = true;
                }   
            }
            if (result && !fFadedLocalAvatar)
            {   
                IHalfFadeAvatar(true);
                return true;
            }
            else
            if (!result && fFadedLocalAvatar)
            {
                IHalfFadeAvatar(false);
                return true;
            }
        }
        if( pLOSMsg->fRequestID == ID_FIND_WALKABLE_GROUND )
        {
            if (!pLOSMsg->fNoHit)
            {
                plAvatarMgr::GetInstance()->GetLocalAvatar()->TurnToPoint(pLOSMsg->fHitPoint);
            }
            return true;
        }
            
        return true;
    }

    plCursorChangeMsg   *fakeReplyMsg = plCursorChangeMsg::ConvertNoRef( msg );
    if( fakeReplyMsg != nil )
    {
        hsBool deniedCurrent = false;
        plKey key = fakeReplyMsg->GetSender();
        for (int i = 0; i < fClickableMap.Count(); i++)
        {
            if (fClickableMap[i]->key == key)
            {
                if( fakeReplyMsg->fType == plCursorChangeMsg::kNullCursor )
                {
                    // Means not clickable--gotta fix this someday
                    fClickableMap[i]->val = false;
                    if (fClickableMap[i]->key == fCurrentClickableLogicMod)
                    {
                        deniedCurrent = true;
                        break;
                    }
                }
                else
                {
                    // And fix this...
                    fClickableMap[i]->val = true;
                }
            }
        }
        if (deniedCurrent)
            ResetClickableState();
        return true;
    }

    plRenderMsg *rMsg = plRenderMsg::ConvertNoRef( msg );
    if( rMsg != nil )
    {
        fPipe = rMsg->Pipeline();
        plgDispatch::Dispatch()->UnRegisterForExactType( plRenderMsg::Index(), fManager->GetKey() );
        return true;
    }
    // reply from coop share book multistage
    plNotifyMsg* pNMsg = plNotifyMsg::ConvertNoRef(msg);
    if (pNMsg)
    {
        for(int x=0; x < pNMsg->GetEventCount();x++)
        {
            proEventData* pED = pNMsg->GetEventRecord(0);
            if ( pED->fEventType == proEventData::kMultiStage )
            {
                proMultiStageEventData* pMS = (proMultiStageEventData*)pED;
                if (pMS->fAvatar == fOffereeKey) // mojo has linked
                {
                    // do something - they linked out but we are still in the multistage
                    fOffereeKey = nil;
                }
                else
                if (pMS->fAvatar == plNetClientMgr::GetInstance()->GetLocalPlayerKey())
                {
                    // do something else
                    if (fBookMode = kNotOffering && fPendingLink == false) // we just linked out
                    {
                        // make me clickable again
                        ISendAvatarDisabledNotification(true);
                    }
                    else // we put the book back after our target linked out
                    {
                        fBookMode = kNotOffering;
                        fPendingLink = false;
                        // make ME clickable again
                        ISendAvatarDisabledNotification(true);
                    }
                }   
                return true;
            }
        }
        return false;
                
    }
    // if someone pages out / in, remove them from our ignore list or notify them to ignore us
    plPlayerPageMsg* pPlayerMsg = plPlayerPageMsg::ConvertNoRef(msg);
    if (pPlayerMsg)
    {
        if (pPlayerMsg->fUnload)
        {
            int x;
            // first, remove this avatar from my list of avatars I ingore for clickable griefing (when the 'ignore avatars' key is pressed)
            for(x = 0; x < fLocalIgnoredAvatars.Count(); x++)
            {
                if (fLocalIgnoredAvatars[x] == pPlayerMsg->fPlayer)
                    fLocalIgnoredAvatars.RemoveItem(pPlayerMsg->fPlayer);
            }
            // now deal with avatars we are always ignoring because of their current activity
            for(x = 0; x < fIgnoredAvatars.Count(); x++)
            {
                if (fIgnoredAvatars[x] == pPlayerMsg->fPlayer)
                    fIgnoredAvatars.RemoveItem(pPlayerMsg->fPlayer);
            }
            for(x = 0; x < fGUIIgnoredAvatars.Count(); x++)
            {
                if (fGUIIgnoredAvatars[x] == pPlayerMsg->fPlayer)
                    fGUIIgnoredAvatars.RemoveItem(pPlayerMsg->fPlayer);
            }
            if (fOffereeKey == pPlayerMsg->fPlayer)
            {
                if (fBookMode == kBookOffered)
                {
                    // and put our own dialog back up...
                    plKey avKey = plNetClientMgr::GetInstance()->GetLocalPlayerKey();
                    ISendOfferNotification(avKey, 0, false);
                    //IManageIgnoredAvatars(fOffereeKey, false);
                    fOffereeKey = nil;
                    fBookMode = kNotOffering;
                    ISendAvatarDisabledNotification(true);
                }
            }
        }
        else
        {   
            // add them to the list we keep of everyone here:
            // but DO NOT add the local avatar
            if (pPlayerMsg->fPlayer != plNetClientMgr::GetInstance()->GetLocalPlayerKey())
                fLocalIgnoredAvatars.Append(pPlayerMsg->fPlayer);
            if (fBookMode != kNotOffering)
            {
                // tell them to ignore us
                
                plInputIfaceMgrMsg* pMsg = new plInputIfaceMgrMsg(plInputIfaceMgrMsg::kDisableAvatarClickable);
                plKey avKey = plNetClientMgr::GetInstance()->GetLocalPlayerKey();
                pMsg->SetAvKey(avKey);
                pMsg->SetBCastFlag(plMessage::kNetPropagate);
                pMsg->SetBCastFlag(plMessage::kNetForce);
                pMsg->SetBCastFlag(plMessage::kLocalPropagate, false);
                pMsg->AddNetReceiver( pPlayerMsg->fClientID );
                pMsg->Send();
                
                // and tell them to ignore our victim

                //plInputIfaceMgrMsg* pMsg2 = new plInputIfaceMgrMsg(plInputIfaceMgrMsg::kDisableAvatarClickable);
                //pMsg2->SetAvKey(fOffereeKey);
                //pMsg2->SetBCastFlag(plMessage::kNetPropagate);
                //pMsg2->SetBCastFlag(plMessage::kNetForce);
                //pMsg2->SetBCastFlag(plMessage::kLocalPropagate, false);
                //pMsg2->AddNetReceiver( pPlayerMsg->fClientID );
                //pMsg2->Send();
                            
            }
            // tell them to ingore us if we are looking at a GUI
            for(int x = 0; x < fGUIIgnoredAvatars.Count(); x++)
            {
                if (fGUIIgnoredAvatars[x] == plNetClientMgr::GetInstance()->GetLocalPlayerKey())
                {
                    plInputIfaceMgrMsg* pMsg3 = new plInputIfaceMgrMsg(plInputIfaceMgrMsg::kGUIDisableAvatarClickable);
                    pMsg3->SetAvKey(fGUIIgnoredAvatars[x]);
                    pMsg3->SetBCastFlag(plMessage::kNetPropagate);
                    pMsg3->SetBCastFlag(plMessage::kNetForce);
                    pMsg3->SetBCastFlag(plMessage::kLocalPropagate, false);
                    pMsg3->AddNetReceiver( pPlayerMsg->fClientID );
                    pMsg3->Send();
                    return true;
                }
            }
        }
    }
    
    plInputIfaceMgrMsg *mgrMsg = plInputIfaceMgrMsg::ConvertNoRef( msg );
    if( mgrMsg != nil )
    {
        if ( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kDisableAvatarClickable )
        {
            // ignore if already in list or this is who WE are offering the book to...
            if (mgrMsg->GetAvKey() == fOffereeKey)
                return true;
            for(int x = 0; x < fIgnoredAvatars.Count(); x++)
            {
                if (fIgnoredAvatars[x] == mgrMsg->GetAvKey())
                    return true;
            }
            fIgnoredAvatars.Append(mgrMsg->GetAvKey());
        }
        else
        if ( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kEnableAvatarClickable )
        {
            for(int x = 0; x < fIgnoredAvatars.Count(); x++)
            {
                if (fIgnoredAvatars[x] == mgrMsg->GetAvKey())
                    fIgnoredAvatars.RemoveItem(mgrMsg->GetAvKey());
            }
        }
        else
        if ( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kGUIDisableAvatarClickable )
        {
            // ignore if already in list or this is who WE are offering the book to...
            if (mgrMsg->GetAvKey() == fOffereeKey)
                return true;
            for(int x = 0; x < fGUIIgnoredAvatars.Count(); x++)
            {
                if (fGUIIgnoredAvatars[x] == mgrMsg->GetAvKey())
                    return true;
            }
            fGUIIgnoredAvatars.Append(mgrMsg->GetAvKey());
        }
        else
        if ( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kGUIEnableAvatarClickable )
        {
            for(int x = 0; x < fGUIIgnoredAvatars.Count(); x++)
            {
                if (fGUIIgnoredAvatars[x] == mgrMsg->GetAvKey())
                    fGUIIgnoredAvatars.RemoveItem(mgrMsg->GetAvKey());
            }
        }
        else
        if( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kEnableClickables )
        {
            fClickability = true;
            return true;
        }
        else if( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kDisableClickables )
        {
            fClickability = false;
            ResetClickableState();
            return true;
        }
        else if ( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kSetOfferBookMode )
        {
            fBookMode = kOfferBook;
            fOffereeKey = nil;
            fBookKey = mgrMsg->GetSender();
            fOfferedAgeInstance = mgrMsg->GetAgeName();
            fOfferedAgeFile = mgrMsg->GetAgeFileName();
            ISendAvatarDisabledNotification(false);

        }
        else if ( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kClearOfferBookMode )
        {
            if (fBookMode == kOfferAccepted || fBookMode == kOfferLinkPending)
            {
                fPendingLink = true;
            }
            else
            if (fOffereeKey != nil)
            {
                // notify any offeree that the offer is rescinded
                ISendOfferNotification(fOffereeKey, -999, true);
                //IManageIgnoredAvatars(fOffereeKey, false);
                fOffereeKey = nil;
            }
            // shut down offer book mode
            fBookMode = kNotOffering;
            ISendAvatarDisabledNotification(true);
        }
        else if ( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kNotifyOfferRejected)
        {
            if (fBookMode == kBookOffered)
            {
                // and put our own dialog back up...
                plKey avKey = plNetClientMgr::GetInstance()->GetLocalPlayerKey();
                ISendOfferNotification(avKey, 0, false);
                //IManageIgnoredAvatars(fOffereeKey, false);
                fBookMode = kOfferBook;
                fOffereeKey = nil;
            }
            else
            if (mgrMsg->GetSender() == plNetClientMgr::GetInstance()->GetLocalPlayerKey())
            {
                fBookMode = kNotOffering;
                ISendAvatarDisabledNotification(true);
            }
        }
        else if ( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kNotifyOfferAccepted && fBookMode == kBookOffered)
        {
            fBookMode = kOfferAccepted;
        }
        else if ( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kNotifyOfferCompleted )
        {
            // must have actually offered the book...
            if (!fPendingLink)
            {
                if (fBookMode == kOfferBook || fBookMode == kBookOffered)
                return true;
            }
            if (!plNetClientMgr::GetInstance())
                return true;

            fOffereeID = mgrMsg->GetPageID();
            ILinkOffereeToAge();
        }
        else if ( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kSetShareSpawnPoint )
        {
            fSpawnPoint = mgrMsg->GetSpawnPoint();
        }
        else if ( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kSetShareAgeInstanceGuid )
        {
            fAgeInstanceGuid = plUUID(mgrMsg->GetAgeInstanceGuid());
        }
    }
    plVaultNotifyMsg* pVaultMsg = plVaultNotifyMsg::ConvertNoRef(msg);
    if (pVaultMsg && pVaultMsg->GetType()==plNetCommon::VaultTasks::kRegisterOwnedAge )
    {
        //sanity check -
        if (fBookMode != kOfferLinkPending && fPendingLink == false)
            return true;
        // stop looking for this message and reset interface to 'offer book' mode again
        plgDispatch::Dispatch()->UnRegisterForExactType(plVaultNotifyMsg::Index(), fManager->GetKey());
        ILinkOffereeToAge();
        return true;
    }
    return false;
}