123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2013 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "sim/simBase.h"
- #include "network/connectionProtocol.h"
- #include "network/netConnection.h"
- #include "network/netObject.h"
- #include "console/consoleTypes.h"
- #include "netObject_ScriptBinding.h"
- IMPLEMENT_CONOBJECT(NetObject);
- //----------------------------------------------------------------------------
- NetObject *NetObject::mDirtyList = NULL;
- NetObject::NetObject()
- {
- // netFlags will clear itself to 0
- mNetIndex = U32(-1);
- mFirstObjectRef = NULL;
- mPrevDirtyList = NULL;
- mNextDirtyList = NULL;
- mDirtyMaskBits = 0;
- }
- NetObject::~NetObject()
- {
- if(mDirtyMaskBits)
- {
- if(mPrevDirtyList)
- mPrevDirtyList->mNextDirtyList = mNextDirtyList;
- else
- mDirtyList = mNextDirtyList;
- if(mNextDirtyList)
- mNextDirtyList->mPrevDirtyList = mPrevDirtyList;
- }
- }
- void NetObject::setMaskBits(U32 orMask)
- {
- AssertFatal(orMask != 0, "Invalid net mask bits set.");
- AssertFatal(mDirtyMaskBits == 0 || (mPrevDirtyList != NULL || mNextDirtyList != NULL || mDirtyList == this), "Invalid dirty list state.");
- if(!mDirtyMaskBits)
- {
- AssertFatal(mNextDirtyList == NULL && mPrevDirtyList == NULL, "Object with zero mask already in list.");
- if(mDirtyList)
- {
- mNextDirtyList = mDirtyList;
- mDirtyList->mPrevDirtyList = this;
- }
- mDirtyList = this;
- }
- mDirtyMaskBits |= orMask;
- AssertFatal(mDirtyMaskBits == 0 || (mPrevDirtyList != NULL || mNextDirtyList != NULL || mDirtyList == this), "Invalid dirty list state.");
- }
- void NetObject::clearMaskBits(U32 orMask)
- {
- if(isDeleted())
- return;
- if(mDirtyMaskBits)
- {
- mDirtyMaskBits &= ~orMask;
- if(!mDirtyMaskBits)
- {
- if(mPrevDirtyList)
- mPrevDirtyList->mNextDirtyList = mNextDirtyList;
- else
- mDirtyList = mNextDirtyList;
- if(mNextDirtyList)
- mNextDirtyList->mPrevDirtyList = mPrevDirtyList;
- mNextDirtyList = mPrevDirtyList = NULL;
- }
- }
- for(GhostInfo *walk = mFirstObjectRef; walk; walk = walk->nextObjectRef)
- {
- if(walk->updateMask && walk->updateMask == orMask)
- {
- walk->updateMask = 0;
- walk->connection->ghostPushToZero(walk);
- }
- else
- walk->updateMask &= ~orMask;
- }
- }
- void NetObject::collapseDirtyList()
- {
- Vector<NetObject *> tempV;
- for(NetObject *t = mDirtyList; t; t = t->mNextDirtyList)
- tempV.push_back(t);
- for(NetObject *obj = mDirtyList; obj; )
- {
- NetObject *next = obj->mNextDirtyList;
- U32 orMask = obj->mDirtyMaskBits;
- obj->mNextDirtyList = NULL;
- obj->mPrevDirtyList = NULL;
- obj->mDirtyMaskBits = 0;
- if(!obj->isDeleted() && orMask)
- {
- for(GhostInfo *walk = obj->mFirstObjectRef; walk; walk = walk->nextObjectRef)
- {
- if(!walk->updateMask)
- {
- walk->updateMask = orMask;
- walk->connection->ghostPushNonZero(walk);
- }
- else
- walk->updateMask |= orMask;
- }
- }
- obj = next;
- }
- mDirtyList = NULL;
- for(U32 i = 0; i < (U32)tempV.size(); i++)
- {
- AssertFatal(tempV[i]->mNextDirtyList == NULL && tempV[i]->mPrevDirtyList == NULL && tempV[i]->mDirtyMaskBits == 0, "Error in collapse");
- }
- }
- //-----------------------------------------------------------------------------
- void NetObject::setScopeAlways()
- {
- if(mNetFlags.test(Ghostable) && !mNetFlags.test(IsGhost))
- {
- mNetFlags.set(ScopeAlways);
- // if it's a ghost always object, add it to the ghost always set
- // for ClientReps created later.
- Sim::getGhostAlwaysSet()->addObject(this);
- // add it to all Connections that already exist.
- SimGroup *clientGroup = Sim::getClientGroup();
- SimGroup::iterator i;
- for(i = clientGroup->begin(); i != clientGroup->end(); i++)
- {
- NetConnection *con = (NetConnection *) (*i);
- if(con->isGhosting())
- con->objectInScope(this);
- }
- }
- }
- void NetObject::clearScopeAlways()
- {
- if(!mNetFlags.test(IsGhost))
- {
- mNetFlags.clear(ScopeAlways);
- Sim::getGhostAlwaysSet()->removeObject(this);
- // Un ghost this object from all the connections
- while(mFirstObjectRef)
- mFirstObjectRef->connection->detachObject(mFirstObjectRef);
- }
- }
- bool NetObject::onAdd()
- {
- if(mNetFlags.test(ScopeAlways))
- setScopeAlways();
- return Parent::onAdd();
- }
- void NetObject::onRemove()
- {
- while(mFirstObjectRef)
- mFirstObjectRef->connection->detachObject(mFirstObjectRef);
- Parent::onRemove();
- }
- //-----------------------------------------------------------------------------
- F32 NetObject::getUpdatePriority(CameraScopeQuery*, U32, S32 updateSkips)
- {
- return F32(updateSkips) * 0.1f;
- }
- U32 NetObject::packUpdate(NetConnection* conn, U32 mask, BitStream* stream)
- {
- return 0;
- }
- void NetObject::unpackUpdate(NetConnection*, BitStream*)
- {
- }
- void NetObject::onCameraScopeQuery(NetConnection *cr, CameraScopeQuery* /*camInfo*/)
- {
- // default behavior -
- // ghost everything that is ghostable
- for (SimSetIterator obj(Sim::getRootGroup()); *obj; ++obj)
- {
- NetObject* nobj = dynamic_cast<NetObject*>(*obj);
- if (nobj)
- {
- AssertFatal(!nobj->mNetFlags.test(NetObject::Ghostable) || !nobj->mNetFlags.test(NetObject::IsGhost),
- "NetObject::onCameraScopeQuery: object marked both ghostable and as ghost");
- // Some objects don't ever want to be ghosted
- if (!nobj->mNetFlags.test(NetObject::Ghostable))
- continue;
- if (!nobj->mNetFlags.test(NetObject::ScopeAlways))
- {
- // it's in scope...
- cr->objectInScope(nobj);
- }
- }
- }
- }
- //-----------------------------------------------------------------------------
- void NetObject::initPersistFields()
- {
- Parent::initPersistFields();
- }
|