Files
megakoop/Game/Scripts/Networking/SteamWeaponNetworkBridge.cs
2025-10-27 12:50:17 +01:00

155 lines
4.5 KiB
C#

using MegaKoop.Game.WeaponSystem;
using Steamworks;
using UnityEngine;
namespace MegaKoop.Game.Networking
{
[DisallowMultipleComponent]
public class SteamWeaponNetworkBridge : MonoBehaviour
{
[SerializeField] private WeaponController weaponController;
[SerializeField] private NetworkIdentity identity;
[SerializeField] private bool disableLocalFiringWhenClient = true;
private SteamCoopNetworkManager networkManager;
private bool isRegistered;
private void Awake()
{
networkManager = SteamCoopNetworkManager.Instance;
if (weaponController == null)
{
weaponController = GetComponent<WeaponController>();
}
if (identity == null)
{
identity = GetComponent<NetworkIdentity>();
}
}
private void OnEnable()
{
if (weaponController == null || identity == null)
{
Debug.LogWarning("[SteamWeaponNetworkBridge] Missing references.");
return;
}
TryEnsureNetworkManager();
weaponController.ProjectileSpawned += OnProjectileSpawned;
ApplyLocalAuthoritySetting();
}
private void OnDisable()
{
if (weaponController != null)
{
weaponController.ProjectileSpawned -= OnProjectileSpawned;
if (disableLocalFiringWhenClient)
{
weaponController.SetLocalAuthority(true);
}
}
if (isRegistered && networkManager != null)
{
networkManager.UnregisterHandler(NetworkMessageType.ProjectileSpawn, HandleProjectileSpawnMessage);
isRegistered = false;
}
}
private void Update()
{
TryEnsureNetworkManager();
}
private bool IsAuthoritative()
{
if (networkManager == null)
{
return true;
}
return networkManager.IsHost;
}
private void TryEnsureNetworkManager()
{
if (networkManager == null)
{
networkManager = SteamCoopNetworkManager.Instance;
}
if (networkManager == null)
{
return;
}
if (!isRegistered)
{
networkManager.RegisterHandler(NetworkMessageType.ProjectileSpawn, HandleProjectileSpawnMessage);
isRegistered = true;
ApplyLocalAuthoritySetting();
}
}
private void OnProjectileSpawned(WeaponController.ProjectileSpawnEvent spawnEvent)
{
if (!IsAuthoritative())
{
return;
}
networkManager ??= SteamCoopNetworkManager.Instance;
if (networkManager == null)
{
return;
}
var message = new ProjectileSpawnMessage(identity.NetworkId, spawnEvent.WeaponIndex, spawnEvent.Position, spawnEvent.Direction, spawnEvent.Speed, spawnEvent.Lifetime, spawnEvent.Damage);
byte[] payload = ProjectileSpawnMessage.Serialize(message);
networkManager.SendToAll(NetworkMessageType.ProjectileSpawn, payload, EP2PSend.k_EP2PSendReliable);
}
private void HandleProjectileSpawnMessage(NetworkMessage message)
{
if (message.Sender == SteamUser.GetSteamID().m_SteamID)
{
// Ignore our own echo.
return;
}
ProjectileSpawnMessage spawnMessage = ProjectileSpawnMessage.Deserialize(message.Payload);
if (spawnMessage.NetworkId != identity.NetworkId)
{
return;
}
if (IsAuthoritative())
{
// Host already spawned real projectile, don't duplicate.
return;
}
weaponController.SpawnNetworkProjectile(spawnMessage.WeaponIndex, spawnMessage.Position, spawnMessage.Direction, spawnMessage.Speed, spawnMessage.Life, spawnMessage.Damage);
}
private void ApplyLocalAuthoritySetting()
{
if (weaponController == null || !disableLocalFiringWhenClient)
{
return;
}
bool allowLocalControl = IsAuthoritative();
weaponController.SetLocalAuthority(allowLocalControl);
}
}
}