Delay NetEvent untill object has been ghosted
by Lukas Joergensen · in Torque 3D Professional · 01/04/2014 (5:02 am) · 8 replies
Hey guys, I have an issue where the following code fails:
So far I've solved this by scheduling it:
Or do you have another idea of how to deal with this issue?
%bhv1 = new AttractionBehaviour(){
attractionrange = 10;
Attraction_offset[0] = "0 0.3 1.5";
Amount[0] = 2;
AttractionMode[0] = Attract;
attractedObjectID[0] = %spell.getSource();
};
%spell.baseEmitter = new ParticleEmitterNode(){
dataBlock = DefaultEmitterNodeData;
emitter = FireballChannelEmitterBASE;
position = %spell.getSource().position;
};
%spell.baseEmitter.addParticleBehaviour(%bhv1, false);Because the "addParticleBehaviour" NetEvent is being networked before the ParticleEmitterNode is ghosted.So far I've solved this by scheduling it:
%spell.baseEmitter.schedule(32, "addParticleBehaviour", %bhv1, false);However it is not very elegant, is there a way to make sure that the NetEvent is called after the object has been ghosted? Kindda like "ProcessAfter" on SceneObjects.
Or do you have another idea of how to deal with this issue?
About the author
IPS Bundle available at: https://www.winterleafentertainment.com/Products/IPS.aspx
#2
01/04/2014 (10:17 am)
Surely there's already a way to handle that synchronously else you would think that would be a problem of spawning projectiles (among other objects) and adding said object to MissionCleanup SimGroup that is used all over the place in TorqueScript.
#3
Behavior instances require 2 dependencies: The template and the Owner. Both are ghosted down with the behaviors.
Because of the weird ordering shenanigans of the netcode, you can't reliably count on what gets ghosted first, so I had to make instances wait until the other stuff was sent over, which looks like this:
PackUpdate:
UnPackUpdate:
So what happens is we check that the ghost is valid for both the template and the owner entity. If one or neither is valid, we re-set the mask so we check again next update. This goes until conditions are met and we're happy.
I'll look a "callAfterGhost()" function or something as that could be useful for some stuff the behavior system is making use of as well as the situation you've got going there.
So yeah, I don't think there's a pure script solution at the moment, but you could rig a callback into script, or just do the event directly, when the above code successfully checks out that the emitter has been ghosted.
01/04/2014 (12:39 pm)
I didn't think of the 'processAfter' function call(for some reason?) but what I've been doing on the behaviors is handled engine sideBehavior instances require 2 dependencies: The template and the Owner. Both are ghosted down with the behaviors.
Because of the weird ordering shenanigans of the netcode, you can't reliably count on what gets ghosted first, so I had to make instances wait until the other stuff was sent over, which looks like this:
PackUpdate:
if ( mask & InitialUpdateMask )
{
S32 tmpltGhostID = con->getGhostIndex(mTemplate);
S32 ownerGhostID = con->getGhostIndex(mBehaviorOwner);
if(tmpltGhostID != -1 && ownerGhostID != -1)
{
stream->writeFlag( true );
stream->writeInt(tmpltGhostID, NetConnection::GhostIdBitSize);
stream->writeInt(ownerGhostID, NetConnection::GhostIdBitSize);
}
else
{
retmask |= InitialUpdateMask;
stream->writeFlag( false );
}
}
else
stream->writeFlag( false );UnPackUpdate:
if(stream->readFlag())
{
S32 gIndex = stream->readInt( NetConnection::GhostIdBitSize );
mTemplate = dynamic_cast<BehaviorTemplate*>( con->resolveGhost( gIndex ) );
gIndex = stream->readInt( NetConnection::GhostIdBitSize );
mBehaviorOwner = dynamic_cast<BehaviorComponent*>( con->resolveGhost( gIndex ) );
}So what happens is we check that the ghost is valid for both the template and the owner entity. If one or neither is valid, we re-set the mask so we check again next update. This goes until conditions are met and we're happy.
I'll look a "callAfterGhost()" function or something as that could be useful for some stuff the behavior system is making use of as well as the situation you've got going there.
So yeah, I don't think there's a pure script solution at the moment, but you could rig a callback into script, or just do the event directly, when the above code successfully checks out that the emitter has been ghosted.
#4
I dunno, I had to do something similar in OneWorld and if I remember right I slide a schedule event into the pack. so after it would pack the data it would schedule a system event to send the netevent in a second or so.
You could also do it differently :)
It would require highjacking in the netGhost.cpp file, but you could put a list of the behaviors on the object, and then before the pack is called around line 491 have it send the net events in the list.
I'd have to research it more, but thats where I would start looking to hijack if I were trying to do it.
vince
01/04/2014 (10:50 pm)
Did you try sending the netevent in the pack? with a schedule say of a few milleseconds.I dunno, I had to do something similar in OneWorld and if I remember right I slide a schedule event into the pack. so after it would pack the data it would schedule a system event to send the netevent in a second or so.
You could also do it differently :)
It would require highjacking in the netGhost.cpp file, but you could put a list of the behaviors on the object, and then before the pack is called around line 491 have it send the net events in the list.
I'd have to research it more, but thats where I would start looking to hijack if I were trying to do it.
vince
#5
Just an idea.
01/04/2014 (10:51 pm)
Or... you could have your object signal an event that it was ghosted...Just an idea.
#6
@Jeff what I ended up doing was something similar to what you did, except I didn't do a check for anything. I just placed the "postNetEvent" code in the ParticleEmitterNode::packUpdate, after the SetEmitterDatablock flag, then it will be ghosted at the time the NetEvent arrives.
I would prefer being able to do this from a function outside the object tho, like "gc->postNetEventWhenGhost(evt, objectToWaitOn);"
01/04/2014 (11:44 pm)
Thanks for all the suggestions guys!@Jeff what I ended up doing was something similar to what you did, except I didn't do a check for anything. I just placed the "postNetEvent" code in the ParticleEmitterNode::packUpdate, after the SetEmitterDatablock flag, then it will be ghosted at the time the NetEvent arrives.
I would prefer being able to do this from a function outside the object tho, like "gc->postNetEventWhenGhost(evt, objectToWaitOn);"
#7
01/05/2014 (8:01 am)
EventManager could handle that....
#8
01/05/2014 (8:07 am)
@Richard, I've never worked with the EventManager, could you tell me how an EventManager solution would look?
Torque Owner Richard Ranft
Roostertail Games