Page MenuHomeFeedback Tracker

1.18.154920 -- Man.ServerTakeEntityToHands method causes hand desync
Assigned, UrgentPublic

Description

Using the ServerTakeEntityToHands method (defined in the Man class) now causes hand desync in DayZ 1.18. This method worked correctly in DayZ 1.17 and earlier.

The following user action code reproduces the issue every time on DayZ 1.18.154920:

class ActionConjureAppleCB : ActionContinuousBaseCB
{
    override void CreateActionComponent()
    {
        m_ActionData.m_ActionComponent = new CAContinuousTime(1);
    }
};

class ActionConjureApple : ActionContinuousBase
{
    static int s_apples = 0;

    void ActionConjureApple()
    {
        m_CallbackClass = ActionConjureAppleCB;
        m_CommandUID = DayZPlayerConstants.CMD_ACTIONFB_INTERACT;
        m_FullBody = true;
        m_StanceMask = DayZPlayerConstants.STANCEMASK_ERECT | DayZPlayerConstants.STANCEMASK_CROUCH;
    }

    override void CreateConditionComponents()
    {
        m_ConditionItem = new CCINone();
        m_ConditionTarget = new CCTNone();
    }

    override string GetText()
    {
        return "Conjure apple";
    }

    override bool SetupAction(
        PlayerBase player, ActionTarget target, ItemBase item, out ActionData action_data,
        Param extra_data = null)
    {
        bool result = super.SetupAction(player, target, item, action_data, extra_data);

        if (!result && GetGame().IsDedicatedServer())
        {
            auto entity = player.GetHumanInventory().GetEntityInHands();

            if (entity != null)
            {
                PrintFormat(
                    "WARNING: Possible hand desync detected! Dropping %1 from player %2 hands",
                    entity.GetType(), player.GetIdentity().GetName());

                player.ServerDropEntity(entity);
            }
        }

        return result;
    }

    override bool ActionCondition(PlayerBase player, ActionTarget target, ItemBase item)
    {
        EntityAI itemInHands = player.GetHumanInventory().GetEntityInHands();
        if (itemInHands)
        {
            return false;
        }

        return true;
    }

    override void OnFinishProgressServer(ActionData action_data)
    {
        s_apples++;
        PrintFormat("%1 apples conjured!", s_apples);

        auto apple = EntityAI.Cast(
            GetGame().CreateObject("Apple", action_data.m_Player.GetPosition()));

        action_data.m_Player.ServerTakeEntityToHands(apple);
    }
};

Full source code:

Details

Severity
Major
Resolution
Open
Reproducibility
Always
Operating System
Windows 10 x64
Category
General
Steps To Reproduce

On DayZ 1.18:

  1. In server-side code, call ServerTakeEntityToHands on a player to move an object into the player's hands.
  2. Observe that the player's hands are empty on the client, but the server thinks the item was moved to the player's hands.

On stable DayZ 1.17, the item ends up in the player's hands on both the client and server.

Additional Information

Tested with DayZ Experimental version 1.18.154920 and stable DayZ version 1.17.154754.

Event Timeline

tjensen created this task.Jun 2 2022, 10:35 PM
Moonny added a subscriber: Moonny.Jun 4 2022, 2:56 PM

The problem exists but here are some workarounds:

  1. You can create new entity directly in hands with special methods (CreateInHands() for EntityAI via HumanInventory f.e.)
  2. You can use presets (used mainly in recipes) to replace items (f.e. ReplaceItemInHandsWithNew() ). Or you can create your own preset.

I recommend looking into ReplaceEdibleWithNew.

Geez changed the task status from New to Assigned.Jun 8 2022, 11:06 AM