online fix

This commit is contained in:
2025-10-27 12:37:18 +01:00
parent 96d50bfad5
commit e6759d6610
281 changed files with 7337 additions and 136 deletions

View File

@@ -19,7 +19,10 @@ namespace Game.Scripts.Runtime.Game
public float Elapsed => _elapsed;
public bool IsRunning => _isRunning && !_isPaused;
public bool IsGameActive => _isRunning;
public bool IsPaused => _isPaused;
public int CurrentWaveIndex => _currentWaveIndex;
public BossSchedule BossSchedule => bossSchedule;
public event Action OnGameStarted;
public event Action OnGamePaused;
@@ -35,6 +38,8 @@ namespace Game.Scripts.Runtime.Game
private bool _isPaused;
private int _currentWaveIndex = -1;
private int _bossCursor;
private bool _hasAuthorityOverride;
private bool _authorityOverride;
private void OnEnable()
{
@@ -66,9 +71,16 @@ namespace Game.Scripts.Runtime.Game
spawner?.SetClock(this);
spawner?.Begin();
UpdateWaveState();
if (HasAuthority())
{
UpdateWaveState();
_loop = StartCoroutine(GameLoop());
}
else
{
_loop = null;
}
_loop = StartCoroutine(GameLoop());
OnGameStarted?.Invoke();
Log($"Game started waveDuration={waveDurationSeconds}s");
}
@@ -268,5 +280,84 @@ namespace Game.Scripts.Runtime.Game
Debug.Log($"[{name}] {message}", this);
}
}
internal void SetAuthorityOverride(bool hasAuthority)
{
_hasAuthorityOverride = true;
if (_authorityOverride == hasAuthority)
{
return;
}
_authorityOverride = hasAuthority;
if (!HasAuthority() && _loop != null)
{
StopCoroutine(_loop);
_loop = null;
}
else if (HasAuthority() && _isRunning && _loop == null)
{
_loop = StartCoroutine(GameLoop());
}
}
internal bool HasAuthority() => !_hasAuthorityOverride || _authorityOverride;
internal void SetElapsedFromRemote(float elapsed)
{
_elapsed = Mathf.Max(0f, elapsed);
}
internal void SetRunningFlagsFromRemote(bool isRunning, bool isPaused)
{
_isRunning = isRunning;
_isPaused = isPaused;
}
internal void ApplyRemoteWaveAdvance(int previousWave, int newWave)
{
int oldWave = _currentWaveIndex;
if (previousWave >= 0 && oldWave == previousWave)
{
OnWaveCompleted?.Invoke(previousWave);
}
else if (oldWave >= 0 && oldWave != newWave)
{
OnWaveCompleted?.Invoke(oldWave);
}
_currentWaveIndex = newWave;
if (_currentWaveIndex >= 0)
{
spawner?.SetWaveIndex(_currentWaveIndex);
OnWaveStarted?.Invoke(_currentWaveIndex);
}
}
internal void ApplyRemoteWaveStarted(int waveIndex)
{
if (_currentWaveIndex != waveIndex)
{
_currentWaveIndex = waveIndex;
}
if (_currentWaveIndex >= 0)
{
spawner?.SetWaveIndex(_currentWaveIndex);
OnWaveStarted?.Invoke(_currentWaveIndex);
}
}
internal void ApplyRemoteWaveCompleted(int waveIndex)
{
OnWaveCompleted?.Invoke(waveIndex);
}
internal void ApplyRemoteBossSpawned(EnemyDefinition boss, int count)
{
OnBossSpawned?.Invoke(boss, count);
}
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using Game.Scripts.Runtime.Abstractions;
using Game.Scripts.Runtime.Data;
using UnityEngine;
using Unity.Netcode;
namespace Game.Scripts.Runtime.Pooling
{
@@ -112,7 +113,7 @@ namespace Game.Scripts.Runtime.Pooling
}
bucket.Active.Add(go);
go.transform.SetParent(null, true);
SetParentSafely(go, null, true);
go.transform.SetPositionAndRotation(position + definition.PrefabPivotOffset, rotation);
go.SetActive(true);
@@ -137,7 +138,12 @@ namespace Game.Scripts.Runtime.Pooling
bucket.Active.Remove(instance);
instance.SetActive(false);
instance.transform.SetParent(poolRoot, false);
var netObj = instance.GetComponent<NetworkObject>();
SetParentSafely(instance, poolRoot, false, netObj, false);
if (netObj != null)
{
Destroy(netObj);
}
bucket.Available.Enqueue(instance);
item.Handle?.NotifyDespawned();
InstanceDespawned?.Invoke(instance, item.Definition);
@@ -172,7 +178,8 @@ namespace Game.Scripts.Runtime.Pooling
}
EnsureRoot();
var go = Instantiate(definition.Prefab, poolRoot);
var go = Instantiate(definition.Prefab);
SetParentSafely(go, poolRoot, false);
go.name = $"{definition.Prefab.name}_Pooled";
go.SetActive(false);
@@ -230,6 +237,38 @@ namespace Game.Scripts.Runtime.Pooling
root.transform.SetParent(transform, false);
poolRoot = root.transform;
}
private void SetParentSafely(GameObject instance, Transform parent, bool worldPositionStays, NetworkObject cachedNetworkObject = null, bool restoreAutoSync = true)
{
if (instance == null)
{
return;
}
var netObj = cachedNetworkObject != null ? cachedNetworkObject : instance.GetComponent<NetworkObject>();
var shouldRestore = false;
var previousAutoSync = false;
if (netObj != null && !HasListeningNetworkManager(netObj))
{
previousAutoSync = netObj.AutoObjectParentSync;
netObj.AutoObjectParentSync = false;
shouldRestore = restoreAutoSync;
}
instance.transform.SetParent(parent, worldPositionStays);
if (shouldRestore && netObj != null)
{
netObj.AutoObjectParentSync = previousAutoSync;
}
}
private static bool HasListeningNetworkManager(NetworkObject netObj)
{
var manager = netObj != null ? (netObj.NetworkManager != null ? netObj.NetworkManager : NetworkManager.Singleton) : NetworkManager.Singleton;
return manager != null && manager.IsListening;
}
}
[DisallowMultipleComponent]

