Skip to content

Elements ​

Everything a resource can point at in the world is an element: players, vehicles, pickups, objects and the rest. The server holds every element; a resource holds only handles to them. This page describes which elements exist, who owns them, what a handle is and what happens to handles and events when an element goes away. The functions of each family are in the API reference, dlmp.lua.

The element tree ​

Events are addressed through a tree of elements (Events):

text
root                                 dlmp.root
├── resource:<id>                    dlmp.resource (of that resource)
│   └── resource_root:<id>           dlmp.resource_root
│       ├── vehicle:<id>             created by this resource
│       ├── pickup:<id>
│       ├── object:<id>
│       ├── checkpoint:<id>
│       ├── colshape:<id>
│       └── gang_zone:<id>
└── player:<id>
  • An element a resource created hangs under that resource's dlmp.resource_root, so a handler attached there hears the events of the resource's own elements and nothing else.
  • Players belong to no resource and hang directly under the root.
  • Only the elements in the tree raise events. Labels, blips, markers and teams have handles but raise none.

These tree nodes reach Lua as Element handles: dlmp.root, dlmp.resource, dlmp.resource_root, and dlmp.source while an event is being dispatched. An Element only addresses events; reading and acting go through the family handles below.

Families ​

FamilyCreated byRemoved byHandle
playera connection joining the server (once the auth resource accepts it, when one is configured)its departure: quit, timeout, kick or banPlayer
vehicledlmp.create_vehicle; a train engine model creates the whole train as one vehicledlmp.destroy_vehicle; the owner's stopVehicle
pickupdlmp.create_pickupdlmp.destroy_pickup; dlmp.collect_pickup of a collectible without respawn_ms; the owner's stopPickup
objectdlmp.create_objectdlmp.destroy_object (with everything attached to it); the owner's stop; the removal of its parent; the departure of the only player who sees itObject
labeldlmp.create_labeldlmp.destroy_label; the owner's stop; the removal of the player or vehicle it is attached to; the departure of the only player who sees itLabel
blipdlmp.create_blipas a labelBlip
markerdlmp.create_markerdlmp.destroy_marker; otherwise as a labelMarker
gang zonedlmp.create_gang_zonedlmp.destroy_gang_zone; the owner's stopGangZone
checkpointdlmp.create_checkpointdlmp.destroy_checkpoint; the owner's stop; the departure of its playerCheckpoint
colshapedlmp.create_colshapedlmp.destroy_colshape; the owner's stopColshape
teamdlmp.create_teamdlmp.destroy_team; the owner's stop; its members go teamlessTeam

The ids of created elements count up and are not reused while the server runs. A player id is a slot: the next connection may get the id of a player who left (Players).

A respawn (dlmp.respawn_vehicle) keeps the vehicle, its id and its handles. A vehicle that blew up or drowned stays a wreck until it is respawned or destroyed. A collectible pickup collected with respawn_ms is not removed: until it respawns, dlmp.collect_pickup returns nil, err, and dlmp.destroy_pickup still removes it.

Other state a resource holds ​

Some things are not elements but still belong to the resource that made them and end with its stop:

  • the dialog, passive table, menu and offer a resource shows a player (one of each per player), and an edit session;
  • views (dlmp.open_view) and the resource's client files;
  • what a map placed (dlmp.load_map; map:unload() removes it earlier);
  • HUD entries (announcements, countdowns, status lines, the kill feed, progress bars, notifications, gauges, the speedometer, action prompts) the resource wrote last;
  • declared actions (dlmp.register_action) and platform key overrides;
  • the UI theme (dlmp.set_ui_theme) and the server list's mode text (dlmp.set_mode_text), when this resource set them.

Server-wide settings are no one's: the spawn point, vehicle jacking, the RC range, the player list scope, garage doors, weapon properties and allowances, damage multipliers, the drive-by interval and the server password stay as they were set after the resource that set them stops. Explosions, fires and projectiles are effects, not elements: there is nothing to hold or remove.

Ownership ​

  • The resource that creates an element owns it. Ownership means two things: the stop of the resource removes the element, and the element's events are sourced under the resource's dlmp.resource_root.
  • Ownership is not access control. Any resource may read, change and destroy an element another resource created, for example any vehicle in dlmp.vehicles(). A destroy by another resource removes the element for its owner too.
  • A stop removes the resource's elements after its resource_stop handlers ran, so the elements those handlers created go as well; elements already gone are skipped. A resource_start that fails removes what it created the same way.
  • A reload is a stop and a start: the elements of the old run are removed, and the old VM's handles go with it.
  • Each family has its own typed dlmp.create_<family> and dlmp.destroy_<family>; there is no generic destroy, since each family checks and cleans up in its own way (destroying a vehicle lets go of its RC driver, its trailer and what its winch carries, and takes the labels, blips, markers and objects attached to it along).
  • A destroy raises no events: no player_exit_vehicle, trailer_detach, winch_detach, colshape_leave or checkpoint_leave comes from it.

