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>
2.1 KiB
PredictiveSynchronizer
An un-networked version of RollbackSynchronizer which manages states during the rollback loop. Its main use case is for short lived or highly deterministic scenarios where using RollbackSynchronizer isn't practical or necessary.
Key Differences from RollbackSynchronizer
Same same, but different.
- No networking - Operates entirely locally
- No input properties - Only manages state properties
Configuration
Basic Setup
Add PredictiveSynchronizer as a child to your target node and configure:
Root Node
The Root property specifies the root node for resolving state properties. Following the same pattern as RollbackSynchronizer, it's recommended to add PredictiveSynchronizer under its target node, making the parent the root.
State Properties
State properties are recorded for each tick and restored during rollback, just like in RollbackSynchronizer. The key difference is that these states are only managed locally - they're never transmitted across the network.
See Property paths for details on specifying properties.
Writing Prediction-Aware Scripts
PredictiveSynchronizer automatically discovers nodes with a
_rollback_tick() method under the specified root. During rollback, it will
call that method for each tick.
Implement _rollback_tick() in your scripts:
extends ShapeCast3D
@export var projectile_speed: float = 50.0
func _rollback_tick(delta: float, tick: int, is_fresh: bool):
shape_cast.force_shapecast_update()
if is_colliding():
handle_collision()
global_position += transform.basis.z.normalized() * projectile_speed
!!!warning Both PredictiveSynchronizer and RollbackSynchronizer use the same callback method. They are intended to manage separate nodes - having the same node be managed both by RollbackSynchronizer and PredictiveSynchronizer is not supported, and may lead to janky behavior.
