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
-14
View File
@@ -1,14 +0,0 @@
[gd_scene load_steps=3 format=3 uid="uid://client_main"]
; Client entry point for testing.
; Connects to server, loads the grey-box test map, and spawns local player.
[ext_resource type="Script" path="res://scripts/network/client_main.gd" id="1_client_main"]
[ext_resource type="PackedScene" uid="uid://test_range_map" path="res://scenes/map/test_range.tscn" id="2_test_map"]
[node name="ClientMain" type="Node3D"]
script = ExtResource("1_client_main")
server_host = "68.202.6.107"
server_port = 34197
[node name="TestMap" parent="." instance=ExtResource("2_test_map")]
-6
View File
@@ -1,6 +0,0 @@
[gd_scene load_steps=2 format=3]
[ext_resource type="Script" path="res://scripts/entry.gd" id="1"]
[node name="Entry" type="Node"]
script = ExtResource("1")
-291
View File
@@ -1,291 +0,0 @@
[gd_scene format=3 uid="uid://test_range_map"]
; ============================================================================
; Grey-box Test Map — "Test Range"
; ============================================================================
; Phase 1 testing arena using CSG nodes with Kenney-style palette.
; 40m x 32m symmetrical layout with cover, pillars, and central structure.
;
; Spawn markers (Marker3D nodes at root level):
; SpawnA, SpawnA2 — Team A spawn (west side, -X)
; SpawnB, SpawnB2 — Team B spawn (east side, +X)
; ============================================================================
; ---------------------------------------------------------------------------
; SUB-RESOURCES
; ---------------------------------------------------------------------------
[sub_resource type="Environment" id=1]
background_mode = 2
ambient_light_source = 1
ambient_light_color = Color(0.3, 0.3, 0.35, 1)
ambient_light_energy = 0.4
tonemap_mode = 0
[sub_resource type="StandardMaterial3D" id=2]
; Floor — dark charcoal
albedo_color = Color(0.227, 0.227, 0.227, 1)
roughness = 0.9
metallic = 0.0
[sub_resource type="StandardMaterial3D" id=3]
; Walls — medium grey
albedo_color = Color(0.4, 0.4, 0.4, 1)
roughness = 0.8
metallic = 0.0
[sub_resource type="StandardMaterial3D" id=4]
; Cover — blue-grey
albedo_color = Color(0.29, 0.435, 0.647, 1)
roughness = 0.7
metallic = 0.0
[sub_resource type="StandardMaterial3D" id=5]
; Center — warm orange accent
albedo_color = Color(0.788, 0.486, 0.239, 1)
roughness = 0.7
metallic = 0.0
[sub_resource type="StandardMaterial3D" id=6]
; Pillars — light grey
albedo_color = Color(0.533, 0.533, 0.533, 1)
roughness = 0.6
metallic = 0.0
[sub_resource type="StandardMaterial3D" id=7]
; Grid lines — darker stripe
albedo_color = Color(0.18, 0.18, 0.18, 1)
roughness = 0.9
metallic = 0.0
[sub_resource type="StandardMaterial3D" id=8]
; Spawn zone — green glow
albedo_color = Color(0.2, 0.5, 0.2, 1)
roughness = 0.3
metallic = 0.1
emission_enabled = true
emission = Color(0.05, 0.15, 0.05, 1)
; ---------------------------------------------------------------------------
; NODES
; ---------------------------------------------------------------------------
[node name="WorldEnvironment" type="WorldEnvironment"]
environment = SubResource(1)
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
transform = Transform3D(0.866025, 0.5, 0, -0.25, 0.433013, 0.866025, 0.433013, -0.75, 0.5, 0, 0, 0)
light_energy = 1.2
shadow_enabled = true
shadow_bias = 0.05
[node name="Map" type="CSGCombiner3D" parent="."]
use_collision = true
calculate_tangents = false
; Floor
[node name="Floor" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.25, 0)
size = Vector3(40, 0.5, 32)
material = SubResource(2)
; Floor grid lines — north-south
[node name="FloorGridNS" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -16, 0.01, 0)
size = Vector3(0.08, 0.04, 32)
material = SubResource(7)
[node name="FloorGridNS2" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8, 0.01, 0)
size = Vector3(0.08, 0.04, 32)
material = SubResource(7)
[node name="FloorGridNS3" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.01, 0)
size = Vector3(0.08, 0.04, 32)
material = SubResource(7)
[node name="FloorGridNS4" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8, 0.01, 0)
size = Vector3(0.08, 0.04, 32)
material = SubResource(7)
[node name="FloorGridNS5" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 16, 0.01, 0)
size = Vector3(0.08, 0.04, 32)
material = SubResource(7)
; Floor grid lines — east-west
[node name="FloorGridEW" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.01, -12)
size = Vector3(40, 0.04, 0.08)
material = SubResource(7)
[node name="FloorGridEW2" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.01, -4)
size = Vector3(40, 0.04, 0.08)
material = SubResource(7)
[node name="FloorGridEW3" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.01, 4)
size = Vector3(40, 0.04, 0.08)
material = SubResource(7)
[node name="FloorGridEW4" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.01, 12)
size = Vector3(40, 0.04, 0.08)
material = SubResource(7)
; Perimeter walls
[node name="WallNorth" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, -16)
size = Vector3(40.4, 4, 0.5)
material = SubResource(3)
[node name="WallSouth" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 16)
size = Vector3(40.4, 4, 0.5)
material = SubResource(3)
[node name="WallEast" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 20, 2, 0)
size = Vector3(0.5, 4, 32.4)
material = SubResource(3)
[node name="WallWest" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -20, 2, 0)
size = Vector3(0.5, 4, 32.4)
material = SubResource(3)
; Cover boxes — Team A side (west)
[node name="CoverBoxA1" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -12, 1, -8)
size = Vector3(3, 2, 3)
material = SubResource(4)
[node name="CoverBoxA2" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -12, 1, 8)
size = Vector3(3, 2, 3)
material = SubResource(4)
[node name="LowCoverA1" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -7, 0.6, -11)
size = Vector3(4, 1.2, 1)
material = SubResource(4)
[node name="LowCoverA2" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -7, 0.6, 11)
size = Vector3(4, 1.2, 1)
material = SubResource(4)
; Cover boxes — Team B side (east)
[node name="CoverBoxB1" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 12, 1, -8)
size = Vector3(3, 2, 3)
material = SubResource(4)
[node name="CoverBoxB2" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 12, 1, 8)
size = Vector3(3, 2, 3)
material = SubResource(4)
[node name="LowCoverB1" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7, 0.6, -11)
size = Vector3(4, 1.2, 1)
material = SubResource(4)
[node name="LowCoverB2" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7, 0.6, 11)
size = Vector3(4, 1.2, 1)
material = SubResource(4)
; Center structure — orange accent
[node name="CenterWall1" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.25, 0)
size = Vector3(6, 2.5, 1.5)
material = SubResource(5)
[node name="CenterWall2" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.25, -6)
size = Vector3(1.5, 2.5, 6)
material = SubResource(5)
[node name="CenterWall3" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.25, 6)
size = Vector3(1.5, 2.5, 6)
material = SubResource(5)
[node name="CenterLow" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0.6, 0)
size = Vector3(2, 1.2, 2)
material = SubResource(5)
[node name="CenterLow2" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0.6, 0)
size = Vector3(2, 1.2, 2)
material = SubResource(5)
; Pillars
[node name="Pillar1" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6, 2, -6)
size = Vector3(1.2, 4, 1.2)
material = SubResource(6)
[node name="Pillar2" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6, 2, 6)
size = Vector3(1.2, 4, 1.2)
material = SubResource(6)
[node name="Pillar3" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6, 2, -6)
size = Vector3(1.2, 4, 1.2)
material = SubResource(6)
[node name="Pillar4" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6, 2, 6)
size = Vector3(1.2, 4, 1.2)
material = SubResource(6)
[node name="PillarMid1" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 2, -3)
size = Vector3(0.8, 4, 0.8)
material = SubResource(6)
[node name="PillarMid2" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 2, 3)
size = Vector3(0.8, 4, 0.8)
material = SubResource(6)
[node name="PillarMid3" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 2, -3)
size = Vector3(0.8, 4, 0.8)
material = SubResource(6)
[node name="PillarMid4" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 2, 3)
size = Vector3(0.8, 4, 0.8)
material = SubResource(6)
; Spawn markers — at root level so _collect_spawn_points finds them
[node name="SpawnA" type="Marker3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -16, 0, -4)
[node name="SpawnA2" type="Marker3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -16, 0, 4)
[node name="SpawnB" type="Marker3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 16, 0, -4)
[node name="SpawnB2" type="Marker3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 16, 0, 4)
; Spawn zone floor indicators
[node name="SpawnAZone" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -16, 0.02, 0)
size = Vector3(4, 0.04, 12)
material = SubResource(8)
[node name="SpawnBZone" type="CSGBox3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 16, 0.02, 0)
size = Vector3(4, 0.04, 12)
material = SubResource(8)
-37
View File
@@ -1,37 +0,0 @@
[gd_scene format=3 uid="uid://player"]
[ext_resource type="Script" path="res://scripts/network/player.gd" id="1_player"]
[ext_resource type="Script" path="res://scripts/characters/fps_camera.gd" id="2_fps_camera"]
[ext_resource type="Script" path="res://scripts/network/player_net_input.gd" id="3_player_net_input"]
[sub_resource type="CapsuleShape3D" id="1"]
radius = 0.4
height = 1.8
[sub_resource type="BoxMesh" id="2"]
size = Vector3(0.8, 0.8, 0.8)
[node name="Player" type="CharacterBody3D"]
script = ExtResource("1_player")
movement_speed = 5.0
local_walk_speed = 5.0
local_sprint_speed = 8.0
local_crouch_speed = 2.5
local_jump_velocity = 4.5
local_gravity = 15.0
local_acceleration = 12.0
[node name="FpsCamera" type="Camera3D" parent="."]
script = ExtResource("2_fps_camera")
current = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.9, 0)
shape = SubResource("1")
[node name="PlayerNetInput" type="Node" parent="."]
script = ExtResource("3_player_net_input")
[node name="Mesh" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0)
mesh = SubResource("2")
-14
View File
@@ -1,14 +0,0 @@
[gd_scene load_steps=3 format=3 uid="uid://server_main"]
; Headless dedicated server entry point.
; Instances the grey-box test map and manages connected players.
[ext_resource type="Script" path="res://scripts/network/server_main.gd" id="1_server_main"]
[ext_resource type="PackedScene" uid="uid://test_range_map" path="res://scenes/map/test_range.tscn" id="2_test_map"]
[node name="ServerMain" type="Node"]
script = ExtResource("1_server_main")
server_port = 34197
[node name="TestMap" type="Node" parent="."]
; Map is instanced on _ready() by server_main.gd when map_scene is provided.
-29
View File
@@ -1,29 +0,0 @@
[gd_scene format=3 uid="uid://server_player"]
; Headless dedicated server player scene.
; No camera, no tick interpolator — server only needs physics representation.
[ext_resource type="Script" path="res://scripts/network/player.gd" id="1_player"]
[ext_resource type="Script" path="res://scripts/network/player_net_input.gd" id="2_player_net_input"]
[sub_resource type="CapsuleShape3D" id="1"]
radius = 0.4
height = 1.8
[sub_resource type="BoxMesh" id="2"]
size = Vector3(0.8, 0.8, 0.8)
[node name="Player" type="CharacterBody3D"]
script = ExtResource("1_player")
movement_speed = 5.0
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.9, 0)
shape = SubResource("1")
[node name="PlayerNetInput" type="Node" parent="."]
script = ExtResource("2_player_net_input")
[node name="Mesh" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0)
mesh = SubResource("2")