备份CatanBuilding瘦身独立工程
This commit is contained in:
@@ -0,0 +1,471 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using static com.fpnn.rtm.RTMClient;
|
||||
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
using UnityEngine;
|
||||
#endif
|
||||
|
||||
namespace com.fpnn.rtm
|
||||
{
|
||||
public static class RTMControlCenter
|
||||
{
|
||||
private static object interLocker = new object();
|
||||
//private static volatile bool networkReachable = true;
|
||||
private static volatile NetworkType networkType = NetworkType.NetworkType_Uninited;
|
||||
private static Dictionary<Int64, RTMClient> rtmClients = new Dictionary<long, RTMClient>();
|
||||
private static Dictionary<Int64, Dictionary<Int64, RTMClient>> pidUidClients = new Dictionary<Int64, Dictionary<Int64, RTMClient>>();
|
||||
private static Dictionary<RTMClient, Int64> reloginClients = new Dictionary<RTMClient, Int64>();
|
||||
|
||||
private static Dictionary<string, Dictionary<TCPClient, long>> fileClients = new Dictionary<string, Dictionary<TCPClient, long>>();
|
||||
|
||||
private static volatile bool routineInited;
|
||||
private static volatile bool routineRunning;
|
||||
private static Thread routineThread;
|
||||
private static GameObject rtmGameObject;
|
||||
public static RTMCallbackQueue callbackQueue;
|
||||
|
||||
static RTMControlCenter()
|
||||
{
|
||||
routineInited = false;
|
||||
}
|
||||
|
||||
public static NetworkType NetworkStatus
|
||||
{
|
||||
get { return networkType; }
|
||||
}
|
||||
//===========================[ Session Functions ]=========================//
|
||||
internal static void RegisterSession(Int64 connectionId, RTMClient client)
|
||||
{
|
||||
CheckRoutineInit();
|
||||
|
||||
lock (interLocker)
|
||||
{
|
||||
rtmClients.Add(connectionId, client);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void UnregisterSession(Int64 connectionId)
|
||||
{
|
||||
lock (interLocker)
|
||||
{
|
||||
rtmClients.Remove(connectionId);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void CloseSession(Int64 connectionId)
|
||||
{
|
||||
RTMClient client = null;
|
||||
lock (interLocker)
|
||||
{
|
||||
rtmClients.TryGetValue(connectionId, out client);
|
||||
}
|
||||
|
||||
if (client != null)
|
||||
client.Close();
|
||||
}
|
||||
|
||||
internal static ClientStatus GetClientStatus(Int64 connectionId)
|
||||
{
|
||||
RTMClient client = null;
|
||||
lock (interLocker)
|
||||
{
|
||||
rtmClients.TryGetValue(connectionId, out client);
|
||||
}
|
||||
|
||||
if (client != null)
|
||||
return client.Status;
|
||||
else
|
||||
return ClientStatus.Closed;
|
||||
}
|
||||
internal static void AddClient(Int64 projectId, Int64 uid, RTMClient client)
|
||||
{
|
||||
lock (interLocker)
|
||||
{
|
||||
pidUidClients.TryGetValue(projectId, out Dictionary<Int64, RTMClient> clients);
|
||||
if (clients == null)
|
||||
{
|
||||
clients = new Dictionary<long, RTMClient>{ { uid, client } };
|
||||
pidUidClients.Add(projectId, clients);
|
||||
}
|
||||
else
|
||||
{
|
||||
clients.TryGetValue(uid, out RTMClient rtmClient);
|
||||
if (rtmClient == null)
|
||||
clients.Add(uid, client);
|
||||
else
|
||||
throw new Exception("duplicated RTMClient pid = " + projectId.ToString() + ", uid = " + uid.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static RTMClient FetchClient(Int64 projectId, Int64 uid)
|
||||
{
|
||||
RTMClient client = null;
|
||||
lock (interLocker)
|
||||
{
|
||||
pidUidClients.TryGetValue(projectId, out Dictionary<Int64, RTMClient> clients);
|
||||
if (clients == null)
|
||||
return null;
|
||||
clients.TryGetValue(uid, out client);
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
//===========================[ Relogin Functions ]=========================//
|
||||
internal static void DelayRelogin(RTMClient client, long triggeredMs)
|
||||
{
|
||||
CheckRoutineInit();
|
||||
|
||||
lock (interLocker)
|
||||
{
|
||||
try
|
||||
{
|
||||
reloginClients.Add(client, triggeredMs);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
//-- Do nothing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReloginCheck()
|
||||
{
|
||||
//if (!networkReachable)
|
||||
//return;
|
||||
if (networkType != NetworkType.NetworkType_4G && networkType != NetworkType.NetworkType_Wifi)
|
||||
return;
|
||||
|
||||
HashSet<RTMClient> clients = new HashSet<RTMClient>();
|
||||
long now = ClientEngine.GetCurrentMilliseconds();
|
||||
|
||||
lock (interLocker)
|
||||
{
|
||||
foreach (KeyValuePair<RTMClient, Int64> kvp in reloginClients)
|
||||
{
|
||||
if (kvp.Value <= now)
|
||||
clients.Add(kvp.Key);
|
||||
}
|
||||
|
||||
foreach (RTMClient client in clients)
|
||||
reloginClients.Remove(client);
|
||||
}
|
||||
|
||||
foreach (RTMClient client in clients)
|
||||
{
|
||||
ClientEngine.RunTask(() => {
|
||||
if (client.CheckRelogin())
|
||||
client.StartRelogin();
|
||||
else
|
||||
{
|
||||
lock (interLocker)
|
||||
{
|
||||
reloginClients.Add(client, now);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//internal static void NetworkReachableChanged(bool reachable)
|
||||
//{
|
||||
// if (reachable != networkReachable)
|
||||
// {
|
||||
// networkReachable = reachable;
|
||||
// long now = ClientEngine.GetCurrentMilliseconds();
|
||||
// if (reachable)
|
||||
// {
|
||||
// Dictionary<RTMClient, Int64> clients = new Dictionary<RTMClient, Int64>();
|
||||
// lock (interLocker)
|
||||
// {
|
||||
// foreach (KeyValuePair<RTMClient, Int64> kvp in reloginClients)
|
||||
// clients.Add(kvp.Key, now);
|
||||
|
||||
// reloginClients = clients;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// lock (interLocker)
|
||||
// {
|
||||
// foreach (KeyValuePair<UInt64, RTMClient> kvp in rtmClients)
|
||||
// {
|
||||
// kvp.Value.Close();
|
||||
// reloginClients.Add(kvp.Value, now);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
internal static void NetworkChanged(NetworkType type)
|
||||
{
|
||||
if (networkType == NetworkType.NetworkType_Uninited)
|
||||
networkType = type;
|
||||
if (type == NetworkType.NetworkType_Unknown)
|
||||
type = NetworkType.NetworkType_Unreachable;
|
||||
if (networkType == type)
|
||||
return;
|
||||
long now = ClientEngine.GetCurrentMilliseconds();
|
||||
NetworkType oldType = networkType;
|
||||
networkType = type;
|
||||
ClientEngine.RunTask(()=>
|
||||
{
|
||||
if (oldType == NetworkType.NetworkType_Unreachable && (type == NetworkType.NetworkType_4G || type == NetworkType.NetworkType_Wifi))
|
||||
{//之前没有网络,现在有网络
|
||||
Dictionary<RTMClient, Int64> clients = new Dictionary<RTMClient, Int64>();
|
||||
List<RTMClient> activeClients = new List<RTMClient>();
|
||||
lock (interLocker)
|
||||
{
|
||||
foreach (KeyValuePair<RTMClient, Int64> kvp in reloginClients)
|
||||
clients.Add(kvp.Key, now);
|
||||
|
||||
foreach (KeyValuePair<Int64, RTMClient> kvp in rtmClients)
|
||||
{
|
||||
if (!clients.ContainsKey(kvp.Value))
|
||||
{
|
||||
if (kvp.Value.Status != ClientStatus.Connecting)
|
||||
{
|
||||
activeClients.Add(kvp.Value);
|
||||
clients.Add(kvp.Value, now);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (RTMClient client in activeClients)
|
||||
client.Close(false, false);
|
||||
|
||||
reloginClients = clients;
|
||||
}
|
||||
}
|
||||
else if ((type == NetworkType.NetworkType_4G && oldType == NetworkType.NetworkType_Wifi) || (oldType == NetworkType.NetworkType_4G && type == NetworkType.NetworkType_Wifi))
|
||||
{
|
||||
lock (interLocker)
|
||||
{
|
||||
List<RTMClient> clients = new List<RTMClient>();
|
||||
foreach (KeyValuePair<Int64, RTMClient> kvp in rtmClients)
|
||||
{
|
||||
if (kvp.Value.Status != ClientStatus.Connecting)
|
||||
{
|
||||
clients.Add(kvp.Value);
|
||||
}
|
||||
}
|
||||
foreach (RTMClient client in clients)
|
||||
client.Close(false, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (interLocker)
|
||||
{
|
||||
List<RTMClient> clients = new List<RTMClient>();
|
||||
foreach (KeyValuePair<Int64, RTMClient> kvp in rtmClients)
|
||||
{
|
||||
if (kvp.Value.Status != ClientStatus.Connecting)
|
||||
{
|
||||
clients.Add(kvp.Value);
|
||||
reloginClients.Add(kvp.Value, now);
|
||||
}
|
||||
}
|
||||
foreach (RTMClient client in clients)
|
||||
client.Close(false, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//===========================[ File Gate Client Functions ]=========================//
|
||||
internal static void ActiveFileGateClient(string endpoint, TCPClient client)
|
||||
{
|
||||
lock (interLocker)
|
||||
{
|
||||
if (fileClients.TryGetValue(endpoint, out Dictionary<TCPClient, long> clients))
|
||||
{
|
||||
if (clients.ContainsKey(client))
|
||||
clients[client] = ClientEngine.GetCurrentSeconds();
|
||||
else
|
||||
clients.Add(client, ClientEngine.GetCurrentSeconds());
|
||||
}
|
||||
else
|
||||
{
|
||||
clients = new Dictionary<TCPClient, long>
|
||||
{
|
||||
{ client, ClientEngine.GetCurrentSeconds() }
|
||||
};
|
||||
fileClients.Add(endpoint, clients);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static TCPClient FecthFileGateClient(string endpoint)
|
||||
{
|
||||
lock (interLocker)
|
||||
{
|
||||
if (fileClients.TryGetValue(endpoint, out Dictionary<TCPClient, long> clients))
|
||||
{
|
||||
foreach (KeyValuePair<TCPClient, long> kvp in clients)
|
||||
return kvp.Key;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void CheckFileGateClients()
|
||||
{
|
||||
HashSet<string> emptyEndpoints = new HashSet<string>();
|
||||
|
||||
lock (interLocker)
|
||||
{
|
||||
long threshold = ClientEngine.GetCurrentSeconds() - RTMConfig.fileGateClientHoldingSeconds;
|
||||
|
||||
foreach (KeyValuePair<string, Dictionary<TCPClient, long>> kvp in fileClients)
|
||||
{
|
||||
HashSet<TCPClient> unactivedClients = new HashSet<TCPClient>();
|
||||
|
||||
foreach (KeyValuePair<TCPClient, long> subKvp in kvp.Value)
|
||||
{
|
||||
if (subKvp.Value <= threshold)
|
||||
unactivedClients.Add(subKvp.Key);
|
||||
}
|
||||
|
||||
foreach (TCPClient client in unactivedClients)
|
||||
{
|
||||
kvp.Value.Remove(client);
|
||||
}
|
||||
|
||||
if (kvp.Value.Count == 0)
|
||||
emptyEndpoints.Add(kvp.Key);
|
||||
}
|
||||
|
||||
foreach (string endpoint in emptyEndpoints)
|
||||
fileClients.Remove(endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================[ Init & Routine Functions ]=========================//
|
||||
public static void Init()
|
||||
{
|
||||
Init(null);
|
||||
}
|
||||
|
||||
public static void Init(RTMConfig config)
|
||||
{
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
StatusMonitor.Instance.Init();
|
||||
#endif
|
||||
InitCallbackQueue();
|
||||
if (config == null)
|
||||
return;
|
||||
|
||||
RTMConfig.Config(config);
|
||||
}
|
||||
|
||||
private static void InitCallbackQueue()
|
||||
{
|
||||
rtmGameObject = new GameObject(RTMConfig.RTMGameObjectName);
|
||||
callbackQueue = rtmGameObject.AddComponent<RTMCallbackQueue>();
|
||||
GameObject.DontDestroyOnLoad(rtmGameObject);
|
||||
rtmGameObject.hideFlags = HideFlags.HideInHierarchy;
|
||||
}
|
||||
|
||||
private static void CheckRoutineInit()
|
||||
{
|
||||
if (routineInited)
|
||||
return;
|
||||
|
||||
lock (interLocker)
|
||||
{
|
||||
if (routineInited)
|
||||
return;
|
||||
|
||||
routineRunning = true;
|
||||
|
||||
routineThread = new Thread(RoutineFunc)
|
||||
{
|
||||
Name = "RTM.ControlCenter.RoutineThread",
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
#else
|
||||
IsBackground = true
|
||||
#endif
|
||||
};
|
||||
routineThread.Start();
|
||||
|
||||
|
||||
routineInited = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static void RoutineFunc()
|
||||
{
|
||||
while (routineRunning)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
|
||||
HashSet<RTMClient> clients;
|
||||
try
|
||||
{
|
||||
clients = new HashSet<RTMClient>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
RTMConfig.errorRecorder?.RecordError(e);
|
||||
continue;
|
||||
}
|
||||
|
||||
lock (interLocker)
|
||||
{
|
||||
foreach (KeyValuePair<Int64, RTMClient> kvp in rtmClients)
|
||||
clients.Add(kvp.Value);
|
||||
}
|
||||
|
||||
foreach (RTMClient client in clients)
|
||||
if (client.ConnectionIsAlive() == false)
|
||||
client.Close(false, true);
|
||||
|
||||
CheckFileGateClients();
|
||||
ReloginCheck();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Close()
|
||||
{
|
||||
#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
|
||||
AudioRecorderNative.destroy();
|
||||
#endif
|
||||
StatusMonitor.Instance.Close();
|
||||
|
||||
lock (interLocker)
|
||||
{
|
||||
if (!routineInited)
|
||||
return;
|
||||
|
||||
if (!routineRunning)
|
||||
return;
|
||||
|
||||
routineRunning = false;
|
||||
}
|
||||
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
routineThread.Join();
|
||||
#endif
|
||||
HashSet<RTMClient> clients = new HashSet<RTMClient>();
|
||||
|
||||
lock (interLocker)
|
||||
{
|
||||
foreach (KeyValuePair<Int64, RTMClient> kvp in rtmClients)
|
||||
clients.Add(kvp.Value);
|
||||
}
|
||||
|
||||
foreach (RTMClient client in clients)
|
||||
client.Close(true, true);
|
||||
|
||||
rtmClients.Clear();
|
||||
pidUidClients.Clear();
|
||||
reloginClients.Clear();
|
||||
fileClients.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user