Adding a tool
A tool is a piece of equipment the player holds and uses — the mining hammer-drill today, maybe a welder, scanner or cutter tomorrow.
Tool base class yetThere is currently one tool, so there is no formal Tool base class. MiningTool
(scenes/normal_player/mining_tool.gd) is the reference implementation, and the generic,
reusable piece is the EquipmentMount (scenes/normal_player/equipment_mount.gd). This
page describes the pattern to follow; copying MiningTool's structure is the fastest start.
See the recommendation at the end about factoring a base class.
The pieces
| Piece | Role |
|---|---|
EquipmentMount (equipment_mount.gd) | Generic hand mount: holds one item under the player's hand and orients it (follows the camera pitch, or aims its tip at a world point). Reusable by any tool/weapon — open/closed, you don't touch the items themselves. |
The tool node (e.g. MiningTool) | A Node3D child of the player holding the tool logic: equip/stow, per-frame update, the action, and its networking. |
| The action channel | How a tool action reaches the server and the other clients — the same client→server channel the player uses (see Props network management). |
1. Where to put the model
Tool models live under assets/models/equipments/tools/<category>/ (e.g. the drill is
assets/models/equipments/tools/mining/hammerdrill.glb). Follow
Files structure and
3D models.
2. The tool node
Add a Node3D-derived script as a child of the player (like $MiningTool), following the
MiningTool shape:
setup(camera_pivot, camera)— called from the player's_ready: cache the camera, get theEquipmentMount, andhold()the tool model in it.toggle_equip()— bound to an input action (the drill usestoggle_tool): shows / hides the held model.update_local(delta)— called each frame for the local player: aim, animate, detect when the action triggers.- State flags the player reads — e.g.
is_aiming,is_perforating. The player uses them to slow movement and freeze the mouse while aiming / using the tool.
The model is held and oriented by the EquipmentMount, placed through exported offsets (hand
offset, item offset / rotation / scale) — you don't move the model node by hand.
3. The tool action (networking)
A tool action is server-authoritative, like everything else. The pattern:
- The local tool emits a
sync_requestedsignal carrying the action data; the player connects it toclient_send_action_to_server, so the tool stays decoupled from the socket. - The server receives it in
server_action_receivedand applies the effect (the drill fractures the aimed rock). - The equipped tool and its visible state are replicated as player properties (the drill
uses a
toolsproperty + the cameraheadpitch) so other clients see you holding and using it. Remote clients apply it through the tool'sapply_remote(data), and the server sets the equipped tool viaserver_set_tool(...).
Any property you replicate for the tool (tools, head, …) must be declared in
player_def.json, or it is dropped silently. See
Replication definition files.
4. Stowing
If the tool must disappear in some states (the drill stows while the player carries an ore),
expose a set_stowed(value) and call it from the player when that state changes.
Recommendation
Because MiningTool is the only tool today, equip/stow, the EquipmentMount wiring and the
sync_requested plumbing all live in one script. When a second tool arrives, factor those
shared parts into a small Tool base class so a new tool only implements its own action —
the same way GenericProp factors carriable props.