How YimMenuV2 Entity Networking Methods Work: ForceControl and PreventMigration Explained

YimMenuV2 uses ForceControl() to seize network ownership of any entity and PreventMigration() to disable GTA V's automatic proximity-based host migration, ensuring stable modding control over vehicles, peds, and objects.

The YimMenu::Entity class serves as the foundation for manipulating in-game objects within the YimMenuV2 codebase. When entities are networked—meaning they possess a corresponding netObject—these methods provide deterministic control over ownership states that standard game scripts cannot guarantee.

Understanding Network Ownership in GTA V

GTA V's networking architecture automatically manages entity ownership to distribute simulation load across connected clients. By default, the player closest to an entity becomes its network owner, granting exclusive write permissions for position updates, health changes, and deletion requests. This automatic migration causes desynchronization issues in modding contexts, requiring explicit intervention through the network object manager (Pointers.NetworkObjectMgr).

How ForceControl() Takes Ownership of Networked Entities

The ForceControl() method programmatically transfers network ownership to the local player without waiting for standard request-control loops. This operation is essential for executing destructive or transformative actions on entities created by other players.

Implementation Details in Entity.cpp

According to the source code in src/game/gta/Entity.cpp, the method executes a strict validation sequence before modifying ownership:

  1. Entity Validation: Uses ENTITY_ASSERT_VALID to ensure the handle references an existing game object
  2. Network Check: Returns early if IsNetworked() returns false or HasControl() returns true (already owned)
  3. Ownership Transfer: Calls ChangeOwner on the network object manager to immediately assign the local player as host
// From src/game/gta/Entity.cpp (lines 137-144)
void Entity::ForceControl()
{
    ENTITY_ASSERT_VALID();
    
    if (!IsNetworked() || HasControl())
        return;
        
    // Forces local player to become network owner
    Pointers.NetworkObjectMgr->ChangeOwner(m_NetObject, Pointers.GetLocalPlayerInfo(), 0);
}

Lua Scripting Access

The scripting interface exposes this functionality through the force_control binding registered in src/game/scripting/libraries/Entity.cpp. This allows Lua scripts to safely manipulate entities selected through the menu interface.

-- Assume 'vehicle' is a YimMenu entity handle
vehicle:force_control()
-- Now safe to modify: set position, apply upgrades, or delete
vehicle:set_position(PLAYER.GET_PLAYER_COORDS(PLAYER.PLAYER_ID()))

How PreventMigration() Stops Automatic Host Transfer

GTA V's proximity-based migration system automatically transfers entity ownership to the nearest player to optimize network traffic. The PreventMigration() method disables this behavior, keeping the entity bound to its current host regardless of physical distance.

The Migration Problem

Without migration prevention, entities transferred between hosts experience:

  • Position snapping and rubber-banding
  • Loss of applied modifications (god mode, custom properties)
  • Failed deletion attempts when the original creator leaves

Implementation Details

The implementation in src/game/gta/Entity.cpp (lines 317-334) verifies session state before invoking the native:

void Entity::PreventMigration()
{
    ENTITY_ASSERT_VALID();
    
    if (!*Pointers.IsSessionStarted)
        return;
        
    if (!NETWORK::NETWORK_HAS_ENTITY_BEEN_REGISTERED_WITH_THIS_THREAD(m_Handle))
        return;
        
    // Disable automatic proximity-based migration
    NETWORK::NETWORK_DISABLE_PROXIMITY_MIGRATION(NETWORK::PED_TO_NET(m_Handle));
}

This method requires:

  • An active game session (*Pointers.IsSessionStarted)
  • Thread registration via NETWORK_HAS_ENTITY_BEEN_REGISTERED_WITH_THIS_THREAD
  • Conversion of the entity handle to a network ID using NETWORK::PED_TO_NET

C++ Usage Example

YimMenu::Entity target = GetEntityByHandle(someVehicle);
target.ForceControl();        // Take ownership first
target.PreventMigration();    // Lock to current host
// Entity remains stable regardless of distance from original owner

Practical Implementation: The Bring Feature

The Bring feature in src/game/features/world/Bring.cpp demonstrates the combined usage pattern (lines 18-52). This feature teleports distant entities to the local player by first ensuring network dominance:

void BringEntity(YimMenu::Entity& obj)
{
    // Seize control to allow position updates
    obj.ForceControl();
    
    // Prevent immediate migration back to original host
    obj.PreventMigration();
    
    // Safely teleport now that we own the network object
    obj.SetPosition(self.GetPosition());
}

This sequence prevents the common failure mode where entities snap back to their original positions after teleportation due to ownership conflicts.

Summary

  • ForceControl() immediately transfers network ownership to the local player through Pointers.NetworkObjectMgr->ChangeOwner(), bypassing standard request queues in src/game/gta/Entity.cpp
  • PreventMigration() calls NETWORK_DISABLE_PROXIMITY_MIGRATION to stop GTA V's automatic host transfer based on player proximity
  • Both methods validate entities using ENTITY_ASSERT_VALID and check session state via rage::tlsContext to prevent crashes
  • The Lua binding in src/game/scripting/libraries/Entity.cpp exposes force_control to scripting environments
  • Production features like Bring in src/game/features/world/Bring.cpp combine these methods to ensure stable entity manipulation

Frequently Asked Questions

What is network ownership in GTA V?

Network ownership determines which client has authority to write state changes (position, health, deletion) to an entity. Only the current network owner can reliably modify networked objects; other players receive desynchronized updates if they attempt changes. YimMenuV2's ForceControl() manipulates this ownership through the netObject system.

Why does ForceControl fail on some entities?

ForceControl() fails when entities are not networked (IsNetworked() returns false) or when the local player already owns the entity (HasControl() returns true). Additionally, the method requires a valid netObject pointer from the network object manager; entities in single-player modes or certain interior cells lack these network components entirely.

Is PreventMigration permanent?

No, PreventMigration() persists only for the current session or until the entity is deleted. If the entity is recreated or the session changes, the protection must be reapplied. The method uses NETWORK_DISABLE_PROXIMITY_MIGRATION, which binds to the specific network ID generated when NETWORK_HAS_ENTITY_BEEN_REGISTERED_WITH_THIS_THREAD validates the script context.

Can these methods be used in Lua scripts?

Yes, force_control is exposed to Lua through the scripting library in src/game/scripting/libraries/Entity.cpp. However, prevent_migration requires direct native calls via the NETWORK_DISABLE_PROXIMITY_MIGRATION native, as the specific method binding may vary by build. Always call force_control before attempting destructive operations on entities created by other players.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →