b0c83af092
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>
182 lines
6.7 KiB
GDScript
182 lines
6.7 KiB
GDScript
extends Node
|
|
class_name _NetworkPerformance
|
|
|
|
const NETWORK_LOOP_DURATION_MONITOR: StringName = &"netfox/Network loop duration (ms)"
|
|
const ROLLBACK_LOOP_DURATION_MONITOR: StringName = &"netfox/Rollback loop duration (ms)"
|
|
const NETWORK_TICKS_MONITOR: StringName = &"netfox/Network ticks simulated"
|
|
const ROLLBACK_TICKS_MONITOR: StringName = &"netfox/Rollback ticks simulated"
|
|
const ROLLBACK_TICK_DURATION_MONITOR: StringName = &"netfox/Rollback tick duration (ms)"
|
|
const ROLLBACK_NODES_SIMULATED_MONITOR: StringName = &"netfox/Rollback nodes simulated"
|
|
const ROLLBACK_NODES_SIMULATED_PER_TICK_MONITOR: StringName = &"netfox/Rollback nodes simulated per tick (avg)"
|
|
|
|
const FULL_STATE_PROPERTIES_COUNT: StringName = &"netfox/Full state properties count"
|
|
const SENT_STATE_PROPERTIES_COUNT: StringName = &"netfox/Sent state properties count"
|
|
const SENT_STATE_PROPERTIES_RATIO: StringName = &"netfox/Sent state properties ratio"
|
|
|
|
var _network_loop_start: float = 0
|
|
var _network_loop_duration: float = 0
|
|
|
|
var _network_ticks: int = 0
|
|
var _network_ticks_accum: int = 0
|
|
|
|
var _rollback_loop_start: float = 0
|
|
var _rollback_loop_duration: float = 0
|
|
|
|
var _rollback_ticks: int = 0
|
|
var _rollback_ticks_accum: int = 0
|
|
|
|
var _rollback_nodes_simulated: int = 0
|
|
var _rollback_nodes_simulated_accum: int = 0
|
|
|
|
var _full_state_props: int = 0
|
|
var _full_state_props_accum: int = 0
|
|
|
|
var _sent_state_props: int = 0
|
|
var _sent_state_props_accum: int = 0
|
|
|
|
static var _logger: NetfoxLogger = NetfoxLogger._for_netfox("NetworkPerformance")
|
|
|
|
## Check if performance monitoring is enabled.
|
|
## [br][br]
|
|
## By default, monitoring is only enabled in debug builds
|
|
## ( see [method OS.is_debug_build] ). [br]
|
|
## Can be forced on with the [code]netfox_perf[/code] feature tag. [br]
|
|
## Can be forced off with the [code]netfox_noperf[/code] feature tag.
|
|
func is_enabled() -> bool:
|
|
if OS.has_feature("netfox_noperf"):
|
|
return false
|
|
|
|
if OS.has_feature("netfox_perf"):
|
|
return true
|
|
|
|
# This returns true in the editor too
|
|
return OS.is_debug_build()
|
|
|
|
## Get time spent in the last network tick loop, in millisec.
|
|
## [br]
|
|
## Note that this also includes time spent in the rollback tick loop.
|
|
func get_network_loop_duration_ms() -> float:
|
|
return _network_loop_duration * 1000
|
|
|
|
## Get the number of ticks simulated in the last network tick loop.
|
|
func get_network_ticks() -> int:
|
|
return _network_ticks
|
|
|
|
## Get time spent in the last rollback tick loop, in millisec.
|
|
func get_rollback_loop_duration_ms() -> float:
|
|
return _rollback_loop_duration * 1000
|
|
|
|
## Get the number of ticks resimulated in the last rollback tick loop.
|
|
func get_rollback_ticks() -> int:
|
|
return _rollback_ticks
|
|
|
|
## Get the average amount of time spent in a rollback tick during the last
|
|
## rollback loop, in millisec.
|
|
func get_rollback_tick_duration_ms() -> float:
|
|
return _rollback_loop_duration * 1000 / maxi(_rollback_ticks, 1)
|
|
|
|
## Get the number of nodes simulated during the last rollback loop.
|
|
func get_rollback_nodes_simulated() -> int:
|
|
return _rollback_nodes_simulated
|
|
|
|
## Get the number of nodes simulated per tick on average during the last
|
|
## rollback loop.
|
|
func get_rollback_nodes_simulated_per_tick() -> float:
|
|
return _rollback_nodes_simulated / maxf(1., _rollback_ticks)
|
|
|
|
func push_rollback_nodes_simulated(count: int):
|
|
_rollback_nodes_simulated_accum += count
|
|
|
|
## Get the number of properties in the full state recorded during the last tick
|
|
## loop.
|
|
func get_full_state_props_count() -> int:
|
|
return _full_state_props
|
|
|
|
## Get the number of properties actually sent during the last tick loop.
|
|
func get_sent_state_props_count() -> int:
|
|
return _sent_state_props
|
|
|
|
## Get the ratio of sent properties count to full state properties count.
|
|
##
|
|
## See [member get_full_state_props_count][br]
|
|
## See [member get_sent_state_props_count]
|
|
func get_sent_state_props_ratio() -> float:
|
|
return _sent_state_props / maxf(1., _full_state_props)
|
|
|
|
func push_full_state(state: Dictionary) -> void:
|
|
_full_state_props_accum += state.size()
|
|
|
|
func push_full_state_props(count: int) -> void:
|
|
_full_state_props_accum += count
|
|
|
|
func push_full_state_broadcast(state: Dictionary) -> void:
|
|
_full_state_props_accum += state.size() * (multiplayer.get_peers().size() - 1)
|
|
|
|
func push_sent_state(state: Dictionary) -> void:
|
|
_sent_state_props_accum += state.size()
|
|
|
|
func push_sent_state_props(count: int) -> void:
|
|
_sent_state_props_accum += count
|
|
|
|
func push_sent_state_broadcast(state: Dictionary) -> void:
|
|
_sent_state_props_accum += state.size() * (multiplayer.get_peers().size() - 1)
|
|
|
|
func _ready() -> void:
|
|
if not is_enabled():
|
|
_logger.debug("Network performance disabled")
|
|
return
|
|
|
|
_logger.debug("Network performance enabled, registering performance monitors")
|
|
Performance.add_custom_monitor(NETWORK_LOOP_DURATION_MONITOR, get_network_loop_duration_ms)
|
|
Performance.add_custom_monitor(ROLLBACK_LOOP_DURATION_MONITOR, get_rollback_loop_duration_ms)
|
|
Performance.add_custom_monitor(NETWORK_TICKS_MONITOR, get_network_ticks)
|
|
Performance.add_custom_monitor(ROLLBACK_TICKS_MONITOR, get_rollback_ticks)
|
|
Performance.add_custom_monitor(ROLLBACK_TICK_DURATION_MONITOR, get_rollback_tick_duration_ms)
|
|
Performance.add_custom_monitor(ROLLBACK_NODES_SIMULATED_MONITOR, get_rollback_nodes_simulated)
|
|
Performance.add_custom_monitor(ROLLBACK_NODES_SIMULATED_PER_TICK_MONITOR, get_rollback_nodes_simulated_per_tick)
|
|
|
|
Performance.add_custom_monitor(FULL_STATE_PROPERTIES_COUNT, get_full_state_props_count)
|
|
Performance.add_custom_monitor(SENT_STATE_PROPERTIES_COUNT, get_sent_state_props_count)
|
|
Performance.add_custom_monitor(SENT_STATE_PROPERTIES_RATIO, get_sent_state_props_ratio)
|
|
|
|
NetworkTime.before_tick_loop.connect(_before_tick_loop)
|
|
NetworkTime.on_tick.connect(_on_network_tick)
|
|
NetworkTime.after_tick_loop.connect(_after_tick_loop)
|
|
|
|
NetworkRollback.before_loop.connect(_before_rollback_loop)
|
|
NetworkRollback.on_process_tick.connect(_on_rollback_tick)
|
|
NetworkRollback.after_loop.connect(_after_rollback_loop)
|
|
|
|
func _before_tick_loop() -> void:
|
|
_network_loop_start = _time()
|
|
_network_ticks_accum = 0
|
|
|
|
func _on_network_tick(_dt, _t) -> void:
|
|
_network_ticks_accum += 1
|
|
|
|
func _after_tick_loop() -> void:
|
|
_network_loop_duration = _time() - _network_loop_start
|
|
_network_ticks = _network_ticks_accum
|
|
|
|
_full_state_props = _full_state_props_accum
|
|
_full_state_props_accum = 0
|
|
|
|
_sent_state_props = _sent_state_props_accum
|
|
_sent_state_props_accum = 0
|
|
|
|
func _before_rollback_loop() -> void:
|
|
_rollback_loop_start = _time()
|
|
_rollback_ticks_accum = 0
|
|
_rollback_nodes_simulated_accum = 0
|
|
|
|
func _on_rollback_tick(_t: int) -> void:
|
|
_rollback_ticks_accum += 1
|
|
|
|
func _after_rollback_loop() -> void:
|
|
_rollback_loop_duration = _time() - _rollback_loop_start
|
|
_rollback_ticks = _rollback_ticks_accum
|
|
_rollback_nodes_simulated = _rollback_nodes_simulated_accum
|
|
|
|
func _time() -> float:
|
|
return Time.get_unix_time_from_system()
|