Phase 7: test server deployment + Windows export
- Fix: export_presets.cfg — platform='Windows Desktop' (correct name) - Fix: server_main.gd — formatting bug on lag-comp string - Fix: game_server.gd — auto-detect GDExtension, fall back to GDScript stub - Add: server/scripts/simulation_server_stub.gd — lightweight SimulationServer in GDScript - Add: docs/playtest-guide.md — connection instructions, control bindings, server commands - Add: systemd user service — tactical-shooter-server (enabled, running) - Add: server config at ~/tactical-shooter-server/server_config.cfg - Build: Windows 109MB PE32+ client (build/tactical-shooter-windows-x86_64/) - Build: Linux server binary (78MB) — running on oplabs:34197 - Temporarily disabled GDExtension (needs C++ build fix in entity.cpp enum casting)
This commit is contained in:
@@ -48,8 +48,11 @@ var entity_to_peer: Dictionary = {} # entity_id (int) → peer_id (int)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
func _ready() -> void:
|
||||
# Create the SimulationServer
|
||||
simulation_server = SimulationServer.new()
|
||||
# Create the SimulationServer (stub if GDExtension not compiled)
|
||||
var SimServerClass = load("res://server/scripts/simulation_server_stub.gd")
|
||||
if ClassDB.class_exists(&"SimulationServer"):
|
||||
SimServerClass = ClassDB.instantiate(&"SimulationServer").get_script()
|
||||
simulation_server = SimServerClass.new()
|
||||
simulation_server.set_tick_rate(128)
|
||||
|
||||
# Apply movement config from ServerConfig singleton if available
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
## SimulationServerStub — lightweight GDScript replacement for GDExtension C++ core.
|
||||
##
|
||||
## Provides the same API surface so game_server.gd and FPSCharacterController
|
||||
## work without the compiled GDExtension library. No 128Hz simulation — just
|
||||
## stores entity state and passes through input. Replace with the C++
|
||||
## SimulationServer once `scons` builds cleanly.
|
||||
extends RefCounted
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Nested: Entity state data
|
||||
# ---------------------------------------------------------------------------
|
||||
class Entity:
|
||||
var id: int = -1
|
||||
var peer_id: int = -1
|
||||
var position: Vector3 = Vector3.ZERO
|
||||
var rotation: Vector3 = Vector3.ZERO
|
||||
var velocity: Vector3 = Vector3.ZERO
|
||||
var alive: bool = true
|
||||
var health: float = 100.0
|
||||
var input_sequence: int = 0
|
||||
|
||||
func is_alive() -> bool:
|
||||
return alive
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Config
|
||||
# ---------------------------------------------------------------------------
|
||||
var _tick_rate: int = 128
|
||||
var _movement_config: Dictionary = {}
|
||||
var _weapon_config: Dictionary = {}
|
||||
var _history_depth: int = 64
|
||||
var _next_entity_id: int = 1
|
||||
var _entities: Dictionary = {} # entity_id → Entity
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# SimulationServer API
|
||||
# ---------------------------------------------------------------------------
|
||||
func set_tick_rate(hz: int) -> void:
|
||||
_tick_rate = hz
|
||||
|
||||
func get_tick_rate() -> int:
|
||||
return _tick_rate
|
||||
|
||||
func set_movement_config(cfg: Dictionary) -> void:
|
||||
_movement_config = cfg
|
||||
|
||||
func set_weapon_config(cfg: Dictionary) -> void:
|
||||
_weapon_config = cfg
|
||||
|
||||
func set_history_depth(depth: int) -> void:
|
||||
_history_depth = depth
|
||||
|
||||
func apply_input(entity_id: int, input_dict: Dictionary) -> void:
|
||||
var e: Entity = _entities.get(entity_id)
|
||||
if e == null:
|
||||
return
|
||||
# Apply movement from input (simplified)
|
||||
if input_dict.has("move_direction"):
|
||||
var dir: Vector3 = input_dict["move_direction"]
|
||||
var speed: float = 5.0
|
||||
if input_dict.get("sprint", false):
|
||||
speed = 8.0
|
||||
elif input_dict.get("crouch", false):
|
||||
speed = 2.5
|
||||
e.velocity = dir * speed
|
||||
e.position += e.velocity * (1.0 / _tick_rate)
|
||||
# Track input sequence
|
||||
if input_dict.has("input_sequence"):
|
||||
e.input_sequence = input_dict["input_sequence"]
|
||||
|
||||
func fire_weapon(entity_id: int) -> void:
|
||||
# Stub: log the event
|
||||
pass
|
||||
|
||||
func get_entity(entity_id: int) -> Entity:
|
||||
return _entities.get(entity_id)
|
||||
|
||||
func spawn_player_entity(peer_id: int, pos: Vector3) -> int:
|
||||
var e = Entity.new()
|
||||
e.id = _next_entity_id
|
||||
e.peer_id = peer_id
|
||||
e.position = pos
|
||||
e.alive = true
|
||||
e.health = 100.0
|
||||
_entities[_next_entity_id] = e
|
||||
_next_entity_id += 1
|
||||
return e.id
|
||||
|
||||
func despawn_player_entity(entity_id: int) -> void:
|
||||
_entities.erase(entity_id)
|
||||
|
||||
func tick(delta: float) -> void:
|
||||
# Stub: in the real C++ SimulationServer this runs the 128Hz simulation
|
||||
pass
|
||||
|
||||
func get_entity_count() -> int:
|
||||
return _entities.size()
|
||||
@@ -0,0 +1 @@
|
||||
uid://b1lw5s1djwsqk
|
||||
Reference in New Issue
Block a user