Fix Windows build: use entry.tscn as main scene, add fallback input handling
- Changed run/main_scene to entry.tscn (smart bootstrap detects headless vs display) - client_main.gd now uses player.tscn instead of old FPS template - Added mouse look (click-to-capture, escape-to-release) to player.gd fallback path - Added _gather() call to player.gd fallback _physics_process() so PlayerNetInput is populated even without NetworkTime singleton (exported builds) - Re-exported Windows build with same tag v0.1.0-windows
This commit is contained in:
+1
-1
@@ -12,7 +12,7 @@ config_version=5
|
|||||||
|
|
||||||
config/name="Tactical Shooter"
|
config/name="Tactical Shooter"
|
||||||
config/description="Phase 0 — Headless Dedicated Server"
|
config/description="Phase 0 — Headless Dedicated Server"
|
||||||
run/main_scene="res://scenes/server/server_main.tscn"
|
run/main_scene="res://scenes/entry.tscn"
|
||||||
config/features=PackedStringArray("4.7", "Forward Plus")
|
config/features=PackedStringArray("4.7", "Forward Plus")
|
||||||
|
|
||||||
[autoload]
|
[autoload]
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ extends Node3D
|
|||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@export var server_host: String = "68.202.6.107"
|
@export var server_host: String = "68.202.6.107"
|
||||||
@export var server_port: int = 34197
|
@export var server_port: int = 34197
|
||||||
@export var fps_scene: PackedScene = preload("res://client/template/player_character.tscn")
|
@export var fps_scene: PackedScene = preload("res://scenes/player.tscn")
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# State
|
# State
|
||||||
|
|||||||
@@ -109,22 +109,72 @@ func _ready() -> void:
|
|||||||
print("[Player] Remote player: %d (authority: %d) — rollback sync" % [
|
print("[Player] Remote player: %d (authority: %d) — rollback sync" % [
|
||||||
multiplayer.get_unique_id(), multiplayer.get_multiplayer_authority()])
|
multiplayer.get_unique_id(), multiplayer.get_multiplayer_authority()])
|
||||||
else:
|
else:
|
||||||
# No RollbackSynchronizer (headless/server mode).
|
# No RollbackSynchronizer (headless/server mode or exported build).
|
||||||
# Enable _physics_process as fallback simulation.
|
# Enable _physics_process as fallback simulation.
|
||||||
set_physics_process(true)
|
set_physics_process(true)
|
||||||
|
# Enable _input for mouse look when this is the local player
|
||||||
|
set_process_input(is_local)
|
||||||
print("[Player] Player %d — rollback not available, using fallback physics" % multiplayer.get_unique_id())
|
print("[Player] Player %d — rollback not available, using fallback physics" % multiplayer.get_unique_id())
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Input (mouse look) — used only in fallback mode (no rollback sync)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## Mouse look variables for fallback mode.
|
||||||
|
var _mouse_look_sensitivity: float = 0.003
|
||||||
|
var _mouse_look_invert_y: bool = false
|
||||||
|
var _mouse_captured: bool = false
|
||||||
|
|
||||||
|
## Handle mouse input for looking around in fallback mode.
|
||||||
|
## Only active when set_process_input(true) was called in _ready.
|
||||||
|
func _input(event: InputEvent) -> void:
|
||||||
|
if not is_local or _rollback_sync != null:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Mouse look
|
||||||
|
if event is InputEventMouseMotion and _mouse_captured:
|
||||||
|
var rel: Vector2 = event.relative
|
||||||
|
_yaw -= rel.x * _mouse_look_sensitivity
|
||||||
|
var invert: float = -1.0 if _mouse_look_invert_y else 1.0
|
||||||
|
_pitch += rel.y * _mouse_look_sensitivity * invert
|
||||||
|
_pitch = clamp(_pitch, deg_to_rad(-89.0), deg_to_rad(89.0))
|
||||||
|
|
||||||
|
# Click to capture mouse
|
||||||
|
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
|
||||||
|
if not _mouse_captured:
|
||||||
|
_capture_mouse_fallback(true)
|
||||||
|
|
||||||
|
func _unhandled_input(event: InputEvent) -> void:
|
||||||
|
if not is_local or _rollback_sync != null:
|
||||||
|
return
|
||||||
|
# Escape to release mouse
|
||||||
|
if event.is_action_pressed("ui_cancel"):
|
||||||
|
_capture_mouse_fallback(false)
|
||||||
|
|
||||||
|
func _capture_mouse_fallback(capture: bool) -> void:
|
||||||
|
if capture == _mouse_captured:
|
||||||
|
return
|
||||||
|
_mouse_captured = capture
|
||||||
|
if capture:
|
||||||
|
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
||||||
|
else:
|
||||||
|
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Fallback physics — used when RollbackSynchronizer is not available
|
# Fallback physics — used when RollbackSynchronizer is not available
|
||||||
# (e.g., headless dedicated server without netfox singletons).
|
# (e.g., headless dedicated server without netfox singletons, or exported builds).
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
func _physics_process(delta: float) -> void:
|
func _physics_process(delta: float) -> void:
|
||||||
# Only run fallback if RollbackSynchronizer is NOT handling ticks
|
# Only run fallback if RollbackSynchronizer is NOT handling ticks
|
||||||
if _rollback_sync != null:
|
if _rollback_sync != null:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Read input from PlayerNetInput (if we're the authority)
|
# Gather current frame input into PlayerNetInput (standalone mode)
|
||||||
var input_node = _find_input_node()
|
var input_node = _find_input_node()
|
||||||
|
if input_node != null and input_node.has_method(&"_gather"):
|
||||||
|
input_node._gather()
|
||||||
|
|
||||||
|
# Read input from PlayerNetInput (if we're the authority)
|
||||||
if input_node == null:
|
if input_node == null:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user