View File

@@ -6,6 +6,7 @@ using Game.Scripts.Runtime.Data;
using Game.Scripts.Runtime.Pooling;
using Game.Scripts.Runtime.Navigation;
using MegaKoop.Game;
using MegaKoop.Game.Networking;
using UnityEngine;
using UnityEngine.AI;
@@ -68,6 +69,8 @@ namespace Game.Scripts.Runtime.Spawning
private IEnemyFactory _factory;
private bool _warnedMissingPlayer;
private bool _warnedMissingNavMesh;
private bool _authorityOverrideSet;
private bool _authorityOverrideValue = true;
private void OnValidate()
{
@@ -170,8 +173,16 @@ namespace Game.Scripts.Runtime.Spawning
_spawnedThisWave.Clear();
_localElapsed = 0f;
_nextSpawnTimestamp = 0f;
_spawnLoop = StartCoroutine(SpawnLoop());
LogLifecycle($"Begin wave {CurrentWaveIndex}, pool prewarm complete, maxConcurrent={_runtimeConfig.MaxConcurrent}");
if (HasAuthority())
{
_spawnLoop = StartCoroutine(SpawnLoop());
LogLifecycle($"Begin wave {CurrentWaveIndex}, pool prewarm complete, maxConcurrent={_runtimeConfig.MaxConcurrent}");
}
else
{
_spawnLoop = null;
LogLifecycle($"Begin follower mode (no spawn loop), wave {CurrentWaveIndex}, maxConcurrent={_runtimeConfig?.MaxConcurrent}");
}
}
public void End()
@@ -226,6 +237,12 @@ namespace Game.Scripts.Runtime.Spawning
_localElapsed = _clock.Elapsed;
}
if (!HasAuthority())
{
yield return null;
continue;
}
if (_localElapsed >= _nextSpawnTimestamp)
{
ExecuteSpawnTick();
@@ -640,6 +657,22 @@ namespace Game.Scripts.Runtime.Spawning
}
}
internal void SetAuthorityOverride(bool hasAuthority)
{
_authorityOverrideSet = true;
_authorityOverrideValue = hasAuthority;
if (!HasAuthority() && _spawnLoop != null)
{
StopCoroutine(_spawnLoop);
_spawnLoop = null;
}
else if (HasAuthority() && _spawnLoop == null && _runtimeConfig != null && _runtimeTable != null)
{
_spawnLoop = StartCoroutine(SpawnLoop());
}
}
private bool RequirePlayerReference()
{
if (EnsurePlayerReference())
@@ -706,5 +739,26 @@ namespace Game.Scripts.Runtime.Spawning
return null;
}
}
private bool HasAuthority()
{
if (_authorityOverrideSet)
{
return _authorityOverrideValue;
}
var manager = SteamCoopNetworkManager.Instance;
if (manager == null)
{
return true;
}
if (!manager.IsConnected)
{
return true;
}
return manager.IsHost;
}
}
}