Handles ​

A handle holds only the element's family and id; a player handle also remembers the connection it belongs to. Every read and every action goes through the server at the moment of the call, so a handle kept across server steps never returns stale data.

  • An event gives each handler fresh handles. Handles of the same element compare equal with ==; tostring names the family and the id ("vehicle:5").
  • A handle is a Lua value, and two equal handles are still two different table keys. Key per-element state by handle:id().
  • A handle belongs to the VM that made it: it cannot cross into another resource (Calling other resources). Pass the id and look the element up on the other side (dlmp.get_player(id)).
  • A handle of the wrong family where another is expected (dlmp.destroy_vehicle(pickup)) raises an error.

Handles after removal ​

CallA player that leftA removed vehicle, pickup or other elementA timer that ended
id(), ==, tostringworkwork—
readsnil, errnil, erris_active() is false
actions, dlmp.destroy_*, passing it to another functionnil, errnil, errcancel() does nothing
after its id is taken againremains bound to the disconnected playerids are not reused—

A timer ends after its last repeat, on cancel() and with the stop of its resource; it is not an element.

Players ​

  • A player comes into being when a connection joins, and lives from player_connect until player_disconnect. With an auth resource configured, a connection is first a Pending that only the auth resource sees; it becomes a player when that resource accepts it (ADR 0052).
  • Players have no owner and hang under the root. Player events therefore reach dlmp.root handlers, never dlmp.resource_root ones, and the stop of a resource does nothing to the players.
  • Every departure goes through one removal path (ADR 0021) and raises player_disconnect(player, reason) with reason "quit", "timeout", "kicked" or "overflow" (Disconnect). It also comes after a kick from a timer or from another handler. Inside its handlers the player is already removed: id() works, reads and actions return nil, err.
  • A player id is a slot that a later connection reuses, but never before player_disconnect of the previous player has been delivered. A handle belongs to one connection: after player_disconnect it can no longer act on any player, even if another player now holds the id, and it equals only handles of its own connection.
  • Keep per-player state in a table keyed by player:id() and clear the entry in player_disconnect.
  • dlmp.source of a player event is the player's tree node, and the tree knows players by id. A handler attached to a saved player dlmp.source stays until the resource stops and fires for the next player of that id too, so attach player handlers to dlmp.root and filter there.
lua
local kills = {}

dlmp.add_event_handler("player_connect", dlmp.root, function(player)
    kills[player:id()] = 0
end)

dlmp.add_event_handler("player_death", dlmp.root, function(victim, killer)
    if killer and kills[killer:id()] then
        kills[killer:id()] = kills[killer:id()] + 1
    end
end)

dlmp.add_event_handler("player_disconnect", dlmp.root, function(player)
    kills[player:id()] = nil
end)

Events with a removed source ​

Events reach the resources one at a time in the order the server committed them (ADR 0048), so an element may be gone by the time an event about it is delivered: a handler of an earlier event in the same server step may have removed it.

  • Removed inside a dispatch. When a handler removes the source of the event it is handling, the remaining handlers of that event still run with the same source; their reads of it return nil, err.
  • Vehicles, objects, checkpoints and colshapes removed after the event was raised take the event with them: it is dropped. A refusable event about a removed vehicle counts as refused, and the server decides the request against the current state. colshape_enter and colshape_leave are also dropped when the player or vehicle crossing was removed. vehicle_syncer names only players who are still there; one who left is nil.
  • Events that need a live player leave with a player who was removed after they were raised: player_action, offer answers, player_stream_in and player_stream_out, checkpoint and colshape crossings, view callbacks, player_key_change, player_weapon_reload and player_suspicion.
  • Facts the server already committed about a removed player are still delivered: damage, death (with the killer for scoring), chat, commands and the rest. Their player handles read nil, err, and player_disconnect of that player follows in the same step.
  • pickup_interact is delivered even when an earlier handler removed the pickup; actions on the pickup then return nil, err.
  • Removal raises nothing on its own: destroying an object raises no object_move_end, destroying a colshape or checkpoint raises no leave, and a player leaving raises only player_disconnect.

Documentation licensed under CC BY 4.0. DarqlineMP is not affiliated with Rockstar Games or Take-Two Interactive. Grand Theft Auto is a trademark of Take-Two Interactive Software, Inc.