Files
tactical-shooter/docs/netfox/tutorials/configuring-properties-from-code.md
shawn b0c83af092 Fresh start: replace with naxIO/netfox-cs-sample foundation
Complete replacement of the tactical-shooter project with the
netfox-cs-sample (MIT) — a CS 1.6 inspired multiplayer FPS built
with Godot 4 and netfox.

## What's new
- Full CS-style gameplay: teams (T/CT), rounds, economy, buy menu
- 6 weapons: Knife, Glock, USP, AK-47, M4A1, AWP
- Bomb plant/defuse with 2 bombsites
- Flashbang & smoke grenades
- Proper netfox rollback netcode at 64 tick
- Network popup UI for host/join
- HUD, crosshair, round timer, scoreboard
- All netfox singletons registered as autoloads (works in exported builds)

## Architecture
- Listen-server (host from client, no dedicated server binary)
- Multiplayer-fps game lives at examples/multiplayer-fps/
- Netfox addons registered as autoloads for exported build compat
- Godot 4.7 with Forward+ renderer

## Removed
- Old headless-server architecture (client_main, server_main, player.gd, etc.)
- Custom netfox bootstrap with ENet fallback
- Old ChaffGames FPS template (2,420 lines, 844 KB)
- SimulationServer GDExtension stub
- Godot-jolt physics (netfox sample uses default Godot physics)
- Duplicate weapon_data.gd, anti_cheat.gd, round_manager.gd, etc.
- Server browser API Python venv (87 MB)
- test_range map and modular assets

## Preserved
- Git history
- Server config at config/default_server_config.cfg
- Windows export preset
- Build directory (gitignored)

Co-authored-by: naxIO <naxIO@users.noreply.github.com>
2026-07-02 20:55:20 -04:00

120 lines
4.3 KiB
Markdown

# Configuring properties from code
In netfox, there are multiple nodes that accept [property paths] as their
configuration, for various purposes. These can be configured as lists of
strings in the editor.
In bigger projects, with many scenes and deeper class trees, manually
configuring property paths may be tedious and unscaleable. Potentially, there
may be cases where these properties are only known at runtime, not when working
in the Editor.
There are solutions for both cases.
## Adding properties from code
Properties can be added at run-time with the following methods:
* `TickInterpolator::add_property(node, property)`
* `StateSynchronizer::add_state(node, property)`
* `RollbackSynchronizer::add_state(node, property)`
* `RollbackSynchronizer::add_input(node, property)`
*node* is a reference to a node - it may be a *string* or a *[NodePath]*
pointing to an existing node, or a *[Node]* instance. When using paths, the
path itself is considered relative to the configured *root* node.
After calling any of the methods above, calling `process_settings()` is not
necessary - it will be called automatically.
!!! warning
The same as with `process_settings()`, configuration changes are not
synchronized automatically! You, the developer, must ensure that
configuration changes happen on all peers, at the same time.
Changing state- and input property configurations is not recommended during
gameplay.
## Adding properties automatically, in the editor
You can ensure that certain properties are added to netfox's nodes'
configuration by making your class a `@tool` script, and implementing the
following methods:
* TickInterpolator: `_get_interpolated_properties()`
* StateSynchronizer: `_get_synchronized_state_properties()`
* RollbackSynchronizer:
* `_get_rollback_state_properties()` for state
* `_get_rollback_input_properties()` for input
These must return an array, with each element being a string, or a two-element
array.
Strings are interpreted as property names.
Arrays are interpreted as node-property pairs. Similarly to the `add_*`
methods, the *node* may be a string, a [NodePath], or an actual [Node]
instance. When using strings or [NodePath]s, keep in mind that the path is
considered *relative to the node itself, not the configured root*.
Each of these nodes will explore nodes under their `root` node, and call the
above methods if implemented. The results will be added to the node
configuration.
This exploration is implemented in the nodes' `_get_configuration_warnings()`
method, which is called when the node tree changes ( i.e. nodes are added /
removed ), and when opening the scene.
The exploration also runs when before saving the scene, to make sure that any
updates are picked up.
!!! tip
To make sure that the updated methods are picked up, save your scene. The
exploration is ran before every scene save.
An example implementation for the above methods:
```gdscript
func _get_interpolated_properties():
# Specify a list of properties
return ["position", "quaternion"]
func _get_synchronized_state_properties() -> Array:
# Specify inherited properties and more
return super() + [
"health", "name",
[weapon, "ammo"], # Specify a property on another node
["Hand/Weapon", "ammo"] # Specify node by path
]
func _get_rollback_state_properties() -> Array:
return [
"transform", # Specify a property on self
[weapon, "ammo"] # Specify a property on another node
]
func _get_rollback_input_propertes() -> Array:
# Specify a list of properties
return ["movement", "is_jumping"]
```
See the [Property configuration example].
!!! note
In general, it's best practice to only specify node's own properties. An
exception is when the given node has no script attached.
### Caveats
**Node renames and removals** are not tracked. Unless fixed manually, they will
result in invalid property warnings.
A workaround is to reset the node's state/input/property configuration to an
empty array and save again. This will gather the tracked properties with the
right node names.
[property paths]: ../guides/property-paths.md
[NodePath]: https://docs.godotengine.org/en/stable/classes/class_nodepath.html
[Node]: https://docs.godotengine.org/en/stable/classes/class_node.html
[Property configuration example]: https://github.com/foxssake/netfox/tree/main/examples/property-configuration