252 lines
8.1 KiB
GDScript
252 lines
8.1 KiB
GDScript
extends Node2D
|
|
|
|
@export var DEBUG_MULTIPLAYER: bool = true
|
|
|
|
var player_scene = preload("res://scripts/entities/player/player.tscn")
|
|
var pot_scene = preload("res://scripts/entities/world/pot.tscn")
|
|
|
|
var has_started = false
|
|
var round_started = false
|
|
var start_round = false
|
|
var round_finished = false
|
|
|
|
func _ready() -> void:
|
|
MultiplayerManager.addPlayerSignal.connect(_addPlayer)
|
|
MultiplayerManager.delPlayerSignal.connect(_delPlayer)
|
|
|
|
MultiplayerManager.finished_hosting.connect(_finishedHosting)
|
|
|
|
MultiplayerManager.countdownFinished.connect(_finishedCountdown)
|
|
|
|
#if id == 1:
|
|
#var pot:CharacterBody2D = pot_scene.instantiate()
|
|
#pot.position = Vector2(90,80)
|
|
#$SpawnRoot.add_child(pot)
|
|
|
|
if DEBUG_MULTIPLAYER:
|
|
# Add a random delay to ensure instances start at different times
|
|
var random_delay = randf_range(0.1, 0.5)
|
|
await get_tree().create_timer(random_delay).timeout
|
|
call_deferred("_setup_debug_multiplayer")
|
|
|
|
pass
|
|
|
|
func _finishedCountdown():
|
|
round_started = true
|
|
# reset all players hp, kills and deaths
|
|
$TimerRound.start($TimerRound.wait_time)
|
|
# sync to other players!
|
|
if multiplayer.is_server():
|
|
_syncTimerToPlayer.rpc($TimerRound.time_left)
|
|
pass
|
|
|
|
func time_to_minutes_secs(time: float):
|
|
var mins = int(floor(int(time) / 60.0))
|
|
time -= mins * 60
|
|
var secs = int(time)
|
|
#var mili = int((time - int(time)) * 100)
|
|
var extraSecZero = "0" if secs < 10 else ""
|
|
var extraMinZero = "0" if mins < 10 else ""
|
|
return extraMinZero + str(mins) + ":" + extraSecZero + str(secs)
|
|
|
|
func _process(_delta: float) -> void:
|
|
if round_finished == false and round_started == false and start_round == false and multiplayer != null and multiplayer.is_server():
|
|
# make sure atleast 2 players are connected
|
|
var _players = 0
|
|
for pl: CharacterBody2D in $SpawnRoot.get_children():
|
|
if "is_player" in pl:
|
|
_players += 1
|
|
#if _players == 2:
|
|
#start_round_func.rpc()
|
|
if round_started:
|
|
$HUD/MarginContainerUpperRight/HBoxContainer/VBoxContainer/LabelTimeValue.text = time_to_minutes_secs($TimerRound.time_left)
|
|
pass
|
|
|
|
@rpc("call_local", "reliable")
|
|
func start_round_func():
|
|
if start_round == true:
|
|
return
|
|
start_round = true
|
|
MultiplayerManager.start_round()
|
|
|
|
pass
|
|
|
|
func _finishedHosting():
|
|
has_started = true
|
|
pass
|
|
|
|
func _addPlayer(id: int):
|
|
print("add player:", id)
|
|
#if id == 1:
|
|
#var pot:CharacterBody2D = pot_scene.instantiate()
|
|
#pot.position = Vector2(90,80)
|
|
#$SpawnRoot.add_child(pot, true)
|
|
|
|
var player: CharacterBody2D = player_scene.instantiate()
|
|
player.name = str(id)
|
|
#find empty 16x16 tile to spawn player
|
|
'
|
|
if get_parent().get_parent() != null and get_parent().get_parent().has_node("TileMapLayerLower"):
|
|
var tile_map = get_parent().get_parent().get_node("TileMapLayerLower")
|
|
if tile_map != null:
|
|
var player_cell = tile_map.local_to_map(self.global_position)
|
|
var cell_tile_data = tile_map.get_cell_tile_data(player_cell)
|
|
if cell_tile_data != null:
|
|
var terrainData = cell_tile_data.get_custom_data("terrain")
|
|
if terrainData != null and terrainData == 8: # 8 = stairs
|
|
terrainMultiplier = 0.5
|
|
pass
|
|
pass'
|
|
# Only server calculates spawn positions - clients receive position via sync
|
|
if multiplayer.is_server():
|
|
var best_spawn = Vector2(0, 0)
|
|
var best_distance = -1
|
|
|
|
for spawnP: Node2D in $PlayerSpawnPoints.get_children():
|
|
var pos = spawnP.position
|
|
var min_distance = INF
|
|
# find spawn position which is furthest from all players...
|
|
for pl: CharacterBody2D in $SpawnRoot.get_children():
|
|
if "is_player" in pl:
|
|
var dist = pl.position.distance_to(pos)
|
|
min_distance = min(min_distance, dist) # Keep the smallest distance
|
|
pass
|
|
# Choose the spawn with the largest minimum distance
|
|
if min_distance > best_distance:
|
|
best_distance = min_distance
|
|
best_spawn = pos
|
|
player.position = best_spawn
|
|
print("Server: Spawning player ", id, " at position: ", best_spawn)
|
|
# else: clients will receive position via MultiplayerSynchronizer after add_child
|
|
|
|
$SpawnRoot.add_child(player)
|
|
|
|
if id == multiplayer.get_unique_id():
|
|
player.initStats(MultiplayerManager.character_data) # iniitate with own stats, cuz this is us...
|
|
|
|
if multiplayer.is_server():
|
|
if !$TimerRound.is_stopped():
|
|
_syncTimerToPlayer.rpc_id(id, $TimerRound.time_left)
|
|
pass
|
|
|
|
@rpc("reliable")
|
|
func _syncTimerToPlayer(iTimeLeft: float):
|
|
round_started = true
|
|
$TimerRound.start(iTimeLeft)
|
|
pass
|
|
|
|
func _delPlayer(id: int):
|
|
if !$SpawnRoot.has_node(str(id)):
|
|
return
|
|
$SpawnRoot.get_node(str(id)).queue_free()
|
|
pass
|
|
|
|
|
|
func _on_timer_timeout() -> void:
|
|
if has_started:
|
|
var countPots = 0
|
|
for child in $SpawnRoot.get_children():
|
|
if "object_name" in child:
|
|
countPots += 1
|
|
pass
|
|
if countPots < 8:
|
|
var pot = pot_scene.instantiate()
|
|
pot.is_spawning = true
|
|
pot.positionZ = 90
|
|
pot.position = Vector2(64 + 16 * randi_range(0, 5), 64 + 16 * randi_range(0, 5))
|
|
# Set server as authority for pot synchronization
|
|
pot.set_multiplayer_authority(1)
|
|
Console.print("Pot spawned with authority: ", pot.get_multiplayer_authority())
|
|
$SpawnRoot.add_child(pot, true)
|
|
$TimerSpawnPots.wait_time = randf_range(0.2, 1.4)
|
|
$TimerSpawnPots.start() # restart timer...
|
|
|
|
pass # Replace with function body.
|
|
|
|
|
|
func _on_timer_round_timeout() -> void:
|
|
round_started = false
|
|
$TimerUntilNextRound.start($TimerUntilNextRound.wait_time)
|
|
if multiplayer.is_server():
|
|
MultiplayerManager.round_finished.rpc()
|
|
pass # Replace with function body.
|
|
|
|
|
|
func _on_timer_until_next_round_timeout() -> void:
|
|
if multiplayer.is_server():
|
|
for pl2: CharacterBody2D in $SpawnRoot.get_children():
|
|
if "is_player" in pl2:
|
|
var best_spawn = Vector2(0, 0)
|
|
var best_distance = -1
|
|
|
|
for spawnP: Node2D in $PlayerSpawnPoints.get_children():
|
|
var pos = spawnP.position
|
|
|
|
var min_distance = INF
|
|
|
|
# find spawn position which is furthest from all players...
|
|
for pl: CharacterBody2D in $SpawnRoot.get_children():
|
|
if "is_player" in pl and pl != pl2:
|
|
var dist = pl.position.distance_to(pos)
|
|
min_distance = min(min_distance, dist) # Keep the smallest distance
|
|
pass
|
|
# Choose the spawn with the largest minimum distance
|
|
if min_distance > best_distance:
|
|
best_distance = min_distance
|
|
best_spawn = pos
|
|
pl2.position = best_spawn # reset player positions...
|
|
start_round = false
|
|
MultiplayerManager.new_round_started()
|
|
if multiplayer.is_server():
|
|
start_round_func.rpc()
|
|
pass # Replace with function body.
|
|
|
|
func _setup_debug_multiplayer():
|
|
# Get the character select scene to access the selected character
|
|
var character_select = get_tree().get_first_node_in_group("character_select")
|
|
if not character_select:
|
|
# Try to find it in the scene tree
|
|
character_select = get_tree().current_scene.get_node_or_null("CanvasLayer/CharacterSelect")
|
|
|
|
if character_select and character_select.has_method("get_current_character_stats"):
|
|
# Set the character data from the character select
|
|
MultiplayerManager.character_data = character_select.get_current_character_stats()
|
|
else:
|
|
# Fallback: create a default character
|
|
MultiplayerManager.character_data = CharacterStats.new()
|
|
MultiplayerManager.character_data.character_name = "DebugPlayer"
|
|
$MainMenu._showHostButton()
|
|
|
|
# Determine if this instance should host or join
|
|
# Check for command line arguments first
|
|
var should_host = false
|
|
var args = OS.get_cmdline_args()
|
|
|
|
# Check if --host or --join argument was passed
|
|
if "--host" in args:
|
|
should_host = true
|
|
print("DEBUG: Host mode specified via command line argument")
|
|
elif "--join" in args:
|
|
should_host = false
|
|
print("DEBUG: Join mode specified via command line argument")
|
|
else:
|
|
# Fallback: use process ID for deterministic behavior
|
|
var process_id = OS.get_process_id()
|
|
should_host = process_id % 2 == 1
|
|
print("DEBUG: No command line args, using process ID: ", process_id, " Should host: ", should_host)
|
|
|
|
if should_host:
|
|
print("DEBUG: Starting as HOST")
|
|
$MainMenu._on_button_host_pressed()
|
|
else:
|
|
print("DEBUG: Starting as CLIENT")
|
|
$MainMenu._on_button_join_pressed()
|
|
|
|
func _exit_tree():
|
|
# Clean up the debug lock file when exiting
|
|
if DEBUG_MULTIPLAYER:
|
|
var lock_file_path = "user://debug_host.lock"
|
|
if FileAccess.file_exists(lock_file_path):
|
|
DirAccess.remove_absolute(lock_file_path)
|
|
print("DEBUG: Cleaned up host lock file")
|