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:
2026-07-02 20:55:20 -04:00
parent ce39b237c3
commit b0c83af092
4416 changed files with 57418 additions and 902676 deletions
@@ -0,0 +1,44 @@
extends NetworkWeapon3D
class_name BrawlerWeapon
@export var projectile: PackedScene
@export var fire_cooldown: float = 0.15
@onready var input: BrawlerInput = $"../Input"
@onready var sound: AudioStreamPlayer3D = $AudioStreamPlayer3D
var last_fire: int = -1
static var _logger := NetfoxLogger.new("fb", "BrawlerWeapon")
func _ready():
NetworkTime.on_tick.connect(_tick)
func _can_fire() -> bool:
return NetworkTime.seconds_between(last_fire, NetworkTime.tick) >= fire_cooldown
func _can_peer_use(peer_id: int) -> bool:
return peer_id == input.get_multiplayer_authority()
func _after_fire(projectile: Node3D):
var bomb := projectile as BombProjectile
last_fire = get_fired_tick()
sound.play()
_logger.trace("[%s] Ticking new bomb %d -> %d", [bomb.name, get_fired_tick(), NetworkTime.tick])
for t in range(get_fired_tick(), NetworkTime.tick):
if bomb.is_queued_for_deletion():
break
bomb._tick(NetworkTime.ticktime, t)
func _spawn() -> Node3D:
var bomb_projectile: BombProjectile = projectile.instantiate() as BombProjectile
get_tree().root.add_child(bomb_projectile, true)
bomb_projectile.global_transform = global_transform
bomb_projectile.fired_by = get_parent()
return bomb_projectile
func _tick(_delta: float, _t: int):
if input.is_firing:
fire()