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>
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
# NetworkCommandServer
|
||||
|
||||
Implements a simpler, lightweight alternative to RPCs. Provided as an autoload.
|
||||
|
||||
Commands consist of a single byte for ID, and the raw binary data. The ID lets
|
||||
the receiving peer decide what to execute, with the binary data serving as the
|
||||
input.
|
||||
|
||||
Being a simpler construct makes commands a good fit for regular, fundamental
|
||||
operations. For example, commands internally are used for time synchronization,
|
||||
or synchronizing state and input between peers.
|
||||
|
||||
Commands are, by default, transmitted over regular RPCs. To use less data,
|
||||
commands can also be transmitted as raw packets, using
|
||||
[SceneMultiplayer.send_bytes()]. This is an opt-in feature - if the game is
|
||||
already using [SceneMultiplayer.send_bytes()], it needs to be aware of
|
||||
commands, and must check each packet whether it's a command or one of its own
|
||||
packets. To check if a packet is a command, use `is_command_packet()`.
|
||||
|
||||
## Implementing custom commands
|
||||
|
||||
Custom commands can be registered with the *NetworkCommandServer*, using
|
||||
`register_command()`. This returns a *Command* object that provides a
|
||||
convenient interface.
|
||||
|
||||
During registration, a callback must be provided, that will be ran when the
|
||||
command is received.
|
||||
|
||||
Commands can be sent using its `send()` method.
|
||||
|
||||
```gdscript
|
||||
@onready var cmd_message := NetworkCommandServer.register_command(handle_message, MultiplayerPeer.TRANSFER_MODE_UNRELIABLE)
|
||||
|
||||
func handle_message(sender: int, data: PackedByteArray) -> void:
|
||||
var message := data.get_string_from_utf8()
|
||||
print("#%d: %s" % [sender, message])
|
||||
|
||||
func _ready() -> void:
|
||||
cmd_message.send("Hello, world!".to_utf8_buffer())
|
||||
```
|
||||
|
||||
!!!tip
|
||||
It is recommended to setup commands once, at game start. When registering
|
||||
commands from autoloads, make sure they run *after* netfox's autoloads.
|
||||
|
||||
## Differences compared to RPCs
|
||||
|
||||
Commands are a fundamentally simpler constructs compared to RPCs.
|
||||
|
||||
### Maximum 256 commands
|
||||
|
||||
Commands are limited to 256 indices - make sure to not register more than that.
|
||||
Some commands are registered by netfox on startup as well.
|
||||
|
||||
This limitation also makes commands a poor fit for registering dynamically.
|
||||
Dynamic registrations often mean registering commands as certain nodes or
|
||||
objects are created. This, in turn, makes it difficult to place an upper bound
|
||||
on the number of commands needed, which can conflict with this limitation.
|
||||
|
||||
### Commands are not tied to any node
|
||||
|
||||
Commands do not refer to any specific node or object in their content. They
|
||||
only contain a command index. Even though the API encapsulates this into
|
||||
*Command* objects, it is completely feasible to have different nodes handle the
|
||||
same command on different peers ( if the game is built as different Godot
|
||||
projects ).
|
||||
|
||||
### Commands do not track authority
|
||||
|
||||
Any peer can send any command to any other peer. It is the receiving peer's
|
||||
responsibility to check whether the sender is allowed to send such a command or
|
||||
not.
|
||||
|
||||
### Commands do not have arguments
|
||||
|
||||
To stay lightweight and to give maximum control, commands contain raw bytes
|
||||
only, no arguments.
|
||||
|
||||
In general, this can be worked around by wrapping the arguments in an array and
|
||||
converting it using [var_to_bytes()] and [bytes_to_var()].
|
||||
|
||||
However, for cases where bandwidth matters, this allows users to encode data in
|
||||
a way that fits best.
|
||||
|
||||
## Settings
|
||||
|
||||
netfox ▸ General ▸ Use Raw Commands
|
||||
|
||||
: When enabled, netfox will transmit commands as raw packets, instead of RPCs.
|
||||
|
||||
|
||||
[SceneMultiplayer.send_bytes()]: https://docs.godotengine.org/en/stable/classes/class_scenemultiplayer.html#class-scenemultiplayer-method-send-bytes
|
||||
[var_to_bytes()]: https://docs.godotengine.org/en/stable/classes/class_%40globalscope.html#class-globalscope-method-var-to-bytes
|
||||
[bytes_to_var()]: https://docs.godotengine.org/en/stable/classes/class_%40globalscope.html#class-globalscope-method-bytes-to-var
|
||||
Reference in New Issue
Block a user