quantum-space-buddies/QSB/QSBNetworkManager.cs

410 lines
13 KiB
C#
Raw Normal View History

2022-02-05 20:13:57 -08:00
using Epic.OnlineServices.Logging;
2022-02-05 19:01:53 -08:00
using Mirror;
2023-06-09 23:57:11 +01:00
using Mirror.FizzySteam;
2022-01-14 22:22:45 -08:00
using OWML.Common;
2022-01-15 02:49:41 -08:00
using OWML.Utils;
using QSB.Anglerfish.TransformSync;
2021-08-09 11:49:58 +01:00
using QSB.ClientServerStateSync;
2020-08-13 21:46:16 +02:00
using QSB.DeathSync;
2022-03-14 07:12:51 +00:00
using QSB.EchoesOfTheEye.AirlockSync.VariableSync;
2022-03-13 16:14:22 +00:00
using QSB.EchoesOfTheEye.EclipseDoors.VariableSync;
using QSB.EchoesOfTheEye.EclipseElevators.VariableSync;
2022-02-25 00:21:21 -08:00
using QSB.EchoesOfTheEye.RaftSync.TransformSync;
using QSB.JellyfishSync.TransformSync;
2023-05-06 18:49:40 -07:00
using QSB.Menus;
using QSB.Messaging;
2022-08-28 01:44:40 -04:00
using QSB.ModelShip;
2022-05-28 20:39:42 +01:00
using QSB.ModelShip.TransformSync;
2021-12-23 17:07:29 -08:00
using QSB.OrbSync.Messages;
2021-04-11 17:05:02 +01:00
using QSB.OrbSync.TransformSync;
2021-12-23 17:07:29 -08:00
using QSB.OrbSync.WorldObjects;
2023-05-08 11:30:59 -07:00
using QSB.OwnershipSync;
2020-11-03 21:11:10 +00:00
using QSB.Patches;
2020-11-03 21:33:48 +00:00
using QSB.Player;
2021-12-23 17:07:29 -08:00
using QSB.Player.Messages;
2021-04-11 17:05:02 +01:00
using QSB.Player.TransformSync;
2022-07-22 13:39:00 +01:00
using QSB.SaveSync;
2022-05-19 14:34:49 +01:00
using QSB.ShipSync;
using QSB.ShipSync.TransformSync;
2022-02-01 09:05:37 +00:00
using QSB.Syncs.Occasional;
using QSB.TimeSync;
using QSB.Tools.ProbeLauncherTool.VariableSync;
using QSB.Tools.ProbeTool.TransformSync;
using QSB.Utility;
2022-05-19 14:34:49 +01:00
using QSB.Utility.VariableSync;
2020-09-04 20:57:35 +01:00
using QSB.WorldSync;
2021-12-07 15:56:08 +00:00
using System;
2022-01-15 20:27:24 -08:00
using System.Linq;
using System.Text.RegularExpressions;
2020-02-21 23:36:07 +01:00
using UnityEngine;
2020-02-13 20:23:26 +01:00
2022-03-02 19:46:33 -08:00
namespace QSB;
public class QSBNetworkManager : NetworkManager, IAddComponentOnStart
2020-02-15 20:48:02 +01:00
{
2022-06-29 15:20:15 -07:00
public new static QSBNetworkManager singleton => (QSBNetworkManager)NetworkManager.singleton;
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
public event Action OnClientConnected;
public event Action<TransportError, string> OnClientDisconnected;
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
public GameObject OrbPrefab { get; private set; }
public GameObject ShipPrefab { get; private set; }
public GameObject AnglerPrefab { get; private set; }
public GameObject JellyfishPrefab { get; private set; }
public GameObject OccasionalPrefab { get; private set; }
public GameObject RaftPrefab { get; private set; }
2022-03-13 16:14:22 +00:00
public GameObject DoorPrefab { get; private set; }
public GameObject ElevatorPrefab { get; private set; }
2022-03-14 07:12:51 +00:00
public GameObject AirlockPrefab { get; private set; }
2022-05-14 12:18:48 +01:00
public GameObject ShipModulePrefab { get; private set; }
public GameObject ShipLegPrefab { get; private set; }
2022-05-28 20:39:42 +01:00
public GameObject ModelShipPrefab { get; private set; }
public GameObject StationaryProbeLauncherPrefab { get; private set; }
2022-03-02 19:46:33 -08:00
private string PlayerName { get; set; }
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
private GameObject _probePrefab;
private bool _everConnected;
2022-01-16 17:45:51 +00:00
2023-05-07 18:51:08 -07:00
private (TransportError error, string reason) _lastTransportError = (TransportError.Unexpected, "transport did not give an error. uh oh");
2023-05-06 18:44:20 -07:00
private static kcp2k.KcpTransport _kcpTransport;
2023-06-09 23:57:11 +01:00
private static FizzySteamworks _steamTransport;
2023-05-06 18:44:20 -07:00
2022-03-02 19:46:33 -08:00
public override void Awake()
{
gameObject.SetActive(false);
2022-03-02 19:46:33 -08:00
{
2023-05-06 18:44:20 -07:00
_kcpTransport = gameObject.AddComponent<kcp2k.KcpTransport>();
2022-03-02 19:46:33 -08:00
}
2023-06-09 22:06:35 +01:00
2023-06-09 23:57:11 +01:00
{
_steamTransport = gameObject.AddComponent<FizzySteamworks>();
}
transport = QSBCore.UseKcpTransport ? _kcpTransport : _steamTransport;
2022-01-16 17:45:51 +00:00
2022-03-02 19:46:33 -08:00
gameObject.SetActive(true);
2022-01-16 17:45:51 +00:00
2022-03-02 19:46:33 -08:00
base.Awake();
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
InitPlayerName();
2022-08-07 20:02:45 +01:00
QSBCore.ProfileManager.OnProfileSignInComplete += _ => InitPlayerName();
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
playerPrefab = QSBCore.NetworkAssetBundle.LoadAsset<GameObject>("Assets/Prefabs/NETWORK_Player_Body.prefab");
2023-04-26 15:38:37 -07:00
playerPrefab.GetRequiredComponent<NetworkIdentity>().SetValue("_assetId", (uint)1);
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
ShipPrefab = MakeNewNetworkObject(2, "NetworkShip", typeof(ShipTransformSync));
2022-05-19 14:34:49 +01:00
var shipVector3Sync = ShipPrefab.AddComponent<Vector3VariableSyncer>();
var shipThrustSync = ShipPrefab.AddComponent<ShipThrusterVariableSyncer>();
shipThrustSync.AccelerationSyncer = shipVector3Sync;
2022-03-02 19:46:33 -08:00
spawnPrefabs.Add(ShipPrefab);
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
_probePrefab = MakeNewNetworkObject(3, "NetworkProbe", typeof(PlayerProbeSync));
spawnPrefabs.Add(_probePrefab);
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
OrbPrefab = MakeNewNetworkObject(4, "NetworkOrb", typeof(NomaiOrbTransformSync));
spawnPrefabs.Add(OrbPrefab);
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
AnglerPrefab = MakeNewNetworkObject(5, "NetworkAngler", typeof(AnglerTransformSync));
spawnPrefabs.Add(AnglerPrefab);
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
JellyfishPrefab = MakeNewNetworkObject(6, "NetworkJellyfish", typeof(JellyfishTransformSync));
spawnPrefabs.Add(JellyfishPrefab);
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
OccasionalPrefab = MakeNewNetworkObject(7, "NetworkOccasional", typeof(OccasionalTransformSync));
spawnPrefabs.Add(OccasionalPrefab);
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
RaftPrefab = MakeNewNetworkObject(8, "NetworkRaft", typeof(RaftTransformSync));
spawnPrefabs.Add(RaftPrefab);
2022-02-25 00:21:21 -08:00
2022-03-13 16:14:22 +00:00
DoorPrefab = MakeNewNetworkObject(9, "NetworkEclipseDoor", typeof(EclipseDoorVariableSyncer));
spawnPrefabs.Add(DoorPrefab);
ElevatorPrefab = MakeNewNetworkObject(10, "NetworkEclipseElevator", typeof(EclipseElevatorVariableSyncer));
spawnPrefabs.Add(ElevatorPrefab);
2022-03-14 07:12:51 +00:00
AirlockPrefab = MakeNewNetworkObject(11, "NetworkGhostAirlock", typeof(AirlockVariableSyncer));
spawnPrefabs.Add(AirlockPrefab);
2022-05-14 12:18:48 +01:00
ShipModulePrefab = MakeNewNetworkObject(12, "NetworkShipModule", typeof(ShipModuleTransformSync));
spawnPrefabs.Add(ShipModulePrefab);
ShipLegPrefab = MakeNewNetworkObject(13, "NetworkShipLeg", typeof(ShipLegTransformSync));
spawnPrefabs.Add(ShipLegPrefab);
2022-05-28 20:39:42 +01:00
ModelShipPrefab = MakeNewNetworkObject(14, "NetworkModelShip", typeof(ModelShipTransformSync));
2022-08-28 01:44:40 -04:00
var modelShipVector3Syncer = ModelShipPrefab.AddComponent<Vector3VariableSyncer>();
var modelShipThrusterVariableSyncer = ModelShipPrefab.AddComponent<ModelShipThrusterVariableSyncer>();
modelShipThrusterVariableSyncer.AccelerationSyncer = modelShipVector3Syncer;
2022-05-28 20:39:42 +01:00
spawnPrefabs.Add(ModelShipPrefab);
2022-08-27 11:21:09 -07:00
StationaryProbeLauncherPrefab = MakeNewNetworkObject(15, "NetworkStationaryProbeLauncher", typeof(StationaryProbeLauncherVariableSyncer));
spawnPrefabs.Add(StationaryProbeLauncherPrefab);
2022-03-02 19:46:33 -08:00
ConfigureNetworkManager();
}
2022-01-14 22:22:45 -08:00
public static void UpdateTransport()
2023-05-06 18:44:20 -07:00
{
2023-05-06 18:49:40 -07:00
if (QSBCore.IsInMultiplayer)
{
return;
2023-05-06 18:49:40 -07:00
}
if (singleton != null)
2023-05-06 18:44:20 -07:00
{
2023-06-09 23:57:11 +01:00
singleton.transport = Transport.active = QSBCore.UseKcpTransport ? _kcpTransport : _steamTransport;
2023-05-06 18:44:20 -07:00
}
2023-05-06 18:49:40 -07:00
if (MenuManager.Instance != null)
{
MenuManager.Instance.OnLanguageChanged(); // hack to update text
}
2023-05-06 18:44:20 -07:00
}
2022-03-02 19:46:33 -08:00
private void InitPlayerName() =>
Delay.RunWhen(PlayerData.IsLoaded, () =>
{
try
2022-02-05 19:34:26 -08:00
{
2022-08-07 20:02:45 +01:00
if (!QSBCore.IsStandalone)
2022-01-18 18:29:14 -08:00
{
2022-08-07 20:02:45 +01:00
PlayerName = QSBMSStoreProfileManager.SharedInstance.userDisplayName;
2022-01-18 18:29:14 -08:00
}
2022-03-02 19:46:33 -08:00
else
2022-01-18 18:29:14 -08:00
{
2022-08-07 20:02:45 +01:00
var currentProfile = QSBStandaloneProfileManager.SharedInstance.currentProfile;
if (currentProfile == null)
{
// probably havent created a profile yet
Delay.RunWhen(() => QSBStandaloneProfileManager.SharedInstance.currentProfile != null, () => InitPlayerName());
return;
}
PlayerName = currentProfile.profileName;
2022-01-18 18:29:14 -08:00
}
2022-03-02 19:46:33 -08:00
}
catch (Exception ex)
{
DebugLog.ToConsole($"Error - Exception when getting player name : {ex}", MessageType.Error);
PlayerName = "Player";
}
});
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
/// create a new network prefab from the network object prefab template.
/// this works by calling Unload(false) and then reloading the AssetBundle,
/// which makes LoadAsset give you a new resource.
/// see https://docs.unity3d.com/Manual/AssetBundles-Native.html.
2023-04-26 15:38:37 -07:00
private static GameObject MakeNewNetworkObject(uint assetId, string name, Type networkBehaviourType)
2022-03-02 19:46:33 -08:00
{
2022-06-29 15:20:15 -07:00
var bundle = QSBCore.Helper.Assets.LoadBundle("AssetBundles/qsb_empty");
if (bundle == null)
{
DebugLog.ToConsole($"FATAL - An assetbundle is missing! Re-install mod or contact devs.", MessageType.Fatal);
return null;
}
2022-03-02 19:46:33 -08:00
var template = bundle.LoadAsset<GameObject>("Assets/Prefabs/Empty.prefab");
bundle.Unload(false);
template.name = name;
2023-04-26 15:38:37 -07:00
template.AddComponent<NetworkIdentity>().SetValue("_assetId", assetId);
template.AddComponent(networkBehaviourType);
2022-03-02 19:46:33 -08:00
return template;
}
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
private void ConfigureNetworkManager()
{
networkAddress = QSBCore.DefaultServerIP;
2022-03-02 19:46:33 -08:00
{
2023-05-07 18:26:38 -07:00
kcp2k.Log.Info = s =>
2022-01-15 23:11:40 -08:00
{
2023-05-07 18:26:38 -07:00
DebugLog.DebugWrite("[KCP] " + s);
// hack
if (s == "KcpPeer: received disconnect message")
{
OnClientError(TransportError.ConnectionClosed, "host disconnected");
2022-03-02 19:46:33 -08:00
}
};
2023-05-07 18:26:38 -07:00
kcp2k.Log.Warning = s => DebugLog.DebugWrite("[KCP] " + s, MessageType.Warning);
kcp2k.Log.Error = s => DebugLog.DebugWrite("[KCP] " + s, MessageType.Error);
2022-01-14 22:22:45 -08:00
}
2022-05-03 21:53:18 -07:00
QSBSceneManager.OnPostSceneLoad += (_, loadScene) =>
{
if (QSBCore.IsInMultiplayer && loadScene == OWScene.TitleScreen)
{
StopHost();
}
};
2022-03-02 19:46:33 -08:00
DebugLog.DebugWrite("Network Manager ready.", MessageType.Success);
}
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
public override void OnServerAddPlayer(NetworkConnectionToClient connection) // Called on the server when a client joins
{
2022-06-29 15:20:15 -07:00
DebugLog.DebugWrite("OnServerAddPlayer", MessageType.Info);
2022-03-02 19:46:33 -08:00
base.OnServerAddPlayer(connection);
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
NetworkServer.Spawn(Instantiate(_probePrefab), connection);
}
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
public override void OnStartClient()
{
QSBCore.DefaultServerIP = networkAddress;
var config = QSBCore.Helper.Config;
config.SetSettingsValue("defaultServerIP", networkAddress);
2022-03-02 19:46:33 -08:00
QSBCore.Helper.Storage.Save(config, Constants.ModConfigFileName);
}
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
public override void OnClientConnect() // Called on the client when connecting to a server
{
DebugLog.DebugWrite("OnClientConnect", MessageType.Info);
base.OnClientConnect();
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
OnClientConnected?.SafeInvoke();
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
QSBMessageManager.Init();
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
gameObject.AddComponent<RespawnOnDeath>();
gameObject.AddComponent<ServerStateManager>();
gameObject.AddComponent<ClientStateManager>();
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
if (QSBSceneManager.IsInUniverse)
{
QSBWorldSync.BuildWorldObjects(QSBSceneManager.CurrentScene).Forget();
}
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
var specificType = QSBCore.IsHost ? QSBPatchTypes.OnServerClientConnect : QSBPatchTypes.OnNonServerClientConnect;
QSBPatchManager.DoPatchType(specificType);
QSBPatchManager.DoPatchType(QSBPatchTypes.OnClientConnect);
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
Delay.RunWhen(() => PlayerTransformSync.LocalInstance,
() => new PlayerJoinMessage(PlayerName).Send());
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
if (!QSBCore.IsHost)
{
2022-03-02 19:46:33 -08:00
Delay.RunWhen(() => PlayerTransformSync.LocalInstance,
() => new RequestStateResyncMessage().Send());
}
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
_everConnected = true;
}
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
public override void OnStopClient() // Called on the client when closing connection
{
DebugLog.DebugWrite("OnStopClient", MessageType.Info);
DebugLog.ToConsole("Disconnecting from server...", MessageType.Info);
Destroy(GetComponent<RespawnOnDeath>());
Destroy(GetComponent<ServerStateManager>());
Destroy(GetComponent<ClientStateManager>());
QSBPlayerManager.PlayerList.ForEach(player =>
{
player.HudMarker?.Remove();
player.MapMarker?.Remove();
});
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
QSBWorldSync.RemoveWorldObjects();
2022-03-02 19:46:33 -08:00
if (WakeUpSync.LocalInstance != null)
{
WakeUpSync.LocalInstance.OnDisconnect();
2022-01-14 22:22:45 -08:00
}
2022-03-02 19:46:33 -08:00
if (_everConnected)
2022-01-14 22:22:45 -08:00
{
2022-03-02 19:46:33 -08:00
var specificType = QSBCore.IsHost ? QSBPatchTypes.OnServerClientConnect : QSBPatchTypes.OnNonServerClientConnect;
QSBPatchManager.DoUnpatchType(specificType);
QSBPatchManager.DoUnpatchType(QSBPatchTypes.OnClientConnect);
2022-01-14 22:22:45 -08:00
}
2022-03-02 19:46:33 -08:00
_everConnected = false;
}
public override void OnClientDisconnect()
{
DebugLog.DebugWrite("OnClientDisconnect");
base.OnClientDisconnect();
OnClientDisconnected?.SafeInvoke(_lastTransportError.error, _lastTransportError.reason);
2023-05-07 18:51:08 -07:00
_lastTransportError = (TransportError.Unexpected, "transport did not give an error. uh oh");
2022-03-02 19:46:33 -08:00
}
public override void OnServerDisconnect(NetworkConnectionToClient conn) // Called on the server when any client disconnects
{
DebugLog.DebugWrite("OnServerDisconnect", MessageType.Info);
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
// local conn = we are host, so skip
if (conn is not LocalConnectionToClient)
{
// revert ownership from ship
2022-03-02 19:46:33 -08:00
if (ShipTransformSync.LocalInstance != null)
{
2022-03-02 19:46:33 -08:00
var identity = ShipTransformSync.LocalInstance.netIdentity;
if (identity != null && identity.connectionToClient == conn)
2022-10-06 19:50:01 -07:00
{
identity.SetOwner(QSBPlayerManager.LocalPlayerId);
2022-10-06 19:50:01 -07:00
}
}
// revert ownership from model ship
2022-10-06 19:50:01 -07:00
if (ModelShipTransformSync.LocalInstance != null)
{
var identity = ModelShipTransformSync.LocalInstance.netIdentity;
if (identity != null && identity.connectionToClient == conn)
2022-01-14 22:22:45 -08:00
{
identity.SetOwner(QSBPlayerManager.LocalPlayerId);
2022-01-14 22:22:45 -08:00
}
2022-03-02 19:46:33 -08:00
}
2022-01-14 22:22:45 -08:00
2022-03-02 19:46:33 -08:00
// stop dragging for the orbs this player was dragging
// i THINK this is here because orb ownership is in network behavior, which may not work properly in OnPlayerLeave
2022-03-02 19:46:33 -08:00
foreach (var qsbOrb in QSBWorldSync.GetWorldObjects<QSBOrb>())
{
if (qsbOrb.NetworkBehaviour == null)
{
2022-03-02 19:46:33 -08:00
DebugLog.ToConsole($"{qsbOrb} TransformSync == null??????????", MessageType.Warning);
continue;
}
var identity = qsbOrb.NetworkBehaviour.netIdentity;
2022-03-02 19:46:33 -08:00
if (identity.connectionToClient == conn)
{
qsbOrb.SetDragging(false);
qsbOrb.SendMessage(new OrbDragMessage(false));
}
}
2022-01-14 22:22:45 -08:00
2023-05-08 11:30:59 -07:00
OwnershipManager.OnDisconnect(conn);
2022-01-14 22:22:45 -08:00
}
2022-03-02 19:46:33 -08:00
base.OnServerDisconnect(conn);
}
2022-03-02 19:46:33 -08:00
public override void OnStopServer()
{
DebugLog.DebugWrite("OnStopServer", MessageType.Info);
Destroy(GetComponent<RespawnOnDeath>());
DebugLog.ToConsole("Server stopped!", MessageType.Info);
QSBPlayerManager.PlayerList.ForEach(player =>
{
player.HudMarker?.Remove();
player.MapMarker?.Remove();
});
2022-03-02 19:46:33 -08:00
base.OnStopServer();
2022-01-14 22:22:45 -08:00
}
2023-05-07 16:06:43 -07:00
public override void OnServerError(NetworkConnectionToClient conn, TransportError error, string reason)
{
2023-05-07 16:06:43 -07:00
DebugLog.DebugWrite($"OnServerError({conn}, {error}, {reason})", MessageType.Error);
_lastTransportError = (error, reason);
}
2023-05-07 16:06:43 -07:00
public override void OnClientError(TransportError error, string reason)
{
2023-05-07 16:06:43 -07:00
DebugLog.DebugWrite($"OnClientError({error}, {reason})", MessageType.Error);
_lastTransportError = (error, reason);
}
2022-06-29 15:20:15 -07:00
}