mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-13 03:33:48 +00:00
Updates to component classes -
Shift from ghosted components to entity-managed for networking Initial implementation of Systems through the Mesh Component
This commit is contained in:
parent
ae5a43de70
commit
68efd8e22a
15 changed files with 706 additions and 312 deletions
|
|
@ -47,7 +47,9 @@
|
|||
#include "T3D/gameBase/std/stdMoveList.h"
|
||||
|
||||
#include "T3D/prefab.h"
|
||||
#include "T3D/gameBase/gameConnection.h"
|
||||
|
||||
#include <thread>
|
||||
//
|
||||
#include "gfx/sim/debugDraw.h"
|
||||
//
|
||||
|
|
@ -118,6 +120,8 @@ Entity::Entity()
|
|||
|
||||
mInitialized = false;
|
||||
|
||||
mLifetimeMS = 0;
|
||||
|
||||
mGameObjectAssetId = StringTable->insert("");
|
||||
|
||||
}
|
||||
|
|
@ -147,6 +151,10 @@ void Entity::initPersistFields()
|
|||
|
||||
endGroup("Transform");
|
||||
|
||||
addGroup("Misc");
|
||||
addField("LifetimeMS", TypeS32, Offset(mLifetimeMS, Entity), "Object world orientation.");
|
||||
endGroup("Misc");
|
||||
|
||||
addGroup("GameObject");
|
||||
addProtectedField("gameObjectName", TypeGameObjectAssetPtr, Offset(mGameObjectAsset, Entity), &_setGameObject, &defaultProtectedGetFn,
|
||||
"The asset Id used for the game object this entity is based on.");
|
||||
|
|
@ -231,8 +239,19 @@ bool Entity::onAdd()
|
|||
addToScene();
|
||||
|
||||
//Make sure we get positioned
|
||||
setMaskBits(TransformMask);
|
||||
setMaskBits(NamespaceMask);
|
||||
if (isServerObject())
|
||||
{
|
||||
setMaskBits(TransformMask);
|
||||
setMaskBits(NamespaceMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
//We can shortcut the initialization here because stuff generally ghosts down in order, and onPostAdd isn't called on ghosts.
|
||||
onPostAdd();
|
||||
}
|
||||
|
||||
if (mLifetimeMS != 0)
|
||||
mStartTimeMS = Platform::getRealMilliseconds();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -245,6 +264,8 @@ void Entity::onRemove()
|
|||
|
||||
onDataSet.removeAll();
|
||||
|
||||
mGameObjectAsset.clear();
|
||||
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
|
|
@ -258,6 +279,27 @@ void Entity::onPostAdd()
|
|||
mComponents[i]->onComponentAdd();
|
||||
}
|
||||
|
||||
//Set up the networked components
|
||||
mNetworkedComponents.clear();
|
||||
for (U32 i = 0; i < mComponents.size(); i++)
|
||||
{
|
||||
if (mComponents[i]->isNetworked())
|
||||
{
|
||||
NetworkedComponent netComp;
|
||||
netComp.componentIndex = i;
|
||||
netComp.updateState = NetworkedComponent::Adding;
|
||||
netComp.updateMaskBits = -1;
|
||||
|
||||
mNetworkedComponents.push_back(netComp);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mNetworkedComponents.empty())
|
||||
{
|
||||
setMaskBits(AddComponentsMask);
|
||||
setMaskBits(ComponentsUpdateMask);
|
||||
}
|
||||
|
||||
if (isMethod("onAdd"))
|
||||
Con::executef(this, "onAdd");
|
||||
}
|
||||
|
|
@ -396,6 +438,14 @@ void Entity::processTick(const Move* move)
|
|||
mDelta.rot[1] = mRot.asQuatF();
|
||||
|
||||
setTransform(getPosition(), mRot);
|
||||
|
||||
//Lifetime test
|
||||
if (mLifetimeMS != 0)
|
||||
{
|
||||
S32 currentTime = Platform::getRealMilliseconds();
|
||||
if (currentTime - mStartTimeMS >= mLifetimeMS)
|
||||
deleteObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -446,62 +496,107 @@ U32 Entity::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|||
mathWrite(*stream, mObjBox);
|
||||
}
|
||||
|
||||
//pass our behaviors around
|
||||
if (mask & ComponentsMask || mask & InitialUpdateMask)
|
||||
if (stream->writeFlag(mask & AddComponentsMask))
|
||||
{
|
||||
stream->writeFlag(true);
|
||||
//now, we run through a list of our to-be-sent behaviors and begin sending them
|
||||
//if any fail, we keep our list and re-queue the mask
|
||||
S32 componentCount = mToLoadComponents.size();
|
||||
U32 toAddComponentCount = 0;
|
||||
|
||||
//build our 'ready' list
|
||||
//This requires both the instance and the instances' template to be prepped(if the template hasn't been ghosted,
|
||||
//then we know we shouldn't be passing the instance's ghosts around yet)
|
||||
U32 ghostedCompCnt = 0;
|
||||
for (U32 i = 0; i < componentCount; i++)
|
||||
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
|
||||
{
|
||||
if (con->getGhostIndex(mToLoadComponents[i]) != -1)
|
||||
ghostedCompCnt++;
|
||||
}
|
||||
|
||||
if (ghostedCompCnt != 0)
|
||||
{
|
||||
stream->writeFlag(true);
|
||||
|
||||
stream->writeFlag(mStartComponentUpdate);
|
||||
|
||||
//if not all the behaviors have been ghosted, we'll need another pass
|
||||
if (ghostedCompCnt != componentCount)
|
||||
retMask |= ComponentsMask;
|
||||
|
||||
//write the currently ghosted behavior count
|
||||
stream->writeInt(ghostedCompCnt, 16);
|
||||
|
||||
for (U32 i = 0; i < mToLoadComponents.size(); i++)
|
||||
if (mNetworkedComponents[i].updateState == NetworkedComponent::Adding)
|
||||
{
|
||||
//now fetch them and pass the ghost
|
||||
S32 ghostIndex = con->getGhostIndex(mToLoadComponents[i]);
|
||||
if (ghostIndex != -1)
|
||||
{
|
||||
stream->writeInt(ghostIndex, NetConnection::GhostIdBitSize);
|
||||
mToLoadComponents.erase(i);
|
||||
i--;
|
||||
|
||||
mStartComponentUpdate = false;
|
||||
}
|
||||
toAddComponentCount++;
|
||||
}
|
||||
}
|
||||
else if (componentCount)
|
||||
|
||||
//you reaaaaally shouldn't have >255 networked components on a single entity
|
||||
stream->writeInt(toAddComponentCount, 8);
|
||||
|
||||
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
|
||||
{
|
||||
//on the odd chance we have behaviors to ghost, but NONE of them have been yet, just set the flag now
|
||||
stream->writeFlag(false);
|
||||
retMask |= ComponentsMask;
|
||||
NetworkedComponent::UpdateState state = mNetworkedComponents[i].updateState;
|
||||
|
||||
if (mNetworkedComponents[i].updateState == NetworkedComponent::Adding)
|
||||
{
|
||||
const char* className = mComponents[mNetworkedComponents[i].componentIndex]->getClassName();
|
||||
stream->writeString(className, strlen(className));
|
||||
|
||||
mNetworkedComponents[i].updateState = NetworkedComponent::Updating;
|
||||
}
|
||||
}
|
||||
else
|
||||
stream->writeFlag(false);
|
||||
}
|
||||
else
|
||||
stream->writeFlag(false);
|
||||
|
||||
if (stream->writeFlag(mask & RemoveComponentsMask))
|
||||
{
|
||||
/*U32 toRemoveComponentCount = 0;
|
||||
|
||||
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
|
||||
{
|
||||
if (mNetworkedComponents[i].updateState == NetworkedComponent::Adding)
|
||||
{
|
||||
toRemoveComponentCount++;
|
||||
}
|
||||
}
|
||||
|
||||
//you reaaaaally shouldn't have >255 networked components on a single entity
|
||||
stream->writeInt(toRemoveComponentCount, 8);
|
||||
|
||||
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
|
||||
{
|
||||
if (mNetworkedComponents[i].updateState == NetworkedComponent::Removing)
|
||||
{
|
||||
stream->writeInt(i, 16);
|
||||
}
|
||||
}*/
|
||||
|
||||
/*for (U32 i = 0; i < mNetworkedComponents.size(); i++)
|
||||
{
|
||||
if (mNetworkedComponents[i].updateState == NetworkedComponent::UpdateState::Removing)
|
||||
{
|
||||
removeComponent(mComponents[mNetworkedComponents[i].componentIndex], true);
|
||||
mNetworkedComponents.erase(i);
|
||||
i--;
|
||||
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
//Update our components
|
||||
if (stream->writeFlag(mask & ComponentsUpdateMask))
|
||||
{
|
||||
U32 toUpdateComponentCount = 0;
|
||||
|
||||
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
|
||||
{
|
||||
if (mNetworkedComponents[i].updateState == NetworkedComponent::Updating)
|
||||
{
|
||||
toUpdateComponentCount++;
|
||||
}
|
||||
}
|
||||
|
||||
//you reaaaaally shouldn't have >255 networked components on a single entity
|
||||
stream->writeInt(toUpdateComponentCount, 8);
|
||||
|
||||
bool forceUpdate = false;
|
||||
|
||||
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
|
||||
{
|
||||
if (mNetworkedComponents[i].updateState == NetworkedComponent::Updating)
|
||||
{
|
||||
stream->writeInt(i, 8);
|
||||
|
||||
mNetworkedComponents[i].updateMaskBits = mComponents[mNetworkedComponents[i].componentIndex]->packUpdate(con, mNetworkedComponents[i].updateMaskBits, stream);
|
||||
|
||||
if (mNetworkedComponents[i].updateMaskBits != 0)
|
||||
forceUpdate = true;
|
||||
else
|
||||
mNetworkedComponents[i].updateState = NetworkedComponent::None;
|
||||
}
|
||||
}
|
||||
|
||||
//If we have leftover, we need to re-iterate our packing
|
||||
if (forceUpdate)
|
||||
setMaskBits(ComponentsUpdateMask);
|
||||
}
|
||||
|
||||
/*if (stream->writeFlag(mask & NamespaceMask))
|
||||
{
|
||||
|
|
@ -594,25 +689,52 @@ void Entity::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
resetWorldBox();
|
||||
}
|
||||
|
||||
//AddComponentMask
|
||||
if (stream->readFlag())
|
||||
{
|
||||
//are we passing any behaviors currently?
|
||||
if (stream->readFlag())
|
||||
U32 addedComponentCount = stream->readInt(8);
|
||||
|
||||
for (U32 i = 0; i < addedComponentCount; i++)
|
||||
{
|
||||
//if we've just started the update, clear our behaviors
|
||||
if (stream->readFlag())
|
||||
clearComponents(false);
|
||||
char className[256] = "";
|
||||
stream->readString(className);
|
||||
|
||||
S32 componentCount = stream->readInt(16);
|
||||
//Change to components, so iterate our list and create any new components
|
||||
// Well, looks like we have to create a new object.
|
||||
const char* componentType = className;
|
||||
|
||||
for (U32 i = 0; i < componentCount; i++)
|
||||
ConsoleObject *object = ConsoleObject::create(componentType);
|
||||
|
||||
// Finally, set currentNewObject to point to the new one.
|
||||
Component* newComponent = dynamic_cast<Component *>(object);
|
||||
|
||||
if (newComponent)
|
||||
{
|
||||
S32 gIndex = stream->readInt(NetConnection::GhostIdBitSize);
|
||||
addComponent(dynamic_cast<Component*>(con->resolveGhost(gIndex)));
|
||||
addComponent(newComponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//RemoveComponentMask
|
||||
if (stream->readFlag())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//ComponentUpdateMask
|
||||
if (stream->readFlag())
|
||||
{
|
||||
U32 updatingComponents = stream->readInt(8);
|
||||
|
||||
for (U32 i = 0; i < updatingComponents; i++)
|
||||
{
|
||||
U32 updateComponentIndex = stream->readInt(8);
|
||||
|
||||
Component* comp = mComponents[updateComponentIndex];
|
||||
comp->unpackUpdate(con, stream);
|
||||
}
|
||||
}
|
||||
|
||||
/*if (stream->readFlag())
|
||||
{
|
||||
if (stream->readFlag())
|
||||
|
|
@ -640,6 +762,26 @@ void Entity::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
}*/
|
||||
}
|
||||
|
||||
void Entity::setComponentNetMask(Component* comp, U32 mask)
|
||||
{
|
||||
setMaskBits(Entity::ComponentsUpdateMask);
|
||||
|
||||
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
|
||||
{
|
||||
U32 netCompId = mComponents[mNetworkedComponents[i].componentIndex]->getId();
|
||||
U32 compId = comp->getId();
|
||||
|
||||
if (netCompId == compId &&
|
||||
(mNetworkedComponents[i].updateState == NetworkedComponent::None || mNetworkedComponents[i].updateState == NetworkedComponent::Updating))
|
||||
{
|
||||
mNetworkedComponents[i].updateState = NetworkedComponent::Updating;
|
||||
mNetworkedComponents[i].updateMaskBits |= mask;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Manipulation
|
||||
void Entity::setTransform(const MatrixF &mat)
|
||||
{
|
||||
|
|
@ -758,7 +900,11 @@ void Entity::setTransform(Point3F position, RotationF rotation)
|
|||
// Update the transforms.
|
||||
Parent::setTransform(newMat);
|
||||
|
||||
onTransformSet.trigger(&newMat);
|
||||
U32 compCount = mComponents.size();
|
||||
for (U32 i = 0; i < compCount; ++i)
|
||||
{
|
||||
mComponents[i]->ownerTransformSet(&newMat);
|
||||
}
|
||||
|
||||
Point3F newPos = newMat.getPosition();
|
||||
RotationF newRot = newMat;
|
||||
|
|
@ -800,7 +946,11 @@ void Entity::setRenderTransform(Point3F position, RotationF rotation)
|
|||
|
||||
Parent::setRenderTransform(newMat);
|
||||
|
||||
onTransformSet.trigger(&newMat);
|
||||
U32 compCount = mComponents.size();
|
||||
for (U32 i = 0; i < compCount; ++i)
|
||||
{
|
||||
mComponents[i]->ownerTransformSet(&newMat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1155,11 +1305,28 @@ bool Entity::addComponent(Component *comp)
|
|||
// Register the component with this owner.
|
||||
comp->setOwner(this);
|
||||
|
||||
comp->setIsServerObject(isServerObject());
|
||||
|
||||
//if we've already been added and this is being added after the fact(at runtime),
|
||||
//then just go ahead and call it's onComponentAdd so it can get to work
|
||||
if (mInitialized)
|
||||
//if (mInitialized)
|
||||
{
|
||||
comp->onComponentAdd();
|
||||
|
||||
if (comp->isNetworked())
|
||||
{
|
||||
NetworkedComponent netComp;
|
||||
netComp.componentIndex = mComponents.size() - 1;
|
||||
netComp.updateState = NetworkedComponent::Adding;
|
||||
netComp.updateMaskBits = -1;
|
||||
|
||||
mNetworkedComponents.push_back(netComp);
|
||||
|
||||
setMaskBits(AddComponentsMask);
|
||||
setMaskBits(ComponentsUpdateMask);
|
||||
}
|
||||
}
|
||||
|
||||
onComponentAdded.trigger(comp);
|
||||
|
||||
return true;
|
||||
|
|
@ -1269,7 +1436,7 @@ Component *Entity::getComponent(String componentType)
|
|||
Namespace *NS = comp->getNamespace();
|
||||
|
||||
//we shouldn't ever go past Component into net object, as we're no longer dealing with component classes
|
||||
while (dStrcmp(NS->getName(), "NetObject"))
|
||||
while (dStrcmp(NS->getName(), "SimObject"))
|
||||
{
|
||||
String namespaceName = NS->getName();
|
||||
|
||||
|
|
@ -1497,7 +1664,8 @@ void Entity::notifyComponents(String signalFunction, String argA, String argB, S
|
|||
|
||||
void Entity::setComponentsDirty()
|
||||
{
|
||||
if (mToLoadComponents.empty())
|
||||
bool tmp = true;
|
||||
/*if (mToLoadComponents.empty())
|
||||
mStartComponentUpdate = true;
|
||||
|
||||
//we need to build a list of behaviors that need to be pushed across the network
|
||||
|
|
@ -1522,7 +1690,7 @@ void Entity::setComponentsDirty()
|
|||
}
|
||||
}
|
||||
|
||||
setMaskBits(ComponentsMask);
|
||||
setMaskBits(ComponentsMask);*/
|
||||
}
|
||||
|
||||
void Entity::setComponentDirty(Component *comp, bool forceUpdate)
|
||||
|
|
@ -1654,7 +1822,7 @@ ConsoleMethod(Entity, addComponents, void, 2, 2, "() - Add all fielded behaviors
|
|||
object->addComponents();
|
||||
}*/
|
||||
|
||||
ConsoleMethod(Entity, addComponent, bool, 3, 3, "(Component* bi) - Add a behavior to the object\n"
|
||||
ConsoleMethod(Entity, addComponent, bool, 3, 3, "(ComponentInstance bi) - Add a behavior to the object\n"
|
||||
"@param bi The behavior instance to add"
|
||||
"@return (bool success) Whether or not the behavior was successfully added")
|
||||
{
|
||||
|
|
@ -1679,7 +1847,7 @@ ConsoleMethod(Entity, addComponent, bool, 3, 3, "(Component* bi) - Add a behavio
|
|||
return false;
|
||||
}
|
||||
|
||||
ConsoleMethod(Entity, removeComponent, bool, 3, 4, "(Component* bi, [bool deleteBehavior = true])\n"
|
||||
ConsoleMethod(Entity, removeComponent, bool, 3, 4, "(ComponentInstance bi, [bool deleteBehavior = true])\n"
|
||||
"@param bi The behavior instance to remove\n"
|
||||
"@param deleteBehavior Whether or not to delete the behavior\n"
|
||||
"@return (bool success) Whether the behavior was successfully removed")
|
||||
|
|
@ -1834,4 +2002,43 @@ DefineConsoleMethod(Entity, notify, void, (String signalFunction, String argA, S
|
|||
return;
|
||||
|
||||
object->notifyComponents(signalFunction, argA, argB, argC, argD, argE);
|
||||
}
|
||||
|
||||
DefineConsoleFunction(findEntitiesByTag, const char*, (SimGroup* searchingGroup, String tags), (nullAsType<SimGroup*>(), ""),
|
||||
"Finds all entities that have the provided tags.\n"
|
||||
"@param searchingGroup The SimGroup to search inside. If null, we'll search the entire dictionary(this can be slow!).\n"
|
||||
"@param tags Word delimited list of tags to search for. If multiple tags are included, the list is eclusively parsed, requiring all tags provided to be found on an entity for a match.\n"
|
||||
"@return A word list of IDs of entities that match the tag search terms.")
|
||||
{
|
||||
//if (tags.isEmpty())
|
||||
return "";
|
||||
|
||||
/*if (searchingGroup == nullptr)
|
||||
{
|
||||
searchingGroup = Sim::getRootGroup();
|
||||
}
|
||||
|
||||
StringTableEntry entityStr = StringTable->insert("Entity");
|
||||
|
||||
std::thread threadBob;
|
||||
|
||||
std::thread::id a = threadBob.get_id();
|
||||
std::thread::id b = std::this_thread::get_id().;
|
||||
|
||||
if (a == b)
|
||||
{
|
||||
//do
|
||||
}
|
||||
|
||||
for (SimGroup::iterator itr = searchingGroup->begin(); itr != searchingGroup->end(); itr++)
|
||||
{
|
||||
Entity* ent = dynamic_cast<Entity*>((*itr));
|
||||
|
||||
if (ent != nullptr)
|
||||
{
|
||||
ent->mTags.
|
||||
}
|
||||
}
|
||||
|
||||
object->notifyComponents(signalFunction, argA, argB, argC, argD, argE);*/
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue