0
\$\begingroup\$

Let's assume I have a CEntity class that describes every entity within the game.

Each entity class has it's own std::vector of CActions. Each CAction is just an action that the entities can perform, for example CActionFight would have the logic for fighting.

To command my player (or any other entity) to fight all I do is:

CActionFight *pActionFight = new CActionFight();
pActionFight->SetTarget(pTargetEntity);
pPlayer->AddAction(pActionFight);

Before this action is started, all other actions queued earlier have to be finished. Imagine player starting to execute the CActionFight over pTargetEntity and suddenly, pTargetEntity disconnects. pTargetEntity is invalid and here's my question.

How do you normally handle that in actions?

If a disconnection event of an entity is received on the server side, do you iterate through the actions of all entity in the map and remove these which are related to an entity that has just dropped connection?

EDIT Liked Josh's approach and implemented the solution, sounds very sensible and worked like a charm.

// Example of an action, checking wether Entity is still valid.
void CActionFight::Execute()
{
    m_iCycles--;

    if(m_iCycles>0)
    {
        if(m_pTarget->IsValid() == false)
        {
            m_pTarget = NULL;
            m_bValid = false;
        }
        else
        {
            printf("Attacking.%s\n", m_pTarget->GetName().data());
        }
    }
    else m_bValid = false;
}
\$\endgroup\$
4
  • \$\begingroup\$ Is location significant in your game? What do you do when one player leaves the location an action was started in? Is the fighting action intended to remain in effect until they disconnect? \$\endgroup\$
    – abathur
    Commented Feb 2, 2015 at 18:20
  • \$\begingroup\$ Yes leaving a location (here a room like in a mud) means stop fighting. Entity is no longer valid in this room \$\endgroup\$
    – PeeS
    Commented Feb 2, 2015 at 18:25
  • \$\begingroup\$ I'm just fishing for whether or not the same mechanism can implicitly handle a disconnected entity which (should?) also not be present? \$\endgroup\$
    – abathur
    Commented Feb 2, 2015 at 18:40
  • \$\begingroup\$ Well think of it this way, remove the networking and add an NPC. Now ActionHarvest on Tree Entity. Imagine NPC was the first one who cut the tree, your Player is still having ActionHarvest on that tree... \$\endgroup\$
    – PeeS
    Commented Feb 2, 2015 at 19:49

1 Answer 1

1
\$\begingroup\$

If a disconnection event of an entity is received on the server side, do you iterate through the actions of all entity in the map and remove these which are related to an entity that has just dropped connection?

You could do that, but it may be unnecessarily inefficient. When an entity gets disconnected from the simulation or otherwise leaves the world, the server should note that and propagate that information through to it's own internal representations of the entity (as well as forward this new information along to clients).

The problem in your scenario, I would say, is this: "pTargetEntity is invalid" once the host for the entity disconnects from the world. The solution is not to invalidate pTargetEntity immediately. Instead, put the entity into a 'invalidated' or 'pending removal from simulation' state. This avoids any issues stemming from deleteing pTargetEntity immediately, leaving everybody else with a dangling pointer.

It also lets you check for that state in the processing of an action. In the action processor, and/or the action itself if appropriate, you can check that all entities involved in the action are still valid. If they are, you continue normally, if they are not, you can abort the action and immediately begin processing the new one.

You can finally release the memory for the disconnected entity once you know all outstanding references to it are removed. There are various ways to do this, such as using a handle idiom or smart pointers to refer to the entity elsewhere, instead of bare pointers. In fact, C++'s built-in std::shared_ptr may be exactly what you need (although it's hard to say for sure if shared ownership is the correct course of action without knowing more about your specific implementation, you should look into it though; if it isn't you can relatively easily build your own handle abstraction).

\$\endgroup\$
1
  • \$\begingroup\$ Sounds sensible, will give it a try. Simple m_bValid flag over every entity should do the trick. Additional checks in CAction classes should check that flag before executing anything. Thanks @Josh \$\endgroup\$
    – PeeS
    Commented Feb 2, 2015 at 19:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .