quantum-space-buddies/QSB/QSBNetworkManager.cs

328 lines
10 KiB
C#
Raw Normal View History

2022-01-15 23:11:40 -08:00
using Mirror;
2022-01-16 17:45:51 +00: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-12-01 17:50:56 -08:00
using QSB.AuthoritySync;
2021-08-09 11:49:58 +01:00
using QSB.ClientServerStateSync;
2020-08-13 21:46:16 +02:00
using QSB.DeathSync;
using QSB.JellyfishSync.TransformSync;
using QSB.Messaging;
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;
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;
using QSB.ShipSync.TransformSync;
using QSB.TimeSync;
using QSB.Tools.ProbeTool.TransformSync;
using QSB.TornadoSync.TransformSync;
using QSB.Utility;
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;
2022-01-15 02:49:41 -08:00
using System.Reflection;
using System.Text.RegularExpressions;
2020-02-21 23:36:07 +01:00
using UnityEngine;
2020-02-13 20:23:26 +01:00
2020-02-15 20:48:02 +01:00
namespace QSB
{
2022-01-14 22:24:31 -08:00
public class QSBNetworkManager : NetworkManager
2022-01-14 22:22:45 -08:00
{
2022-01-14 22:28:44 -08:00
public new static QSBNetworkManager singleton => (QSBNetworkManager)NetworkManager.singleton;
2022-01-14 22:22:45 -08:00
public event Action OnClientConnected;
2022-01-15 23:11:40 -08:00
public event Action<string> OnClientDisconnected;
2022-01-14 22:22:45 -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 string PlayerName { get; private set; }
private const int MaxConnections = 128;
private const int MaxBufferedPackets = 64;
private GameObject _probePrefab;
private bool _everConnected;
2022-01-15 23:11:40 -08:00
private string _lastTransportError;
2022-01-24 11:26:46 -08:00
private static readonly string[] _kcpErrorLogs =
{
"KCP: received disconnect message",
"Failed to resolve host: .*"
};
2022-01-24 02:14:53 -08:00
private const int _defaultSteamAppID = 753640;
2022-01-15 23:11:40 -08:00
2022-01-14 22:22:45 -08:00
public override void Awake()
{
2022-01-15 20:27:24 -08:00
AppDomain.CurrentDomain.GetAssemblies()
.Where(x => x.GetName().Name.StartsWith("Mirror"))
.Append(typeof(QSBNetworkManager).Assembly)
.SelectMany(x => x.GetTypes())
.SelectMany(x => x.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly))
.Where(x => x.GetCustomAttribute<RuntimeInitializeOnLoadMethodAttribute>() != null)
.ForEach(x => x.Invoke(null, null));
2022-01-15 02:49:41 -08:00
2022-01-16 17:45:51 +00:00
gameObject.SetActive(false);
2022-01-21 22:38:41 +00:00
if (QSBCore.UseKcpTransport)
{
transport = gameObject.AddComponent<kcp2k.KcpTransport>();
}
else
{
var fizzy = gameObject.AddComponent<FizzyFacepunch>();
fizzy.SteamAppID = QSBCore.OverrideAppId == -1
2022-01-24 02:14:53 -08:00
? _defaultSteamAppID.ToString()
: QSBCore.OverrideAppId.ToString();
2022-01-24 02:35:37 -08:00
fizzy.SetTransportError = error => _lastTransportError = error;
2022-01-21 22:38:41 +00:00
transport = fizzy;
}
2022-01-16 17:45:51 +00:00
gameObject.SetActive(true);
2022-01-14 22:22:45 -08:00
base.Awake();
2022-01-18 18:29:14 -08:00
InitPlayerName();
2022-01-14 22:22:45 -08:00
playerPrefab = QSBCore.NetworkAssetBundle.LoadAsset<GameObject>("Assets/Prefabs/NETWORK_Player_Body.prefab");
2022-01-15 20:27:24 -08:00
playerPrefab.GetRequiredComponent<NetworkIdentity>().SetValue("m_AssetId", 1.ToGuid().ToString("N"));
2022-01-14 22:22:45 -08:00
ShipPrefab = MakeNewNetworkObject(2, "NetworkShip", typeof(ShipTransformSync));
spawnPrefabs.Add(ShipPrefab);
_probePrefab = MakeNewNetworkObject(3, "NetworkProbe", typeof(PlayerProbeSync));
spawnPrefabs.Add(_probePrefab);
OrbPrefab = MakeNewNetworkObject(4, "NetworkOrb", typeof(NomaiOrbTransformSync));
spawnPrefabs.Add(OrbPrefab);
AnglerPrefab = MakeNewNetworkObject(5, "NetworkAngler", typeof(AnglerTransformSync));
spawnPrefabs.Add(AnglerPrefab);
JellyfishPrefab = MakeNewNetworkObject(6, "NetworkJellyfish", typeof(JellyfishTransformSync));
spawnPrefabs.Add(JellyfishPrefab);
OccasionalPrefab = MakeNewNetworkObject(7, "NetworkOccasional", typeof(OccasionalTransformSync));
spawnPrefabs.Add(OccasionalPrefab);
ConfigureNetworkManager();
}
2022-01-18 18:29:14 -08:00
private void InitPlayerName()
2022-01-14 22:22:45 -08:00
{
2022-01-18 18:29:14 -08:00
QSBCore.UnityEvents.RunWhen(PlayerData.IsLoaded, () =>
2022-01-14 22:22:45 -08:00
{
2022-01-18 18:29:14 -08:00
try
{
var titleScreenManager = FindObjectOfType<TitleScreenManager>();
var profileManager = titleScreenManager._profileManager;
if (profileManager.GetType().Name == "MSStoreProfileManager")
{
PlayerName = (string)profileManager.GetType().GetProperty("userDisplayName").GetValue(profileManager);
}
else
{
PlayerName = StandaloneProfileManager.SharedInstance.currentProfile.profileName;
}
}
catch (Exception ex)
{
DebugLog.ToConsole($"Error - Exception when getting player name : {ex}", MessageType.Error);
PlayerName = "Player";
}
});
2022-01-14 22:22:45 -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.
private static GameObject MakeNewNetworkObject(int assetId, string name, Type transformSyncType)
{
QSBCore.NetworkAssetBundle.Unload(false);
QSBCore.NetworkAssetBundle = QSBCore.Helper.Assets.LoadBundle("AssetBundles/network");
var template = QSBCore.NetworkAssetBundle.LoadAsset<GameObject>("Assets/Prefabs/NetworkObject.prefab");
DebugLog.DebugWrite($"MakeNewNetworkObject - prefab id {template.GetInstanceID()} "
+ $"for {assetId} {name} {transformSyncType.Name}");
template.name = name;
2022-01-15 20:27:24 -08:00
template.GetRequiredComponent<NetworkIdentity>().SetValue("m_AssetId", assetId.ToGuid().ToString("N"));
2022-01-14 22:22:45 -08:00
template.AddComponent(transformSyncType);
return template;
}
private void ConfigureNetworkManager()
{
networkAddress = QSBCore.DefaultServerIP;
maxConnections = MaxConnections;
if (QSBCore.UseKcpTransport)
2022-01-15 23:11:40 -08:00
{
kcp2k.Log.Info = s =>
{
DebugLog.DebugWrite("[KCP] " + s);
2022-01-24 11:26:46 -08:00
if (_kcpErrorLogs.Any(p => Regex.IsMatch(s, p)))
{
_lastTransportError = s;
}
};
kcp2k.Log.Warning = s =>
{
DebugLog.DebugWrite("[KCP] " + s, MessageType.Warning);
_lastTransportError = s;
};
kcp2k.Log.Error = s =>
{
DebugLog.DebugWrite("[KCP] " + s, MessageType.Error);
_lastTransportError = s;
};
}
2022-01-14 22:22:45 -08:00
DebugLog.DebugWrite("Network Manager ready.", MessageType.Success);
}
public override void OnStartServer()
{
DebugLog.DebugWrite("OnStartServer", MessageType.Info);
if (QSBWorldSync.OldDialogueTrees.Count == 0 && QSBSceneManager.IsInUniverse)
{
QSBWorldSync.OldDialogueTrees.AddRange(QSBWorldSync.GetUnityObjects<CharacterDialogueTree>());
}
}
public override void OnServerAddPlayer(NetworkConnection connection) // Called on the server when a client joins
{
DebugLog.DebugWrite($"OnServerAddPlayer", MessageType.Info);
base.OnServerAddPlayer(connection);
NetworkServer.Spawn(Instantiate(_probePrefab), connection);
}
public override void OnStartClient()
{
QSBCore.DefaultServerIP = networkAddress;
2022-01-14 22:22:45 -08:00
var config = QSBCore.Helper.Config;
config.SetSettingsValue("defaultServerIP", networkAddress);
QSBCore.Helper.Storage.Save(config, Constants.ModConfigFileName);
}
public override void OnClientConnect() // Called on the client when connecting to a server
{
DebugLog.DebugWrite("OnClientConnect", MessageType.Info);
base.OnClientConnect();
OnClientConnected?.SafeInvoke();
QSBMessageManager.Init();
gameObject.AddComponent<RespawnOnDeath>();
gameObject.AddComponent<ServerStateManager>();
gameObject.AddComponent<ClientStateManager>();
if (QSBSceneManager.IsInUniverse)
{
QSBWorldSync.BuildWorldObjects(QSBSceneManager.CurrentScene);
2022-01-14 22:22:45 -08:00
}
var specificType = QSBCore.IsHost ? QSBPatchTypes.OnServerClientConnect : QSBPatchTypes.OnNonServerClientConnect;
2022-01-14 22:22:45 -08:00
QSBPatchManager.DoPatchType(specificType);
QSBPatchManager.DoPatchType(QSBPatchTypes.OnClientConnect);
QSBCore.UnityEvents.RunWhen(() => PlayerTransformSync.LocalInstance,
() => new PlayerJoinMessage(PlayerName).Send());
if (!QSBCore.IsHost)
{
QSBCore.UnityEvents.RunWhen(() => PlayerTransformSync.LocalInstance,
() => new RequestStateResyncMessage().Send());
}
_everConnected = true;
}
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());
QSBWorldSync.RemoveWorldObjects();
2022-01-14 22:22:45 -08:00
if (WakeUpSync.LocalInstance != null)
{
WakeUpSync.LocalInstance.OnDisconnect();
}
if (_everConnected)
{
var specificType = QSBCore.IsHost ? QSBPatchTypes.OnServerClientConnect : QSBPatchTypes.OnNonServerClientConnect;
2022-01-14 22:22:45 -08:00
QSBPatchManager.DoUnpatchType(specificType);
QSBPatchManager.DoUnpatchType(QSBPatchTypes.OnClientConnect);
}
_everConnected = false;
}
public override void OnClientDisconnect()
{
base.OnClientDisconnect();
2022-01-15 23:11:40 -08:00
OnClientDisconnected?.SafeInvoke(_lastTransportError);
2022-01-24 02:35:37 -08:00
_lastTransportError = null;
2022-01-14 22:22:45 -08:00
}
public override void OnServerDisconnect(NetworkConnection conn) // Called on the server when any client disconnects
{
DebugLog.DebugWrite("OnServerDisconnect", MessageType.Info);
// revert authority from ship
2022-01-14 22:31:23 -08:00
if (ShipTransformSync.LocalInstance != null)
2022-01-14 22:22:45 -08:00
{
2022-01-14 22:31:23 -08:00
var identity = ShipTransformSync.LocalInstance.netIdentity;
2022-01-14 22:22:45 -08:00
if (identity != null && identity.connectionToClient == conn)
{
identity.SetAuthority(QSBPlayerManager.LocalPlayerId);
}
}
// stop dragging for the orbs this player was dragging
foreach (var qsbOrb in QSBWorldSync.GetWorldObjects<QSBOrb>())
{
if (qsbOrb.TransformSync == null)
{
2022-01-23 00:31:15 -08:00
DebugLog.ToConsole($"{qsbOrb} TransformSync == null??????????", MessageType.Warning);
2022-01-14 22:22:45 -08:00
continue;
}
var identity = qsbOrb.TransformSync.netIdentity;
if (identity.connectionToClient == conn)
{
qsbOrb.SetDragging(false);
qsbOrb.SendMessage(new OrbDragMessage(false));
}
}
2022-01-14 22:36:13 -08:00
AuthorityManager.OnDisconnect(conn);
2022-01-14 22:22:45 -08:00
base.OnServerDisconnect(conn);
}
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());
base.OnStopServer();
}
}
2021-11-09 17:56:45 -08:00
}